diff options
Diffstat (limited to 'usr/src/cmd/ssh')
-rw-r--r-- | usr/src/cmd/ssh/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/include/key.h | 15 | ||||
-rw-r--r-- | usr/src/cmd/ssh/include/servconf.h | 1 | ||||
-rw-r--r-- | usr/src/cmd/ssh/libssh/common/canohost.c | 35 | ||||
-rw-r--r-- | usr/src/cmd/ssh/libssh/common/key.c | 17 | ||||
-rw-r--r-- | usr/src/cmd/ssh/sftp-server/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/sftp/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/ssh-add/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/ssh-agent/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/ssh-keygen/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/ssh-keygen/ssh-keygen.c | 277 | ||||
-rw-r--r-- | usr/src/cmd/ssh/ssh-keyscan/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/ssh-keysign/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/ssh/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/sshd/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/ssh/sshd/auth2-pubkey.c | 109 | ||||
-rw-r--r-- | usr/src/cmd/ssh/sshd/servconf.c | 9 | ||||
-rw-r--r-- | usr/src/cmd/ssh/sshd/sshlogin.c | 3 |
18 files changed, 380 insertions, 106 deletions
diff --git a/usr/src/cmd/ssh/Makefile b/usr/src/cmd/ssh/Makefile index a36a9fb762..62f30b3f36 100644 --- a/usr/src/cmd/ssh/Makefile +++ b/usr/src/cmd/ssh/Makefile @@ -77,7 +77,7 @@ check: $(CHECKHDRS) _msg: $(RM) $(POFILE) $(TOUCH) $(POFILE) - $(MAKE) $(POFILE) XGETTEXT=/usr/bin/gxgettext + $(MAKE) $(POFILE) XGETTEXT=$(GNUXGETTEXT) $(CP) $(POFILE) $(MSGFILE) $(CP) $(MSGFILE) $(MSGDOMAIN) diff --git a/usr/src/cmd/ssh/include/key.h b/usr/src/cmd/ssh/include/key.h index 862b2d81d4..ec4993a9c1 100644 --- a/usr/src/cmd/ssh/include/key.h +++ b/usr/src/cmd/ssh/include/key.h @@ -39,11 +39,17 @@ extern "C" { typedef struct Key Key; enum types { - KEY_RSA1, - KEY_RSA, - KEY_DSA, + KEY_RSA1, + KEY_RSA, + KEY_DSA, + KEY_ECDSA, + KEY_RSA_CERT, + KEY_DSA_CERT, + KEY_ECDSA_CERT, + KEY_RSA_CERT_V00, + KEY_DSA_CERT_V00, KEY_NULL, - KEY_UNSPEC + KEY_UNSPEC }; enum fp_type { SSH_FP_SHA1, @@ -87,6 +93,7 @@ int key_names_valid2(const char *); int key_sign(Key *, u_char **, u_int *, u_char *, u_int); int key_verify(Key *, u_char *, u_int, u_char *, u_int); +int key_type_plain(int type); #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/ssh/include/servconf.h b/usr/src/cmd/ssh/include/servconf.h index a66c6415cb..9a32544c2a 100644 --- a/usr/src/cmd/ssh/include/servconf.h +++ b/usr/src/cmd/ssh/include/servconf.h @@ -167,6 +167,7 @@ typedef struct { char *pre_userauth_hook; char *pam_service_prefix; char *pam_service_name; + char *pubkey_plugin; } ServerOptions; diff --git a/usr/src/cmd/ssh/libssh/common/canohost.c b/usr/src/cmd/ssh/libssh/common/canohost.c index 2d427b9e8d..87aab396cf 100644 --- a/usr/src/cmd/ssh/libssh/common/canohost.c +++ b/usr/src/cmd/ssh/libssh/common/canohost.c @@ -73,9 +73,6 @@ get_remote_hostname(int socket, int verify_reverse_mapping) if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), NULL, 0, NI_NAMEREQD) != 0) { /* Host name not found. Use ip address. */ -#if 0 - log("Could not reverse map address %.100s.", ntop); -#endif return xstrdup(ntop); } @@ -206,36 +203,6 @@ get_socket_address(int socket, int remote, int flags) return (xstrdup(result)); } -#if 0 -static char * -get_socket_address(int socket, int remote, int flags) -{ - struct sockaddr_storage addr; - socklen_t addrlen; - char ntop[NI_MAXHOST]; - - /* Get IP address of client. */ - addrlen = sizeof(addr); - memset(&addr, 0, sizeof(addr)); - - if (remote) { - if (getpeername(socket, (struct sockaddr *)&addr, &addrlen) - < 0) - return NULL; - } else { - if (getsockname(socket, (struct sockaddr *)&addr, &addrlen) - < 0) - return NULL; - } - /* Get the address in ascii. */ - if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop), - NULL, 0, flags) != 0) { - error("get_socket_ipaddr: getnameinfo %d failed", flags); - return NULL; - } - return xstrdup(ntop); -} -#endif char * get_peer_ipaddr(int socket) @@ -388,4 +355,4 @@ inet_ntop_native(int af, const void *src, char *dst, size_t size) } return (result); -} +} diff --git a/usr/src/cmd/ssh/libssh/common/key.c b/usr/src/cmd/ssh/libssh/common/key.c index f648d3b640..8ee2583d93 100644 --- a/usr/src/cmd/ssh/libssh/common/key.c +++ b/usr/src/cmd/ssh/libssh/common/key.c @@ -874,3 +874,20 @@ key_demote(Key *k) return (pk); } + +int +key_type_plain(int type) +{ + switch (type) { + case KEY_RSA_CERT_V00: + case KEY_RSA_CERT: + return KEY_RSA; + case KEY_DSA_CERT_V00: + case KEY_DSA_CERT: + return KEY_DSA; + case KEY_ECDSA_CERT: + return KEY_ECDSA; + default: + return type; + } +} diff --git a/usr/src/cmd/ssh/sftp-server/Makefile b/usr/src/cmd/ssh/sftp-server/Makefile index c2bdf26c1e..f49dde54ee 100644 --- a/usr/src/cmd/ssh/sftp-server/Makefile +++ b/usr/src/cmd/ssh/sftp-server/Makefile @@ -31,7 +31,7 @@ SRCS = $(OBJS:.o=.c) include ../../Makefile.cmd include ../Makefile.ssh-common -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lcrypto +LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lsunw_crypto POFILE_DIR = .. diff --git a/usr/src/cmd/ssh/sftp/Makefile b/usr/src/cmd/ssh/sftp/Makefile index 8bd8bb4ac3..f3c0ea7a75 100644 --- a/usr/src/cmd/ssh/sftp/Makefile +++ b/usr/src/cmd/ssh/sftp/Makefile @@ -35,7 +35,7 @@ SRCS = $(OBJS:.o=.c) include ../../Makefile.cmd include ../Makefile.ssh-common -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lcrypto -ltecla +LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lsunw_crypto -ltecla POFILE_DIR = .. diff --git a/usr/src/cmd/ssh/ssh-add/Makefile b/usr/src/cmd/ssh/ssh-add/Makefile index 1fb132f741..3235839e06 100644 --- a/usr/src/cmd/ssh/ssh-add/Makefile +++ b/usr/src/cmd/ssh/ssh-add/Makefile @@ -32,7 +32,7 @@ SRCS = $(OBJS:.o=.c) include ../../Makefile.cmd include ../Makefile.ssh-common -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lcrypto +LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lsunw_crypto POFILE_DIR= .. diff --git a/usr/src/cmd/ssh/ssh-agent/Makefile b/usr/src/cmd/ssh/ssh-agent/Makefile index 3d4a366c17..ab2e1eb49d 100644 --- a/usr/src/cmd/ssh/ssh-agent/Makefile +++ b/usr/src/cmd/ssh/ssh-agent/Makefile @@ -32,7 +32,7 @@ SRCS = $(OBJS:.o=.c) include ../../Makefile.cmd include ../Makefile.ssh-common -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lcrypto +LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lsunw_crypto POFILE_DIR= .. diff --git a/usr/src/cmd/ssh/ssh-keygen/Makefile b/usr/src/cmd/ssh/ssh-keygen/Makefile index f92c437045..0c90716768 100644 --- a/usr/src/cmd/ssh/ssh-keygen/Makefile +++ b/usr/src/cmd/ssh/ssh-keygen/Makefile @@ -32,7 +32,7 @@ SRCS = $(OBJS:.o=.c) include ../../Makefile.cmd include ../Makefile.ssh-common -LDLIBS += $(SSH_COMMON_LDLIBS) -lcrypto -lsocket +LDLIBS += $(SSH_COMMON_LDLIBS) -lsunw_crypto -lsocket POFILE_DIR= .. diff --git a/usr/src/cmd/ssh/ssh-keygen/ssh-keygen.c b/usr/src/cmd/ssh/ssh-keygen/ssh-keygen.c index ebad79b0f8..c79e76ae36 100644 --- a/usr/src/cmd/ssh/ssh-keygen/ssh-keygen.c +++ b/usr/src/cmd/ssh/ssh-keygen/ssh-keygen.c @@ -11,7 +11,7 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* $OpenBSD: ssh-keygen.c,v 1.160 2007/01/21 01:41:54 stevesk Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.205 2011/01/11 06:13:10 djm Exp $ */ #include "includes.h" #include <openssl/evp.h> @@ -76,9 +76,14 @@ char *identity_new_passphrase = NULL; /* This is set to the new comment if given on the command line. */ char *identity_comment = NULL; -/* Dump public key file in format used by real and the original SSH 2 */ -int convert_to_ssh2 = 0; -int convert_from_ssh2 = 0; +/* Conversion to/from various formats */ +int convert_to = 0; +int convert_from = 0; +enum { + FMT_RFC4716, + FMT_PKCS8, + FMT_PEM +} convert_format = FMT_RFC4716; int print_public = 0; char *key_type_name = NULL; @@ -154,41 +159,105 @@ load_identity(char *filename) #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb static void -do_convert_to_ssh2(struct passwd *pw) +do_convert_to_ssh2(struct passwd *pw, Key *k) { - Key *k; u_int len; u_char *blob; - struct stat st; + char comment[61]; - if (!have_identity) - ask_filename(pw, gettext("Enter file in which the key is")); - if (stat(identity_file, &st) < 0) { - perror(identity_file); + if (key_to_blob(k, &blob, &len) <= 0) { + fprintf(stderr, "key_to_blob failed\n"); exit(1); } + /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */ + snprintf(comment, sizeof(comment), + "%u-bit %s, converted by %s@%s from OpenSSH", + key_size(k), key_type(k), + pw->pw_name, hostname); + + fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); + fprintf(stdout, "Comment: \"%s\"\n", comment); + dump_base64(stdout, blob, len); + fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); + key_free(k); + xfree(blob); + exit(0); +} + +static void +do_convert_to_pkcs8(Key *k) +{ + switch (key_type_plain(k->type)) { + case KEY_RSA: + if (!PEM_write_RSA_PUBKEY(stdout, k->rsa)) + fatal("PEM_write_RSA_PUBKEY failed"); + break; + case KEY_DSA: + if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) + fatal("PEM_write_DSA_PUBKEY failed"); + break; + default: + fatal("%s: unsupported key type %s", __func__, key_type(k)); + } + exit(0); +} + +static void +do_convert_to_pem(Key *k) +{ + switch (key_type_plain(k->type)) { + case KEY_RSA: + if (!PEM_write_RSAPublicKey(stdout, k->rsa)) + fatal("PEM_write_RSAPublicKey failed"); + break; + case KEY_DSA: + if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) + fatal("PEM_write_DSAPublicKey failed"); + break; + default: + fatal("%s: unsupported key type %s", __func__, key_type(k)); + } + exit(0); +} + +static void +do_convert_to(struct passwd *pw) +{ + Key *k; + struct stat st; + + if (!have_identity) + ask_filename(pw, "Enter file in which the key is"); + if (stat(identity_file, &st) < 0) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); if ((k = key_load_public(identity_file, NULL)) == NULL) { if ((k = load_identity(identity_file)) == NULL) { - fprintf(stderr, gettext("load failed\n")); + fprintf(stderr, "load failed\n"); exit(1); } } - if (key_to_blob(k, &blob, &len) <= 0) { - fprintf(stderr, gettext("key_to_blob failed\n")); + if (k->type == KEY_RSA1) { + fprintf(stderr, "version 1 keys are not supported\n"); exit(1); } - fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); - fprintf(stdout, gettext( - "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n"), - key_size(k), key_type(k), - pw->pw_name, hostname); - dump_base64(stdout, blob, len); - fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); - key_free(k); - xfree(blob); + + switch (convert_format) { + case FMT_RFC4716: + do_convert_to_ssh2(pw, k); + break; + case FMT_PKCS8: + do_convert_to_pkcs8(k); + break; + case FMT_PEM: + do_convert_to_pem(k); + break; + default: + fatal("%s: unknown key format %d", __func__, convert_format); + } exit(0); } + static void buffer_get_bignum_bits(Buffer *b, BIGNUM *value) { @@ -327,24 +396,16 @@ get_line(FILE *fp, char *line, size_t len) } static void -do_convert_from_ssh2(struct passwd *pw) +do_convert_from_ssh2(struct passwd *pw, Key **k, int *private) { - Key *k; int blen; u_int len; char line[1024]; u_char blob[8096]; char encoded[8096]; - struct stat st; - int escaped = 0, private = 0, ok; + int escaped = 0; FILE *fp; - if (!have_identity) - ask_filename(pw, gettext("Enter file in which the key is")); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } fp = fopen(identity_file, "r"); if (fp == NULL) { perror(identity_file); @@ -357,7 +418,7 @@ do_convert_from_ssh2(struct passwd *pw) if (strncmp(line, "----", 4) == 0 || strstr(line, ": ") != NULL) { if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL) - private = 1; + *private = 1; if (strstr(line, " END ") != NULL) { break; } @@ -382,26 +443,117 @@ do_convert_from_ssh2(struct passwd *pw) fprintf(stderr, gettext("uudecode failed.\n")); exit(1); } - k = private ? + *k = *private ? do_convert_private_ssh2_from_blob(blob, blen) : key_from_blob(blob, blen); - if (k == NULL) { + if (*k == NULL) { fprintf(stderr, gettext("decode blob failed.\n")); exit(1); } - ok = private ? - (k->type == KEY_DSA ? - PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) : - PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) : - key_write(k, stdout); + fclose(fp); +} + +static void +do_convert_from_pkcs8(Key **k, int *private) +{ + EVP_PKEY *pubkey; + FILE *fp; + + if ((fp = fopen(identity_file, "r")) == NULL) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); + if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) { + fatal("%s: %s is not a recognised public key format", __func__, + identity_file); + } + fclose(fp); + switch (EVP_PKEY_type(pubkey->type)) { + case EVP_PKEY_RSA: + *k = key_new(KEY_UNSPEC); + (*k)->type = KEY_RSA; + (*k)->rsa = EVP_PKEY_get1_RSA(pubkey); + break; + case EVP_PKEY_DSA: + *k = key_new(KEY_UNSPEC); + (*k)->type = KEY_DSA; + (*k)->dsa = EVP_PKEY_get1_DSA(pubkey); + break; + default: + fatal("%s: unsupported pubkey type %d", __func__, + EVP_PKEY_type(pubkey->type)); + } + EVP_PKEY_free(pubkey); + return; +} + +static void +do_convert_from_pem(Key **k, int *private) +{ + FILE *fp; + RSA *rsa; + + if ((fp = fopen(identity_file, "r")) == NULL) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); + if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) { + *k = key_new(KEY_UNSPEC); + (*k)->type = KEY_RSA; + (*k)->rsa = rsa; + fclose(fp); + return; + } + fatal("%s: unrecognised raw private key format", __func__); +} + +static void +do_convert_from(struct passwd *pw) +{ + Key *k = NULL; + int private = 0, ok = 0; + struct stat st; + + if (!have_identity) + ask_filename(pw, "Enter file in which the key is"); + if (stat(identity_file, &st) < 0) + fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); + + switch (convert_format) { + case FMT_RFC4716: + do_convert_from_ssh2(pw, &k, &private); + break; + case FMT_PKCS8: + do_convert_from_pkcs8(&k, &private); + break; + case FMT_PEM: + do_convert_from_pem(&k, &private); + break; + default: + fatal("%s: unknown key format %d", __func__, convert_format); + } + + if (!private) + ok = key_write(k, stdout); + if (ok) + fprintf(stdout, "\n"); + else { + switch (k->type) { + case KEY_DSA: + ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, + NULL, 0, NULL, NULL); + break; + case KEY_RSA: + ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, + NULL, 0, NULL, NULL); + break; + default: + fatal("%s: unsupported key type %s", __func__, + key_type(k)); + } + } + if (!ok) { - fprintf(stderr, gettext("key write failed")); + fprintf(stderr, "key write failed\n"); exit(1); } key_free(k); - if (!private) - fprintf(stdout, "\n"); - fclose(fp); exit(0); } @@ -917,12 +1069,13 @@ usage(void) " -B Show bubblebabble digest of key file.\n" " -c Change comment in private and public key files.\n" " -C comment Provide new comment.\n" - " -e Convert OpenSSH to IETF SECSH key file.\n" + " -e Convert OpenSSH to foreign format key file.\n" " -f filename Filename of the key file.\n" " -F hostname Find hostname in known hosts file.\n" " -H Hash names in known_hosts file.\n" - " -i Convert IETF SECSH to OpenSSH key file.\n" + " -i Convert foreign format to OpenSSH key file.\n" " -l Show fingerprint of key file.\n" + " -m key_fmt Conversion format for -e/-i (PEM|PKCS8|RFC4716).\n" " -N phrase Provide new passphrase.\n" " -p Change passphrase of private key file.\n" " -P phrase Provide old passphrase.\n" @@ -974,7 +1127,7 @@ main(int argc, char **argv) exit(1); } -#define GETOPT_ARGS "BcdeHilpqxXyb:C:f:F:N:P:R:t:" +#define GETOPT_ARGS "BcdeHilpqxXyb:C:f:F:m:N:P:R:t:" while ((opt = getopt(argc, argv, GETOPT_ARGS)) != -1) { switch (opt) { @@ -1002,6 +1155,22 @@ main(int argc, char **argv) case 'B': print_bubblebabble = 1; break; + case 'm': + if (strcasecmp(optarg, "RFC4716") == 0 || + strcasecmp(optarg, "ssh2") == 0) { + convert_format = FMT_RFC4716; + break; + } + if (strcasecmp(optarg, "PKCS8") == 0) { + convert_format = FMT_PKCS8; + break; + } + if (strcasecmp(optarg, "PEM") == 0) { + convert_format = FMT_PEM; + break; + } + fatal("Unsupported conversion format \"%s\"", optarg); + /*NOTREACHED*/ case 'p': change_passphrase = 1; break; @@ -1027,12 +1196,12 @@ main(int argc, char **argv) case 'e': case 'x': /* export key */ - convert_to_ssh2 = 1; + convert_to = 1; break; case 'i': case 'X': /* import key */ - convert_from_ssh2 = 1; + convert_from = 1; break; case 'y': print_public = 1; @@ -1064,10 +1233,10 @@ main(int argc, char **argv) do_change_passphrase(pw); if (change_comment) do_change_comment(pw); - if (convert_to_ssh2) - do_convert_to_ssh2(pw); - if (convert_from_ssh2) - do_convert_from_ssh2(pw); + if (convert_to) + do_convert_to(pw); + if (convert_from) + do_convert_from(pw); if (print_public) do_print_public(pw); diff --git a/usr/src/cmd/ssh/ssh-keyscan/Makefile b/usr/src/cmd/ssh/ssh-keyscan/Makefile index 9e2fd17160..90428880a3 100644 --- a/usr/src/cmd/ssh/ssh-keyscan/Makefile +++ b/usr/src/cmd/ssh/ssh-keyscan/Makefile @@ -32,7 +32,7 @@ SRCS = $(OBJS:.o=.c) include ../../Makefile.cmd include ../Makefile.ssh-common -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lnsl -lz -lcrypto +LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lnsl -lz -lsunw_crypto POFILE_DIR= .. diff --git a/usr/src/cmd/ssh/ssh-keysign/Makefile b/usr/src/cmd/ssh/ssh-keysign/Makefile index e31ae681a1..649935a050 100644 --- a/usr/src/cmd/ssh/ssh-keysign/Makefile +++ b/usr/src/cmd/ssh/ssh-keysign/Makefile @@ -36,7 +36,7 @@ include ../Makefile.ssh-common FILEMODE= 04555 -LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lnsl -lz -lcrypto +LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket -lnsl -lz -lsunw_crypto POFILE_DIR= .. diff --git a/usr/src/cmd/ssh/ssh/Makefile b/usr/src/cmd/ssh/ssh/Makefile index 7bdd4f6be5..2d77334497 100644 --- a/usr/src/cmd/ssh/ssh/Makefile +++ b/usr/src/cmd/ssh/ssh/Makefile @@ -40,7 +40,7 @@ include ../Makefile.ssh-common LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket \ -lnsl \ -lz \ - -lcrypto \ + -lsunw_crypto \ -lgss POFILE_DIR= .. diff --git a/usr/src/cmd/ssh/sshd/Makefile b/usr/src/cmd/ssh/sshd/Makefile index a52e9b1cc8..4c82633347 100644 --- a/usr/src/cmd/ssh/sshd/Makefile +++ b/usr/src/cmd/ssh/sshd/Makefile @@ -75,7 +75,7 @@ LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket \ -lpam \ -lbsm \ -lwrap \ - -lcrypto \ + -lsunw_crypto \ -lgss \ -lcontract MAPFILES = $(MAPFILE.INT) $(MAPFILE.NGB) diff --git a/usr/src/cmd/ssh/sshd/auth2-pubkey.c b/usr/src/cmd/ssh/sshd/auth2-pubkey.c index 658634c195..c1c5f540e4 100644 --- a/usr/src/cmd/ssh/sshd/auth2-pubkey.c +++ b/usr/src/cmd/ssh/sshd/auth2-pubkey.c @@ -26,6 +26,8 @@ * Use is subject to license terms. */ +#include <dlfcn.h> + #include "includes.h" RCSID("$OpenBSD: auth2-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); @@ -54,6 +56,13 @@ extern ServerOptions options; extern u_char *session_id2; extern int session_id2_len; +/* global plugin function requirements */ +static const char *RSA_SYM_NAME = "sshd_user_rsa_key_allowed"; +static const char *DSA_SYM_NAME = "sshd_user_rsa_key_allowed"; +typedef int (*RSA_SYM)(struct passwd *, RSA *, const char *); +typedef int (*DSA_SYM)(struct passwd *, DSA *, const char *); + + static void userauth_pubkey(Authctxt *authctxt) { @@ -309,7 +318,98 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) return found_key; } -/* check whether given key is in .ssh/authorized_keys* */ +/** + * Checks whether or not access is allowed based on a plugin specified + * in sshd_config (PubKeyPlugin). + * + * Note that this expects a symbol in the loaded library that takes + * the current user (pwd entry), the current RSA key and it's fingerprint. + * The symbol is expected to return 1 on success and 0 on failure. + * + * While we could optimize this code to dlopen once in the process' lifetime, + * sshd is already a slow beast, so this is really not a concern. + * The overhead is basically a rounding error compared to everything else, and + * it keeps this code minimally invasive. + */ +static int +user_key_allowed_from_plugin(struct passwd *pw, Key *key) +{ + RSA_SYM rsa_sym = NULL; + DSA_SYM dsa_sym = NULL; + char *fp = NULL; + void *handle = NULL; + int success = 0; + + if (options.pubkey_plugin == NULL || pw == NULL || key == NULL || + (key->type != KEY_RSA && key->type != KEY_RSA1 && + key->type != KEY_DSA && key->type != KEY_ECDSA)) + return success; + + handle = dlopen(options.pubkey_plugin, RTLD_NOW); + if ((handle == NULL)) { + debug("Unable to open library %s: %s", options.pubkey_plugin, + dlerror()); + goto out; + } + + fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + if (fp == NULL) { + debug("failed to generate fingerprint"); + goto out; + } + + switch (key->type) { + case KEY_RSA1: + case KEY_RSA: + rsa_sym = (RSA_SYM)dlsym(handle, RSA_SYM_NAME); + if (rsa_sym == NULL) { + debug("Unable to resolve symbol %s: %s", RSA_SYM_NAME, + dlerror()); + goto out; + } + debug2("Invoking %s from %s", RSA_SYM_NAME, + options.pubkey_plugin); + success = (*rsa_sym)(pw, key->rsa, fp); + break; + case KEY_DSA: + case KEY_ECDSA: + dsa_sym = (DSA_SYM)dlsym(handle, RSA_SYM_NAME); + if (dsa_sym == NULL) { + debug("Unable to resolve symbol %s: %s", DSA_SYM_NAME, + dlerror()); + goto out; + } + debug2("Invoking %s from %s", DSA_SYM_NAME, + options.pubkey_plugin); + success = (*dsa_sym)(pw, key->dsa, fp); + break; + default: + debug2("user_key_plugins only support RSA keys"); + } + + debug("sshd_plugin returned: %d", success); + +out: + if (handle != NULL) { + dlclose(handle); + dsa_sym = NULL; + rsa_sym = NULL; + handle = NULL; + } + + if (success) + verbose("Found matching %s key: %s", key_type(key), fp); + + if (fp != NULL) { + xfree(fp); + fp = NULL; + } + + return success; +} + + +/* check whether given key is in .ssh/authorized_keys or a plugin */ int user_key_allowed(struct passwd *pw, Key *key) { @@ -329,6 +429,13 @@ user_key_allowed(struct passwd *pw, Key *key) file = authorized_keys_file2(pw); success = user_key_allowed2(pw, key, file); xfree(file); + + if (success) + return success; + + /* try from a plugin */ + success = user_key_allowed_from_plugin(pw, key); + return success; } diff --git a/usr/src/cmd/ssh/sshd/servconf.c b/usr/src/cmd/ssh/sshd/servconf.c index 516466bbc1..16f1dcecf7 100644 --- a/usr/src/cmd/ssh/sshd/servconf.c +++ b/usr/src/cmd/ssh/sshd/servconf.c @@ -155,6 +155,7 @@ initialize_server_options(ServerOptions *options) options->pre_userauth_hook = NULL; options->pam_service_name = NULL; options->pam_service_prefix = NULL; + options->pubkey_plugin = NULL; } #ifdef HAVE_DEFOPEN @@ -419,13 +420,14 @@ typedef enum { sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, - sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, + sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sBanner, sVerifyReverseMapping, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, sMaxAuthTries, sMaxAuthTriesLog, sUsePrivilegeSeparation, sLookupClientHostnames, sUseOpenSSLEngine, sChrootDirectory, sPreUserauthHook, sMatch, sPAMServicePrefix, sPAMServiceName, + sMaxStartups, sPubKeyPlugin, sDeprecated } ServerOpCodes; @@ -532,6 +534,7 @@ static struct { { "match", sMatch, SSHCFG_ALL }, { "pamserviceprefix", sPAMServicePrefix, SSHCFG_GLOBAL }, { "pamservicename", sPAMServiceName, SSHCFG_GLOBAL }, + { "pubkeyplugin", sPubKeyPlugin, SSHCFG_ALL }, { NULL, sBadOption, 0 } }; @@ -1356,6 +1359,10 @@ parse_flag: options->pam_service_name = xstrdup(arg); break; + case sPubKeyPlugin: + charptr = &options->pubkey_plugin; + goto parse_filename; + default: fatal("%s line %d: Missing handler for opcode %s (%d)", filename, linenum, arg, opcode); diff --git a/usr/src/cmd/ssh/sshd/sshlogin.c b/usr/src/cmd/ssh/sshd/sshlogin.c index c21877355c..c2bd3bacb7 100644 --- a/usr/src/cmd/ssh/sshd/sshlogin.c +++ b/usr/src/cmd/ssh/sshd/sshlogin.c @@ -101,8 +101,7 @@ record_login(pid_t pid, const char *ttyname, const char *progname, fatal_cleanup(); } } - remote_name_or_ip = get_remote_name_or_ip(utmp_len, - options.verify_reverse_mapping); + remote_name_or_ip = get_remote_ipaddr(); initialized = 1; } |