Bugzilla – Attachment 2980 Details for
Bug 2408
Expose authentication information to PAM
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
add ExposeAuthInfo option
userauthinfo.diff (text/plain), 29.92 KB, created by
Damien Miller
on 2017-05-17 11:10:12 AEST
(
hide
)
Description:
add ExposeAuthInfo option
Filename:
MIME Type:
Creator:
Damien Miller
Created:
2017-05-17 11:10:12 AEST
Size:
29.92 KB
patch
obsolete
>commit 59ea0c5974ffa8cc321f338f9c650f1ed6e3b14a >Author: Damien Miller <djm@mindrot.org> >Date: Mon May 15 18:36:50 2017 -0700 > > expose userauth info via environment > >diff --git a/auth-pam.c b/auth-pam.c >index 9574d9ac..5dcf9faf 100644 >--- a/auth-pam.c >+++ b/auth-pam.c >@@ -670,6 +670,7 @@ sshpam_init_ctx(Authctxt *authctxt) > { > struct pam_ctxt *ctxt; > int socks[2]; >+ char *auth_info; > > debug3("PAM: %s entering", __func__); > /* >@@ -685,6 +686,12 @@ sshpam_init_ctx(Authctxt *authctxt) > return (NULL); > } > >+ if (authctxt->session_info != NULL && >+ (auth_info = sshbuf_dup_string(authctxt->session_info)) != NULL) { >+ do_pam_putenv("SSH_USER_AUTH", auth_info); >+ free(auth_info); >+ } >+ > ctxt = xcalloc(1, sizeof *ctxt); > > /* Start the authentication thread */ >@@ -1091,12 +1098,8 @@ do_pam_putenv(char *name, char *value) > int ret = 1; > #ifdef HAVE_PAM_PUTENV > char *compound; >- size_t len; >- >- len = strlen(name) + strlen(value) + 2; >- compound = xmalloc(len); > >- snprintf(compound, len, "%s=%s", name, value); >+ xasprintf(&compound, "%s=%s", name, value); > ret = pam_putenv(sshpam_handle, compound); > free(compound); > #endif >diff --git a/auth.c b/auth.c >index 6ee6116d..997f2306 100644 >--- a/auth.c >+++ b/auth.c >@@ -267,21 +267,41 @@ allowed_user(struct passwd * pw) > return 1; > } > >-void >-auth_info(Authctxt *authctxt, const char *fmt, ...) >+/* >+ * Formats any key left in authctxt->auth_method_key for inclusion in >+ * auth_log()'s message. Also includes authxtct->auth_method_info if present. >+ */ >+static char * >+format_method_key(Authctxt *authctxt) > { >- va_list ap; >- int i; >- >- free(authctxt->info); >- authctxt->info = NULL; >+ const struct sshkey *key = authctxt->auth_method_key; >+ const char *methinfo = authctxt->auth_method_info; >+ char *fp, *ret = NULL; > >- va_start(ap, fmt); >- i = vasprintf(&authctxt->info, fmt, ap); >- va_end(ap); >+ if (key == NULL) >+ return NULL; > >- if (i < 0 || authctxt->info == NULL) >- fatal("vasprintf failed"); >+ if (key_is_cert(key)) { >+ fp = sshkey_fingerprint(key->cert->signature_key, >+ options.fingerprint_hash, SSH_FP_DEFAULT); >+ xasprintf(&ret, "%s ID %s (serial %llu) CA %s %s%s%s", >+ sshkey_type(key), key->cert->key_id, >+ (unsigned long long)key->cert->serial, >+ sshkey_type(key->cert->signature_key), >+ fp == NULL ? "(null)" : fp, >+ methinfo == NULL ? "" : ", ", >+ methinfo == NULL ? "" : methinfo); >+ free(fp); >+ } else { >+ fp = sshkey_fingerprint(key, options.fingerprint_hash, >+ SSH_FP_DEFAULT); >+ xasprintf(&ret, "%s %s%s%s", sshkey_type(key), >+ fp == NULL ? "(null)" : fp, >+ methinfo == NULL ? "" : ", ", >+ methinfo == NULL ? "" : methinfo); >+ free(fp); >+ } >+ return ret; > } > > void >@@ -290,7 +310,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, > { > struct ssh *ssh = active_state; /* XXX */ > void (*authlog) (const char *fmt,...) = verbose; >- char *authmsg; >+ const char *authmsg; >+ char *extra = NULL; > > if (use_privsep && !mm_is_monitor() && !authctxt->postponed) > return; >@@ -309,6 +330,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, > else > authmsg = authenticated ? "Accepted" : "Failed"; > >+ if ((extra = format_method_key(authctxt)) == NULL) { >+ if (authctxt->auth_method_info != NULL) >+ extra = xstrdup(authctxt->auth_method_info); >+ } >+ > authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s", > authmsg, > method, >@@ -317,10 +343,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, > authctxt->user, > ssh_remote_ipaddr(ssh), > ssh_remote_port(ssh), >- authctxt->info != NULL ? ": " : "", >- authctxt->info != NULL ? authctxt->info : ""); >- free(authctxt->info); >- authctxt->info = NULL; >+ extra != NULL ? ": " : "", >+ extra != NULL ? extra : ""); > > #ifdef CUSTOM_FAILED_LOGIN > if (authenticated == 0 && !authctxt->postponed && >@@ -340,6 +364,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, > if (authenticated == 0 && !authctxt->postponed) > audit_event(audit_classify_auth(method)); > #endif >+ >+ free(extra); > } > > >diff --git a/auth.h b/auth.h >index 338a62da..3463eb4d 100644 >--- a/auth.h >+++ b/auth.h >@@ -62,13 +62,17 @@ struct Authctxt { > char *service; > struct passwd *pw; /* set if 'valid' */ > char *style; >+ >+ /* Method lists for multiple authentication */ >+ char **auth_methods; /* modified from server config */ >+ u_int num_auth_methods; >+ >+ /* Authentication method-specific data */ >+ void *methoddata; > void *kbdintctxt; >- char *info; /* Extra info for next auth_log */ > #ifdef BSD_AUTH > auth_session_t *as; > #endif >- char **auth_methods; /* modified from server config */ >- u_int num_auth_methods; > #ifdef KRB5 > krb5_context krb5_ctx; > krb5_ccache krb5_fwd_ccache; >@@ -76,11 +80,18 @@ struct Authctxt { > char *krb5_ticket_file; > char *krb5_ccname; > #endif >- Buffer *loginmsg; >- void *methoddata; > >- struct sshkey **prev_userkeys; >- u_int nprev_userkeys; >+ /* Authentication keys already used; these will be refused henceforth */ >+ struct sshkey **prev_keys; >+ u_int nprev_keys; >+ >+ /* Last used key and ancilliary information from active auth method */ >+ struct sshkey *auth_method_key; >+ char *auth_method_info; >+ >+ /* Information exposed to session */ >+ Buffer *loginmsg; /* Messages to be displayed to pty */ >+ struct sshbuf *session_info; /* Auth info for environment */ > }; > /* > * Every authentication method has to handle authentication requests for >@@ -119,10 +130,18 @@ int auth_password(Authctxt *, const char *); > > int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); > int user_key_allowed(struct passwd *, Key *, int); >-void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) >- __attribute__((__format__ (printf, 3, 4))); >-void auth2_record_userkey(Authctxt *, struct sshkey *); >-int auth2_userkey_already_used(Authctxt *, struct sshkey *); >+int auth2_key_already_used(Authctxt *, const struct sshkey *); >+ >+/* >+ * Handling auth method-specific information for logging and prevention >+ * of key reuse during multiple authentication. >+ */ >+void auth2_authctxt_reset_info(Authctxt *); >+void auth2_record_key(Authctxt *, int, const struct sshkey *); >+void auth2_record_info(Authctxt *authctxt, const char *, ...) >+ __attribute__((__format__ (printf, 2, 3))) >+ __attribute__((__nonnull__ (2))); >+void auth2_update_session_info(Authctxt *, const char *, const char *); > > struct stat; > int auth_secure_path(const char *, struct stat *, const char *, uid_t, >@@ -149,9 +168,6 @@ void disable_forwarding(void); > > void do_authentication2(Authctxt *); > >-void auth_info(Authctxt *authctxt, const char *, ...) >- __attribute__((__format__ (printf, 2, 3))) >- __attribute__((__nonnull__ (2))); > void auth_log(Authctxt *, int, int, const char *, const char *); > void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn)); > void userauth_finish(Authctxt *, int, const char *, const char *); >diff --git a/auth2-gss.c b/auth2-gss.c >index 1ca83577..1b6b3e6e 100644 >--- a/auth2-gss.c >+++ b/auth2-gss.c >@@ -227,6 +227,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) > { > Authctxt *authctxt = ctxt; > int authenticated; >+ const char *displayname; > > if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) > fatal("No authentication or GSSAPI context"); >@@ -240,6 +241,10 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) > > authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); > >+ if ((!use_privsep || mm_is_monitor()) && >+ (displayname = ssh_gssapi_displayname()) != NULL) >+ auth2_record_info(authctxt, "%s", displayname); >+ > authctxt->postponed = 0; > dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); > dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); >@@ -258,6 +263,7 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) > Buffer b; > gss_buffer_desc mic, gssbuf; > u_int len; >+ const char *displayname; > > if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) > fatal("No authentication or GSSAPI context"); >@@ -281,6 +287,10 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) > buffer_free(&b); > free(mic.value); > >+ if ((!use_privsep || mm_is_monitor()) && >+ (displayname = ssh_gssapi_displayname()) != NULL) >+ auth2_record_info(authctxt, "%s", displayname); >+ > authctxt->postponed = 0; > dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); > dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); >diff --git a/auth2-hostbased.c b/auth2-hostbased.c >index 1b3c3b20..0b1727b8 100644 >--- a/auth2-hostbased.c >+++ b/auth2-hostbased.c >@@ -132,21 +132,21 @@ userauth_hostbased(Authctxt *authctxt) > buffer_dump(&b); > #endif > >- pubkey_auth_info(authctxt, key, >+ auth2_record_info(authctxt, > "client user \"%.100s\", client host \"%.100s\"", cuser, chost); > > /* test for allowed key and correct signature */ > authenticated = 0; > if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && > PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), >- buffer_len(&b))) == 1) >+ buffer_len(&b))) == 1) > authenticated = 1; > >+ auth2_record_key(authctxt, authenticated, key); > buffer_free(&b); > done: >- debug2("userauth_hostbased: authenticated %d", authenticated); >- if (key != NULL) >- key_free(key); >+ debug2("%s: authenticated %d", __func__, authenticated); >+ sshkey_free(key); > free(pkalg); > free(pkblob); > free(cuser); >diff --git a/auth2-pubkey.c b/auth2-pubkey.c >index 3e5706f4..a510fe3b 100644 >--- a/auth2-pubkey.c >+++ b/auth2-pubkey.c >@@ -127,7 +127,7 @@ userauth_pubkey(Authctxt *authctxt) > goto done; > } > fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); >- if (auth2_userkey_already_used(authctxt, key)) { >+ if (auth2_key_already_used(authctxt, key)) { > logit("refusing previously-used %s key", key_type(key)); > goto done; > } >@@ -171,7 +171,6 @@ userauth_pubkey(Authctxt *authctxt) > #ifdef DEBUG_PK > buffer_dump(&b); > #endif >- pubkey_auth_info(authctxt, key, NULL); > > /* test for correct signature */ > authenticated = 0; >@@ -179,12 +178,10 @@ userauth_pubkey(Authctxt *authctxt) > PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), > buffer_len(&b))) == 1) { > authenticated = 1; >- /* Record the successful key to prevent reuse */ >- auth2_record_userkey(authctxt, key); >- key = NULL; /* Don't free below */ > } > buffer_free(&b); > free(sig); >+ auth2_record_key(authctxt, authenticated, key); > } else { > debug("%s: test whether pkalg/pkblob are acceptable for %s %s", > __func__, sshkey_type(key), fp); >@@ -211,51 +208,13 @@ userauth_pubkey(Authctxt *authctxt) > auth_clear_options(); > done: > debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg); >- if (key != NULL) >- key_free(key); >+ sshkey_free(key); > free(pkalg); > free(pkblob); > free(fp); > return authenticated; > } > >-void >-pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) >-{ >- char *fp, *extra; >- va_list ap; >- int i; >- >- extra = NULL; >- if (fmt != NULL) { >- va_start(ap, fmt); >- i = vasprintf(&extra, fmt, ap); >- va_end(ap); >- if (i < 0 || extra == NULL) >- fatal("%s: vasprintf failed", __func__); >- } >- >- if (key_is_cert(key)) { >- fp = sshkey_fingerprint(key->cert->signature_key, >- options.fingerprint_hash, SSH_FP_DEFAULT); >- auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", >- key_type(key), key->cert->key_id, >- (unsigned long long)key->cert->serial, >- key_type(key->cert->signature_key), >- fp == NULL ? "(null)" : fp, >- extra == NULL ? "" : ", ", extra == NULL ? "" : extra); >- free(fp); >- } else { >- fp = sshkey_fingerprint(key, options.fingerprint_hash, >- SSH_FP_DEFAULT); >- auth_info(authctxt, "%s %s%s%s", key_type(key), >- fp == NULL ? "(null)" : fp, >- extra == NULL ? "" : ", ", extra == NULL ? "" : extra); >- free(fp); >- } >- free(extra); >-} >- > /* > * Splits 's' into an argument vector. Handles quoted string and basic > * escape characters (\\, \", \'). Caller must free the argument vector >@@ -1119,36 +1078,6 @@ user_key_allowed(struct passwd *pw, Key *key, int auth_attempt) > > return success; > } >- >-/* Records a public key in the list of previously-successful keys */ >-void >-auth2_record_userkey(Authctxt *authctxt, struct sshkey *key) >-{ >- struct sshkey **tmp; >- >- if (authctxt->nprev_userkeys >= INT_MAX || >- (tmp = reallocarray(authctxt->prev_userkeys, >- authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL) >- fatal("%s: reallocarray failed", __func__); >- authctxt->prev_userkeys = tmp; >- authctxt->prev_userkeys[authctxt->nprev_userkeys] = key; >- authctxt->nprev_userkeys++; >-} >- >-/* Checks whether a key has already been used successfully for authentication */ >-int >-auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key) >-{ >- u_int i; >- >- for (i = 0; i < authctxt->nprev_userkeys; i++) { >- if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) { >- return 1; >- } >- } >- return 0; >-} >- > Authmethod method_pubkey = { > "publickey", > userauth_pubkey, >diff --git a/auth2.c b/auth2.c >index 97dd2ef0..b6b91fe9 100644 >--- a/auth2.c >+++ b/auth2.c >@@ -50,6 +50,7 @@ > #include "dispatch.h" > #include "pathnames.h" > #include "buffer.h" >+#include "ssherr.h" > > #ifdef GSSAPI > #include "ssh-gss.h" >@@ -275,6 +276,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) > dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); > #endif > >+ auth2_authctxt_reset_info(authctxt); > authctxt->postponed = 0; > authctxt->server_caused_failure = 0; > >@@ -322,6 +324,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, > } > } > >+ /* Update information exposed to session */ >+ if (authenticated || partial) >+ auth2_update_session_info(authctxt, method, submethod); >+ > /* Log before sending the reply */ > auth_log(authctxt, authenticated, partial, method, submethod); > >@@ -622,4 +628,129 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method, > return 0; > } > >+/* Reset method-specific information */ >+void auth2_authctxt_reset_info(Authctxt *authctxt) >+{ >+ sshkey_free(authctxt->auth_method_key); >+ free(authctxt->auth_method_info); >+ authctxt->auth_method_key = NULL; >+ authctxt->auth_method_info = NULL; >+} >+ >+/* Record auth method-specific information for logs */ >+void >+auth2_record_info(Authctxt *authctxt, const char *fmt, ...) >+{ >+ va_list ap; >+ int i; >+ >+ free(authctxt->auth_method_info); >+ authctxt->auth_method_info = NULL; >+ >+ va_start(ap, fmt); >+ i = vasprintf(&authctxt->auth_method_info, fmt, ap); >+ va_end(ap); >+ >+ if (i < 0 || authctxt->auth_method_info == NULL) >+ fatal("%s: vasprintf failed", __func__); >+} >+ >+/* >+ * Records a public key used in authentication. This is used for logging >+ * and to ensure that the same key is not subsequently accepted again for >+ * multiple authentication. >+ */ >+void >+auth2_record_key(Authctxt *authctxt, int authenticated, >+ const struct sshkey *key) >+{ >+ struct sshkey **tmp, *dup; >+ int r; >+ >+ if ((r = sshkey_demote(key, &dup)) != 0) >+ fatal("%s: copy key: %s", __func__, ssh_err(r)); >+ sshkey_free(authctxt->auth_method_key); >+ authctxt->auth_method_key = dup; >+ >+ if (!authenticated) >+ return; >+ >+ /* If authenticated, make sure we don't accept this key again */ >+ if ((r = sshkey_demote(key, &dup)) != 0) >+ fatal("%s: copy key: %s", __func__, ssh_err(r)); >+ if (authctxt->nprev_keys >= INT_MAX || >+ (tmp = reallocarray(authctxt->prev_keys, authctxt->nprev_keys + 1, >+ sizeof(*authctxt->prev_keys))) == NULL) >+ fatal("%s: reallocarray failed", __func__); >+ authctxt->prev_keys = tmp; >+ authctxt->prev_keys[authctxt->nprev_keys] = dup; >+ authctxt->nprev_keys++; >+ >+} >+ >+/* Checks whether a key has already been previously used for authentication */ >+int >+auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key) >+{ >+ u_int i; >+ char *fp; >+ >+ for (i = 0; i < authctxt->nprev_keys; i++) { >+ if (sshkey_equal_public(key, authctxt->prev_keys[i])) { >+ fp = sshkey_fingerprint(authctxt->prev_keys[i], >+ options.fingerprint_hash, SSH_FP_DEFAULT); >+ debug3("%s: key already used: %s %s", __func__, >+ sshkey_type(authctxt->prev_keys[i]), >+ fp == NULL ? "UNKNOWN" : fp); >+ free(fp); >+ return 1; >+ } >+ } >+ return 0; >+} >+ >+/* >+ * Updates authctxt->session_info with details of authentication. Should be >+ * whenever an authentication method succeeds. >+ */ >+void >+auth2_update_session_info(Authctxt *authctxt, const char *method, >+ const char *submethod) >+{ >+ int r; >+ >+ /* Prepare or append to session info buffer */ >+ if (authctxt->session_info == NULL) { >+ if ((authctxt->session_info = sshbuf_new()) == NULL) >+ fatal("%s: sshbuf_new", __func__); >+ } else if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0) >+ fatal("%s: append: %s", __func__, ssh_err(r)); >+ >+ /* Append method[/submethod] */ >+ if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s", >+ method, submethod == NULL ? "" : "/", >+ submethod == NULL ? "" : submethod)) != 0) >+ fatal("%s: append method: %s", __func__, ssh_err(r)); >+ >+ /* Append key if present */ >+ if (authctxt->auth_method_key != NULL) { >+ if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || >+ (r = sshkey_format_text(authctxt->auth_method_key, >+ authctxt->session_info)) != 0) >+ fatal("%s: append key: %s", __func__, ssh_err(r)); >+ } >+ >+ if (authctxt->auth_method_info != NULL) { >+ /* Ensure no ambiguity here */ >+ if (strchr(authctxt->auth_method_info, '\n') != NULL) >+ fatal("%s: auth_method_info contains \\n", __func__); >+ if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || >+ (r = sshbuf_putf(authctxt->session_info, "%s", >+ authctxt->auth_method_info)) != 0) { >+ fatal("%s: append method info: %s", >+ __func__, ssh_err(r)); >+ } >+ } >+ auth2_authctxt_reset_info(authctxt); >+} > >diff --git a/gss-serv.c b/gss-serv.c >index 53993d67..aafcb431 100644 >--- a/gss-serv.c >+++ b/gss-serv.c >@@ -393,4 +393,13 @@ ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) > return (ctx->major); > } > >+/* Privileged */ >+const char *ssh_gssapi_displayname(void) >+{ >+ if (gssapi_client.displayname.length == 0 || >+ gssapi_client.displayname.value == NULL) >+ return NULL; >+ return (char *)gssapi_client.displayname.value; >+} >+ > #endif >diff --git a/monitor.c b/monitor.c >index 96d22b7e..bf65f373 100644 >--- a/monitor.c >+++ b/monitor.c >@@ -308,6 +308,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) > partial = 0; > auth_method = "unknown"; > auth_submethod = NULL; >+ auth2_authctxt_reset_info(authctxt); >+ > authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); > > /* Special handling for multiple required authentications */ >@@ -343,6 +345,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) > #endif > } > if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { >+ if (authenticated || partial) { >+ auth2_update_session_info(authctxt, >+ auth_method, auth_submethod); >+ } > auth_log(authctxt, authenticated, partial, > auth_method, auth_submethod); > if (!partial && !authenticated) >@@ -1147,24 +1153,26 @@ mm_answer_keyallowed(int sock, Buffer *m) > switch (type) { > case MM_USERKEY: > allowed = options.pubkey_authentication && >- !auth2_userkey_already_used(authctxt, key) && >+ !auth2_key_already_used(authctxt, key) && > match_pattern_list(sshkey_ssh_name(key), > options.pubkey_key_types, 0) == 1 && > user_key_allowed(authctxt->pw, key, > pubkey_auth_attempt); >- pubkey_auth_info(authctxt, key, NULL); > auth_method = "publickey"; >+ auth2_record_key(authctxt, 0, key); > if (options.pubkey_authentication && > (!pubkey_auth_attempt || allowed != 1)) > auth_clear_options(); > break; > case MM_HOSTKEY: > allowed = options.hostbased_authentication && >+ !auth2_key_already_used(authctxt, key) && > match_pattern_list(sshkey_ssh_name(key), > options.hostbased_key_types, 0) == 1 && > hostbased_key_allowed(authctxt->pw, > cuser, chost, key); >- pubkey_auth_info(authctxt, key, >+ auth2_record_key(authctxt, 0, key); >+ auth2_record_info(authctxt, > "client user \"%.100s\", client host \"%.100s\"", > cuser, chost); > auth_method = "hostbased"; >@@ -1175,11 +1183,9 @@ mm_answer_keyallowed(int sock, Buffer *m) > } > } > >- debug3("%s: key %p is %s", >- __func__, key, allowed ? "allowed" : "not allowed"); >+ debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed"); > >- if (key != NULL) >- key_free(key); >+ sshkey_free(key); > > /* clear temporarily storage (used by verify) */ > monitor_reset_key_state(); >@@ -1353,10 +1359,12 @@ mm_answer_keyverify(int sock, Buffer *m) > switch (key_blobtype) { > case MM_USERKEY: > valid_data = monitor_valid_userblob(data, datalen); >+ auth_method = "publickey"; > break; > case MM_HOSTKEY: > valid_data = monitor_valid_hostbasedblob(data, datalen, > hostbased_cuser, hostbased_chost); >+ auth_method = "hostbased"; > break; > default: > valid_data = 0; >@@ -1366,23 +1374,17 @@ mm_answer_keyverify(int sock, Buffer *m) > fatal("%s: bad signature data blob", __func__); > > verified = key_verify(key, signature, signaturelen, data, datalen); >- debug3("%s: key %p signature %s", >- __func__, key, (verified == 1) ? "verified" : "unverified"); >- >- /* If auth was successful then record key to ensure it isn't reused */ >- if (verified == 1 && key_blobtype == MM_USERKEY) >- auth2_record_userkey(authctxt, key); >- else >- key_free(key); >+ debug3("%s: %s %p signature %s", __func__, auth_method, key, >+ (verified == 1) ? "verified" : "unverified"); >+ auth2_record_key(authctxt, verified == 1, key); > > free(blob); > free(signature); > free(data); > >- auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; >- > monitor_reset_key_state(); > >+ sshkey_free(key); > buffer_clear(m); > buffer_put_int(m, verified); > mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); >@@ -1774,6 +1776,7 @@ int > mm_answer_gss_userok(int sock, Buffer *m) > { > int authenticated; >+ const char *displayname; > > if (!options.gss_authentication) > fatal("%s: GSSAPI authentication not enabled", __func__); >@@ -1788,6 +1791,9 @@ mm_answer_gss_userok(int sock, Buffer *m) > > auth_method = "gssapi-with-mic"; > >+ if ((displayname = ssh_gssapi_displayname()) != NULL) >+ auth2_record_info(authctxt, "%s", displayname); >+ > /* Monitor loop will terminate if authenticated */ > return (authenticated); > } >diff --git a/servconf.c b/servconf.c >index 73f2c2b1..96fa4f06 100644 >--- a/servconf.c >+++ b/servconf.c >@@ -164,6 +164,7 @@ initialize_server_options(ServerOptions *options) > options->version_addendum = NULL; > options->fingerprint_hash = -1; > options->disable_forwarding = -1; >+ options->expose_userauth_info = -1; > } > > /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ >@@ -333,6 +334,8 @@ fill_default_server_options(ServerOptions *options) > options->fingerprint_hash = SSH_FP_HASH_DEFAULT; > if (options->disable_forwarding == -1) > options->disable_forwarding = 0; >+ if (options->expose_userauth_info == -1) >+ options->expose_userauth_info = 0; > > assemble_algorithms(options); > >@@ -418,6 +421,7 @@ typedef enum { > sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, > sStreamLocalBindMask, sStreamLocalBindUnlink, > sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, >+ sExposeAuthInfo, > sDeprecated, sIgnore, sUnsupported > } ServerOpCodes; > >@@ -561,6 +565,7 @@ static struct { > { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, > { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, > { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, >+ { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, > { NULL, sBadOption, 0 } > }; > >@@ -1835,6 +1840,10 @@ process_server_config_line(ServerOptions *options, char *line, > options->fingerprint_hash = value; > break; > >+ case sExposeAuthInfo: >+ intptr = &options->expose_userauth_info; >+ goto parse_flag; >+ > case sDeprecated: > case sIgnore: > case sUnsupported: >@@ -1973,6 +1982,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) > M_CP_INTOPT(allow_streamlocal_forwarding); > M_CP_INTOPT(allow_agent_forwarding); > M_CP_INTOPT(disable_forwarding); >+ M_CP_INTOPT(expose_userauth_info); > M_CP_INTOPT(permit_tun); > M_CP_INTOPT(fwd_opts.gateway_ports); > M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); >@@ -2271,6 +2281,7 @@ dump_config(ServerOptions *o) > dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); > dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); > dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); >+ dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); > > /* string arguments */ > dump_cfg_string(sPidFile, o->pid_file); >diff --git a/servconf.h b/servconf.h >index 5853a974..f4332ccd 100644 >--- a/servconf.h >+++ b/servconf.h >@@ -189,6 +189,7 @@ typedef struct { > char *auth_methods[MAX_AUTH_METHODS]; > > int fingerprint_hash; >+ int expose_userauth_info; > } ServerOptions; > > /* Information about the incoming connection as used by Match */ >diff --git a/session.c b/session.c >index a08aa69d..ea2bec9b 100644 >--- a/session.c >+++ b/session.c >@@ -161,6 +161,8 @@ login_cap_t *lc; > static int is_child = 0; > static int in_chroot = 0; > >+static const char *auth_info = NULL; >+ > /* Name and directory of socket for authentication agent forwarding. */ > static char *auth_sock_name = NULL; > static char *auth_sock_dir = NULL; >@@ -265,7 +267,9 @@ do_authenticated(Authctxt *authctxt) > > auth_debug_send(); > >+ auth_info = sshbuf_dup_string(authctxt->session_info); > do_authenticated2(authctxt); >+ > do_cleanup(authctxt); > } > >@@ -951,8 +955,9 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid) > } > #endif /* HAVE_ETC_DEFAULT_LOGIN */ > >-void >-copy_environment(char **source, char ***env, u_int *envsize) >+static void >+copy_environment_filtered(char **source, char ***env, u_int *envsize, >+ const char *blacklist, const char *whitelist) > { > char *var_name, *var_val; > int i; >@@ -968,13 +973,30 @@ copy_environment(char **source, char ***env, u_int *envsize) > } > *var_val++ = '\0'; > >- debug3("Copy environment: %s=%s", var_name, var_val); >- child_set_env(env, envsize, var_name, var_val); >+ /* Apply any filters specified */ >+ if (blacklist != NULL && >+ match_pattern_list(var_name, blacklist, 0) == 1) { >+ debug3("%s: skipped %s, on blacklist", >+ __func__, var_name); >+ } else if (whitelist != NULL && >+ match_pattern_list(var_name, whitelist, 0) != 1) { >+ debug3("%s: skipped %s, not on whitelist", >+ __func__, var_name); >+ } else { >+ debug3("Copy environment: %s=%s", var_name, var_val); >+ child_set_env(env, envsize, var_name, var_val); >+ } > > free(var_name); > } > } > >+void >+copy_environment(char **source, char ***env, u_int *envsize) >+{ >+ copy_environment_filtered(source, env, envsize, NULL, NULL); >+} >+ > static char ** > do_setup_env(Session *s, const char *shell) > { >@@ -1001,6 +1023,7 @@ do_setup_env(Session *s, const char *shell) > char **p; > > p = fetch_windows_environment(); >+ /* XXX use whitelist */ > copy_environment(p, &env, &envsize); > free_windows_environment(p); > } >@@ -1056,6 +1079,27 @@ do_setup_env(Session *s, const char *shell) > if (getenv("TZ")) > child_set_env(&env, &envsize, "TZ", getenv("TZ")); > >+#ifdef USE_PAM >+ /* >+ * Pull in any environment variables that may have >+ * been set by PAM. >+ */ >+ if (options.use_pam) { >+ char **p; >+ >+ /* Don't allow SSH_USER_AUTH to leak back from PAM */ >+ p = fetch_pam_child_environment(); >+ copy_environment_filtered(p, &env, &envsize, >+ "SSH_USER_AUTH", NULL); >+ free_pam_environment(p); >+ >+ p = fetch_pam_environment(); >+ copy_environment_filtered(p, &env, &envsize, >+ "SSH_USER_AUTH", NULL); >+ free_pam_environment(p); >+ } >+#endif /* USE_PAM */ >+ > /* Set custom environment options from RSA authentication. */ > while (custom_environment) { > struct envstring *ce = custom_environment; >@@ -1085,6 +1129,8 @@ do_setup_env(Session *s, const char *shell) > free(laddr); > child_set_env(&env, &envsize, "SSH_CONNECTION", buf); > >+ if (auth_info && options.expose_userauth_info) >+ child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info); > if (s->ttyfd != -1) > child_set_env(&env, &envsize, "SSH_TTY", s->tty); > if (s->term) >@@ -1094,7 +1140,6 @@ do_setup_env(Session *s, const char *shell) > if (original_command) > child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", > original_command); >- > #ifdef _UNICOS > if (cray_tmpdir[0] != '\0') > child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir); >@@ -1126,23 +1171,6 @@ do_setup_env(Session *s, const char *shell) > child_set_env(&env, &envsize, "KRB5CCNAME", > s->authctxt->krb5_ccname); > #endif >-#ifdef USE_PAM >- /* >- * Pull in any environment variables that may have >- * been set by PAM. >- */ >- if (options.use_pam) { >- char **p; >- >- p = fetch_pam_child_environment(); >- copy_environment(p, &env, &envsize); >- free_pam_environment(p); >- >- p = fetch_pam_environment(); >- copy_environment(p, &env, &envsize); >- free_pam_environment(p); >- } >-#endif /* USE_PAM */ > > if (auth_sock_name != NULL) > child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, >diff --git a/ssh-gss.h b/ssh-gss.h >index a99d7f08..d4ef8d73 100644 >--- a/ssh-gss.h >+++ b/ssh-gss.h >@@ -128,6 +128,7 @@ 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); > void ssh_gssapi_storecreds(void); >+const char *ssh_gssapi_displayname(void); > > #endif /* GSSAPI */ > >diff --git a/sshkey.c b/sshkey.c >index f9518bd7..47766c86 100644 >--- a/sshkey.c >+++ b/sshkey.c >@@ -1331,7 +1331,7 @@ sshkey_to_base64(const struct sshkey *key, char **b64p) > return r; > } > >-static int >+int > sshkey_format_text(const struct sshkey *key, struct sshbuf *b) > { > int r = SSH_ERR_INTERNAL_ERROR; >diff --git a/sshkey.h b/sshkey.h >index b0b5b274..da89fc0f 100644 >--- a/sshkey.h >+++ b/sshkey.h >@@ -124,6 +124,7 @@ int sshkey_fingerprint_raw(const struct sshkey *k, > int, u_char **retp, size_t *lenp); > const char *sshkey_type(const struct sshkey *); > const char *sshkey_cert_type(const struct sshkey *); >+int sshkey_format_text(const struct sshkey *, struct sshbuf *); > int sshkey_write(const struct sshkey *, FILE *); > int sshkey_read(struct sshkey *, char **); > u_int sshkey_size(const struct sshkey *);
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 2408
:
2754
|
2791
|
2792
|
2812
|
2846
|
2978
|
2980
|
2999
|
3022
|
3089
|
3091