diff options
Diffstat (limited to 'auth2-pubkey.c')
-rw-r--r-- | auth2-pubkey.c | 102 |
1 files changed, 94 insertions, 8 deletions
diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 83ecd659..6b4a9972 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; |