Bugzilla – Attachment 2562 Details for
Bug 1927
authorized_credentials (aka authorized_keys for GSSAPI-MIC)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch against GIT implementing the above.
openssh-authorized_credentials_2.patch (text/plain), 13.55 KB, created by
Matthew N. Dodd
on 2015-03-06 06:16:37 AEDT
(
hide
)
Description:
Patch against GIT implementing the above.
Filename:
MIME Type:
Creator:
Matthew N. Dodd
Created:
2015-03-06 06:16:37 AEDT
Size:
13.55 KB
patch
obsolete
>diff --git a/auth.c b/auth.c >index f9b7673..ba40a2b 100644 >--- a/auth.c >+++ b/auth.c >@@ -406,6 +406,12 @@ authorized_principals_file(struct passwd *pw) > return expand_authorized_keys(options.authorized_principals_file, pw); > } > >+char * >+authorized_credentials_file(struct passwd *pw) >+{ >+ return expand_authorized_keys(options.authorized_credentials_file, pw); >+} >+ > /* return ok if key exists in sysfile or userfile */ > HostStatus > check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, >@@ -600,6 +606,13 @@ auth_openprincipals(const char *file, struct passwd *pw, int strict_modes) > "authorized principals"); > } > >+FILE * >+auth_opencredentialfile(const char *file, struct passwd *pw, int strict_modes) >+{ >+ return auth_openfile(file, pw, strict_modes, 0, >+ "authorized credentials"); >+} >+ > struct passwd * > getpwnamallow(const char *user) > { >diff --git a/auth.h b/auth.h >index db86037..42fb405 100644 >--- a/auth.h >+++ b/auth.h >@@ -192,9 +192,11 @@ void abandon_challenge_response(Authctxt *); > > char *expand_authorized_keys(const char *, struct passwd *pw); > char *authorized_principals_file(struct passwd *); >+char *authorized_credentials_file(struct passwd *); > > FILE *auth_openkeyfile(const char *, struct passwd *, int); > FILE *auth_openprincipals(const char *, struct passwd *, int); >+FILE *auth_opencredentialfile(const char *, struct passwd *, int); > int auth_key_is_revoked(Key *); > > HostStatus >diff --git a/auth2-gss.c b/auth2-gss.c >index 1ca8357..21459d0 100644 >--- a/auth2-gss.c >+++ b/auth2-gss.c >@@ -43,6 +43,7 @@ > #include "misc.h" > #include "servconf.h" > #include "packet.h" >+#include "auth-options.h" > #include "ssh-gss.h" > #include "monitor_wrap.h" > >@@ -238,7 +239,9 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) > > packet_check_eom(); > >- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); >+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt)); >+ if (authenticated != 1) >+ auth_clear_options(); > > authctxt->postponed = 0; > dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); >@@ -273,9 +276,11 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) > gssbuf.value = buffer_ptr(&b); > gssbuf.length = buffer_len(&b); > >- if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) >- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); >- else >+ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) { >+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt)); >+ if (authenticated != 1) >+ auth_clear_options(); >+ } else > logit("GSSAPI MIC check failed"); > > buffer_free(&b); >diff --git a/gss-serv.c b/gss-serv.c >index e7b8c52..b6a27f0 100644 >--- a/gss-serv.c >+++ b/gss-serv.c >@@ -33,13 +33,20 @@ > #include <stdarg.h> > #include <string.h> > #include <unistd.h> >+#include <krb5.h> > > #include "openbsd-compat/sys-queue.h" > #include "xmalloc.h" >+#include "ssh.h" > #include "buffer.h" >+#include "log.h" >+#include "misc.h" >+#include "servconf.h" > #include "key.h" > #include "hostfile.h" > #include "auth.h" >+#include "uidswap.h" >+#include "auth-options.h" > #include "log.h" > #include "channels.h" > #include "session.h" >@@ -47,6 +54,8 @@ > > #include "ssh-gss.h" > >+extern ServerOptions options; >+ > static ssh_gssapi_client gssapi_client = > { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, > GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; >@@ -345,10 +354,191 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep) > } > } > >+static int >+credential_read(krb5_context context, krb5_principal *princ, char **cpp) >+{ >+ char *cp; >+ char *name; >+ size_t len; >+ krb5_error_code retval; >+ cp = *cpp; >+ >+ len = strcspn(cp, " \t\n#"); >+ if (len == 0) >+ return 0; >+ name = strndup(cp, len); >+ if (name == NULL) >+ return 0; >+ logit("%s(): cred \"%s\"", __func__, name); >+ retval = krb5_parse_name_flags(context, name, >+ KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, princ); >+ if (retval) { >+ debug("krb5_parse_name(\"%s\"): %.100s", >+ name, krb5_get_err_text(context, retval)); >+ free(name); >+ return 0; >+ } >+ *cpp += len; >+ >+ free(name); >+ return 1; >+} >+ >+static int >+user_credential_allowed(Authctxt *authctxt, char *cred) >+{ >+ char _line[SSH_MAX_PUBKEY_BYTES]; >+ krb5_context context = NULL; >+ krb5_principal sprinc = NULL, aprinc = NULL; >+ krb5_error_code retval; >+ char *file; >+ FILE *f; >+ struct passwd *pw = authctxt->pw; >+ int found_credential = 0; >+ u_long linenum = 0; >+ char *line = NULL; >+ const char *sp_name = NULL, *sp_inst = NULL, *sp_realm = NULL; >+ >+ /* Temporarily use the user's uid. */ >+ temporarily_use_uid(pw); >+ >+ retval = krb5_init_context(&context); >+ if (retval) { >+ logit("%s: krb5_init_context(): %.100s", __func__, >+ krb5_get_err_text(context, retval)); >+ restore_uid(); >+ return 0; >+ } >+ >+ /* Session Principal */ >+ retval = krb5_parse_name_flags(context, cred, >+ KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &sprinc); >+ if (retval) { >+ logit("%s: krb5_parse_name(\"%s\"): %.100s", __func__, >+ cred, krb5_get_err_text(context, retval)); >+ krb5_free_context(context); >+ restore_uid(); >+ return 0; >+ } >+ >+#ifdef HAVE_KRB5_PRINCIPAL_GET >+ sp_name = krb5_principal_get_comp_string(context, sprinc, 0); >+ sp_inst = krb5_principal_get_comp_string(context, sprinc, 1); >+ sp_realm = krb5_principal_get_realm(context, sprinc); >+#else >+ krb5_data *tmp; >+ >+ tmp = krb5_princ_component(context, sprinc, 0); >+ if (tmp) >+ sp_name = tmp->data; >+ tmp = krb5_princ_component(context, sprinc, 0); >+ if (tmp) >+ sp_inst = tmp->data; >+ tmp = krb5_princ_realm(context, sprinc); >+ if (tmp) >+ sp_realm = tmp->data; >+#endif >+ >+ logit("%s: %s/%s@%s", __func__, sp_name, sp_inst, sp_realm); >+ >+ file = authorized_credentials_file(pw); >+ debug("trying allowed credentials file %s", file); >+ >+ f = auth_opencredentialfile(file, pw, options.strict_modes); >+ if (!f) { >+ krb5_free_principal(context, sprinc); >+ krb5_free_context(context); >+ restore_uid(); >+ return 0; >+ } >+ >+ found_credential = 0; >+ while (read_keyfile_line(f, file, _line, sizeof(_line), &linenum) != -1) { >+ char *cp, *cred_options = NULL; >+ int quoted = 0; >+ int len = 0; >+ >+ if (line) >+ free(line); >+ line = percent_expand(_line, >+ "c", cred, >+ "h", pw->pw_dir, >+ "u", pw->pw_name, >+ "n", sp_name ? sp_name : "NONAME", >+ "i", sp_inst ? sp_inst : "NOINST", >+ "r", sp_realm ? sp_realm : "NOREALM", >+ (char *)NULL); >+ >+ debug("original line: %s", _line); >+ debug("expanded line: %s", line); >+ >+ auth_clear_options(); >+ >+ /* Skip leading whitespace, empty and comment lines. */ >+ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) >+ ; >+ if (!*cp || *cp == '\n' || *cp == '#') >+ continue; >+ >+ cred_options = cp; >+ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { >+ if (*cp == '\\' && cp[1] == '"') >+ cp++; /* Skip both */ >+ else if (*cp == '"') >+ quoted = !quoted; >+ } >+ >+ if (*cp == '\n' || *cp == '\0') { /* No options, rewind */ >+ cp = cred_options; >+ cred_options = NULL; >+ } else { >+ len = cp - cred_options; >+ /* Skip remaining whitespace. */ >+ for (; *cp == ' ' || *cp == '\t'; cp++) >+ ; >+ } >+ debug("%lu: cred: \"%s\"", linenum, cp); >+ if (cred_options) >+ debug("%lu: options: \"%.*s\"", >+ linenum, len, cred_options); >+ >+ >+ if (credential_read(context, &aprinc, &cp) != 1) { >+ debug2("%s: advance: '%s'", __func__, cp); >+ continue; >+ } >+ debug("%lu: options \"%.*s\"", linenum, len, cred_options); >+ >+ if (auth_parse_options(pw, cred_options, file, linenum) != 1) >+ continue; >+ >+ if (krb5_principal_compare(context, sprinc, aprinc)) { >+ found_credential = 1; >+ debug("matching credential found: file %s, line %lu", >+ file, linenum); >+ break; >+ } >+ } >+ if (sprinc) >+ krb5_free_principal(context, sprinc); >+ if (aprinc) >+ krb5_free_principal(context, aprinc); >+ if (context) >+ krb5_free_context(context); >+ restore_uid(); >+ fclose(f); >+ if (line) >+ free(line); >+ if (!found_credential) >+ debug2("credential not found"); >+ return found_credential; >+} >+ > /* Privileged */ > int >-ssh_gssapi_userok(char *user) >+ssh_gssapi_userok(Authctxt *authctxt) > { >+ char *user = authctxt->user; > OM_uint32 lmin; > > if (gssapi_client.exportedname.length == 0 || >@@ -357,7 +547,9 @@ ssh_gssapi_userok(char *user) > return 0; > } > if (gssapi_client.mech && gssapi_client.mech->userok) >- if ((*gssapi_client.mech->userok)(&gssapi_client, user)) >+ if (user_credential_allowed(authctxt, >+ (char *)gssapi_client.displayname.value) || >+ (*gssapi_client.mech->userok)(&gssapi_client, user)) > return 1; > else { > /* Destroy delegated credentials if userok fails */ >diff --git a/monitor.c b/monitor.c >index bab6ce8..0dd9c17 100644 >--- a/monitor.c >+++ b/monitor.c >@@ -2040,7 +2040,7 @@ mm_answer_gss_userok(int sock, Buffer *m) > { > int authenticated; > >- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); >+ authenticated = authctxt->valid && ssh_gssapi_userok(authctxt); > > buffer_clear(m); > buffer_put_int(m, authenticated); >diff --git a/monitor_wrap.c b/monitor_wrap.c >index b379f05..16383ad 100644 >--- a/monitor_wrap.c >+++ b/monitor_wrap.c >@@ -1068,7 +1068,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) > } > > int >-mm_ssh_gssapi_userok(char *user) >+mm_ssh_gssapi_userok(Authctxt *authctxt) > { > Buffer m; > int authenticated = 0; >diff --git a/monitor_wrap.h b/monitor_wrap.h >index e18784a..e5c47b3 100644 >--- a/monitor_wrap.h >+++ b/monitor_wrap.h >@@ -58,7 +58,7 @@ BIGNUM *mm_auth_rsa_generate_challenge(Key *); > OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); > OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, > gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); >-int mm_ssh_gssapi_userok(char *user); >+int mm_ssh_gssapi_userok(struct Authctxt *); > OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); > #endif > >diff --git a/pathnames.h b/pathnames.h >index ec89fc6..7ddfa83 100644 >--- a/pathnames.h >+++ b/pathnames.h >@@ -102,6 +102,12 @@ > #define _PATH_SSH_USER_PERMITTED_KEYS2 _PATH_SSH_USER_DIR "/authorized_keys2" > > /* >+ * As above but containing a one per line list of credentials with >+ * options. >+ */ >+#define _PATH_SSH_USER_PERMITTED_CREDENTIALS ".ssh/authorized_credentials" >+ >+/* > * Per-user and system-wide ssh "rc" files. These files are executed with > * /bin/sh before starting the shell or command if they exist. They will be > * passed "proto cookie" as arguments if X11 forwarding with spoofing is in >diff --git a/servconf.c b/servconf.c >index 3185462..be71107 100644 >--- a/servconf.c >+++ b/servconf.c >@@ -159,6 +159,7 @@ initialize_server_options(ServerOptions *options) > options->revoked_keys_file = NULL; > options->trusted_user_ca_keys = NULL; > options->authorized_principals_file = NULL; >+ options->authorized_credentials_file = NULL; > options->ip_qos_interactive = -1; > options->ip_qos_bulk = -1; > options->version_addendum = NULL; >@@ -321,6 +322,9 @@ fill_default_server_options(ServerOptions *options) > } > if (options->permit_tun == -1) > options->permit_tun = SSH_TUNMODE_NO; >+ if (options->authorized_credentials_file == NULL) >+ options->authorized_credentials_file = >+ xstrdup(_PATH_SSH_USER_PERMITTED_CREDENTIALS); > if (options->ip_qos_interactive == -1) > options->ip_qos_interactive = IPTOS_LOWDELAY; > if (options->ip_qos_bulk == -1) >@@ -396,6 +400,7 @@ typedef enum { > sUsePrivilegeSeparation, sAllowAgentForwarding, > sHostCertificate, > sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, >+ sAuthorizedCredentialsFile, > sKexAlgorithms, sIPQoS, sVersionAddendum, > sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, > sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, >@@ -524,6 +529,7 @@ static struct { > { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, > { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, > { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, >+ { "authorizedcredentialsfile", sAuthorizedCredentialsFile, SSHCFG_ALL }, > { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, > { "ipqos", sIPQoS, SSHCFG_ALL }, > { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, >@@ -1508,7 +1514,11 @@ process_server_config_line(ServerOptions *options, char *line, > return 0; > > case sAuthorizedPrincipalsFile: >- charptr = &options->authorized_principals_file; >+ case sAuthorizedCredentialsFile: >+ charptr = (opcode == sAuthorizedPrincipalsFile) ? >+ &options->authorized_principals_file : >+ &options->authorized_credentials_file; >+ > arg = strdelim(&cp); > if (!arg || *arg == '\0') > fatal("%s line %d: missing file name.", >@@ -2163,6 +2173,9 @@ dump_config(ServerOptions *o) > dump_cfg_string(sRevokedKeys, o->revoked_keys_file); > dump_cfg_string(sAuthorizedPrincipalsFile, > o->authorized_principals_file); >+ dump_cfg_string(sAuthorizedCredentialsFile, >+ o->authorized_credentials_file); >+ > dump_cfg_string(sVersionAddendum, o->version_addendum); > dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); > dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); >diff --git a/servconf.h b/servconf.h >index 9922f0c..91c336b 100644 >--- a/servconf.h >+++ b/servconf.h >@@ -177,6 +177,7 @@ typedef struct { > char *revoked_keys_file; > char *trusted_user_ca_keys; > char *authorized_principals_file; >+ char *authorized_credentials_file; > char *authorized_keys_command; > char *authorized_keys_command_user; > >diff --git a/ssh-gss.h b/ssh-gss.h >index a99d7f0..31280aa 100644 >--- a/ssh-gss.h >+++ b/ssh-gss.h >@@ -123,7 +123,8 @@ int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); > > /* In the server */ > OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); >-int ssh_gssapi_userok(char *name); >+struct Authctxt; >+int ssh_gssapi_userok(struct Authctxt *); > OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); > void ssh_gssapi_do_child(char ***, u_int *); > void ssh_gssapi_cleanup_creds(void);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1927
:
2076
| 2562