From 4e270b05dd9d850fb9e2e0ac43f33cb4090d3ebc Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 16 Apr 2010 15:56:21 +1000 Subject: - djm@cvs.openbsd.org 2010/04/16 01:47:26 [PROTOCOL.certkeys auth-options.c auth-options.h auth-rsa.c] [auth2-pubkey.c authfd.c key.c key.h myproposal.h ssh-add.c] [ssh-agent.c ssh-dss.c ssh-keygen.1 ssh-keygen.c ssh-rsa.c] [sshconnect.c sshconnect2.c sshd.c] revised certificate format ssh-{dss,rsa}-cert-v01@openssh.com with the following changes: move the nonce field to the beginning of the certificate where it can better protect against chosen-prefix attacks on the signature hash Rename "constraints" field to "critical options" Add a new non-critical "extensions" field Add a serial number The older format is still support for authentication and cert generation (use "ssh-keygen -t v00 -s ca_key ..." to generate a v00 certificate) ok markus@ --- auth2-pubkey.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/auth2-pubkey.c b/auth2-pubkey.c index c4cadf4e7..83ecd6590 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.22 2010/03/10 23:27:17 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.23 2010/04/16 01:47:26 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -235,7 +235,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) } if (auth_parse_options(pw, key_options, file, linenum) != 1) continue; - if (key->type == KEY_RSA_CERT || key->type == KEY_DSA_CERT) { + if (key_is_cert(key)) { if (!key_is_cert_authority) continue; if (!key_equal(found, key->cert->signature_key)) @@ -251,8 +251,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) auth_debug_add("%s", reason); continue; } - if (auth_cert_constraints(&key->cert->constraints, - pw) != 0) { + if (auth_cert_options(key, pw) != 0) { xfree(fp); continue; } @@ -307,7 +306,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) auth_debug_add("%s", reason); goto out; } - if (auth_cert_constraints(&key->cert->constraints, pw) != 0) + if (auth_cert_options(key, pw) != 0) goto out; verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s", -- cgit v1.2.3 From 30da3447d2ef3329cb0eb083cdddf84532659454 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 10 May 2010 11:58:03 +1000 Subject: - djm@cvs.openbsd.org 2010/05/07 11:30:30 [auth-options.c auth-options.h auth.c auth.h auth2-pubkey.c] [key.c servconf.c servconf.h sshd.8 sshd_config.5] add some optional indirection to matching of principal names listed in certificates. Currently, a certificate must include the a user's name to be accepted for authentication. This change adds the ability to specify a list of certificate principal names that are acceptable. When authenticating using a CA trusted through ~/.ssh/authorized_keys, this adds a new principals="name1[,name2,...]" key option. For CAs listed through sshd_config's TrustedCAKeys option, a new config option "AuthorizedPrincipalsFile" specifies a per-user file containing the list of acceptable names. If either option is absent, the current behaviour of requiring the username to appear in principals continues to apply. These options are useful for role accounts, disjoint account namespaces and "user@realm"-style naming policies in certificates. feedback and ok markus@ --- ChangeLog | 22 +++++++++++++ auth-options.c | 43 +++++++++++++++++++++++- auth-options.h | 3 +- auth.c | 41 ++++++++++++++++------- auth.h | 4 ++- auth2-pubkey.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- key.c | 4 +-- servconf.c | 18 +++++++--- servconf.h | 3 +- sshd.8 | 15 +++++++-- sshd_config.5 | 41 +++++++++++++++++++++-- 11 files changed, 262 insertions(+), 34 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/ChangeLog b/ChangeLog index 684609459..090e2352c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,6 +31,28 @@ [sftp.c] restore mput and mget which got lost in the tab-completion changes. found by Kenneth Whitaker, ok djm@ + - djm@cvs.openbsd.org 2010/05/07 11:30:30 + [auth-options.c auth-options.h auth.c auth.h auth2-pubkey.c] + [key.c servconf.c servconf.h sshd.8 sshd_config.5] + add some optional indirection to matching of principal names listed + in certificates. Currently, a certificate must include the a user's name + to be accepted for authentication. This change adds the ability to + specify a list of certificate principal names that are acceptable. + + When authenticating using a CA trusted through ~/.ssh/authorized_keys, + this adds a new principals="name1[,name2,...]" key option. + + For CAs listed through sshd_config's TrustedCAKeys option, a new config + option "AuthorizedPrincipalsFile" specifies a per-user file containing + the list of acceptable names. + + If either option is absent, the current behaviour of requiring the + username to appear in principals continues to apply. + + These options are useful for role accounts, disjoint account namespaces + and "user@realm"-style naming policies in certificates. + + feedback and ok markus@ 20100423 - (dtucker) [configure.ac] Bug #1756: Check for the existence of a lib64 dir diff --git a/auth-options.c b/auth-options.c index 60d5f749b..57a67ec79 100644 --- a/auth-options.c +++ b/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.50 2010/04/16 01:47:26 djm Exp $ */ +/* $OpenBSD: auth-options.c,v 1.51 2010/05/07 11:30:29 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -55,6 +55,9 @@ struct envstring *custom_environment = NULL; /* "tunnel=" option. */ int forced_tun_device = -1; +/* "principals=" option. */ +char *authorized_principals = NULL; + extern ServerOptions options; void @@ -76,6 +79,10 @@ auth_clear_options(void) xfree(forced_command); forced_command = NULL; } + if (authorized_principals) { + xfree(authorized_principals); + authorized_principals = NULL; + } forced_tun_device = -1; channel_clear_permitted_opens(); } @@ -141,6 +148,8 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) cp = "command=\""; if (strncasecmp(opts, cp, strlen(cp)) == 0) { opts += strlen(cp); + if (forced_command != NULL) + xfree(forced_command); forced_command = xmalloc(strlen(opts) + 1); i = 0; while (*opts) { @@ -167,6 +176,38 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) opts++; goto next_option; } + cp = "principals=\""; + if (strncasecmp(opts, cp, strlen(cp)) == 0) { + opts += strlen(cp); + if (authorized_principals != NULL) + xfree(authorized_principals); + authorized_principals = xmalloc(strlen(opts) + 1); + i = 0; + while (*opts) { + if (*opts == '"') + break; + if (*opts == '\\' && opts[1] == '"') { + opts += 2; + authorized_principals[i++] = '"'; + continue; + } + authorized_principals[i++] = *opts++; + } + if (!*opts) { + debug("%.100s, line %lu: missing end quote", + file, linenum); + auth_debug_add("%.100s, line %lu: missing end quote", + file, linenum); + xfree(authorized_principals); + authorized_principals = NULL; + goto bad_option; + } + authorized_principals[i] = '\0'; + auth_debug_add("principals: %.900s", + authorized_principals); + opts++; + goto next_option; + } cp = "environment=\""; if (options.permit_user_env && strncasecmp(opts, cp, strlen(cp)) == 0) { diff --git a/auth-options.h b/auth-options.h index 20f0dbe3e..7455c9454 100644 --- a/auth-options.h +++ b/auth-options.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.h,v 1.19 2010/04/16 01:47:26 djm Exp $ */ +/* $OpenBSD: auth-options.h,v 1.20 2010/05/07 11:30:29 djm Exp $ */ /* * Author: Tatu Ylonen @@ -31,6 +31,7 @@ extern char *forced_command; extern struct envstring *custom_environment; extern int forced_tun_device; extern int key_is_cert_authority; +extern char *authorized_principals; int auth_parse_options(struct passwd *, char *, char *, u_long); void auth_clear_options(void); diff --git a/auth.c b/auth.c index 89a936068..bec191a59 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.86 2010/03/05 02:58:11 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.87 2010/05/07 11:30:29 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -366,6 +366,14 @@ authorized_keys_file2(struct passwd *pw) return expand_authorized_keys(options.authorized_keys_file2, pw); } +char * +authorized_principals_file(struct passwd *pw) +{ + if (options.authorized_principals_file == NULL) + return NULL; + return expand_authorized_keys(options.authorized_principals_file, pw); +} + /* return ok if key exists in sysfile or userfile */ HostStatus check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, @@ -477,21 +485,18 @@ secure_filename(FILE *f, const char *file, struct passwd *pw, return 0; } -FILE * -auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes) +static FILE * +auth_openfile(const char *file, struct passwd *pw, int strict_modes, + int log_missing, char *file_type) { char line[1024]; struct stat st; int fd; FILE *f; - /* - * Open the file containing the authorized keys - * Fail quietly if file does not exist - */ if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) { - if (errno != ENOENT) - debug("Could not open keyfile '%s': %s", file, + if (log_missing || errno != ENOENT) + debug("Could not open %s '%s': %s", file_type, file, strerror(errno)); return NULL; } @@ -501,8 +506,8 @@ auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes) return NULL; } if (!S_ISREG(st.st_mode)) { - logit("User %s authorized keys %s is not a regular file", - pw->pw_name, file); + logit("User %s %s %s is not a regular file", + pw->pw_name, file_type, file); close(fd); return NULL; } @@ -521,6 +526,20 @@ auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes) return f; } + +FILE * +auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes) +{ + return auth_openfile(file, pw, strict_modes, 1, "authorized keys"); +} + +FILE * +auth_openprincipals(const char *file, struct passwd *pw, int strict_modes) +{ + return auth_openfile(file, pw, strict_modes, 0, + "authorized principals"); +} + struct passwd * getpwnamallow(const char *user) { diff --git a/auth.h b/auth.h index a65b87dd1..77317aee6 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.65 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.66 2010/05/07 11:30:29 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -169,8 +169,10 @@ void abandon_challenge_response(Authctxt *); char *authorized_keys_file(struct passwd *); char *authorized_keys_file2(struct passwd *); +char *authorized_principals_file(struct passwd *); FILE *auth_openkeyfile(const char *, struct passwd *, int); +FILE *auth_openprincipals(const char *, struct passwd *, int); int auth_key_is_revoked(Key *); HostStatus diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 83ecd6590..6b4a99725 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.23 2010/04/16 01:47:26 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.24 2010/05/07 11:30:29 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -57,6 +57,7 @@ #include "monitor_wrap.h" #include "misc.h" #include "authfile.h" +#include "match.h" /* import */ extern ServerOptions options; @@ -176,6 +177,63 @@ done: return authenticated; } +static int +match_principals_option(const char *principal_list, struct KeyCert *cert) +{ + char *result; + u_int i; + + /* XXX percent_expand() sequences for authorized_principals? */ + + for (i = 0; i < cert->nprincipals; i++) { + if ((result = match_list(cert->principals[i], + principal_list, NULL)) != NULL) { + debug3("matched principal from key options \"%.100s\"", + result); + xfree(result); + return 1; + } + } + return 0; +} + +static int +match_principals_file(const char *file, struct passwd *pw, struct KeyCert *cert) +{ + FILE *f; + char line[SSH_MAX_PUBKEY_BYTES], *cp; + u_long linenum = 0; + u_int i; + + temporarily_use_uid(pw); + debug("trying authorized principals file %s", file); + if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) { + restore_uid(); + return 0; + } + while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { + /* Skip leading whitespace, empty and comment lines. */ + for (cp = line; *cp == ' ' || *cp == '\t'; cp++) + ; + if (!*cp || *cp == '\n' || *cp == '#') + continue; + line[strcspn(line, "\n")] = '\0'; + + for (i = 0; i < cert->nprincipals; i++) { + if (strcmp(cp, cert->principals[i]) == 0) { + debug3("matched principal from file \"%.100s\"", + cert->principals[i]); + fclose(f); + restore_uid(); + return 1; + } + } + } + fclose(f); + restore_uid(); + return 0; +} + /* return 1 if user allows given key */ static int user_key_allowed2(struct passwd *pw, Key *key, char *file) @@ -244,13 +302,26 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) SSH_FP_HEX); debug("matching CA found: file %s, line %lu, %s %s", file, linenum, key_type(found), fp); - if (key_cert_check_authority(key, 0, 0, pw->pw_name, - &reason) != 0) { + /* + * If the user has specified a list of principals as + * a key option, then prefer that list to matching + * their username in the certificate principals list. + */ + if (authorized_principals != NULL && + !match_principals_option(authorized_principals, + key->cert)) { + reason = "Certificate does not contain an " + "authorized principal"; + fail_reason: xfree(fp); error("%s", reason); auth_debug_add("%s", reason); continue; } + if (key_cert_check_authority(key, 0, 0, + authorized_principals == NULL ? pw->pw_name : NULL, + &reason) != 0) + goto fail_reason; if (auth_cert_options(key, pw) != 0) { xfree(fp); continue; @@ -284,7 +355,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) static int user_cert_trusted_ca(struct passwd *pw, Key *key) { - char *ca_fp; + char *ca_fp, *principals_file = NULL; const char *reason; int ret = 0; @@ -301,11 +372,24 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) options.trusted_user_ca_keys); goto out; } - if (key_cert_check_authority(key, 0, 1, pw->pw_name, &reason) != 0) { - error("%s", reason); - auth_debug_add("%s", reason); - goto out; + /* + * If AuthorizedPrincipals is in use, then compare the certificate + * principals against the names in that file rather than matching + * against the username. + */ + if ((principals_file = authorized_principals_file(pw)) != NULL) { + if (!match_principals_file(principals_file, pw, key->cert)) { + reason = "Certificate does not contain an " + "authorized principal"; + fail_reason: + error("%s", reason); + auth_debug_add("%s", reason); + goto out; + } } + if (key_cert_check_authority(key, 0, 1, + principals_file == NULL ? pw->pw_name : NULL, &reason) != 0) + goto fail_reason; if (auth_cert_options(key, pw) != 0) goto out; @@ -315,6 +399,8 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) ret = 1; out: + if (principals_file != NULL) + xfree(principals_file); if (ca_fp != NULL) xfree(ca_fp); return ret; diff --git a/key.c b/key.c index 34f678b38..c4d9d5771 100644 --- a/key.c +++ b/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.87 2010/04/16 01:47:26 djm Exp $ */ +/* $OpenBSD: key.c,v 1.88 2010/05/07 11:30:29 djm Exp $ */ /* * read_bignum(): * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1623,7 +1623,7 @@ key_cert_check_authority(const Key *k, int want_host, int require_principal, *reason = "Certificate lacks principal list"; return -1; } - } else { + } else if (name != NULL) { principal_matches = 0; for (i = 0; i < k->cert->nprincipals; i++) { if (strcmp(name, k->cert->principals[i]) == 0) { diff --git a/servconf.c b/servconf.c index 7d027ddb9..c556986e3 100644 --- a/servconf.c +++ b/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.207 2010/03/25 23:38:28 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.208 2010/05/07 11:30:29 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -131,6 +131,7 @@ initialize_server_options(ServerOptions *options) options->zero_knowledge_password_authentication = -1; options->revoked_keys_file = NULL; options->trusted_user_ca_keys = NULL; + options->authorized_principals_file = NULL; } void @@ -310,7 +311,7 @@ typedef enum { sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, sZeroKnowledgePasswordAuthentication, sHostCertificate, - sRevokedKeys, sTrustedUserCAKeys, + sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, sDeprecated, sUnsupported } ServerOpCodes; @@ -432,6 +433,7 @@ static struct { { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, + { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_GLOBAL }, { NULL, sBadOption, 0 } }; @@ -1218,10 +1220,14 @@ process_server_config_line(ServerOptions *options, char *line, * AuthorizedKeysFile /etc/ssh_keys/%u */ case sAuthorizedKeysFile: + charptr = &options->authorized_keys_file; + goto parse_tilde_filename; case sAuthorizedKeysFile2: - charptr = (opcode == sAuthorizedKeysFile) ? - &options->authorized_keys_file : - &options->authorized_keys_file2; + charptr = &options->authorized_keys_file2; + goto parse_tilde_filename; + case sAuthorizedPrincipalsFile: + charptr = &options->authorized_principals_file; + parse_tilde_filename: arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", @@ -1682,6 +1688,8 @@ dump_config(ServerOptions *o) dump_cfg_string(sChrootDirectory, o->chroot_directory); dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); dump_cfg_string(sRevokedKeys, o->revoked_keys_file); + dump_cfg_string(sAuthorizedPrincipalsFile, + o->authorized_principals_file); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); diff --git a/servconf.h b/servconf.h index 860009f9c..45d2a2ae3 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.92 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.93 2010/05/07 11:30:30 djm Exp $ */ /* * Author: Tatu Ylonen @@ -156,6 +156,7 @@ typedef struct { char *chroot_directory; char *revoked_keys_file; char *trusted_user_ca_keys; + char *authorized_principals_file; } ServerOptions; void initialize_server_options(ServerOptions *); diff --git a/sshd.8 b/sshd.8 index 5f1966005..6eb49238a 100644 --- a/sshd.8 +++ b/sshd.8 @@ -34,8 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.255 2010/03/05 06:50:35 jmc Exp $ -.Dd $Mdocdate: March 5 2010 $ +.\" $OpenBSD: sshd.8,v 1.256 2010/05/07 11:30:30 djm Exp $ +.Dd $Mdocdate: May 7 2010 $ .Dt SSHD 8 .Os .Sh NAME @@ -602,6 +602,17 @@ Multiple options may be applied separated by commas. No pattern matching is performed on the specified hostnames, they must be literal domains or addresses. +.It Cm principals="principals" +On a +.Cm cert-authority +line, specifies allowed principals for certificate authentication as a +comma-separated list. +At least one name from the list must appear in the certificate's +list of principals for the certificate to be accepted. +This option is ignored for keys that are not marked as trusted certificate +signers using the +.Cm cert-authority +option. .It Cm tunnel="n" Force a .Xr tun 4 diff --git a/sshd_config.5 b/sshd_config.5 index 2f5410281..a5260d358 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -34,8 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.120 2010/03/04 23:17:25 djm Exp $ -.Dd $Mdocdate: March 4 2010 $ +.\" $OpenBSD: sshd_config.5,v 1.121 2010/05/07 11:30:30 djm Exp $ +.Dd $Mdocdate: May 7 2010 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -167,6 +167,43 @@ is taken to be an absolute path or one relative to the user's home directory. The default is .Dq .ssh/authorized_keys . +.It Cm AuthorizedPrincipalsFile +Specifies a file that lists principal names that are accepted for +certificate authentication. +When using certificates signed by a key listed in +.Cm TrustedUserCAKeys , +this file lists names, one of which must appear in the certificate for it +to be accepted for authentication. +Names are listed one per line; empty lines and comments starting with +.Ql # +are ignored. +.Pp +.Cm AuthorizedPrincipalsFile +may contain tokens of the form %T which are substituted during connection +setup. +The following tokens are defined: %% is replaced by a literal '%', +%h is replaced by the home directory of the user being authenticated, and +%u is replaced by the username of that user. +After expansion, +.Cm AuthorizedPrincipalsFile +is taken to be an absolute path or one relative to the user's home +directory. +.Pp +The default is not to use a principals file - in this case, the username +of the user must appear in a certificate's principals list for it to be +accepted. +Note that +.Cm AuthorizedPrincipalsFile +is only used when authentication proceeds using a CA listed in +.Cm TrustedUserCAKeys +and is not consulted for certification authorities trusted via +.Pa ~/.ssh/authorized_keys , +though the +.Cm principals= +key option offers a similar facility (see +.Xr sshd 8 +for details). +.Pp .It Cm Banner The contents of the specified file are sent to the remote user before authentication is allowed. -- cgit v1.2.3 From 84399555f0a3c78b96c3e5a56ce9c83eaa814228 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 21 May 2010 14:58:12 +1000 Subject: - djm@cvs.openbsd.org 2010/05/20 11:25:26 [auth2-pubkey.c] fix logspam when key options (from="..." especially) deny non-matching keys; reported by henning@ also bz#1765; ok markus@ dtucker@ --- ChangeLog | 4 ++++ auth2-pubkey.c | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/ChangeLog b/ChangeLog index fffbd727e..2cc1369fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,10 @@ use with LPORT=`ssh -S muxsocket -R0:localhost:25 -O forward somehost` feedback and ok djm@ + - djm@cvs.openbsd.org 2010/05/20 11:25:26 + [auth2-pubkey.c] + fix logspam when key options (from="..." especially) deny non-matching + keys; reported by henning@ also bz#1765; ok markus@ dtucker@ 20100511 - (dtucker) [Makefile.in] Bug #1770: Link libopenbsd-compat twice to solve diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 6b4a99725..faab0e771 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.24 2010/05/07 11:30:29 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.25 2010/05/20 11:25:26 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -291,13 +291,14 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) continue; } } - if (auth_parse_options(pw, key_options, file, linenum) != 1) - continue; if (key_is_cert(key)) { - if (!key_is_cert_authority) - continue; if (!key_equal(found, key->cert->signature_key)) continue; + if (auth_parse_options(pw, key_options, file, + linenum) != 1) + continue; + if (!key_is_cert_authority) + continue; fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); debug("matching CA found: file %s, line %lu, %s %s", @@ -332,7 +333,12 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) xfree(fp); found_key = 1; break; - } else if (!key_is_cert_authority && key_equal(found, key)) { + } else if (key_equal(found, key)) { + if (auth_parse_options(pw, key_options, file, + linenum) != 1) + continue; + if (key_is_cert_authority) + continue; found_key = 1; debug("matching key found: file %s, line %lu", file, linenum); -- cgit v1.2.3 From 6018a36864643ad0e5ff1f7205a7187b961c2c57 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 2 Jul 2010 13:35:19 +1000 Subject: - djm@cvs.openbsd.org 2010/06/29 23:16:46 [auth2-pubkey.c sshd_config.5] allow key options (command="..." and friends) in AuthorizedPrincipals; ok markus@ --- ChangeLog | 4 ++++ auth2-pubkey.c | 34 +++++++++++++++++++++++++++------- sshd_config.5 | 15 ++++++++++++--- 3 files changed, 43 insertions(+), 10 deletions(-) (limited to 'auth2-pubkey.c') diff --git a/ChangeLog b/ChangeLog index ee40f10eb..586b23c13 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,10 @@ [ssh-keygen.1 ssh-keygen.c] allow import (-i) and export (-e) of PEM and PKCS#8 encoded keys; bz#1749; ok markus@ + - djm@cvs.openbsd.org 2010/06/29 23:16:46 + [auth2-pubkey.c sshd_config.5] + allow key options (command="..." and friends) in AuthorizedPrincipals; + ok markus@ 20100627 - (tim) [openbsd-compat/port-uw.c] Reorder includes. auth-options.h now needs diff --git a/auth2-pubkey.c b/auth2-pubkey.c index faab0e771..35cf79c9f 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.25 2010/05/20 11:25:26 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.26 2010/06/29 23:16:46 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -198,10 +198,10 @@ match_principals_option(const char *principal_list, struct KeyCert *cert) } static int -match_principals_file(const char *file, struct passwd *pw, struct KeyCert *cert) +match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert) { FILE *f; - char line[SSH_MAX_PUBKEY_BYTES], *cp; + char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts; u_long linenum = 0; u_int i; @@ -212,17 +212,37 @@ match_principals_file(const char *file, struct passwd *pw, struct KeyCert *cert) return 0; } while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { - /* Skip leading whitespace, empty and comment lines. */ + /* Skip leading whitespace. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; - if (!*cp || *cp == '\n' || *cp == '#') + /* Skip blank and comment lines. */ + if ((ep = strchr(cp, '#')) != NULL) + *ep = '\0'; + if (!*cp || *cp == '\n') continue; - line[strcspn(line, "\n")] = '\0'; - + /* Trim trailing whitespace. */ + ep = cp + strlen(cp) - 1; + while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t')) + *ep-- = '\0'; + /* + * If the line has internal whitespace then assume it has + * key options. + */ + line_opts = NULL; + if ((ep = strrchr(cp, ' ')) != NULL || + (ep = strrchr(cp, '\t')) != NULL) { + for (; *ep == ' ' || *ep == '\t'; ep++) + ;; + line_opts = cp; + cp = ep; + } for (i = 0; i < cert->nprincipals; i++) { if (strcmp(cp, cert->principals[i]) == 0) { debug3("matched principal from file \"%.100s\"", cert->principals[i]); + if (auth_parse_options(pw, line_opts, + file, linenum) != 1) + continue; fclose(f); restore_uid(); return 1; diff --git a/sshd_config.5 b/sshd_config.5 index acaf809db..4d066eb8a 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -34,8 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.123 2010/06/22 04:22:59 djm Exp $ -.Dd $Mdocdate: June 22 2010 $ +.\" $OpenBSD: sshd_config.5,v 1.124 2010/06/29 23:16:46 djm Exp $ +.Dd $Mdocdate: June 29 2010 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -155,6 +155,10 @@ for more information on patterns. .It Cm AuthorizedKeysFile Specifies the file that contains the public keys that can be used for user authentication. +The format is described in the +.Sx AUTHORIZED_KEYS FILE FORMAT +section of +.Xr sshd 8 . .Cm AuthorizedKeysFile may contain tokens of the form %T which are substituted during connection setup. @@ -174,7 +178,12 @@ When using certificates signed by a key listed in .Cm TrustedUserCAKeys , this file lists names, one of which must appear in the certificate for it to be accepted for authentication. -Names are listed one per line; empty lines and comments starting with +Names are listed one per line preceeded by key options (as described +in +.Sx AUTHORIZED_KEYS FILE FORMAT +in +.Xr sshd 8 ). +Empty lines and comments starting with .Ql # are ignored. .Pp -- cgit v1.2.3