From c756e9b56e5b4649f120c417eb9bc99cf23db10f Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 17 Nov 2003 21:41:42 +1100 Subject: [PATCH] - (djm) Export environment variables from authentication subprocess to parent. Part of Bug #717 --- ChangeLog | 4 ++- auth-pam.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++----- auth-pam.h | 3 +- session.c | 7 ++++- 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index b850f42dd..bec42ac50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -45,6 +45,8 @@ return error on msg send/receive failure (rather than fatal); ok markus@ - (djm) Bug #632: Don't call pam_end indirectly from within kbd-int conversation function + - (djm) Export environment variables from authentication subprocess to + parent. Part of Bug #717 20031115 - (dtucker) [regress/agent-ptrace.sh] Test for GDB output from Solaris and @@ -1465,4 +1467,4 @@ - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo. Report from murple@murple.net, diagnosis from dtucker@zip.com.au -$Id: ChangeLog,v 1.3110 2003/11/17 10:27:55 djm Exp $ +$Id: ChangeLog,v 1.3111 2003/11/17 10:41:42 djm Exp $ diff --git a/auth-pam.c b/auth-pam.c index 4d2f9c597..92a3da406 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -31,7 +31,7 @@ /* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */ #include "includes.h" -RCSID("$Id: auth-pam.c,v 1.79 2003/11/17 10:27:55 djm Exp $"); +RCSID("$Id: auth-pam.c,v 1.80 2003/11/17 10:41:42 djm Exp $"); #ifdef USE_PAM #include @@ -117,6 +117,7 @@ static int sshpam_authenticated = 0; static int sshpam_new_authtok_reqd = 0; static int sshpam_session_open = 0; static int sshpam_cred_established = 0; +static char **sshpam_env = NULL; struct pam_ctxt { sp_pthread_t pam_thread; @@ -128,6 +129,51 @@ struct pam_ctxt { static void sshpam_free_ctx(void *); static struct pam_ctxt *cleanup_ctxt; +/* Some PAM implementations don't implement this */ +#ifndef HAVE_PAM_GETENVLIST +static char ** +pam_getenvlist(pam_handle_t *pamh) +{ + /* + * XXX - If necessary, we can still support envrionment passing + * for platforms without pam_getenvlist by searching for known + * env vars (e.g. KRB5CCNAME) from the PAM environment. + */ + return NULL; +} +#endif + +/* Import regular and PAM environment from subprocess */ +static void +import_environments(Buffer *b) +{ + char *env; + u_int i, num_env; + int err; + + /* Import environment from subprocess */ + num_env = buffer_get_int(b); + sshpam_env = xmalloc((num_env + 1) * sizeof(*sshpam_env)); + debug3("PAM: num env strings %d", num_env); + for(i = 0; i < num_env; i++) + sshpam_env[i] = buffer_get_string(b, NULL); + + sshpam_env[num_env] = NULL; + + /* Import PAM environment from subprocess */ + num_env = buffer_get_int(b); + debug("PAM: num PAM env strings %d", num_env); + for(i = 0; i < num_env; i++) { + env = buffer_get_string(b, NULL); + + /* Errors are not fatal here */ + if ((err = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) { + error("PAM: pam_putenv: %s", + pam_strerror(sshpam_handle, sshpam_err)); + } + } +} + /* * Conversation function for authentication thread. */ @@ -220,10 +266,14 @@ sshpam_thread(void *ctxtp) Buffer buffer; struct pam_conv sshpam_conv; #ifndef USE_POSIX_THREADS + extern char **environ; + char **env_from_pam; + u_int i; const char *pam_user; pam_get_item(sshpam_handle, PAM_USER, (const void **)&pam_user); setproctitle("%s [pam]", pam_user); + environ[0] = NULL; #endif sshpam_conv.conv = sshpam_thread_conv; @@ -238,6 +288,24 @@ sshpam_thread(void *ctxtp) if (sshpam_err != PAM_SUCCESS) goto auth_fail; buffer_put_cstring(&buffer, "OK"); + +#ifndef USE_POSIX_THREADS + /* Export any environment strings set in child */ + for(i = 0; environ[i] != NULL; i++) + ; /* Count */ + buffer_put_int(&buffer, i); + for(i = 0; environ[i] != NULL; i++) + buffer_put_cstring(&buffer, environ[i]); + + /* Export any environment strings set by PAM in child */ + env_from_pam = pam_getenvlist(sshpam_handle); + for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) + ; /* Count */ + buffer_put_int(&buffer, i); + for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) + buffer_put_cstring(&buffer, env_from_pam[i]); +#endif /* USE_POSIX_THREADS */ + /* XXX - can't do much about an error here */ ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer); buffer_free(&buffer); @@ -440,6 +508,7 @@ sshpam_query(void *ctx, char **name, char **info, **prompts = NULL; } if (type == PAM_SUCCESS) { + import_environments(&buffer); *num = 0; **echo_on = 0; ctxt->pam_done = 1; @@ -704,7 +773,6 @@ do_pam_chauthtok(void) * modules can handle things like Kerberos/GSI credentials that appear * during the ssh authentication process. */ - int do_pam_putenv(char *name, char *value) { @@ -730,15 +798,16 @@ print_pam_messages(void) /* XXX */ } +char ** +fetch_pam_child_environment(void) +{ + return sshpam_env; +} + char ** fetch_pam_environment(void) { -#ifdef HAVE_PAM_GETENVLIST - debug("PAM: retrieving environment"); return (pam_getenvlist(sshpam_handle)); -#else - return (NULL); -#endif } void diff --git a/auth-pam.h b/auth-pam.h index 58176f013..fd62e9534 100644 --- a/auth-pam.h +++ b/auth-pam.h @@ -1,4 +1,4 @@ -/* $Id: auth-pam.h,v 1.22 2003/10/07 01:30:16 dtucker Exp $ */ +/* $Id: auth-pam.h,v 1.23 2003/11/17 10:41:42 djm Exp $ */ /* * Copyright (c) 2000 Damien Miller. All rights reserved. @@ -42,6 +42,7 @@ void do_pam_chauthtok(void); int do_pam_putenv(char *, char *); void print_pam_messages(void); char ** fetch_pam_environment(void); +char ** fetch_pam_child_environment(void); void free_pam_environment(char **); void sshpam_thread_cleanup(void); void sshpam_cleanup(void); diff --git a/session.c b/session.c index 0f8032430..b1e6255f4 100644 --- a/session.c +++ b/session.c @@ -1095,8 +1095,13 @@ do_setup_env(Session *s, const char *shell) * been set by PAM. */ if (options.use_pam) { - char **p = fetch_pam_environment(); + 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); }