rpms/openssh/devel openssh-5.2p1-fips.patch, NONE, 1.1 openssh-5.2p1-nss-keys.patch, NONE, 1.1 openssh-5.2p1-redhat.patch, NONE, 1.1 openssh-5.2p1-selinux.patch, NONE, 1.1 openssh-5.2p1-vendor.patch, NONE, 1.1 openssh.spec, 1.137, 1.138 openssh-5.1p1-bannerlen.patch, 1.1, NONE openssh-5.1p1-compat-sessions.patch, 1.1, NONE openssh-5.1p1-fips.patch, 1.1, NONE openssh-5.1p1-nss-keys.patch, 1.2, NONE openssh-5.1p1-redhat.patch, 1.2, NONE openssh-5.1p1-selinux.patch, 1.1, NONE openssh-5.1p1-vendor.patch, 1.1, NONE
Jan F. Chadima
jfch2222 at fedoraproject.org
Tue Mar 10 11:55:14 UTC 2009
Author: jfch2222
Update of /cvs/pkgs/rpms/openssh/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv27146
Modified Files:
openssh.spec
Added Files:
openssh-5.2p1-fips.patch openssh-5.2p1-nss-keys.patch
openssh-5.2p1-redhat.patch openssh-5.2p1-selinux.patch
openssh-5.2p1-vendor.patch
Removed Files:
openssh-5.1p1-bannerlen.patch
openssh-5.1p1-compat-sessions.patch openssh-5.1p1-fips.patch
openssh-5.1p1-nss-keys.patch openssh-5.1p1-redhat.patch
openssh-5.1p1-selinux.patch openssh-5.1p1-vendor.patch
Log Message:
Bounce openssh to version 5.2p1
openssh-5.2p1-fips.patch:
--- NEW FILE openssh-5.2p1-fips.patch ---
diff -up openssh-5.2p1/auth2-pubkey.c.fips openssh-5.2p1/auth2-pubkey.c
--- openssh-5.2p1/auth2-pubkey.c.fips 2009-03-10 03:51:55.047234449 +0100
+++ openssh-5.2p1/auth2-pubkey.c 2009-03-10 03:51:56.174214480 +0100
@@ -33,6 +33,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+#include <openssl/fips.h>
#include "xmalloc.h"
#include "ssh.h"
@@ -243,7 +244,7 @@ user_key_allowed2(struct passwd *pw, Key
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(found, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(found), fp);
xfree(fp);
diff -up openssh-5.2p1/cipher.c.fips openssh-5.2p1/cipher.c
--- openssh-5.2p1/cipher.c.fips 2009-03-09 09:47:30.000000000 +0100
+++ openssh-5.2p1/cipher.c 2009-03-10 03:51:56.297398184 +0100
@@ -40,6 +40,7 @@
#include <sys/types.h>
#include <openssl/md5.h>
+#include <openssl/fips.h>
#include <string.h>
#include <stdarg.h>
@@ -93,6 +94,22 @@ struct Cipher {
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL }
};
+struct Cipher fips_ciphers[] = {
+ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null },
+ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des },
+
+ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc },
+ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc },
+ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc },
+ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
+ { "rijndael-cbc at lysator.liu.se",
+ SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
+ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr },
+ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr },
+ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr },
+ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL }
+};
+
/*--*/
u_int
@@ -135,7 +152,7 @@ Cipher *
cipher_by_name(const char *name)
{
Cipher *c;
- for (c = ciphers; c->name != NULL; c++)
+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++)
if (strcmp(c->name, name) == 0)
return c;
return NULL;
@@ -145,7 +162,7 @@ Cipher *
cipher_by_number(int id)
{
Cipher *c;
- for (c = ciphers; c->name != NULL; c++)
+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++)
if (c->number == id)
return c;
return NULL;
@@ -189,7 +206,7 @@ cipher_number(const char *name)
Cipher *c;
if (name == NULL)
return -1;
- for (c = ciphers; c->name != NULL; c++)
+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++)
if (strcasecmp(c->name, name) == 0)
return c->number;
return -1;
diff -up openssh-5.2p1/mac.c.fips openssh-5.2p1/mac.c
--- openssh-5.2p1/mac.c.fips 2008-06-13 02:58:50.000000000 +0200
+++ openssh-5.2p1/mac.c 2009-03-10 03:51:56.227222184 +0100
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <openssl/hmac.h>
+#include <openssl/fips.h>
#include <stdarg.h>
#include <string.h>
@@ -47,14 +48,14 @@
#define SSH_EVP 1 /* OpenSSL EVP-based MAC */
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */
-struct {
+struct Macs {
char *name;
int type;
const EVP_MD * (*mdfunc)(void);
int truncatebits; /* truncate digest if != 0 */
int key_len; /* just for UMAC */
int len; /* just for UMAC */
-} macs[] = {
+} all_macs[] = {
{ "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 },
{ "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 },
{ "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1 },
@@ -65,9 +66,15 @@ struct {
{ NULL, 0, NULL, 0, -1, -1 }
};
+struct Macs fips_macs[] = {
+ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 },
+ { NULL, 0, NULL, 0, -1, -1 }
+};
+
static void
mac_setup_by_id(Mac *mac, int which)
{
+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs;
int evp_len;
mac->type = macs[which].type;
if (mac->type == SSH_EVP) {
@@ -88,6 +95,7 @@ int
mac_setup(Mac *mac, char *name)
{
int i;
+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs;
for (i = 0; macs[i].name; i++) {
if (strcmp(name, macs[i].name) == 0) {
diff -up openssh-5.2p1/Makefile.in.fips openssh-5.2p1/Makefile.in
--- openssh-5.2p1/Makefile.in.fips 2009-03-10 03:51:55.910250677 +0100
+++ openssh-5.2p1/Makefile.in 2009-03-10 03:51:56.222702935 +0100
@@ -134,28 +134,28 @@ libssh.a: $(LIBSSH_OBJS)
$(RANLIB) $@
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) -lfipscheck $(LIBS)
scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
$(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o
- $(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o
- $(LD) -o $@ ssh-keysign.o readconf.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-keysign.o readconf.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
- $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+ $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
$(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
diff -up openssh-5.2p1/myproposal.h.fips openssh-5.2p1/myproposal.h
--- openssh-5.2p1/myproposal.h.fips 2009-01-28 06:33:31.000000000 +0100
+++ openssh-5.2p1/myproposal.h 2009-03-10 03:51:56.257243733 +0100
@@ -53,7 +53,11 @@
"hmac-sha1-96,hmac-md5-96"
#define KEX_DEFAULT_COMP "none,zlib at openssh.com,zlib"
#define KEX_DEFAULT_LANG ""
-
+#define KEX_FIPS_ENCRYPT \
+ "aes128-cbc,3des-cbc," \
+ "aes192-cbc,aes256-cbc,rijndael-cbc at lysator.liu.se"
+#define KEX_FIPS_MAC \
+ "hmac-sha1"
static char *myproposal[PROPOSAL_MAX] = {
KEX_DEFAULT_KEX,
diff -up openssh-5.2p1/nsskeys.c.fips openssh-5.2p1/nsskeys.c
--- openssh-5.2p1/nsskeys.c.fips 2009-03-10 03:51:55.871242620 +0100
+++ openssh-5.2p1/nsskeys.c 2009-03-10 03:51:56.251363837 +0100
@@ -183,8 +183,8 @@ nss_convert_pubkey(Key *k)
break;
}
- p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
- debug("fingerprint %u %s", key_size(k), p);
+ p = key_fingerprint(k, SSH_FP_SHA1, SSH_FP_HEX);
+ debug("SHA1 fingerprint %u %s", key_size(k), p);
xfree(p);
return 0;
diff -up openssh-5.2p1/openbsd-compat/bsd-arc4random.c.fips openssh-5.2p1/openbsd-compat/bsd-arc4random.c
--- openssh-5.2p1/openbsd-compat/bsd-arc4random.c.fips 2008-06-04 02:54:00.000000000 +0200
+++ openssh-5.2p1/openbsd-compat/bsd-arc4random.c 2009-03-10 03:51:56.255331659 +0100
@@ -39,6 +39,7 @@
static int rc4_ready = 0;
static RC4_KEY rc4;
+#if 0
unsigned int
arc4random(void)
{
@@ -82,6 +83,32 @@ arc4random_stir(void)
rc4_ready = REKEY_BYTES;
}
+#else
+unsigned int
+arc4random(void)
+{
+ unsigned int r = 0;
+ void *rp = &r;
+
+ if (!rc4_ready) {
+ arc4random_stir();
+ }
+ RAND_bytes(rp, sizeof(r));
+
+ return(r);
+}
+
+void
+arc4random_stir(void)
+{
+ unsigned char rand_buf[SEED_SIZE];
+
+ if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0)
+ fatal("Couldn't obtain random bytes (error %ld)",
+ ERR_get_error());
+ rc4_ready = 1;
+}
+#endif
#endif /* !HAVE_ARC4RANDOM */
#ifndef ARC4RANDOM_BUF
diff -up openssh-5.2p1/ssh-add.c.fips openssh-5.2p1/ssh-add.c
--- openssh-5.2p1/ssh-add.c.fips 2009-03-10 03:51:55.928225121 +0100
+++ openssh-5.2p1/ssh-add.c 2009-03-10 03:51:56.254252403 +0100
@@ -42,6 +42,8 @@
#include <sys/param.h>
#include <openssl/evp.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#ifdef HAVE_LIBNSS
@@ -254,7 +256,7 @@ list_identities(AuthenticationConnection
key = ssh_get_next_identity(ac, &comment, version)) {
had_identities = 1;
if (do_fp) {
- fp = key_fingerprint(key, SSH_FP_MD5,
+ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5,
SSH_FP_HEX);
printf("%d %s %s (%s)\n",
key_size(key), fp, comment, key_type(key));
@@ -463,11 +465,16 @@ main(int argc, char **argv)
sanitise_stdfd();
__progname = ssh_get_progname(argv[0]);
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fprintf(stderr,
+ "FIPS integrity verification test failed.\n");
+ exit(3);
+ }
+
init_rng();
seed_rng();
- SSLeay_add_all_algorithms();
-
/* At first, get a connection to the authentication agent. */
ac = ssh_get_authentication_connection();
if (ac == NULL) {
diff -up openssh-5.2p1/ssh-agent.c.fips openssh-5.2p1/ssh-agent.c
--- openssh-5.2p1/ssh-agent.c.fips 2009-03-10 03:51:55.846341085 +0100
+++ openssh-5.2p1/ssh-agent.c 2009-03-10 03:51:56.171221623 +0100
@@ -51,6 +51,8 @@
#include <openssl/evp.h>
#include <openssl/md5.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#include <errno.h>
@@ -200,9 +202,9 @@ confirm_key(Identity *id)
char *p;
int ret = -1;
- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
- if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
- id->comment, p))
+ p = key_fingerprint(id->key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX);
+ if (ask_permission("Allow use of key %s?\nKey %sfingerprint %s.",
+ id->comment, FIPS_mode() ? "SHA1 " : "", p))
ret = 0;
xfree(p);
@@ -1196,6 +1198,11 @@ main(int ac, char **av)
#endif
SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fprintf(stderr,
+ "FIPS integrity verification test failed.\n");
+ exit(3);
+ }
__progname = ssh_get_progname(av[0]);
init_rng();
diff -up openssh-5.2p1/ssh.c.fips openssh-5.2p1/ssh.c
--- openssh-5.2p1/ssh.c.fips 2009-03-10 03:51:55.906266464 +0100
+++ openssh-5.2p1/ssh.c 2009-03-10 03:51:56.176206362 +0100
@@ -71,6 +71,8 @@
#include <openssl/evp.h>
#include <openssl/err.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
@@ -220,6 +222,10 @@ main(int ac, char **av)
sanitise_stdfd();
__progname = ssh_get_progname(av[0]);
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fatal("FIPS integrity verification test failed.");
+ }
init_rng();
/*
@@ -550,7 +556,6 @@ main(int ac, char **av)
if (!host)
usage();
- SSLeay_add_all_algorithms();
ERR_load_crypto_strings();
/* Initialize the command to execute on remote host. */
diff -up openssh-5.2p1/sshconnect2.c.fips openssh-5.2p1/sshconnect2.c
--- openssh-5.2p1/sshconnect2.c.fips 2009-03-10 03:51:56.079247745 +0100
+++ openssh-5.2p1/sshconnect2.c 2009-03-10 03:51:56.197416110 +0100
@@ -44,6 +44,8 @@
#include <vis.h>
#endif
+#include <openssl/fips.h>
+
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
@@ -115,6 +117,10 @@ ssh_kex2(char *host, struct sockaddr *ho
if (options.ciphers != NULL) {
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT;
+
}
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
@@ -130,7 +136,11 @@ ssh_kex2(char *host, struct sockaddr *ho
if (options.macs != NULL) {
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC;
}
+
if (options.hostkeyalgorithms != NULL)
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
options.hostkeyalgorithms;
@@ -507,8 +517,8 @@ input_userauth_pk_ok(int type, u_int32_t
key->type, pktype);
goto done;
}
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
- debug2("input_userauth_pk_ok: fp %s", fp);
+ fp = key_fingerprint(key, SSH_FP_SHA1, SSH_FP_HEX);
+ debug2("input_userauth_pk_ok: SHA1 fp %s", fp);
xfree(fp);
/*
diff -up openssh-5.2p1/sshconnect.c.fips openssh-5.2p1/sshconnect.c
--- openssh-5.2p1/sshconnect.c.fips 2009-03-10 03:51:56.085211598 +0100
+++ openssh-5.2p1/sshconnect.c 2009-03-10 03:51:56.315348971 +0100
@@ -40,6 +40,8 @@
#include <unistd.h>
#include <fcntl.h>
+#include <openssl/fips.h>
+
#include "xmalloc.h"
#include "key.h"
#include "hostfile.h"
@@ -761,6 +763,7 @@ check_host_key(char *hostname, struct so
goto fail;
} else if (options.strict_host_key_checking == 2) {
char msg1[1024], msg2[1024];
+ int fips_on = FIPS_mode();
if (show_other_keys(host, host_key))
snprintf(msg1, sizeof(msg1),
@@ -769,8 +772,8 @@ check_host_key(char *hostname, struct so
else
snprintf(msg1, sizeof(msg1), ".");
/* The default */
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
- ra = key_fingerprint(host_key, SSH_FP_MD5,
+ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX);
+ ra = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5,
SSH_FP_RANDOMART);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
@@ -786,10 +789,10 @@ check_host_key(char *hostname, struct so
snprintf(msg, sizeof(msg),
"The authenticity of host '%.200s (%s)' can't be "
"established%s\n"
- "%s key fingerprint is %s.%s%s\n%s"
+ "%s key %sfingerprint is %s.%s%s\n%s"
"Are you sure you want to continue connecting "
"(yes/no)? ",
- host, ip, msg1, type, fp,
+ host, ip, msg1, type, fips_on ? "SHA1 " : "", fp,
options.visual_host_key ? "\n" : "",
options.visual_host_key ? ra : "",
msg2);
@@ -1077,17 +1080,18 @@ show_key_from_file(const char *file, con
Key *found;
char *fp, *ra;
int line, ret;
+ int fips_on = FIPS_mode();
found = key_new(keytype);
if ((ret = lookup_key_in_hostfile_by_type(file, host,
keytype, found, &line))) {
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
- ra = key_fingerprint(found, SSH_FP_MD5, SSH_FP_RANDOMART);
+ fp = key_fingerprint(found, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX);
+ ra = key_fingerprint(found, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_RANDOMART);
logit("WARNING: %s key found for host %s\n"
"in %s:%d\n"
- "%s key fingerprint %s.\n%s\n",
+ "%s key %sfingerprint %s.\n%s\n",
key_type(found), host, file, line,
- key_type(found), fp, ra);
+ key_type(found), fips_on ? "SHA1 ":"", fp, ra);
xfree(ra);
xfree(fp);
}
@@ -1133,8 +1137,9 @@ warn_changed_key(Key *host_key)
{
char *fp;
const char *type = key_type(host_key);
+ int fips_on = FIPS_mode();
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
@@ -1142,8 +1147,8 @@ warn_changed_key(Key *host_key)
error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
error("It is also possible that the %s host key has just been changed.", type);
- error("The fingerprint for the %s key sent by the remote host is\n%s.",
- type, fp);
+ error("The %sfingerprint for the %s key sent by the remote host is\n%s.",
+ fips_on ? "SHA1 ":"", type, fp);
error("Please contact your system administrator.");
xfree(fp);
diff -up openssh-5.2p1/sshd.c.fips openssh-5.2p1/sshd.c
--- openssh-5.2p1/sshd.c.fips 2009-03-10 03:51:55.512212775 +0100
+++ openssh-5.2p1/sshd.c 2009-03-10 03:51:56.224238563 +0100
@@ -76,6 +76,8 @@
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#ifdef HAVE_SECUREWARE
@@ -1260,6 +1262,12 @@ main(int ac, char **av)
(void)set_auth_parameters(ac, av);
#endif
__progname = ssh_get_progname(av[0]);
+
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fatal("FIPS integrity verification test failed.");
+ }
+
init_rng();
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
@@ -1412,8 +1420,6 @@ main(int ac, char **av)
else
closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
- SSLeay_add_all_algorithms();
-
/*
* Force logging to stderr until we have loaded the private host
* key (unless started from inetd)
@@ -2182,6 +2188,9 @@ do_ssh2_kex(void)
if (options.ciphers != NULL) {
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT;
}
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
@@ -2191,6 +2200,9 @@ do_ssh2_kex(void)
if (options.macs != NULL) {
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC;
}
if (options.compression == COMP_NONE) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] =
diff -up openssh-5.2p1/ssh-keygen.c.fips openssh-5.2p1/ssh-keygen.c
--- openssh-5.2p1/ssh-keygen.c.fips 2009-03-10 03:51:55.948283636 +0100
+++ openssh-5.2p1/ssh-keygen.c 2009-03-10 03:51:56.249239228 +0100
@@ -21,6 +21,8 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#include <errno.h>
@@ -537,7 +539,7 @@ do_fingerprint(struct passwd *pw)
enum fp_type fptype;
struct stat st;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+ fptype = print_bubblebabble ? SSH_FP_SHA1 : FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
if (!have_identity)
@@ -1125,6 +1127,12 @@ main(int argc, char **argv)
__progname = ssh_get_progname(argv[0]);
SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fprintf(stderr,
+ "FIPS integrity verification test failed.\n");
+ exit(3);
+ }
+
log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
init_rng();
@@ -1506,14 +1514,15 @@ passphrase_again:
fclose(f);
if (!quiet) {
- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
- char *ra = key_fingerprint(public, SSH_FP_MD5,
+ int fips_on = FIPS_mode();
+ char *fp = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX);
+ char *ra = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5,
SSH_FP_RANDOMART);
printf("Your public key has been saved in %s.\n",
identity_file);
- printf("The key fingerprint is:\n");
+ printf("The key %sfingerprint is:\n", fips_on ? "SHA1 " : "");
printf("%s %s\n", fp, comment);
- printf("The key's randomart image is:\n");
+ printf("The key's %srandomart image is:\n", fips_on ? "SHA1 " :"");
printf("%s\n", ra);
xfree(ra);
xfree(fp);
diff -up openssh-5.2p1/ssh-keyscan.c.fips openssh-5.2p1/ssh-keyscan.c
--- openssh-5.2p1/ssh-keyscan.c.fips 2009-01-28 06:31:23.000000000 +0100
+++ openssh-5.2p1/ssh-keyscan.c 2009-03-10 03:51:56.313291759 +0100
@@ -19,6 +19,8 @@
#include <arpa/inet.h>
#include <openssl/bn.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include <netdb.h>
#include <errno.h>
@@ -731,6 +733,13 @@ main(int argc, char **argv)
extern char *optarg;
__progname = ssh_get_progname(argv[0]);
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fprintf(stderr,
+ "FIPS integrity verification test failed.\n");
+ exit(3);
+ }
+
init_rng();
seed_rng();
TAILQ_INIT(&tq);
diff -up openssh-5.2p1/ssh-keysign.c.fips openssh-5.2p1/ssh-keysign.c
--- openssh-5.2p1/ssh-keysign.c.fips 2006-09-01 07:38:37.000000000 +0200
+++ openssh-5.2p1/ssh-keysign.c 2009-03-10 03:51:56.295222876 +0100
@@ -38,6 +38,8 @@
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "xmalloc.h"
#include "log.h"
@@ -175,6 +177,11 @@ main(int argc, char **argv)
permanently_set_uid(pw);
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fatal("FIPS integrity verification test failed");
+ }
+
init_rng();
seed_rng();
arc4random_stir();
@@ -194,7 +201,6 @@ main(int argc, char **argv)
if (key_fd[0] == -1 && key_fd[1] == -1)
fatal("could not open any host key");
- SSLeay_add_all_algorithms();
for (i = 0; i < 256; i++)
rnd[i] = arc4random();
RAND_seed(rnd, sizeof(rnd));
openssh-5.2p1-nss-keys.patch:
--- NEW FILE openssh-5.2p1-nss-keys.patch ---
diff -up openssh-5.2p1/authfd.c.nss-keys openssh-5.2p1/authfd.c
--- openssh-5.2p1/authfd.c.nss-keys 2006-09-01 07:38:36.000000000 +0200
+++ openssh-5.2p1/authfd.c 2009-03-10 03:51:55.866208145 +0100
@@ -626,6 +626,45 @@ ssh_update_card(AuthenticationConnection
return decode_reply(type);
}
+int
+ssh_update_nss_key(AuthenticationConnection *auth, int add,
+ const char *tokenname, const char *keyname,
+ const char *pass, u_int life, u_int confirm)
+{
+ Buffer msg;
+ int type, constrained = (life || confirm);
+
+ if (add) {
+ type = constrained ?
+ SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED :
+ SSH_AGENTC_ADD_NSS_KEY;
+ } else
+ type = SSH_AGENTC_REMOVE_NSS_KEY;
+
+ buffer_init(&msg);
+ buffer_put_char(&msg, type);
+ buffer_put_cstring(&msg, tokenname);
+ buffer_put_cstring(&msg, keyname);
+ buffer_put_cstring(&msg, pass);
+
+ if (constrained) {
+ if (life != 0) {
+ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
+ buffer_put_int(&msg, life);
+ }
+ if (confirm != 0)
+ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM);
+ }
+
+ if (ssh_request_reply(auth, &msg, &msg) == 0) {
+ buffer_free(&msg);
+ return 0;
+ }
+ type = buffer_get_char(&msg);
+ buffer_free(&msg);
+ return decode_reply(type);
+}
+
/*
* Removes all identities from the agent. This call is not meant to be used
* by normal applications.
diff -up openssh-5.2p1/authfd.h.nss-keys openssh-5.2p1/authfd.h
--- openssh-5.2p1/authfd.h.nss-keys 2006-08-05 04:39:39.000000000 +0200
+++ openssh-5.2p1/authfd.h 2009-03-10 03:51:55.847449129 +0100
@@ -49,6 +49,12 @@
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
+/* nss */
+#define SSH_AGENTC_ADD_NSS_KEY 30
+#define SSH_AGENTC_REMOVE_NSS_KEY 31
+#define SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED 32
+
+
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
@@ -83,6 +89,8 @@ int ssh_remove_all_identities(Authentic
int ssh_lock_agent(AuthenticationConnection *, int, const char *);
int ssh_update_card(AuthenticationConnection *, int, const char *,
const char *, u_int, u_int);
+int ssh_update_nss_key(AuthenticationConnection *, int, const char *,
+ const char *, const char *, u_int, u_int);
int
ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],
diff -up openssh-5.2p1/configure.ac.nss-keys openssh-5.2p1/configure.ac
--- openssh-5.2p1/configure.ac.nss-keys 2009-03-10 03:51:55.285821039 +0100
+++ openssh-5.2p1/configure.ac 2009-03-10 03:51:55.850215090 +0100
@@ -3462,6 +3462,20 @@ AC_ARG_WITH(kerberos5,
]
)
+# Check whether user wants NSS support
+LIBNSS_MSG="no"
+AC_ARG_WITH(nss,
+ [ --with-nss Enable NSS support],
+ [ if test "x$withval" != "xno" ; then
+ AC_DEFINE(HAVE_LIBNSS,1,[Define if you want NSS support.])
+ LIBNSS_MSG="yes"
+ CPPFLAGS="$CPPFLAGS -I/usr/include/nss3 -I/usr/include/nspr4"
+ AC_CHECK_HEADERS(pk11pub.h)
+ LIBS="$LIBS -lnss3"
+ fi
+ ])
+AC_SUBST(LIBNSS)
+
# Looking for programs, paths and files
PRIVSEP_PATH=/var/empty
@@ -4189,6 +4203,7 @@ echo " TCP Wrappers support
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " Solaris process contract support: $SPC_MSG"
+echo " NSS support: $LIBNSS_MSG"
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
echo " BSD Auth support: $BSD_AUTH_MSG"
diff -up openssh-5.2p1/key.c.nss-keys openssh-5.2p1/key.c
--- openssh-5.2p1/key.c.nss-keys 2008-11-03 09:24:17.000000000 +0100
+++ openssh-5.2p1/key.c 2009-03-10 03:51:55.840226575 +0100
@@ -96,6 +96,54 @@ key_new(int type)
return k;
}
+#ifdef HAVE_LIBNSS
+Key *
+key_new_nss(int type)
+{
+ Key *k = key_new(type);
+
+ k->nss = xcalloc(1, sizeof(*k->nss));
+ k->flags = KEY_FLAG_EXT | KEY_FLAG_NSS;
+
+ return k;
+}
+
+Key *
+key_new_nss_copy(int type, const Key *c)
+{
+ Key *k = key_new_nss(type);
+
+ switch (k->type) {
+ case KEY_RSA:
+ if ((BN_copy(k->rsa->n, c->rsa->n) == NULL) ||
+ (BN_copy(k->rsa->e, c->rsa->e) == NULL))
+ fatal("key_new_nss_copy: BN_copy failed");
+ break;
+ case KEY_DSA:
+ if ((BN_copy(k->dsa->p, c->rsa->p) == NULL) ||
+ (BN_copy(k->dsa->q, c->dsa->q) == NULL) ||
+ (BN_copy(k->dsa->g, c->dsa->g) == NULL) ||
+ (BN_copy(k->dsa->pub_key, c->dsa->pub_key) == NULL))
+ fatal("key_new_nss_copy: BN_copy failed");
+ break;
+ }
+
+ k->nss->privk = SECKEY_CopyPrivateKey(c->nss->privk);
+ if (k->nss->privk == NULL)
+ fatal("key_new_nss_copy: SECKEY_CopyPrivateKey failed");
+
+ k->nss->pubk = SECKEY_CopyPublicKey(c->nss->pubk);
+ if (k->nss->pubk == NULL)
+ fatal("key_new_nss_copy: SECKEY_CopyPublicKey failed");
+
+ if (c->nss->privk->wincx)
+ k->nss->privk->wincx = xstrdup(c->nss->privk->wincx);
+
+ return k;
+}
+#endif
+
+
Key *
key_new_private(int type)
{
@@ -151,6 +199,19 @@ key_free(Key *k)
fatal("key_free: bad key type %d", k->type);
break;
}
+#ifdef HAVE_LIBNSS
+ if (k->flags & KEY_FLAG_NSS) {
+ if (k->nss->privk != NULL && k->nss->privk->wincx != NULL) {
+ memset(k->nss->privk->wincx, 0,
+ strlen(k->nss->privk->wincx));
+ xfree(k->nss->privk->wincx);
+ k->nss->privk->wincx = NULL;
+ }
+ SECKEY_DestroyPrivateKey(k->nss->privk);
+ SECKEY_DestroyPublicKey(k->nss->pubk);
+ xfree(k->nss);
+ }
+#endif
xfree(k);
}
diff -up openssh-5.2p1/key.h.nss-keys openssh-5.2p1/key.h
--- openssh-5.2p1/key.h.nss-keys 2008-06-12 20:40:35.000000000 +0200
+++ openssh-5.2p1/key.h 2009-03-10 03:51:55.925279322 +0100
@@ -29,11 +29,17 @@
#include <openssl/rsa.h>
#include <openssl/dsa.h>
+#ifdef HAVE_LIBNSS
+#include <nss.h>
+#include <keyhi.h>
+#endif
+
typedef struct Key Key;
enum types {
KEY_RSA1,
KEY_RSA,
KEY_DSA,
+ KEY_NSS,
KEY_UNSPEC
};
enum fp_type {
@@ -48,16 +54,30 @@ enum fp_rep {
/* key is stored in external hardware */
#define KEY_FLAG_EXT 0x0001
+#define KEY_FLAG_NSS 0x0002
+
+#ifdef HAVE_LIBNSS
+typedef struct NSSKey NSSKey;
+struct NSSKey {
+ SECKEYPrivateKey *privk;
+ SECKEYPublicKey *pubk;
+};
+#endif
struct Key {
int type;
int flags;
RSA *rsa;
DSA *dsa;
+#ifdef HAVE_LIBNSS
+ NSSKey *nss;
+#endif
};
Key *key_new(int);
Key *key_new_private(int);
+Key *key_new_nss(int);
+Key *key_new_nss_copy(int, const Key *);
void key_free(Key *);
Key *key_demote(const Key *);
int key_equal(const Key *, const Key *);
diff -up openssh-5.2p1/Makefile.in.nss-keys openssh-5.2p1/Makefile.in
--- openssh-5.2p1/Makefile.in.nss-keys 2008-11-05 06:20:46.000000000 +0100
+++ openssh-5.2p1/Makefile.in 2009-03-10 03:51:56.222702935 +0100
@@ -71,7 +71,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
- entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o
+ entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o nsskeys.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
sshconnect.o sshconnect1.o sshconnect2.o mux.o
@@ -134,28 +134,28 @@ libssh.a: $(LIBSSH_OBJS)
$(RANLIB) $@
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) -lfipscheck $(LIBS)
scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
$(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o
- $(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o
- $(LD) -o $@ ssh-keysign.o readconf.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-keysign.o readconf.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
- $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+ $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
$(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
diff -up /dev/null openssh-5.2p1/nsskeys.c
--- /dev/null 2009-03-09 14:26:59.819020596 +0100
+++ openssh-5.2p1/nsskeys.c 2009-03-10 03:51:56.251363837 +0100
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ * Copyright (c) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+#ifdef HAVE_LIBNSS
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/evp.h>
+
+#include <nss.h>
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <cert.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "log.h"
+#include "misc.h"
+#include "nsskeys.h"
+#include "pathnames.h"
+
+static char *
+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *password = arg;
+ if (retry || password == NULL)
+ return NULL;
+
+ return PL_strdup(password);
+}
+
+int
+nss_init(PK11PasswordFunc pwfn)
+{
+ char *dbpath;
+ char buf[MAXPATHLEN];
+
+ if (NSS_IsInitialized())
+ return 0;
+
+ if ((dbpath=getenv("NSS_DB_PATH")) == NULL) {
+ struct passwd *pw;
+ if ((pw = getpwuid(getuid())) == NULL ||
+ pw->pw_dir == NULL) {
+ return -1;
+ }
+ snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
+ _PATH_SSH_USER_DIR);
+ dbpath = buf;
+ }
+
+ if (NSS_Init(dbpath) != SECSuccess)
+ return -1;
+
+ if (pwfn == NULL) {
+ pwfn = password_cb;
+ }
+
+ PK11_SetPasswordFunc(pwfn);
+
+ return 0;
+}
+
+static Key *
+make_key_from_privkey(SECKEYPrivateKey *privk, char *password)
+{
+ Key *k;
+ switch (SECKEY_GetPrivateKeyType(privk)) {
+ case rsaKey:
+ k = key_new_nss(KEY_RSA);
+ break;
+ case dsaKey:
+ k = key_new_nss(KEY_DSA);
+ break;
+ default:
+ return NULL;
+ }
+ k->nss->pubk = SECKEY_ConvertToPublicKey(privk);
+ if (k->nss->pubk != NULL) {
+ k->nss->privk = SECKEY_CopyPrivateKey(privk);
+ }
+ if (k->nss->privk != NULL) {
+ if (password != NULL) {
+ k->nss->privk->wincx = xstrdup(password);
+ }
+ return k;
+ }
+ key_free(k);
+ return NULL;
+}
+
+static Key **
+add_key_to_list(Key *k, Key **keys, size_t *i, size_t *allocated)
+{
+ if (*allocated < *i + 2) {
+ *allocated += 16;
+ keys = xrealloc(keys, *allocated, sizeof(k));
+ }
+ keys[*i] = k;
+ (*i)++;
+ keys[*i] = NULL;
+ return keys;
+}
+
+static int
+nss_convert_pubkey(Key *k)
+{
+ u_char *n;
+ unsigned int len;
+ char *p;
+
+ switch (k->type) {
+ case KEY_RSA:
+ n = k->nss->pubk->u.rsa.modulus.data;
+ len = k->nss->pubk->u.rsa.modulus.len;
+
+ if (BN_bin2bn(n, len, k->rsa->n) == NULL) {
+ fatal("nss_convert_pubkey: BN_bin2bn failed");
+ }
+
+ n = k->nss->pubk->u.rsa.publicExponent.data;
+ len = k->nss->pubk->u.rsa.publicExponent.len;
+
+ if (BN_bin2bn(n, len, k->rsa->e) == NULL) {
+ fatal("nss_convert_pubkey: BN_bin2bn failed");
+ }
+ break;
+ case KEY_DSA:
+ n = k->nss->pubk->u.dsa.params.prime.data;
+ len = k->nss->pubk->u.dsa.params.prime.len;
+
+ if (BN_bin2bn(n, len, k->dsa->p) == NULL) {
+ fatal("nss_convert_pubkey: BN_bin2bn failed");
+ }
+
+ n = k->nss->pubk->u.dsa.params.subPrime.data;
+ len = k->nss->pubk->u.dsa.params.subPrime.len;
+
+ if (BN_bin2bn(n, len, k->dsa->q) == NULL) {
+ fatal("nss_convert_pubkey: BN_bin2bn failed");
+ }
+
+ n = k->nss->pubk->u.dsa.params.base.data;
+ len = k->nss->pubk->u.dsa.params.base.len;
+
+ if (BN_bin2bn(n, len, k->dsa->g) == NULL) {
+ fatal("nss_convert_pubkey: BN_bin2bn failed");
+ }
+
+ n = k->nss->pubk->u.dsa.publicValue.data;
+ len = k->nss->pubk->u.dsa.publicValue.len;
+
+ if (BN_bin2bn(n, len, k->dsa->pub_key) == NULL) {
+ fatal("nss_convert_pubkey: BN_bin2bn failed");
+ }
+ break;
+ }
+
+ p = key_fingerprint(k, SSH_FP_SHA1, SSH_FP_HEX);
+ debug("SHA1 fingerprint %u %s", key_size(k), p);
+ xfree(p);
+
+ return 0;
+}
+
+static Key **
+nss_find_privkeys(const char *tokenname, const char *keyname,
+ char *password)
+{
+ Key *k = NULL;
+ Key **keys = NULL;
+ PK11SlotList *slots;
+ PK11SlotListElement *sle;
+ size_t allocated = 0;
+ size_t i = 0;
+
+ if ((slots=PK11_FindSlotsByNames(NULL, NULL, tokenname, PR_TRUE)) == NULL) {
+ if (tokenname == NULL) {
+ debug("No NSS token found");
+ } else {
+ debug("NSS token not found: %s", tokenname);
+ }
+ return NULL;
+ }
+
+ for (sle = slots->head; sle; sle = sle->next) {
+ SECKEYPrivateKeyList *list;
+ SECKEYPrivateKeyListNode *node;
+ char *tmppass = password;
+
+ if (PK11_NeedLogin(sle->slot)) {
+ if (password == NULL) {
+ char *prompt;
+ if (asprintf(&prompt, "Enter passphrase for token %s: ",
+ PK11_GetTokenName(sle->slot)) < 0)
+ fatal("password_cb: asprintf failed");
+ tmppass = read_passphrase(prompt, RP_ALLOW_STDIN);
+ }
+ PK11_Authenticate(sle->slot, PR_TRUE, tmppass);
+ }
+
+ debug("Looking for: %s:%s", tokenname, keyname);
+ list = PK11_ListPrivKeysInSlot(sle->slot, (char *)keyname,
+ tmppass);
+ if (list == NULL && keyname != NULL) {
+ char *fooname;
+ /* NSS bug workaround */
+ if (asprintf(&fooname, "%s~", keyname) < 0) {
+ error("nss_find_privkey: asprintf failed");
+ PK11_FreeSlotList(slots);
+ return NULL;
+ }
+ list = PK11_ListPrivKeysInSlot(sle->slot, fooname,
+ tmppass);
+ free(fooname);
+ }
+ if (list == NULL && keyname != NULL) {
+ CERTCertificate *cert;
+ SECKEYPrivateKey *privk;
+ cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(),
+ (char *)keyname);
+ if (cert == NULL)
+ goto cleanup;
+ privk = PK11_FindPrivateKeyFromCert(sle->slot, cert, tmppass);
+ CERT_DestroyCertificate(cert);
+ if (privk == NULL)
+ goto cleanup;
+ if ((k=make_key_from_privkey(privk, tmppass)) != NULL) {
+ nss_convert_pubkey(k);
+ keys = add_key_to_list(k, keys, &i, &allocated);
+ }
+ SECKEY_DestroyPrivateKey(privk);
+ } else {
+ if (list == NULL)
+ goto cleanup;
+ for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list);
+ node=PRIVKEY_LIST_NEXT(node))
+ if ((k=make_key_from_privkey(node->key, tmppass)) != NULL) {
+ nss_convert_pubkey(k);
+ keys = add_key_to_list(k, keys, &i, &allocated);
+ }
+ SECKEY_DestroyPrivateKeyList(list);
+ }
+cleanup:
+ if (password == NULL && tmppass != NULL) {
+ memset(tmppass, 0, strlen(tmppass));
+ xfree(tmppass);
+ }
+ }
+ PK11_FreeSlotList(slots);
+
+ return keys;
+}
+
+Key **
+nss_get_keys(const char *tokenname, const char *keyname,
+ char *password)
+{
+ Key **keys;
+
+ if (nss_init(NULL) == -1) {
+ error("Failed to initialize NSS library");
+ return NULL;
+ }
+
+ keys = nss_find_privkeys(tokenname, keyname, password);
+ if (keys == NULL && keyname != NULL) {
+ error("Cannot find key in nss, token removed");
+ return NULL;
+ }
+#if 0
+ keys = xcalloc(3, sizeof(Key *));
+
+ if (k->type == KEY_RSA) {
+ n = key_new_nss_copy(KEY_RSA1, k);
+
+ keys[0] = n;
+ keys[1] = k;
+ keys[2] = NULL;
+ } else {
+ keys[0] = k;
+ keys[1] = NULL;
+ }
+#endif
+ return keys;
+}
+
+char *
+nss_get_key_label(Key *key)
+{
+ char *label, *nickname;
+
+ nickname = PK11_GetPrivateKeyNickname(key->nss->privk);
+ label = xstrdup(nickname);
+ PORT_Free(nickname);
+
+ return label;
+}
+
+#endif /* HAVE_LIBNSS */
diff -up /dev/null openssh-5.2p1/nsskeys.h
--- /dev/null 2009-03-09 14:26:59.819020596 +0100
+++ openssh-5.2p1/nsskeys.h 2009-03-10 03:51:55.908243644 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ * Copyright (c) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NSSKEYS_H
+#define NSSKEYS_H
+#ifdef HAVE_LIBNSS
+#include <pk11func.h>
+#include <prtypes.h>
+
+int nss_init(PK11PasswordFunc);
+Key **nss_get_keys(const char *, const char *, char *);
+char *nss_get_key_label(Key *);
+/*void sc_close(void);*/
+/*int sc_put_key(Key *, const char *);*/
+
+#endif
+#endif
diff -up openssh-5.2p1/readconf.c.nss-keys openssh-5.2p1/readconf.c
--- openssh-5.2p1/readconf.c.nss-keys 2009-02-14 06:28:21.000000000 +0100
+++ openssh-5.2p1/readconf.c 2009-03-10 03:51:55.950217925 +0100
@@ -124,6 +124,7 @@ typedef enum {
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
+ oUseNSS, oNSSToken,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
@@ -210,6 +211,13 @@ static struct {
#else
{ "smartcarddevice", oUnsupported },
#endif
+#ifdef HAVE_LIBNSS
+ { "usenss", oUseNSS },
+ { "nsstoken", oNSSToken },
+#else
+ { "usenss", oUnsupported },
+ { "nsstoken", oNSSToken },
+#endif
{ "clearallforwardings", oClearAllForwardings },
{ "enablesshkeysign", oEnableSSHKeysign },
{ "verifyhostkeydns", oVerifyHostKeyDNS },
@@ -612,6 +620,14 @@ parse_string:
charptr = &options->smartcard_device;
goto parse_string;
+ case oUseNSS:
+ intptr = &options->use_nss;
+ goto parse_flag;
+
+ case oNSSToken:
+ charptr = &options->nss_token;
+ goto parse_command;
+
case oProxyCommand:
charptr = &options->proxy_command;
parse_command:
@@ -1047,6 +1063,8 @@ initialize_options(Options * options)
options->preferred_authentications = NULL;
options->bind_address = NULL;
options->smartcard_device = NULL;
+ options->use_nss = -1;
+ options->nss_token = NULL;
options->enable_ssh_keysign = - 1;
options->no_host_authentication_for_localhost = - 1;
options->identities_only = - 1;
@@ -1177,6 +1195,8 @@ fill_default_options(Options * options)
options->no_host_authentication_for_localhost = 0;
if (options->identities_only == -1)
options->identities_only = 0;
+ if (options->use_nss == -1)
+ options->use_nss = 0;
if (options->enable_ssh_keysign == -1)
options->enable_ssh_keysign = 0;
if (options->rekey_limit == -1)
diff -up openssh-5.2p1/readconf.h.nss-keys openssh-5.2p1/readconf.h
--- openssh-5.2p1/readconf.h.nss-keys 2009-02-14 06:28:21.000000000 +0100
+++ openssh-5.2p1/readconf.h 2009-03-10 03:51:55.868252768 +0100
@@ -85,6 +85,8 @@ typedef struct {
char *preferred_authentications;
char *bind_address; /* local socket address for connection to sshd */
char *smartcard_device; /* Smartcard reader device */
+ int use_nss; /* Use NSS library for keys */
+ char *nss_token; /* Look for NSS keys on token */
int verify_host_key_dns; /* Verify host key using DNS */
int num_identity_files; /* Number of files for RSA/DSA identities. */
diff -up openssh-5.2p1/ssh-add.c.nss-keys openssh-5.2p1/ssh-add.c
--- openssh-5.2p1/ssh-add.c.nss-keys 2008-02-28 09:13:52.000000000 +0100
+++ openssh-5.2p1/ssh-add.c 2009-03-10 03:51:56.254252403 +0100
@@ -42,8 +42,18 @@
#include <sys/param.h>
#include <openssl/evp.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
+#ifdef HAVE_LIBNSS
+#include <nss.h>
+#include <secmod.h>
+#include <pk11pub.h>
+#include <keyhi.h>
+#include <cert.h>
+#endif
+
#include <fcntl.h>
#include <pwd.h>
#include <stdarg.h>
@@ -57,6 +67,7 @@
#include "rsa.h"
#include "log.h"
#include "key.h"
+#include "nsskeys.h"
#include "buffer.h"
#include "authfd.h"
#include "authfile.h"
@@ -245,7 +256,7 @@ list_identities(AuthenticationConnection
key = ssh_get_next_identity(ac, &comment, version)) {
had_identities = 1;
if (do_fp) {
- fp = key_fingerprint(key, SSH_FP_MD5,
+ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5,
SSH_FP_HEX);
printf("%d %s %s (%s)\n",
key_size(key), fp, comment, key_type(key));
@@ -307,6 +318,117 @@ do_file(AuthenticationConnection *ac, in
return 0;
}
+#ifdef HAVE_LIBNSS
+static char *
+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char **passcache = arg;
+ char *password, *p2 = NULL;
+ char *prompt;
+
+ if (retry)
+ return NULL;
+
+ if (asprintf(&prompt, "Enter passphrase for token %s: ",
+ PK11_GetTokenName(slot)) < 0)
+ fatal("password_cb: asprintf failed");
+
+ password = read_passphrase(prompt, RP_ALLOW_STDIN);
+
+ if (password != NULL && (p2=PL_strdup(password)) == NULL) {
+ memset(password, 0, strlen(password));
+ fatal("password_cb: PL_strdup failed");
+ }
+
+ if (passcache != NULL) {
+ if (*passcache != NULL) {
+ memset(*passcache, 0, strlen(*passcache));
+ xfree(*passcache);
+ }
+ *passcache = password;
+ } else {
+ memset(password, 0, strlen(password));
+ xfree(password);
+ }
+
+ return p2;
+}
+
+static int
+add_slot_keys(AuthenticationConnection *ac, PK11SlotInfo *slot, int add)
+{
+ SECKEYPrivateKeyList *list;
+ SECKEYPrivateKeyListNode *node;
+ char *passcache = NULL;
+ char *tokenname;
+
+ int count = 0;
+
+ if (PK11_NeedLogin(slot))
+ PK11_Authenticate(slot, PR_TRUE, &passcache);
+
+ if ((list=PK11_ListPrivKeysInSlot(slot, NULL, NULL)) == NULL) {
+ return 0;
+ }
+
+ tokenname = PK11_GetTokenName(slot);
+
+ for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list);
+ node=PRIVKEY_LIST_NEXT(node)) {
+ char *keyname;
+ SECKEYPublicKey *pub;
+
+ keyname = PK11_GetPrivateKeyNickname(node->key);
+ if (keyname == NULL || *keyname == '\0') {
+ /* no nickname to refer to */
+ CERTCertificate *cert;
+ char *kn;
+ cert = PK11_GetCertFromPrivateKey(node->key);
+ if (cert == NULL)
+ continue;
+ kn = strchr(cert->nickname, ':');
+ if (kn == NULL)
+ kn = cert->nickname;
+ else
+ kn++;
+ keyname = PORT_Strdup(kn);
+ CERT_DestroyCertificate(cert);
+ if (keyname == NULL)
+ continue;
+ }
+ pub = SECKEY_ConvertToPublicKey(node->key);
+ if (pub == NULL) {
+ fprintf(stderr, "No public key for: %s:%s\n",
+ tokenname, keyname);
+ continue; /* not possible to obtain public key */
+ }
+ SECKEY_DestroyPublicKey(pub);
+
+ if (ssh_update_nss_key(ac, add, tokenname, keyname,
+ passcache?passcache:"", lifetime, confirm)) {
+ fprintf(stderr, "Key %s: %s:%s\n",
+ add?"added":"removed", tokenname, keyname);
+ count++;
+ } else {
+ fprintf(stderr, "Could not %s key: %s:%s\n",
+ add?"add":"remove", tokenname, keyname);
+ }
+
+ PORT_Free(keyname);
+ count++;
+ }
+
+ if (passcache != NULL) {
+ memset(passcache, 0, strlen(passcache));
+ xfree(passcache);
+ }
+
+ SECKEY_DestroyPrivateKeyList(list);
+
+ return count;
+}
+#endif
+
static void
usage(void)
{
@@ -334,16 +456,25 @@ main(int argc, char **argv)
AuthenticationConnection *ac = NULL;
char *sc_reader_id = NULL;
int i, ch, deleting = 0, ret = 0;
+#ifdef HAVE_LIBNSS
+ char *token_id = NULL;
+ int use_nss = 0;
+#endif
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
__progname = ssh_get_progname(argv[0]);
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fprintf(stderr,
+ "FIPS integrity verification test failed.\n");
+ exit(3);
+ }
+
init_rng();
seed_rng();
- SSLeay_add_all_algorithms();
-
/* At first, get a connection to the authentication agent. */
ac = ssh_get_authentication_connection();
if (ac == NULL) {
@@ -351,7 +482,7 @@ main(int argc, char **argv)
"Could not open a connection to your authentication agent.\n");
exit(2);
}
- while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) {
+ while ((ch = getopt(argc, argv, "lLcdDnxXe:s:t:T:")) != -1) {
switch (ch) {
case 'l':
case 'L':
@@ -373,6 +504,11 @@ main(int argc, char **argv)
if (delete_all(ac) == -1)
ret = 1;
goto done;
+#ifdef HAVE_LIBNSS
+ case 'n':
+ use_nss = 1;
+ break;
+#endif
case 's':
sc_reader_id = optarg;
break;
@@ -387,6 +523,11 @@ main(int argc, char **argv)
goto done;
}
break;
+#ifdef HAVE_LIBNSS
+ case 'T':
+ token_id = optarg;
+ break;
+#endif
default:
usage();
ret = 1;
@@ -400,6 +541,40 @@ main(int argc, char **argv)
ret = 1;
goto done;
}
+#ifdef HAVE_LIBNSS
+ if (use_nss) {
+ PK11SlotList *slots;
+ PK11SlotListElement *sle;
+ int count = 0;
+ if (nss_init(password_cb) == -1) {
+ fprintf(stderr, "Failed to initialize NSS library\n");
+ ret = 1;
+ goto done;
+ }
+
+ if ((slots=PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE,
+ NULL)) == NULL) {
+ fprintf(stderr, "No tokens found\n");
+ ret = 1;
+ goto nss_done;
+ }
+
+ for (sle = slots->head; sle; sle = sle->next) {
+ int rv;
+ if ((rv=add_slot_keys(ac, sle->slot, !deleting)) == -1) {
+ ret = 1;
+ }
+ count += rv;
+ }
+ if (count == 0) {
+ ret = 1;
+ }
+nss_done:
+ NSS_Shutdown();
+ clear_pass();
+ goto done;
+ }
+#endif
if (argc == 0) {
char buf[MAXPATHLEN];
struct passwd *pw;
diff -up openssh-5.2p1/ssh-agent.c.nss-keys openssh-5.2p1/ssh-agent.c
--- openssh-5.2p1/ssh-agent.c.nss-keys 2008-07-04 15:10:49.000000000 +0200
+++ openssh-5.2p1/ssh-agent.c 2009-03-10 03:51:56.171221623 +0100
@@ -51,6 +51,8 @@
#include <openssl/evp.h>
#include <openssl/md5.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#include <errno.h>
@@ -80,6 +82,10 @@
#include "scard.h"
#endif
+#ifdef HAVE_LIBNSS
+#include "nsskeys.h"
+#endif
+
#if defined(HAVE_SYS_PRCTL_H)
#include <sys/prctl.h> /* For prctl() and PR_SET_DUMPABLE */
#endif
@@ -196,9 +202,9 @@ confirm_key(Identity *id)
char *p;
int ret = -1;
- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
- if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
- id->comment, p))
+ p = key_fingerprint(id->key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX);
+ if (ask_permission("Allow use of key %s?\nKey %sfingerprint %s.",
+ id->comment, FIPS_mode() ? "SHA1 " : "", p))
ret = 0;
xfree(p);
@@ -714,6 +720,114 @@ send:
}
#endif /* SMARTCARD */
+#ifdef HAVE_LIBNSS
+static void
+process_add_nss_key (SocketEntry *e)
+{
+ char *tokenname = NULL, *keyname = NULL, *password = NULL;
+ int i, version, success = 0, death = 0, confirm = 0;
+ Key **keys, *k;
+ Identity *id;
+ Idtab *tab;
+
+ tokenname = buffer_get_string(&e->request, NULL);
+ keyname = buffer_get_string(&e->request, NULL);
+ password = buffer_get_string(&e->request, NULL);
+
+ while (buffer_len(&e->request)) {
+ switch (buffer_get_char(&e->request)) {
+ case SSH_AGENT_CONSTRAIN_LIFETIME:
+ death = time(NULL) + buffer_get_int(&e->request);
+ break;
+ case SSH_AGENT_CONSTRAIN_CONFIRM:
+ confirm = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ if (lifetime && !death)
+ death = time(NULL) + lifetime;
+
+ keys = nss_get_keys(tokenname, keyname, password);
+ /* password is owned by keys[0] now */
+ xfree(tokenname);
+ xfree(keyname);
+
+ if (keys == NULL) {
+ memset(password, 0, strlen(password));
+ xfree(password);
+ error("nss_get_keys failed");
+ goto send;
+ }
+ for (i = 0; keys[i] != NULL; i++) {
+ k = keys[i];
+ version = k->type == KEY_RSA1 ? 1 : 2;
+ tab = idtab_lookup(version);
+ if (lookup_identity(k, version) == NULL) {
+ id = xmalloc(sizeof(Identity));
+ id->key = k;
+ id->comment = nss_get_key_label(k);
+ id->death = death;
+ id->confirm = confirm;
+ TAILQ_INSERT_TAIL(&tab->idlist, id, next);
+ tab->nentries++;
+ success = 1;
+ } else {
+ key_free(k);
+ }
+ keys[i] = NULL;
+ }
+ xfree(keys);
+send:
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output,
+ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
+}
+
+static void
+process_remove_nss_key(SocketEntry *e)
+{
+ char *tokenname = NULL, *keyname = NULL, *password = NULL;
+ int i, version, success = 0;
+ Key **keys, *k = NULL;
+ Identity *id;
+ Idtab *tab;
+
+ tokenname = buffer_get_string(&e->request, NULL);
+ keyname = buffer_get_string(&e->request, NULL);
+ password = buffer_get_string(&e->request, NULL);
+
+ keys = nss_get_keys(tokenname, keyname, password);
+ xfree(tokenname);
+ xfree(keyname);
+ xfree(password);
+
+ if (keys == NULL || keys[0] == NULL) {
+ error("nss_get_keys failed");
+ goto send;
+ }
+ for (i = 0; keys[i] != NULL; i++) {
+ k = keys[i];
+ version = k->type == KEY_RSA1 ? 1 : 2;
+ if ((id = lookup_identity(k, version)) != NULL) {
+ tab = idtab_lookup(version);
+ TAILQ_REMOVE(&tab->idlist, id, next);
+ tab->nentries--;
+ free_identity(id);
+ success = 1;
+ }
+ key_free(k);
+ keys[i] = NULL;
+ }
+ xfree(keys);
+send:
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output,
+ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
+}
+#endif /* HAVE_LIBNSS */
+
/* dispatch incoming messages */
static void
@@ -806,6 +920,15 @@ process_message(SocketEntry *e)
process_remove_smartcard_key(e);
break;
#endif /* SMARTCARD */
+#ifdef HAVE_LIBNSS
+ case SSH_AGENTC_ADD_NSS_KEY:
+ case SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED:
+ process_add_nss_key(e);
+ break;
+ case SSH_AGENTC_REMOVE_NSS_KEY:
+ process_remove_nss_key(e);
+ break;
+#endif /* SMARTCARD */
default:
/* Unknown message. Respond with failure. */
error("Unknown message %d", type);
@@ -1075,6 +1198,11 @@ main(int ac, char **av)
#endif
SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fprintf(stderr,
+ "FIPS integrity verification test failed.\n");
+ exit(3);
+ }
__progname = ssh_get_progname(av[0]);
init_rng();
diff -up openssh-5.2p1/ssh.c.nss-keys openssh-5.2p1/ssh.c
--- openssh-5.2p1/ssh.c.nss-keys 2009-02-14 06:28:21.000000000 +0100
+++ openssh-5.2p1/ssh.c 2009-03-10 03:51:56.176206362 +0100
@@ -71,6 +71,8 @@
#include <openssl/evp.h>
#include <openssl/err.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
@@ -104,6 +106,9 @@
#ifdef SMARTCARD
#include "scard.h"
#endif
+#ifdef HAVE_LIBNSS
+#include "nsskeys.h"
+#endif
extern char *__progname;
@@ -217,6 +222,10 @@ main(int ac, char **av)
sanitise_stdfd();
__progname = ssh_get_progname(av[0]);
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fatal("FIPS integrity verification test failed.");
+ }
init_rng();
/*
@@ -547,7 +556,6 @@ main(int ac, char **av)
if (!host)
usage();
- SSLeay_add_all_algorithms();
ERR_load_crypto_strings();
/* Initialize the command to execute on remote host. */
@@ -1231,9 +1239,11 @@ load_public_identity_files(void)
int i = 0;
Key *public;
struct passwd *pw;
-#ifdef SMARTCARD
+#if defined(SMARTCARD) || defined(HAVE_LIBNSS)
Key **keys;
+#endif
+#ifdef SMARTCARD
if (options.smartcard_device != NULL &&
options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
(keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) {
@@ -1256,6 +1266,27 @@ load_public_identity_files(void)
xfree(keys);
}
#endif /* SMARTCARD */
+#ifdef HAVE_LIBNSS
+ if (options.use_nss &&
+ options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
+ (keys = nss_get_keys(options.nss_token, NULL, NULL)) != NULL) {
+ int count;
+ for (count = 0; keys[count] != NULL; count++) {
+ memmove(&options.identity_files[1], &options.identity_files[0],
+ sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
+ memmove(&options.identity_keys[1], &options.identity_keys[0],
+ sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
+ options.num_identity_files++;
+ options.identity_keys[0] = keys[count];
+ options.identity_files[0] = nss_get_key_label(keys[count]);
+ }
+ if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
+ options.num_identity_files = SSH_MAX_IDENTITY_FILES;
+ i += count;
+ xfree(keys);
+ }
+#endif /* HAVE_LIBNSS */
+
if ((pw = getpwuid(original_real_uid)) == NULL)
fatal("load_public_identity_files: getpwuid failed");
pwname = xstrdup(pw->pw_name);
diff -up openssh-5.2p1/ssh-dss.c.nss-keys openssh-5.2p1/ssh-dss.c
--- openssh-5.2p1/ssh-dss.c.nss-keys 2006-11-07 13:14:42.000000000 +0100
+++ openssh-5.2p1/ssh-dss.c 2009-03-10 03:51:55.843232632 +0100
@@ -39,6 +39,10 @@
#include "log.h"
#include "key.h"
+#ifdef HAVE_LIBNSS
+#include <cryptohi.h>
+#endif
+
#define INTBLOB_LEN 20
#define SIGBLOB_LEN (2*INTBLOB_LEN)
@@ -57,6 +61,34 @@ ssh_dss_sign(const Key *key, u_char **si
error("ssh_dss_sign: no DSA key");
return -1;
}
+#ifdef HAVE_LIBNSS
+ if (key->flags & KEY_FLAG_NSS) {
+ SECItem sigitem;
+ SECItem *rawsig;
+
+ memset(&sigitem, 0, sizeof(sigitem));
+ if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk,
+ SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) != SECSuccess) {
+ error("ssh_dss_sign: sign failed");
+ return -1;
+ }
+
+ if ((rawsig=DSAU_DecodeDerSig(&sigitem)) == NULL) {
+ error("ssh_dss_sign: der decode failed");
+ SECITEM_ZfreeItem(&sigitem, PR_FALSE);
+ return -1;
+ }
+ SECITEM_ZfreeItem(&sigitem, PR_FALSE);
+ if (rawsig->len != SIGBLOB_LEN) {
+ error("ssh_dss_sign: unsupported signature length %d",
+ rawsig->len);
+ SECITEM_ZfreeItem(rawsig, PR_TRUE);
+ return -1;
+ }
+ memcpy(sigblob, rawsig->data, SIGBLOB_LEN);
+ SECITEM_ZfreeItem(rawsig, PR_TRUE);
+ } else {
+#endif
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, data, datalen);
EVP_DigestFinal(&md, digest, &dlen);
@@ -80,7 +112,9 @@ ssh_dss_sign(const Key *key, u_char **si
BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
DSA_SIG_free(sig);
-
+#ifdef HAVE_LIBNSS
+ }
+#endif
if (datafellows & SSH_BUG_SIGBLOB) {
if (lenp != NULL)
*lenp = SIGBLOB_LEN;
diff -up openssh-5.2p1/ssh-keygen.c.nss-keys openssh-5.2p1/ssh-keygen.c
--- openssh-5.2p1/ssh-keygen.c.nss-keys 2009-02-21 22:47:02.000000000 +0100
+++ openssh-5.2p1/ssh-keygen.c 2009-03-10 03:51:56.249239228 +0100
@@ -21,6 +21,8 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#include <errno.h>
@@ -53,6 +55,11 @@
#include "scard.h"
#endif
+#ifdef HAVE_LIBNSS
+#include <nss.h>
+#include "nsskeys.h"
+#endif
+
/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
#define DEFAULT_BITS 2048
#define DEFAULT_BITS_DSA 1024
@@ -501,6 +508,26 @@ do_download(struct passwd *pw, const cha
}
#endif /* SMARTCARD */
+#ifdef HAVE_LIBNSS
+static void
+do_nss_download(struct passwd *pw, const char *tokenname, const char *keyname)
+{
+ Key **keys = NULL;
+ int i;
+
+ keys = nss_get_keys(tokenname, keyname, NULL);
+ if (keys == NULL)
+ fatal("cannot find public key in NSS");
+ for (i = 0; keys[i]; i++) {
+ key_write(keys[i], stdout);
+ key_free(keys[i]);
+ fprintf(stdout, "\n");
+ }
+ xfree(keys);
+ exit(0);
+}
+#endif /* HAVE_LIBNSS */
+
static void
do_fingerprint(struct passwd *pw)
{
@@ -512,7 +539,7 @@ do_fingerprint(struct passwd *pw)
enum fp_type fptype;
struct stat st;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+ fptype = print_bubblebabble ? SSH_FP_SHA1 : FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
if (!have_identity)
@@ -1083,7 +1110,8 @@ main(int argc, char **argv)
Key *private, *public;
struct passwd *pw;
struct stat st;
- int opt, type, fd, download = 0;
+ int opt, type, fd, download = 1;
+ int use_nss = 0;
u_int32_t memory = 0, generator_wanted = 0, trials = 100;
int do_gen_candidates = 0, do_screen_candidates = 0;
BIGNUM *start = NULL;
@@ -1099,6 +1127,12 @@ main(int argc, char **argv)
__progname = ssh_get_progname(argv[0]);
SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fprintf(stderr,
+ "FIPS integrity verification test failed.\n");
+ exit(3);
+ }
+
log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
init_rng();
@@ -1116,7 +1150,7 @@ main(int argc, char **argv)
}
while ((opt = getopt(argc, argv,
- "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
+ "degiqpclnBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
switch (opt) {
case 'b':
bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
@@ -1156,6 +1190,10 @@ main(int argc, char **argv)
case 'g':
print_generic = 1;
break;
+ case 'n':
+ use_nss = 1;
+ download = 1;
+ break;
case 'P':
identity_passphrase = optarg;
break;
@@ -1187,10 +1225,10 @@ main(int argc, char **argv)
case 't':
key_type_name = optarg;
break;
- case 'D':
- download = 1;
- /*FALLTHROUGH*/
case 'U':
+ download = 0;
+ /*FALLTHROUGH*/
+ case 'D':
reader_id = optarg;
break;
case 'v':
@@ -1299,6 +1337,17 @@ main(int argc, char **argv)
exit(0);
}
}
+
+ if (use_nss) {
+#ifdef HAVE_LIBNSS
+ if (download)
+ do_nss_download(pw, reader_id, identity_file);
+ else
+ fatal("no support for NSS key upload.");
+#else
+ fatal("no support for NSS keys.");
+#endif
+ }
if (reader_id != NULL) {
#ifdef SMARTCARD
if (download)
@@ -1465,14 +1514,15 @@ passphrase_again:
fclose(f);
if (!quiet) {
- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
- char *ra = key_fingerprint(public, SSH_FP_MD5,
+ int fips_on = FIPS_mode();
+ char *fp = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX);
+ char *ra = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5,
SSH_FP_RANDOMART);
printf("Your public key has been saved in %s.\n",
identity_file);
- printf("The key fingerprint is:\n");
+ printf("The key %sfingerprint is:\n", fips_on ? "SHA1 " : "");
printf("%s %s\n", fp, comment);
- printf("The key's randomart image is:\n");
+ printf("The key's %srandomart image is:\n", fips_on ? "SHA1 " :"");
printf("%s\n", ra);
xfree(ra);
xfree(fp);
diff -up openssh-5.2p1/ssh-rsa.c.nss-keys openssh-5.2p1/ssh-rsa.c
--- openssh-5.2p1/ssh-rsa.c.nss-keys 2006-09-01 07:38:37.000000000 +0200
+++ openssh-5.2p1/ssh-rsa.c 2009-03-10 03:51:55.930219040 +0100
@@ -32,6 +32,10 @@
#include "compat.h"
#include "ssh.h"
+#ifdef HAVE_LIBNSS
+#include <cryptohi.h>
+#endif
+
static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
@@ -50,6 +54,38 @@ ssh_rsa_sign(const Key *key, u_char **si
error("ssh_rsa_sign: no RSA key");
return -1;
}
+
+ slen = RSA_size(key->rsa);
+ sig = xmalloc(slen);
+
+#ifdef HAVE_LIBNSS
+ if (key->flags & KEY_FLAG_NSS) {
+ SECItem sigitem;
+ SECOidTag alg;
+
+ memset(&sigitem, 0, sizeof(sigitem));
+ alg = (datafellows & SSH_BUG_RSASIGMD5) ?
+ SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION :
+ SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+
+ if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk,
+ alg) != SECSuccess) {
+ error("ssh_rsa_sign: sign failed");
+ return -1;
+ }
+ if (sigitem.len > slen) {
+ error("ssh_rsa_sign: slen %u slen2 %u", slen, sigitem.len);
+ xfree(sig);
+ SECITEM_ZfreeItem(&sigitem, PR_FALSE);
+ return -1;
+ }
+ if (sigitem.len < slen) {
+ memset(sig, 0, slen - sigitem.len);
+ }
+ memcpy(sig+slen-sigitem.len, sigitem.data, sigitem.len);
+ SECITEM_ZfreeItem(&sigitem, PR_FALSE);
+ } else {
+#endif
nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid);
@@ -59,9 +95,6 @@ ssh_rsa_sign(const Key *key, u_char **si
EVP_DigestUpdate(&md, data, datalen);
EVP_DigestFinal(&md, digest, &dlen);
- slen = RSA_size(key->rsa);
- sig = xmalloc(slen);
-
ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
memset(digest, 'd', sizeof(digest));
@@ -83,6 +116,9 @@ ssh_rsa_sign(const Key *key, u_char **si
xfree(sig);
return -1;
}
+#ifdef HAVE_LIBNSS
+ }
+#endif
/* encode signature */
buffer_init(&b);
buffer_put_cstring(&b, "ssh-rsa");
openssh-5.2p1-redhat.patch:
--- NEW FILE openssh-5.2p1-redhat.patch ---
diff -up openssh-5.2p1/ssh_config.redhat openssh-5.2p1/ssh_config
--- openssh-5.2p1/ssh_config.redhat 2009-02-21 02:45:02.000000000 +0100
+++ openssh-5.2p1/ssh_config 2009-03-10 03:51:54.749290375 +0100
@@ -44,3 +44,13 @@
# TunnelDevice any:any
# PermitLocalCommand no
# VisualHostKey no
+Host *
+ GSSAPIAuthentication yes
+# If this option is set to yes then remote X11 clients will have full access
+# to the original X11 display. As virtually no X11 client supports the untrusted
+# mode correctly we set this to yes.
+ ForwardX11Trusted yes
+# Send locale-related environment variables
+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
diff -up openssh-5.2p1/sshd_config.0.redhat openssh-5.2p1/sshd_config.0
--- openssh-5.2p1/sshd_config.0.redhat 2009-02-23 01:18:15.000000000 +0100
+++ openssh-5.2p1/sshd_config.0 2009-03-10 03:51:54.958364611 +0100
@@ -467,6 +467,11 @@ DESCRIPTION
Defines the number of bits in the ephemeral protocol version 1
server key. The minimum value is 512, and the default is 1024.
+ ShowPatchLevel
+ Specifies whether sshd will display the specific patch level of
+ the binary in the server identification string. The patch level
+ is set at compile-time. The default is M-bM-^@M-^\noM-bM-^@M-^].
+
StrictModes
Specifies whether sshd(8) should check file modes and ownership
of the user's files and home directory before accepting login.
@@ -491,9 +496,9 @@ DESCRIPTION
SyslogFacility
Gives the facility code that is used when logging messages from
- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0,
- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The de-
- fault is AUTH.
+ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV,
+ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+ The default is AUTH.
TCPKeepAlive
Specifies whether the system should send TCP keepalive messages
diff -up openssh-5.2p1/sshd_config.5.redhat openssh-5.2p1/sshd_config.5
--- openssh-5.2p1/sshd_config.5.redhat 2009-02-23 01:00:24.000000000 +0100
+++ openssh-5.2p1/sshd_config.5 2009-03-10 03:51:54.931352756 +0100
@@ -814,6 +814,14 @@ This option applies to protocol version
.It Cm ServerKeyBits
Defines the number of bits in the ephemeral protocol version 1 server key.
The minimum value is 512, and the default is 1024.
+.It Cm ShowPatchLevel
+Specifies whether
+.Nm sshd
+will display the patch level of the binary in the identification string.
+The patch level is set at compile-time.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
.It Cm StrictModes
Specifies whether
.Xr sshd 8
@@ -848,7 +856,7 @@ Note that this option applies to protoco
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Xr sshd 8 .
-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2,
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
The default is AUTH.
.It Cm TCPKeepAlive
diff -up openssh-5.2p1/sshd_config.redhat openssh-5.2p1/sshd_config
--- openssh-5.2p1/sshd_config.redhat 2008-07-02 14:35:43.000000000 +0200
+++ openssh-5.2p1/sshd_config 2009-03-10 03:51:54.960221540 +0100
@@ -33,6 +33,7 @@ Protocol 2
# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
+SyslogFacility AUTHPRIV
#LogLevel INFO
# Authentication:
@@ -60,9 +61,11 @@ Protocol 2
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
+PasswordAuthentication yes
# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
+ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
@@ -72,7 +75,9 @@ Protocol 2
# GSSAPI options
#GSSAPIAuthentication no
+GSSAPIAuthentication yes
#GSSAPICleanupCredentials yes
+GSSAPICleanupCredentials yes
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
@@ -84,11 +89,18 @@ Protocol 2
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM no
+UsePAM yes
+
+# Accept locale-related environment variables
+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
+X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PrintMotd yes
@@ -100,6 +112,7 @@ Protocol 2
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
+#ShowPatchLevel no
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10
openssh-5.2p1-selinux.patch:
--- NEW FILE openssh-5.2p1-selinux.patch ---
diff -up openssh-5.2p1/auth1.c.selinux openssh-5.2p1/auth1.c
--- openssh-5.2p1/auth1.c.selinux 2009-03-10 03:51:54.813223420 +0100
+++ openssh-5.2p1/auth1.c 2009-03-10 03:51:55.045214236 +0100
@@ -391,7 +391,7 @@ void
do_authentication(Authctxt *authctxt)
{
u_int ulen;
- char *user, *style = NULL;
+ char *user, *style = NULL, *role=NULL;
/* Get the name of the user that we wish to log in as. */
packet_read_expect(SSH_CMSG_USER);
@@ -400,11 +400,19 @@ do_authentication(Authctxt *authctxt)
user = packet_get_string(&ulen);
packet_check_eom();
+ if ((role = strchr(user, '/')) != NULL)
+ *role++ = '\0';
+
if ((style = strchr(user, ':')) != NULL)
*style++ = '\0';
+ else
+ if (role && (style = strchr(role, ':')) != NULL)
+ *style++ = '\0';
+
authctxt->user = user;
authctxt->style = style;
+ authctxt->role = role;
/* Verify that the user is a valid user. */
if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
diff -up openssh-5.2p1/auth2.c.selinux openssh-5.2p1/auth2.c
--- openssh-5.2p1/auth2.c.selinux 2008-11-05 06:20:46.000000000 +0100
+++ openssh-5.2p1/auth2.c 2009-03-10 03:51:55.071216534 +0100
@@ -215,7 +215,7 @@ input_userauth_request(int type, u_int32
{
Authctxt *authctxt = ctxt;
Authmethod *m = NULL;
- char *user, *service, *method, *style = NULL;
+ char *user, *service, *method, *style = NULL, *role = NULL;
int authenticated = 0;
if (authctxt == NULL)
@@ -227,6 +227,9 @@ input_userauth_request(int type, u_int32
debug("userauth-request for user %s service %s method %s", user, service, method);
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
+ if ((role = strchr(user, '/')) != NULL)
+ *role++ = 0;
+
if ((style = strchr(user, ':')) != NULL)
*style++ = 0;
@@ -252,8 +255,11 @@ input_userauth_request(int type, u_int32
use_privsep ? " [net]" : "");
authctxt->service = xstrdup(service);
authctxt->style = style ? xstrdup(style) : NULL;
- if (use_privsep)
+ authctxt->role = role ? xstrdup(role) : NULL;
+ if (use_privsep) {
mm_inform_authserv(service, style);
+ mm_inform_authrole(role);
+ }
userauth_banner();
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
diff -up openssh-5.2p1/auth2-hostbased.c.selinux openssh-5.2p1/auth2-hostbased.c
--- openssh-5.2p1/auth2-hostbased.c.selinux 2008-07-17 10:57:19.000000000 +0200
+++ openssh-5.2p1/auth2-hostbased.c 2009-03-10 03:51:55.052265447 +0100
@@ -106,7 +106,14 @@ userauth_hostbased(Authctxt *authctxt)
buffer_put_string(&b, session_id2, session_id2_len);
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, authctxt->user);
+ if (authctxt->role) {
+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1);
+ buffer_append(&b, authctxt->user, strlen(authctxt->user));
+ buffer_put_char(&b, '/');
+ buffer_append(&b, authctxt->role, strlen(authctxt->role));
+ } else {
+ buffer_put_cstring(&b, authctxt->user);
+ }
buffer_put_cstring(&b, service);
buffer_put_cstring(&b, "hostbased");
buffer_put_string(&b, pkalg, alen);
diff -up openssh-5.2p1/auth2-pubkey.c.selinux openssh-5.2p1/auth2-pubkey.c
--- openssh-5.2p1/auth2-pubkey.c.selinux 2008-07-04 04:54:25.000000000 +0200
+++ openssh-5.2p1/auth2-pubkey.c 2009-03-10 03:51:56.174214480 +0100
@@ -33,6 +33,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+#include <openssl/fips.h>
#include "xmalloc.h"
#include "ssh.h"
@@ -117,7 +118,14 @@ userauth_pubkey(Authctxt *authctxt)
}
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, authctxt->user);
+ if (authctxt->role) {
+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1);
+ buffer_append(&b, authctxt->user, strlen(authctxt->user));
+ buffer_put_char(&b, '/');
+ buffer_append(&b, authctxt->role, strlen(authctxt->role));
+ } else {
+ buffer_put_cstring(&b, authctxt->user);
+ }
buffer_put_cstring(&b,
datafellows & SSH_BUG_PKSERVICE ?
"ssh-userauth" :
@@ -236,7 +244,7 @@ user_key_allowed2(struct passwd *pw, Key
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(found, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(found), fp);
xfree(fp);
diff -up openssh-5.2p1/auth.h.selinux openssh-5.2p1/auth.h
--- openssh-5.2p1/auth.h.selinux 2008-11-05 06:20:46.000000000 +0100
+++ openssh-5.2p1/auth.h 2009-03-10 03:51:55.069276014 +0100
@@ -58,6 +58,7 @@ struct Authctxt {
char *service;
struct passwd *pw; /* set if 'valid' */
char *style;
+ char *role;
void *kbdintctxt;
void *jpake_ctx;
#ifdef BSD_AUTH
diff -up openssh-5.2p1/configure.ac.selinux openssh-5.2p1/configure.ac
--- openssh-5.2p1/configure.ac.selinux 2009-03-10 03:51:54.901396765 +0100
+++ openssh-5.2p1/configure.ac 2009-03-10 03:51:55.850215090 +0100
@@ -3335,11 +3335,25 @@ AC_ARG_WITH(selinux,
AC_CHECK_LIB(selinux, setexeccon, [ LIBSELINUX="-lselinux" ],
AC_MSG_ERROR(SELinux support requires libselinux library))
SSHDLIBS="$SSHDLIBS $LIBSELINUX"
+ LIBS="$LIBS $LIBSELINUX"
AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level)
+ AC_CHECK_FUNCS(setkeycreatecon)
LIBS="$save_LIBS"
fi ]
)
+# Check whether user wants Linux audit support
+LINUX_AUDIT_MSG="no"
+AC_ARG_WITH(linux-audit,
+ [ --with-linux-audit Enable Linux audit support],
+ [ if test "x$withval" != "xno" ; then
+ AC_DEFINE(HAVE_LINUX_AUDIT,1,[Define if you want Linux audit support.])
+ LINUX_AUDIT_MSG="yes"
+ AC_CHECK_HEADERS(libaudit.h)
+ SSHDLIBS="$SSHDLIBS -laudit"
+ fi ]
+)
+
# Check whether user wants Kerberos 5 support
KRB5_MSG="no"
AC_ARG_WITH(kerberos5,
@@ -3448,6 +3462,20 @@ AC_ARG_WITH(kerberos5,
]
)
+# Check whether user wants NSS support
+LIBNSS_MSG="no"
+AC_ARG_WITH(nss,
+ [ --with-nss Enable NSS support],
+ [ if test "x$withval" != "xno" ; then
+ AC_DEFINE(HAVE_LIBNSS,1,[Define if you want NSS support.])
+ LIBNSS_MSG="yes"
+ CPPFLAGS="$CPPFLAGS -I/usr/include/nss3 -I/usr/include/nspr4"
+ AC_CHECK_HEADERS(pk11pub.h)
+ LIBS="$LIBS -lnss3"
+ fi
+ ])
+AC_SUBST(LIBNSS)
+
# Looking for programs, paths and files
PRIVSEP_PATH=/var/empty
@@ -4168,12 +4196,14 @@ echo " PAM support
echo " OSF SIA support: $SIA_MSG"
echo " KerberosV support: $KRB5_MSG"
echo " SELinux support: $SELINUX_MSG"
+echo " Linux audit support: $LINUX_AUDIT_MSG"
echo " Smartcard support: $SCARD_MSG"
echo " S/KEY support: $SKEY_MSG"
echo " TCP Wrappers support: $TCPW_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " Solaris process contract support: $SPC_MSG"
+echo " NSS support: $LIBNSS_MSG"
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
echo " BSD Auth support: $BSD_AUTH_MSG"
diff -up openssh-5.2p1/monitor.c.selinux openssh-5.2p1/monitor.c
--- openssh-5.2p1/monitor.c.selinux 2009-02-14 06:33:31.000000000 +0100
+++ openssh-5.2p1/monitor.c 2009-03-10 03:51:55.099559692 +0100
@@ -135,6 +135,7 @@ int mm_answer_sign(int, Buffer *);
int mm_answer_pwnamallow(int, Buffer *);
int mm_answer_auth2_read_banner(int, Buffer *);
int mm_answer_authserv(int, Buffer *);
+int mm_answer_authrole(int, Buffer *);
int mm_answer_authpassword(int, Buffer *);
int mm_answer_bsdauthquery(int, Buffer *);
int mm_answer_bsdauthrespond(int, Buffer *);
@@ -211,6 +212,7 @@ struct mon_table mon_dispatch_proto20[]
{MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
{MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
+ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
{MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
{MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
#ifdef USE_PAM
@@ -680,6 +682,7 @@ mm_answer_pwnamallow(int sock, Buffer *m
else {
/* Allow service/style information on the auth context */
monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
}
@@ -725,6 +728,23 @@ mm_answer_authserv(int sock, Buffer *m)
}
int
+mm_answer_authrole(int sock, Buffer *m)
+{
+ monitor_permit_authentications(1);
+
+ authctxt->role = buffer_get_string(m, NULL);
+ debug3("%s: role=%s",
+ __func__, authctxt->role);
+
+ if (strlen(authctxt->role) == 0) {
+ xfree(authctxt->role);
+ authctxt->role = NULL;
+ }
+
+ return (0);
+}
+
+int
mm_answer_authpassword(int sock, Buffer *m)
{
static int call_count;
@@ -1102,7 +1122,7 @@ static int
monitor_valid_userblob(u_char *data, u_int datalen)
{
Buffer b;
- char *p;
+ char *p, *r;
u_int len;
int fail = 0;
@@ -1128,6 +1148,8 @@ monitor_valid_userblob(u_char *data, u_i
if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
fail++;
p = buffer_get_string(&b, NULL);
+ if ((r = strchr(p, '/')) != NULL)
+ *r = '\0';
if (strcmp(authctxt->user, p) != 0) {
logit("wrong user name passed to monitor: expected %s != %.100s",
authctxt->user, p);
@@ -1159,7 +1181,7 @@ monitor_valid_hostbasedblob(u_char *data
char *chost)
{
Buffer b;
- char *p;
+ char *p, *r;
u_int len;
int fail = 0;
@@ -1176,6 +1198,8 @@ monitor_valid_hostbasedblob(u_char *data
if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
fail++;
p = buffer_get_string(&b, NULL);
+ if ((r = strchr(p, '/')) != NULL)
+ *r = '\0';
if (strcmp(authctxt->user, p) != 0) {
logit("wrong user name passed to monitor: expected %s != %.100s",
authctxt->user, p);
diff -up openssh-5.2p1/monitor.h.selinux openssh-5.2p1/monitor.h
--- openssh-5.2p1/monitor.h.selinux 2008-11-05 06:20:46.000000000 +0100
+++ openssh-5.2p1/monitor.h 2009-03-10 03:51:55.050519421 +0100
@@ -30,7 +30,7 @@
enum monitor_reqtype {
MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
- MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
+ MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,MONITOR_REQ_AUTHROLE,
MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
diff -up openssh-5.2p1/monitor_wrap.c.selinux openssh-5.2p1/monitor_wrap.c
--- openssh-5.2p1/monitor_wrap.c.selinux 2008-11-05 06:20:47.000000000 +0100
+++ openssh-5.2p1/monitor_wrap.c 2009-03-10 03:51:55.066210099 +0100
@@ -297,6 +297,23 @@ mm_inform_authserv(char *service, char *
buffer_free(&m);
}
+/* Inform the privileged process about role */
+
+void
+mm_inform_authrole(char *role)
+{
+ Buffer m;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, role ? role : "");
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m);
+
+ buffer_free(&m);
+}
+
/* Do the password authentication */
int
mm_auth_password(Authctxt *authctxt, char *password)
diff -up openssh-5.2p1/monitor_wrap.h.selinux openssh-5.2p1/monitor_wrap.h
--- openssh-5.2p1/monitor_wrap.h.selinux 2008-11-05 06:20:47.000000000 +0100
+++ openssh-5.2p1/monitor_wrap.h 2009-03-10 03:51:55.048731957 +0100
@@ -41,6 +41,7 @@ int mm_is_monitor(void);
DH *mm_choose_dh(int, int, int);
int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
void mm_inform_authserv(char *, char *);
+void mm_inform_authrole(char *);
struct passwd *mm_getpwnamallow(const char *);
char *mm_auth2_read_banner(void);
int mm_auth_password(struct Authctxt *, char *);
diff -up openssh-5.2p1/openbsd-compat/port-linux.c.selinux openssh-5.2p1/openbsd-compat/port-linux.c
--- openssh-5.2p1/openbsd-compat/port-linux.c.selinux 2008-03-26 21:27:21.000000000 +0100
+++ openssh-5.2p1/openbsd-compat/port-linux.c 2009-03-10 03:51:55.407292576 +0100
@@ -30,10 +30,28 @@
#ifdef WITH_SELINUX
#include "log.h"
#include "port-linux.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "xmalloc.h"
+#include "servconf.h"
#include <selinux/selinux.h>
#include <selinux/flask.h>
+#include <selinux/context.h>
#include <selinux/get_context_list.h>
+#include <selinux/get_default_type.h>
+#include <selinux/av_permissions.h>
+
+#ifdef HAVE_LINUX_AUDIT
+#include <libaudit.h>
+#include <unistd.h>
+#endif
+
+extern ServerOptions options;
+extern Authctxt *the_authctxt;
+extern int inetd_flag;
+extern int rexeced_flag;
/* Wrapper around is_selinux_enabled() to log its return value once only */
int
@@ -49,42 +67,245 @@ ssh_selinux_enabled(void)
return (enabled);
}
+/* Send audit message */
+static int
+send_audit_message(int success, security_context_t default_context,
+ security_context_t selected_context)
+{
+ int rc=0;
+#ifdef HAVE_LINUX_AUDIT
+ char *msg = NULL;
+ int audit_fd = audit_open();
+ security_context_t default_raw=NULL;
+ security_context_t selected_raw=NULL;
+ rc = -1;
+ if (audit_fd < 0) {
+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
+ errno == EAFNOSUPPORT)
+ return 0; /* No audit support in kernel */
+ error("Error connecting to audit system.");
+ return rc;
+ }
+ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
+ error("Error translating default context.");
+ default_raw = NULL;
+ }
+ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
+ error("Error translating selected context.");
+ selected_raw = NULL;
+ }
+ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
+ default_raw ? default_raw : (default_context ? default_context: "?"),
+ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
+ error("Error allocating memory.");
+ goto out;
+ }
+ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
+ msg, NULL, NULL, NULL, success) <= 0) {
+ error("Error sending audit message.");
+ goto out;
+ }
+ rc = 0;
+ out:
+ free(msg);
+ freecon(default_raw);
+ freecon(selected_raw);
+ close(audit_fd);
+#endif
+ return rc;
+}
+
+static int
+mls_range_allowed(security_context_t src, security_context_t dst)
+{
+ struct av_decision avd;
+ int retval;
+ unsigned int bit = CONTEXT__CONTAINS;
+
+ debug("%s: src:%s dst:%s", __func__, src, dst);
+ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
+ if (retval || ((bit & avd.allowed) != bit))
+ return 0;
+
+ return 1;
+}
+
+static int
+get_user_context(const char *sename, const char *role, const char *lvl,
+ security_context_t *sc) {
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
+ /* User may have requested a level completely outside of his
+ allowed range. We get a context just for auditing as the
+ range check below will certainly fail for default context. */
+#endif
+ if (get_default_context(sename, NULL, sc) != 0) {
+ *sc = NULL;
+ return -1;
+ }
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+ }
+#endif
+ if (role != NULL && role[0]) {
+ context_t con;
+ char *type=NULL;
+ if (get_default_type(role, &type) != 0) {
+ error("get_default_type: failed to get default type for '%s'",
+ role);
+ goto out;
+ }
+ con = context_new(*sc);
+ if (!con) {
+ goto out;
+ }
+ context_role_set(con, role);
+ context_type_set(con, type);
+ freecon(*sc);
+ *sc = strdup(context_str(con));
+ context_free(con);
+ if (!*sc)
+ return -1;
+ }
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+ if (lvl != NULL && lvl[0]) {
+ /* verify that the requested range is obtained */
+ context_t con;
+ security_context_t obtained_raw;
+ security_context_t requested_raw;
+ con = context_new(*sc);
+ if (!con) {
+ goto out;
+ }
+ context_range_set(con, lvl);
+ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
+ context_free(con);
+ goto out;
+ }
+ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
+ freecon(obtained_raw);
+ context_free(con);
+ goto out;
+ }
+
+ debug("get_user_context: obtained context '%s' requested context '%s'",
+ obtained_raw, requested_raw);
+ if (strcmp(obtained_raw, requested_raw)) {
+ /* set the context to the real requested one but fail */
+ freecon(requested_raw);
+ freecon(obtained_raw);
+ freecon(*sc);
+ *sc = strdup(context_str(con));
+ context_free(con);
+ return -1;
+ }
+ freecon(requested_raw);
+ freecon(obtained_raw);
+ context_free(con);
+ }
+#endif
+ return 0;
+ out:
+ freecon(*sc);
+ *sc = NULL;
+ return -1;
+}
+
+static void
+ssh_selinux_get_role_level(char **role, const char **level)
+{
+ *role = NULL;
+ *level = NULL;
+ if (the_authctxt) {
+ if (the_authctxt->role != NULL) {
+ char *slash;
+ *role = xstrdup(the_authctxt->role);
+ if ((slash = strchr(*role, '/')) != NULL) {
+ *slash = '\0';
+ *level = slash + 1;
+ }
+ }
+ }
+}
+
/* Return the default security context for the given username */
-static security_context_t
-ssh_selinux_getctxbyname(char *pwname)
+static int
+ssh_selinux_getctxbyname(char *pwname,
+ security_context_t *default_sc, security_context_t *user_sc)
{
- security_context_t sc;
- char *sename = NULL, *lvl = NULL;
- int r;
+ char *sename, *lvl;
+ const char *reqlvl;
+ char *role;
+ int r = -1;
+ context_t con = NULL;
+
+ *default_sc = NULL;
+ *user_sc = NULL;
+
+ ssh_selinux_get_role_level(&role, &reqlvl);
#ifdef HAVE_GETSEUSERBYNAME
- if (getseuserbyname(pwname, &sename, &lvl) != 0)
- return NULL;
+ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
+ sename = NULL;
+ lvl = NULL;
+ }
#else
sename = pwname;
- lvl = NULL;
+ lvl = "";
#endif
+ if (r == 0) {
#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
- r = get_default_context_with_level(sename, lvl, NULL, &sc);
+ r = get_default_context_with_level(sename, lvl, NULL, default_sc);
#else
- r = get_default_context(sename, NULL, &sc);
+ r = get_default_context(sename, NULL, default_sc);
#endif
+ }
- if (r != 0) {
- switch (security_getenforce()) {
- case -1:
- fatal("%s: ssh_selinux_getctxbyname: "
- "security_getenforce() failed", __func__);
- case 0:
- error("%s: Failed to get default SELinux security "
- "context for %s", __func__, pwname);
- break;
- default:
- fatal("%s: Failed to get default SELinux security "
- "context for %s (in enforcing mode)",
- __func__, pwname);
+ if (r == 0) {
+ /* If launched from xinetd, we must use current level */
+ if (inetd_flag && !rexeced_flag) {
+ security_context_t sshdsc=NULL;
+
+ if (getcon_raw(&sshdsc) < 0)
+ fatal("failed to allocate security context");
+
+ if ((con=context_new(sshdsc)) == NULL)
+ fatal("failed to allocate selinux context");
+ reqlvl = context_range_get(con);
+ freecon(sshdsc);
+ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
+ /* we actually don't change level */
+ reqlvl = "";
+
+ debug("%s: current connection level '%s'", __func__, reqlvl);
}
+
+ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
+ r = get_user_context(sename, role, reqlvl, user_sc);
+
+ if (r == 0 && reqlvl != NULL && reqlvl[0]) {
+ security_context_t default_level_sc = *default_sc;
+ if (role != NULL && role[0]) {
+ if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
+ default_level_sc = *default_sc;
+ }
+ /* verify that the requested range is contained in the user range */
+ if (mls_range_allowed(default_level_sc, *user_sc)) {
+ logit("permit MLS level %s (user range %s)", reqlvl, lvl);
+ } else {
+ r = -1;
+ error("deny MLS level %s (user range %s)", reqlvl, lvl);
+ }
+ if (default_level_sc != *default_sc)
+ freecon(default_level_sc);
+ }
+ } else {
+ *user_sc = *default_sc;
+ }
+ }
+ if (r != 0) {
+ error("%s: Failed to get default SELinux security "
+ "context for %s", __func__, pwname);
}
#ifdef HAVE_GETSEUSERBYNAME
@@ -93,37 +314,114 @@ ssh_selinux_getctxbyname(char *pwname)
if (lvl != NULL)
xfree(lvl);
#endif
+ if (role != NULL)
+ xfree(role);
+ if (con)
+ context_free(con);
- return (sc);
+ return (r);
+}
+
+/* Setup environment variables for pam_selinux */
+static int
+ssh_selinux_setup_pam_variables(void)
+{
+ const char *reqlvl;
+ char *role;
+ char *use_current;
+ int rv;
+
+ debug3("%s: setting execution context", __func__);
+
+ ssh_selinux_get_role_level(&role, &reqlvl);
+
+ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : "");
+
+ if (inetd_flag && !rexeced_flag) {
+ use_current = "1";
+ } else {
+ use_current = "";
+ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
+ }
+
+ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current);
+
+ if (role != NULL)
+ xfree(role);
+
+ return rv;
}
/* Set the execution context to the default for the specified user */
void
ssh_selinux_setup_exec_context(char *pwname)
{
+ int r = 0;
+ security_context_t default_ctx = NULL;
security_context_t user_ctx = NULL;
if (!ssh_selinux_enabled())
return;
+ if (options.use_pam) {
+ /* do not compute context, just setup environment for pam_selinux */
+ if (ssh_selinux_setup_pam_variables()) {
+ switch (security_getenforce()) {
+ case -1:
+ fatal("%s: security_getenforce() failed", __func__);
+ case 0:
+ error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.",
+ __func__);
+ break;
+ default:
+ fatal("%s: SELinux PAM variable setup failure. Aborting connection.",
+ __func__);
+ }
+ }
+ return;
+ }
+
debug3("%s: setting execution context", __func__);
- user_ctx = ssh_selinux_getctxbyname(pwname);
- if (setexeccon(user_ctx) != 0) {
+ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
+ if (r >= 0) {
+ r = setexeccon(user_ctx);
+ if (r < 0) {
+ error("%s: Failed to set SELinux execution context %s for %s",
+ __func__, user_ctx, pwname);
+ }
+#ifdef HAVE_SETKEYCREATECON
+ else if (setkeycreatecon(user_ctx) < 0) {
+ error("%s: Failed to set SELinux keyring creation context %s for %s",
+ __func__, user_ctx, pwname);
+ }
+#endif
+ }
+ if (user_ctx == NULL) {
+ user_ctx = default_ctx;
+ }
+ if (r < 0 || user_ctx != default_ctx) {
+ /* audit just the case when user changed a role or there was
+ a failure */
+ send_audit_message(r >= 0, default_ctx, user_ctx);
+ }
+ if (r < 0) {
switch (security_getenforce()) {
case -1:
fatal("%s: security_getenforce() failed", __func__);
case 0:
- error("%s: Failed to set SELinux execution "
- "context for %s", __func__, pwname);
+ error("%s: SELinux failure. Continuing in permissive mode.",
+ __func__);
break;
default:
- fatal("%s: Failed to set SELinux execution context "
- "for %s (in enforcing mode)", __func__, pwname);
+ fatal("%s: SELinux failure. Aborting connection.",
+ __func__);
}
}
- if (user_ctx != NULL)
+ if (user_ctx != NULL && user_ctx != default_ctx)
freecon(user_ctx);
+ if (default_ctx != NULL)
+ freecon(default_ctx);
debug3("%s: done", __func__);
}
@@ -141,7 +439,10 @@ ssh_selinux_setup_pty(char *pwname, cons
debug3("%s: setting TTY context on %s", __func__, tty);
- user_ctx = ssh_selinux_getctxbyname(pwname);
+ if (getexeccon(&user_ctx) < 0) {
+ error("%s: getexeccon: %s", __func__, strerror(errno));
+ goto out;
+ }
/* XXX: should these calls fatal() upon failure in enforcing mode? */
openssh-5.2p1-vendor.patch:
--- NEW FILE openssh-5.2p1-vendor.patch ---
diff -up openssh-5.2p1/configure.ac.vendor openssh-5.2p1/configure.ac
--- openssh-5.2p1/configure.ac.vendor 2009-03-10 03:51:54.862255585 +0100
+++ openssh-5.2p1/configure.ac 2009-03-10 03:51:55.850215090 +0100
@@ -3335,11 +3335,25 @@ AC_ARG_WITH(selinux,
AC_CHECK_LIB(selinux, setexeccon, [ LIBSELINUX="-lselinux" ],
AC_MSG_ERROR(SELinux support requires libselinux library))
SSHDLIBS="$SSHDLIBS $LIBSELINUX"
+ LIBS="$LIBS $LIBSELINUX"
AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level)
+ AC_CHECK_FUNCS(setkeycreatecon)
LIBS="$save_LIBS"
fi ]
)
+# Check whether user wants Linux audit support
+LINUX_AUDIT_MSG="no"
+AC_ARG_WITH(linux-audit,
+ [ --with-linux-audit Enable Linux audit support],
+ [ if test "x$withval" != "xno" ; then
+ AC_DEFINE(HAVE_LINUX_AUDIT,1,[Define if you want Linux audit support.])
+ LINUX_AUDIT_MSG="yes"
+ AC_CHECK_HEADERS(libaudit.h)
+ SSHDLIBS="$SSHDLIBS -laudit"
+ fi ]
+)
+
# Check whether user wants Kerberos 5 support
KRB5_MSG="no"
AC_ARG_WITH(kerberos5,
@@ -3448,6 +3462,20 @@ AC_ARG_WITH(kerberos5,
]
)
+# Check whether user wants NSS support
+LIBNSS_MSG="no"
+AC_ARG_WITH(nss,
+ [ --with-nss Enable NSS support],
+ [ if test "x$withval" != "xno" ; then
+ AC_DEFINE(HAVE_LIBNSS,1,[Define if you want NSS support.])
+ LIBNSS_MSG="yes"
+ CPPFLAGS="$CPPFLAGS -I/usr/include/nss3 -I/usr/include/nspr4"
+ AC_CHECK_HEADERS(pk11pub.h)
+ LIBS="$LIBS -lnss3"
+ fi
+ ])
+AC_SUBST(LIBNSS)
+
# Looking for programs, paths and files
PRIVSEP_PATH=/var/empty
@@ -3916,6 +3944,12 @@ AC_ARG_WITH(lastlog,
fi
]
)
+AC_ARG_ENABLE(vendor-patchlevel,
+ [ --enable-vendor-patchlevel=TAG specify a vendor patch level],
+ [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.])
+ SSH_VENDOR_PATCHLEVEL="$enableval"],
+ [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.])
+ SSH_VENDOR_PATCHLEVEL=none])
dnl lastlog, [uw]tmpx? detection
dnl NOTE: set the paths in the platform section to avoid the
@@ -4162,16 +4196,19 @@ echo " PAM support
echo " OSF SIA support: $SIA_MSG"
echo " KerberosV support: $KRB5_MSG"
echo " SELinux support: $SELINUX_MSG"
+echo " Linux audit support: $LINUX_AUDIT_MSG"
echo " Smartcard support: $SCARD_MSG"
echo " S/KEY support: $SKEY_MSG"
echo " TCP Wrappers support: $TCPW_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " Solaris process contract support: $SPC_MSG"
+echo " NSS support: $LIBNSS_MSG"
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
echo " BSD Auth support: $BSD_AUTH_MSG"
echo " Random number source: $RAND_MSG"
+echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL"
if test ! -z "$USE_RAND_HELPER" ; then
echo " ssh-rand-helper collects from: $RAND_HELPER_MSG"
fi
diff -up openssh-5.2p1/servconf.c.vendor openssh-5.2p1/servconf.c
--- openssh-5.2p1/servconf.c.vendor 2009-01-28 06:31:23.000000000 +0100
+++ openssh-5.2p1/servconf.c 2009-03-10 03:51:54.956273911 +0100
@@ -117,6 +117,7 @@ initialize_server_options(ServerOptions
options->max_authtries = -1;
options->max_sessions = -1;
options->banner = NULL;
+ options->show_patchlevel = -1;
options->use_dns = -1;
options->client_alive_interval = -1;
options->client_alive_count_max = -1;
@@ -262,6 +263,9 @@ fill_default_server_options(ServerOption
if (options->zero_knowledge_password_authentication == -1)
options->zero_knowledge_password_authentication = 0;
+ if (options->show_patchlevel == -1)
+ options->show_patchlevel = 0;
+
/* Turn privilege separation on by default */
if (use_privsep == -1)
use_privsep = 1;
@@ -299,7 +303,7 @@ typedef enum {
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
sMaxStartups, sMaxAuthTries, sMaxSessions,
- sBanner, sUseDNS, sHostbasedAuthentication,
+ sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
@@ -410,6 +414,7 @@ static struct {
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
{ "maxsessions", sMaxSessions, SSHCFG_ALL },
{ "banner", sBanner, SSHCFG_ALL },
+ { "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL },
{ "usedns", sUseDNS, SSHCFG_GLOBAL },
{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
@@ -1033,6 +1038,10 @@ process_server_config_line(ServerOptions
intptr = &use_privsep;
goto parse_flag;
+ case sShowPatchLevel:
+ intptr = &options->show_patchlevel;
+ goto parse_flag;
+
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
@@ -1613,6 +1622,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sUseLogin, o->use_login);
dump_cfg_fmtint(sCompression, o->compression);
dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
+ dump_cfg_fmtint(sShowPatchLevel, o->show_patchlevel);
dump_cfg_fmtint(sUseDNS, o->use_dns);
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
diff -up openssh-5.2p1/servconf.h.vendor openssh-5.2p1/servconf.h
--- openssh-5.2p1/servconf.h.vendor 2009-01-28 06:31:23.000000000 +0100
+++ openssh-5.2p1/servconf.h 2009-03-10 03:51:54.933236643 +0100
@@ -128,6 +128,7 @@ typedef struct {
int max_authtries;
int max_sessions;
char *banner; /* SSH-2 banner message */
+ int show_patchlevel; /* Show vendor patch level to clients */
int use_dns;
int client_alive_interval; /*
* poke the client this often to
diff -up openssh-5.2p1/sshd_config.0.vendor openssh-5.2p1/sshd_config.0
--- openssh-5.2p1/sshd_config.0.vendor 2009-03-10 03:51:54.775230993 +0100
+++ openssh-5.2p1/sshd_config.0 2009-03-10 03:51:54.958364611 +0100
@@ -467,6 +467,11 @@ DESCRIPTION
Defines the number of bits in the ephemeral protocol version 1
server key. The minimum value is 512, and the default is 1024.
+ ShowPatchLevel
+ Specifies whether sshd will display the specific patch level of
+ the binary in the server identification string. The patch level
+ is set at compile-time. The default is M-bM-^@M-^\noM-bM-^@M-^].
+
StrictModes
Specifies whether sshd(8) should check file modes and ownership
of the user's files and home directory before accepting login.
diff -up openssh-5.2p1/sshd_config.5.vendor openssh-5.2p1/sshd_config.5
--- openssh-5.2p1/sshd_config.5.vendor 2009-03-10 03:51:54.785628316 +0100
+++ openssh-5.2p1/sshd_config.5 2009-03-10 03:51:54.931352756 +0100
@@ -814,6 +814,14 @@ This option applies to protocol version
.It Cm ServerKeyBits
Defines the number of bits in the ephemeral protocol version 1 server key.
The minimum value is 512, and the default is 1024.
+.It Cm ShowPatchLevel
+Specifies whether
+.Nm sshd
+will display the patch level of the binary in the identification string.
+The patch level is set at compile-time.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
.It Cm StrictModes
Specifies whether
.Xr sshd 8
diff -up openssh-5.2p1/sshd_config.vendor openssh-5.2p1/sshd_config
--- openssh-5.2p1/sshd_config.vendor 2009-03-10 03:51:54.747256884 +0100
+++ openssh-5.2p1/sshd_config 2009-03-10 03:51:54.960221540 +0100
@@ -112,6 +112,7 @@ X11Forwarding yes
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
+#ShowPatchLevel no
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10
diff -up openssh-5.2p1/sshd.c.vendor openssh-5.2p1/sshd.c
--- openssh-5.2p1/sshd.c.vendor 2009-01-28 06:31:23.000000000 +0100
+++ openssh-5.2p1/sshd.c 2009-03-10 03:51:56.224238563 +0100
@@ -76,6 +76,8 @@
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#ifdef HAVE_SECUREWARE
@@ -415,7 +417,7 @@ sshd_exchange_identification(int sock_in
minor = PROTOCOL_MINOR_1;
}
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
- SSH_VERSION, newline);
+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION, newline);
server_version_string = xstrdup(buf);
/* Send our protocol version identification. */
@@ -590,6 +592,10 @@ privsep_preauth_child(void)
/* Demote the private keys to public keys. */
demote_sensitive_data();
+ /* Open the syslog permanently so the chrooted process still
+ can write to syslog. */
+ open_log();
+
/* Change our root directory */
if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
@@ -1256,6 +1262,12 @@ main(int ac, char **av)
(void)set_auth_parameters(ac, av);
#endif
__progname = ssh_get_progname(av[0]);
+
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fatal("FIPS integrity verification test failed.");
+ }
+
init_rng();
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
@@ -1408,8 +1420,6 @@ main(int ac, char **av)
else
closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
- SSLeay_add_all_algorithms();
-
/*
* Force logging to stderr until we have loaded the private host
* key (unless started from inetd)
@@ -1483,7 +1493,8 @@ main(int ac, char **av)
exit(1);
}
- debug("sshd version %.100s", SSH_RELEASE);
+ debug("sshd version %.100s",
+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_RELEASE);
/* Store privilege separation user for later use if required. */
if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
@@ -1894,6 +1905,9 @@ main(int ac, char **av)
restore_uid();
}
#endif
+#ifdef WITH_SELINUX
+ ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
+#endif
#ifdef USE_PAM
if (options.use_pam) {
do_pam_setcred(1);
@@ -2174,6 +2188,9 @@ do_ssh2_kex(void)
if (options.ciphers != NULL) {
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT;
}
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
@@ -2183,6 +2200,9 @@ do_ssh2_kex(void)
if (options.macs != NULL) {
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC;
}
if (options.compression == COMP_NONE) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] =
Index: openssh.spec
===================================================================
RCS file: /cvs/pkgs/rpms/openssh/devel/openssh.spec,v
retrieving revision 1.137
retrieving revision 1.138
diff -u -r1.137 -r1.138
--- openssh.spec 26 Feb 2009 08:48:36 -0000 1.137
+++ openssh.spec 10 Mar 2009 11:54:44 -0000 1.138
@@ -62,8 +62,8 @@
Summary: An open source implementation of SSH protocol versions 1 and 2
Name: openssh
-Version: 5.1p1
-Release: 8%{?dist}%{?rescue_rel}
+Version: 5.2p1
+Release: 1%{?dist}%{?rescue_rel}
URL: http://www.openssh.com/portable.html
#Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
#Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc
@@ -74,11 +74,11 @@
Source1: openssh-nukeacss.sh
Source2: sshd.pam
Source3: sshd.init
-Patch0: openssh-5.1p1-redhat.patch
+Patch0: openssh-5.2p1-redhat.patch
Patch2: openssh-5.1p1-skip-initial.patch
Patch3: openssh-3.8.1p1-krb5-config.patch
-Patch4: openssh-5.1p1-vendor.patch
-Patch12: openssh-5.1p1-selinux.patch
+Patch4: openssh-5.2p1-vendor.patch
+Patch12: openssh-5.2p1-selinux.patch
Patch13: openssh-5.1p1-mls.patch
Patch16: openssh-4.7p1-audit.patch
Patch17: openssh-4.3p2-cve-2007-3102.patch
@@ -92,13 +92,11 @@
Patch39: openssh-4.3p2-no-v6only.patch
Patch44: openssh-4.3p2-allow-ip-opts.patch
Patch49: openssh-4.3p2-gssapi-canohost.patch
-Patch51: openssh-5.1p1-nss-keys.patch
+Patch51: openssh-5.2p1-nss-keys.patch
Patch54: openssh-5.1p1-gssapi-role.patch
Patch55: openssh-5.1p1-cloexec.patch
Patch62: openssh-5.1p1-scp-manpage.patch
-Patch63: openssh-5.1p1-bannerlen.patch
-Patch64: openssh-5.1p1-compat-sessions.patch
-Patch65: openssh-5.1p1-fips.patch
+Patch65: openssh-5.2p1-fips.patch
License: BSD
Group: Applications/Internet
@@ -229,8 +227,6 @@
%patch54 -p1 -b .gssapi-role
%patch55 -p1 -b .cloexec
%patch62 -p1 -b .manpage
-%patch63 -p1 -b .bannerlen
-%patch64 -p1 -b .compat-sessions
%patch65 -p1 -b .fips
autoreconf
@@ -476,6 +472,9 @@
%endif
%changelog
+* Thu Mar 9 2009 Jan F. Chadima <jchadima at redhat.com> - 5.2p1-1
+- upgrade to new upstream release
+
* Thu Feb 26 2009 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 5.1p1-8
- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
--- openssh-5.1p1-bannerlen.patch DELETED ---
--- openssh-5.1p1-compat-sessions.patch DELETED ---
--- openssh-5.1p1-fips.patch DELETED ---
--- openssh-5.1p1-nss-keys.patch DELETED ---
--- openssh-5.1p1-redhat.patch DELETED ---
--- openssh-5.1p1-selinux.patch DELETED ---
--- openssh-5.1p1-vendor.patch DELETED ---
More information about the fedora-extras-commits
mailing list