From 3f0786bbe73609ac96e5a0d91425ee21129f8e04 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 20 Jan 2019 10:22:18 +1100 Subject: remove PAM dependencies on old packet API Requires some caching of values, because the PAM code isn't always called with packet context. --- auth-pam.c | 68 ++++++++++++++++++++++++++++++++++++---------------------- auth-pam.h | 2 +- auth2.c | 2 +- monitor.c | 2 +- monitor_wrap.c | 2 +- monitor_wrap.h | 2 +- 6 files changed, 47 insertions(+), 31 deletions(-) diff --git a/auth-pam.c b/auth-pam.c index d67324e1f..bde0a8f56 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -248,6 +248,9 @@ static int sshpam_maxtries_reached = 0; static char **sshpam_env = NULL; static Authctxt *sshpam_authctxt = NULL; static const char *sshpam_password = NULL; +static char *sshpam_rhost = NULL; +static char *sshpam_laddr = NULL; +static char *sshpam_conninfo = NULL; /* Some PAM implementations don't implement this */ #ifndef HAVE_PAM_GETENVLIST @@ -669,14 +672,17 @@ sshpam_cleanup(void) } static int -sshpam_init(Authctxt *authctxt) +sshpam_init(struct ssh *ssh, Authctxt *authctxt) { - const char *pam_rhost, *pam_user, *user = authctxt->user; + const char *pam_user, *user = authctxt->user; const char **ptr_pam_user = &pam_user; - char *laddr, *conninfo; - struct ssh *ssh = active_state; /* XXX */ - if (sshpam_handle != NULL) { + if (sshpam_handle == NULL) { + if (ssh == NULL) { + fatal("%s: called initially with no " + "packet context", __func__); + } + } if (sshpam_handle != NULL) { /* We already have a PAM context; check if the user matches */ sshpam_err = pam_get_item(sshpam_handle, PAM_USER, (sshpam_const void **)ptr_pam_user); @@ -690,27 +696,37 @@ sshpam_init(Authctxt *authctxt) pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle); sshpam_authctxt = authctxt; - if (sshpam_err != PAM_SUCCESS) { - pam_end(sshpam_handle, sshpam_err); - sshpam_handle = NULL; - return (-1); - } - pam_rhost = auth_get_canonical_hostname(ssh, options.use_dns); - debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost); - sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost); if (sshpam_err != PAM_SUCCESS) { pam_end(sshpam_handle, sshpam_err); sshpam_handle = NULL; return (-1); } - laddr = get_local_ipaddr(packet_get_connection_in()); - xasprintf(&conninfo, "SSH_CONNECTION=%.50s %d %.50s %d", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - laddr, ssh_local_port(ssh)); - pam_putenv(sshpam_handle, conninfo); - free(laddr); - free(conninfo); + if (ssh != NULL && sshpam_rhost == NULL) { + /* + * We need to cache these as we don't have packet context + * during the kbdint flow. + */ + sshpam_rhost = xstrdup(auth_get_canonical_hostname(ssh, + options.use_dns)); + sshpam_laddr = get_local_ipaddr( + ssh_packet_get_connection_in(ssh)); + xasprintf(&sshpam_conninfo, "SSH_CONNECTION=%.50s %d %.50s %d", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + sshpam_laddr, ssh_local_port(ssh)); + } + if (sshpam_rhost != NULL) { + debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost); + sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, + sshpam_rhost); + if (sshpam_err != PAM_SUCCESS) { + pam_end(sshpam_handle, sshpam_err); + sshpam_handle = NULL; + return (-1); + } + /* Put SSH_CONNECTION in the PAM environment too */ + pam_putenv(sshpam_handle, sshpam_conninfo); + } #ifdef PAM_TTY_KLUDGE /* @@ -765,7 +781,7 @@ sshpam_init_ctx(Authctxt *authctxt) return NULL; /* Initialize PAM */ - if (sshpam_init(authctxt) == -1) { + if (sshpam_init(NULL, authctxt) == -1) { error("PAM: initialization failed"); return (NULL); } @@ -797,7 +813,6 @@ static int sshpam_query(void *ctx, char **name, char **info, u_int *num, char ***prompts, u_int **echo_on) { - struct ssh *ssh = active_state; /* XXX */ struct sshbuf *buffer; struct pam_ctxt *ctxt = ctx; size_t plen; @@ -887,8 +902,7 @@ sshpam_query(void *ctx, char **name, char **info, } error("PAM: %s for %s%.100s from %.100s", msg, sshpam_authctxt->valid ? "" : "illegal user ", - sshpam_authctxt->user, - auth_get_canonical_hostname(ssh, options.use_dns)); + sshpam_authctxt->user, sshpam_rhost); /* FALLTHROUGH */ default: *num = 0; @@ -1005,12 +1019,14 @@ KbdintDevice mm_sshpam_device = { * This replaces auth-pam.c */ void -start_pam(Authctxt *authctxt) +start_pam(struct ssh *ssh) { + Authctxt *authctxt = (Authctxt *)ssh->authctxt; + if (!options.use_pam) fatal("PAM: initialisation requested when UsePAM=no"); - if (sshpam_init(authctxt) == -1) + if (sshpam_init(ssh, authctxt) == -1) fatal("PAM: initialisation failed"); } diff --git a/auth-pam.h b/auth-pam.h index 419860745..9fcea270f 100644 --- a/auth-pam.h +++ b/auth-pam.h @@ -27,7 +27,7 @@ struct ssh; -void start_pam(Authctxt *); +void start_pam(struct ssh *); void finish_pam(void); u_int do_pam_account(void); void do_pam_session(struct ssh *); diff --git a/auth2.c b/auth2.c index 2e996fa59..a80b3f872 100644 --- a/auth2.c +++ b/auth2.c @@ -299,7 +299,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) } #ifdef USE_PAM if (options.use_pam) - PRIVSEP(start_pam(authctxt)); + PRIVSEP(start_pam(ssh)); #endif ssh_packet_set_log_preamble(ssh, "%suser %s", authctxt->valid ? "authenticating " : "invalid ", user); diff --git a/monitor.c b/monitor.c index 1dcf930d4..5fa30b2a8 100644 --- a/monitor.c +++ b/monitor.c @@ -991,7 +991,7 @@ mm_answer_pam_start(struct ssh *ssh, int sock, struct sshbuf *m) if (!options.use_pam) fatal("UsePAM not set, but ended up in %s anyway", __func__); - start_pam(authctxt); + start_pam(ssh); monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1); if (options.kbd_interactive_authentication) diff --git a/monitor_wrap.c b/monitor_wrap.c index 5a0964b69..f52b9c88c 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -626,7 +626,7 @@ mm_session_pty_cleanup2(Session *s) #ifdef USE_PAM void -mm_start_pam(Authctxt *authctxt) +mm_start_pam(struct ssh *ssh) { struct sshbuf *m; diff --git a/monitor_wrap.h b/monitor_wrap.h index 2b7052202..c7e0c91dd 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -66,7 +66,7 @@ OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); #endif #ifdef USE_PAM -void mm_start_pam(struct Authctxt *); +void mm_start_pam(struct ssh *ssh); u_int mm_do_pam_account(void); void *mm_sshpam_init_ctx(struct Authctxt *); int mm_sshpam_query(void *, char **, char **, u_int *, char ***, u_int **); -- cgit v1.2.3