109958426SBrian Feldman /* 209958426SBrian Feldman * Copyright (c) 2000 Damien Miller. All rights reserved. 309958426SBrian Feldman * 409958426SBrian Feldman * Redistribution and use in source and binary forms, with or without 509958426SBrian Feldman * modification, are permitted provided that the following conditions 609958426SBrian Feldman * are met: 709958426SBrian Feldman * 1. Redistributions of source code must retain the above copyright 809958426SBrian Feldman * notice, this list of conditions and the following disclaimer. 909958426SBrian Feldman * 2. Redistributions in binary form must reproduce the above copyright 1009958426SBrian Feldman * notice, this list of conditions and the following disclaimer in the 1109958426SBrian Feldman * documentation and/or other materials provided with the distribution. 1209958426SBrian Feldman * 1309958426SBrian Feldman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1409958426SBrian Feldman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1509958426SBrian Feldman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1609958426SBrian Feldman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1709958426SBrian Feldman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1809958426SBrian Feldman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1909958426SBrian Feldman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2009958426SBrian Feldman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2109958426SBrian Feldman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2209958426SBrian Feldman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2309958426SBrian Feldman */ 2409958426SBrian Feldman 2509958426SBrian Feldman #include "includes.h" 2609958426SBrian Feldman 2709958426SBrian Feldman #ifdef USE_PAM 2809958426SBrian Feldman #include "xmalloc.h" 294c5de869SBrian Feldman #include "log.h" 30989dd127SDag-Erling Smørgrav #include "auth.h" 31f388f5efSDag-Erling Smørgrav #include "auth-options.h" 32989dd127SDag-Erling Smørgrav #include "auth-pam.h" 3309958426SBrian Feldman #include "servconf.h" 344c5de869SBrian Feldman #include "canohost.h" 35989dd127SDag-Erling Smørgrav #include "readpass.h" 3609958426SBrian Feldman 37989dd127SDag-Erling Smørgrav extern char *__progname; 38989dd127SDag-Erling Smørgrav 39f388f5efSDag-Erling Smørgrav extern int use_privsep; 40f388f5efSDag-Erling Smørgrav 41f388f5efSDag-Erling Smørgrav RCSID("$Id: auth-pam.c,v 1.54 2002/07/28 20:24:08 stevesk Exp $"); 42f388f5efSDag-Erling Smørgrav RCSID("$FreeBSD$"); 4309958426SBrian Feldman 4409958426SBrian Feldman #define NEW_AUTHTOK_MSG \ 45f388f5efSDag-Erling Smørgrav "Warning: Your password has expired, please change it now." 46f388f5efSDag-Erling Smørgrav #define NEW_AUTHTOK_MSG_PRIVSEP \ 47f388f5efSDag-Erling Smørgrav "Your password has expired, the session cannot proceed." 4809958426SBrian Feldman 492c917d39SAlfred Perlstein static int do_pam_conversation(int num_msg, const struct pam_message **msg, 5009958426SBrian Feldman struct pam_response **resp, void *appdata_ptr); 5109958426SBrian Feldman 5209958426SBrian Feldman /* module-local variables */ 5309958426SBrian Feldman static struct pam_conv conv = { 54f388f5efSDag-Erling Smørgrav (int (*)())do_pam_conversation, 5509958426SBrian Feldman NULL 5609958426SBrian Feldman }; 57989dd127SDag-Erling Smørgrav static char *__pam_msg = NULL; 58989dd127SDag-Erling Smørgrav static pam_handle_t *__pamh = NULL; 59989dd127SDag-Erling Smørgrav static const char *__pampasswd = NULL; 6009958426SBrian Feldman 612c917d39SAlfred Perlstein /* states for do_pam_conversation() */ 62989dd127SDag-Erling Smørgrav enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN; 63f388f5efSDag-Erling Smørgrav /* remember whether pam_acct_mgmt() returned PAM_NEW_AUTHTOK_REQD */ 6409958426SBrian Feldman static int password_change_required = 0; 652c917d39SAlfred Perlstein /* remember whether the last pam_authenticate() succeeded or not */ 662c917d39SAlfred Perlstein static int was_authenticated = 0; 672c917d39SAlfred Perlstein 682c917d39SAlfred Perlstein /* Remember what has been initialised */ 692c917d39SAlfred Perlstein static int session_opened = 0; 702c917d39SAlfred Perlstein static int creds_set = 0; 712c917d39SAlfred Perlstein 72989dd127SDag-Erling Smørgrav /* accessor which allows us to switch conversation structs according to 73989dd127SDag-Erling Smørgrav * the authentication method being used */ 742c917d39SAlfred Perlstein void do_pam_set_conv(struct pam_conv *conv) 752c917d39SAlfred Perlstein { 76989dd127SDag-Erling Smørgrav pam_set_item(__pamh, PAM_CONV, conv); 77989dd127SDag-Erling Smørgrav } 78989dd127SDag-Erling Smørgrav 79989dd127SDag-Erling Smørgrav /* start an authentication run */ 80989dd127SDag-Erling Smørgrav int do_pam_authenticate(int flags) 81989dd127SDag-Erling Smørgrav { 82989dd127SDag-Erling Smørgrav int retval = pam_authenticate(__pamh, flags); 83989dd127SDag-Erling Smørgrav was_authenticated = (retval == PAM_SUCCESS); 84989dd127SDag-Erling Smørgrav return retval; 852c917d39SAlfred Perlstein } 8609958426SBrian Feldman 8709958426SBrian Feldman /* 8809958426SBrian Feldman * PAM conversation function. 8909958426SBrian Feldman * There are two states this can run in. 9009958426SBrian Feldman * 9109958426SBrian Feldman * INITIAL_LOGIN mode simply feeds the password from the client into 9209958426SBrian Feldman * PAM in response to PAM_PROMPT_ECHO_OFF, and collects output 93989dd127SDag-Erling Smørgrav * messages with into __pam_msg. This is used during initial 9409958426SBrian Feldman * authentication to bypass the normal PAM password prompt. 9509958426SBrian Feldman * 96989dd127SDag-Erling Smørgrav * OTHER mode handles PAM_PROMPT_ECHO_OFF with read_passphrase() 9709958426SBrian Feldman * and outputs messages to stderr. This mode is used if pam_chauthtok() 9809958426SBrian Feldman * is called to update expired passwords. 9909958426SBrian Feldman */ 1002c917d39SAlfred Perlstein static int do_pam_conversation(int num_msg, const struct pam_message **msg, 10109958426SBrian Feldman struct pam_response **resp, void *appdata_ptr) 10209958426SBrian Feldman { 10309958426SBrian Feldman struct pam_response *reply; 10409958426SBrian Feldman int count; 10509958426SBrian Feldman char buf[1024]; 10609958426SBrian Feldman 10709958426SBrian Feldman /* PAM will free this later */ 108f388f5efSDag-Erling Smørgrav reply = xmalloc(num_msg * sizeof(*reply)); 10909958426SBrian Feldman 11009958426SBrian Feldman for (count = 0; count < num_msg; count++) { 111989dd127SDag-Erling Smørgrav if (pamstate == INITIAL_LOGIN) { 112989dd127SDag-Erling Smørgrav /* 113989dd127SDag-Erling Smørgrav * We can't use stdio yet, queue messages for 114989dd127SDag-Erling Smørgrav * printing later 115989dd127SDag-Erling Smørgrav */ 116989dd127SDag-Erling Smørgrav switch(PAM_MSG_MEMBER(msg, count, msg_style)) { 11709958426SBrian Feldman case PAM_PROMPT_ECHO_ON: 118f388f5efSDag-Erling Smørgrav xfree(reply); 11909958426SBrian Feldman return PAM_CONV_ERR; 12009958426SBrian Feldman case PAM_PROMPT_ECHO_OFF: 121989dd127SDag-Erling Smørgrav if (__pampasswd == NULL) { 122f388f5efSDag-Erling Smørgrav xfree(reply); 12309958426SBrian Feldman return PAM_CONV_ERR; 12409958426SBrian Feldman } 125989dd127SDag-Erling Smørgrav reply[count].resp = xstrdup(__pampasswd); 12609958426SBrian Feldman reply[count].resp_retcode = PAM_SUCCESS; 12709958426SBrian Feldman break; 12809958426SBrian Feldman case PAM_ERROR_MSG: 12909958426SBrian Feldman case PAM_TEXT_INFO: 130f388f5efSDag-Erling Smørgrav if (PAM_MSG_MEMBER(msg, count, msg) != NULL) { 131989dd127SDag-Erling Smørgrav message_cat(&__pam_msg, 132989dd127SDag-Erling Smørgrav PAM_MSG_MEMBER(msg, count, msg)); 13309958426SBrian Feldman } 13409958426SBrian Feldman reply[count].resp = xstrdup(""); 13509958426SBrian Feldman reply[count].resp_retcode = PAM_SUCCESS; 13609958426SBrian Feldman break; 13709958426SBrian Feldman default: 138f388f5efSDag-Erling Smørgrav xfree(reply); 13909958426SBrian Feldman return PAM_CONV_ERR; 14009958426SBrian Feldman } 141989dd127SDag-Erling Smørgrav } else { 142989dd127SDag-Erling Smørgrav /* 143989dd127SDag-Erling Smørgrav * stdio is connected, so interact directly 144989dd127SDag-Erling Smørgrav */ 145989dd127SDag-Erling Smørgrav switch(PAM_MSG_MEMBER(msg, count, msg_style)) { 146989dd127SDag-Erling Smørgrav case PAM_PROMPT_ECHO_ON: 147989dd127SDag-Erling Smørgrav fputs(PAM_MSG_MEMBER(msg, count, msg), stderr); 148989dd127SDag-Erling Smørgrav fgets(buf, sizeof(buf), stdin); 149989dd127SDag-Erling Smørgrav reply[count].resp = xstrdup(buf); 150989dd127SDag-Erling Smørgrav reply[count].resp_retcode = PAM_SUCCESS; 151989dd127SDag-Erling Smørgrav break; 152989dd127SDag-Erling Smørgrav case PAM_PROMPT_ECHO_OFF: 153989dd127SDag-Erling Smørgrav reply[count].resp = 154989dd127SDag-Erling Smørgrav read_passphrase(PAM_MSG_MEMBER(msg, count, 155989dd127SDag-Erling Smørgrav msg), RP_ALLOW_STDIN); 156989dd127SDag-Erling Smørgrav reply[count].resp_retcode = PAM_SUCCESS; 157989dd127SDag-Erling Smørgrav break; 158989dd127SDag-Erling Smørgrav case PAM_ERROR_MSG: 159989dd127SDag-Erling Smørgrav case PAM_TEXT_INFO: 160f388f5efSDag-Erling Smørgrav if (PAM_MSG_MEMBER(msg, count, msg) != NULL) 161989dd127SDag-Erling Smørgrav fprintf(stderr, "%s\n", 162989dd127SDag-Erling Smørgrav PAM_MSG_MEMBER(msg, count, msg)); 163989dd127SDag-Erling Smørgrav reply[count].resp = xstrdup(""); 164989dd127SDag-Erling Smørgrav reply[count].resp_retcode = PAM_SUCCESS; 165989dd127SDag-Erling Smørgrav break; 166989dd127SDag-Erling Smørgrav default: 167f388f5efSDag-Erling Smørgrav xfree(reply); 168989dd127SDag-Erling Smørgrav return PAM_CONV_ERR; 169989dd127SDag-Erling Smørgrav } 170989dd127SDag-Erling Smørgrav } 17109958426SBrian Feldman } 17209958426SBrian Feldman 17309958426SBrian Feldman *resp = reply; 17409958426SBrian Feldman 17509958426SBrian Feldman return PAM_SUCCESS; 17609958426SBrian Feldman } 17709958426SBrian Feldman 17809958426SBrian Feldman /* Called at exit to cleanly shutdown PAM */ 1792c917d39SAlfred Perlstein void do_pam_cleanup_proc(void *context) 18009958426SBrian Feldman { 181989dd127SDag-Erling Smørgrav int pam_retval = PAM_SUCCESS; 18209958426SBrian Feldman 183989dd127SDag-Erling Smørgrav if (__pamh && session_opened) { 184989dd127SDag-Erling Smørgrav pam_retval = pam_close_session(__pamh, 0); 185989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 18609958426SBrian Feldman log("Cannot close PAM session[%d]: %.200s", 187989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 1882c917d39SAlfred Perlstein } 18909958426SBrian Feldman 190989dd127SDag-Erling Smørgrav if (__pamh && creds_set) { 191989dd127SDag-Erling Smørgrav pam_retval = pam_setcred(__pamh, PAM_DELETE_CRED); 192989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 19309958426SBrian Feldman debug("Cannot delete credentials[%d]: %.200s", 194989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 1952c917d39SAlfred Perlstein } 19609958426SBrian Feldman 197989dd127SDag-Erling Smørgrav if (__pamh) { 198989dd127SDag-Erling Smørgrav pam_retval = pam_end(__pamh, pam_retval); 199989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 20009958426SBrian Feldman log("Cannot release PAM authentication[%d]: %.200s", 201989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 20209958426SBrian Feldman } 20309958426SBrian Feldman } 20409958426SBrian Feldman 20509958426SBrian Feldman /* Attempt password authentation using PAM */ 2064c5de869SBrian Feldman int auth_pam_password(Authctxt *authctxt, const char *password) 20709958426SBrian Feldman { 208989dd127SDag-Erling Smørgrav extern ServerOptions options; 20909958426SBrian Feldman int pam_retval; 210989dd127SDag-Erling Smørgrav struct passwd *pw = authctxt->pw; 21109958426SBrian Feldman 2122c917d39SAlfred Perlstein do_pam_set_conv(&conv); 2132c917d39SAlfred Perlstein 21409958426SBrian Feldman /* deny if no user. */ 21509958426SBrian Feldman if (pw == NULL) 21609958426SBrian Feldman return 0; 217989dd127SDag-Erling Smørgrav if (pw->pw_uid == 0 && options.permit_root_login == PERMIT_NO_PASSWD) 21809958426SBrian Feldman return 0; 21909958426SBrian Feldman if (*password == '\0' && options.permit_empty_passwd == 0) 22009958426SBrian Feldman return 0; 22109958426SBrian Feldman 222989dd127SDag-Erling Smørgrav __pampasswd = password; 22309958426SBrian Feldman 22409958426SBrian Feldman pamstate = INITIAL_LOGIN; 225989dd127SDag-Erling Smørgrav pam_retval = do_pam_authenticate( 226989dd127SDag-Erling Smørgrav options.permit_empty_passwd == 0 ? PAM_DISALLOW_NULL_AUTHTOK : 0); 22709958426SBrian Feldman if (pam_retval == PAM_SUCCESS) { 228989dd127SDag-Erling Smørgrav debug("PAM Password authentication accepted for " 229989dd127SDag-Erling Smørgrav "user \"%.100s\"", pw->pw_name); 23009958426SBrian Feldman return 1; 23109958426SBrian Feldman } else { 232989dd127SDag-Erling Smørgrav debug("PAM Password authentication for \"%.100s\" " 233989dd127SDag-Erling Smørgrav "failed[%d]: %s", pw->pw_name, pam_retval, 234989dd127SDag-Erling Smørgrav PAM_STRERROR(__pamh, pam_retval)); 23509958426SBrian Feldman return 0; 23609958426SBrian Feldman } 23709958426SBrian Feldman } 23809958426SBrian Feldman 23909958426SBrian Feldman /* Do account management using PAM */ 24009958426SBrian Feldman int do_pam_account(char *username, char *remote_user) 24109958426SBrian Feldman { 24209958426SBrian Feldman int pam_retval; 24309958426SBrian Feldman 2442c917d39SAlfred Perlstein do_pam_set_conv(&conv); 2452c917d39SAlfred Perlstein 246989dd127SDag-Erling Smørgrav if (remote_user) { 24709958426SBrian Feldman debug("PAM setting ruser to \"%.200s\"", remote_user); 248989dd127SDag-Erling Smørgrav pam_retval = pam_set_item(__pamh, PAM_RUSER, remote_user); 249989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 250989dd127SDag-Erling Smørgrav fatal("PAM set ruser failed[%d]: %.200s", pam_retval, 251989dd127SDag-Erling Smørgrav PAM_STRERROR(__pamh, pam_retval)); 25209958426SBrian Feldman } 25309958426SBrian Feldman 254989dd127SDag-Erling Smørgrav pam_retval = pam_acct_mgmt(__pamh, 0); 255989dd127SDag-Erling Smørgrav debug2("pam_acct_mgmt() = %d", pam_retval); 25609958426SBrian Feldman switch (pam_retval) { 25709958426SBrian Feldman case PAM_SUCCESS: 25809958426SBrian Feldman /* This is what we want */ 25909958426SBrian Feldman break; 260989dd127SDag-Erling Smørgrav #if 0 26109958426SBrian Feldman case PAM_NEW_AUTHTOK_REQD: 262f388f5efSDag-Erling Smørgrav message_cat(&__pam_msg, use_privsep ? 263f388f5efSDag-Erling Smørgrav NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG); 26409958426SBrian Feldman /* flag that password change is necessary */ 26509958426SBrian Feldman password_change_required = 1; 266f388f5efSDag-Erling Smørgrav /* disallow other functionality for now */ 267f388f5efSDag-Erling Smørgrav no_port_forwarding_flag |= 2; 268f388f5efSDag-Erling Smørgrav no_agent_forwarding_flag |= 2; 269f388f5efSDag-Erling Smørgrav no_x11_forwarding_flag |= 2; 27009958426SBrian Feldman break; 271989dd127SDag-Erling Smørgrav #endif 27209958426SBrian Feldman default: 273989dd127SDag-Erling Smørgrav log("PAM rejected by account configuration[%d]: " 274989dd127SDag-Erling Smørgrav "%.200s", pam_retval, PAM_STRERROR(__pamh, 275989dd127SDag-Erling Smørgrav pam_retval)); 27609958426SBrian Feldman return(0); 27709958426SBrian Feldman } 27809958426SBrian Feldman 27909958426SBrian Feldman return(1); 28009958426SBrian Feldman } 28109958426SBrian Feldman 28209958426SBrian Feldman /* Do PAM-specific session initialisation */ 28309958426SBrian Feldman void do_pam_session(char *username, const char *ttyname) 28409958426SBrian Feldman { 28509958426SBrian Feldman int pam_retval; 28609958426SBrian Feldman 2872c917d39SAlfred Perlstein do_pam_set_conv(&conv); 2882c917d39SAlfred Perlstein 28909958426SBrian Feldman if (ttyname != NULL) { 29009958426SBrian Feldman debug("PAM setting tty to \"%.200s\"", ttyname); 291989dd127SDag-Erling Smørgrav pam_retval = pam_set_item(__pamh, PAM_TTY, ttyname); 292989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 29309958426SBrian Feldman fatal("PAM set tty failed[%d]: %.200s", 294989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 29509958426SBrian Feldman } 29609958426SBrian Feldman 297989dd127SDag-Erling Smørgrav pam_retval = pam_open_session(__pamh, 0); 298989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 29909958426SBrian Feldman fatal("PAM session setup failed[%d]: %.200s", 300989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 3012c917d39SAlfred Perlstein 3022c917d39SAlfred Perlstein session_opened = 1; 30309958426SBrian Feldman } 30409958426SBrian Feldman 30509958426SBrian Feldman /* Set PAM credentials */ 306989dd127SDag-Erling Smørgrav void do_pam_setcred(int init) 30709958426SBrian Feldman { 30809958426SBrian Feldman int pam_retval; 30909958426SBrian Feldman 310989dd127SDag-Erling Smørgrav if (__pamh == NULL) 311989dd127SDag-Erling Smørgrav return; 312989dd127SDag-Erling Smørgrav 3132c917d39SAlfred Perlstein do_pam_set_conv(&conv); 3142c917d39SAlfred Perlstein 31509958426SBrian Feldman debug("PAM establishing creds"); 316989dd127SDag-Erling Smørgrav pam_retval = pam_setcred(__pamh, 317989dd127SDag-Erling Smørgrav init ? PAM_ESTABLISH_CRED : PAM_REINITIALIZE_CRED); 31809958426SBrian Feldman if (pam_retval != PAM_SUCCESS) { 3192c917d39SAlfred Perlstein if (was_authenticated) 3202c917d39SAlfred Perlstein fatal("PAM setcred failed[%d]: %.200s", 321989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 3222c917d39SAlfred Perlstein else 32300e38eafSBrian Feldman debug("PAM setcred failed[%d]: %.200s", 324989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 3252c917d39SAlfred Perlstein } else 3262c917d39SAlfred Perlstein creds_set = 1; 32709958426SBrian Feldman } 32809958426SBrian Feldman 32909958426SBrian Feldman /* accessor function for file scope static variable */ 330989dd127SDag-Erling Smørgrav int is_pam_password_change_required(void) 33109958426SBrian Feldman { 33209958426SBrian Feldman return password_change_required; 33309958426SBrian Feldman } 33409958426SBrian Feldman 33509958426SBrian Feldman /* 33609958426SBrian Feldman * Have user change authentication token if pam_acct_mgmt() indicated 33709958426SBrian Feldman * it was expired. This needs to be called after an interactive 33809958426SBrian Feldman * session is established and the user's pty is connected to 339f388f5efSDag-Erling Smørgrav * stdin/stdout/stderr. 34009958426SBrian Feldman */ 34109958426SBrian Feldman void do_pam_chauthtok(void) 34209958426SBrian Feldman { 34309958426SBrian Feldman int pam_retval; 34409958426SBrian Feldman 3452c917d39SAlfred Perlstein do_pam_set_conv(&conv); 3462c917d39SAlfred Perlstein 34709958426SBrian Feldman if (password_change_required) { 348f388f5efSDag-Erling Smørgrav if (use_privsep) 349f388f5efSDag-Erling Smørgrav fatal("Password changing is currently unsupported" 350f388f5efSDag-Erling Smørgrav " with privilege separation"); 35109958426SBrian Feldman pamstate = OTHER; 352989dd127SDag-Erling Smørgrav pam_retval = pam_chauthtok(__pamh, PAM_CHANGE_EXPIRED_AUTHTOK); 353989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 354989dd127SDag-Erling Smørgrav fatal("PAM pam_chauthtok failed[%d]: %.200s", 355989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 356f388f5efSDag-Erling Smørgrav #if 0 357f388f5efSDag-Erling Smørgrav /* XXX: This would need to be done in the parent process, 358f388f5efSDag-Erling Smørgrav * but there's currently no way to pass such request. */ 359f388f5efSDag-Erling Smørgrav no_port_forwarding_flag &= ~2; 360f388f5efSDag-Erling Smørgrav no_agent_forwarding_flag &= ~2; 361f388f5efSDag-Erling Smørgrav no_x11_forwarding_flag &= ~2; 362f388f5efSDag-Erling Smørgrav if (!no_port_forwarding_flag && options.allow_tcp_forwarding) 363f388f5efSDag-Erling Smørgrav channel_permit_all_opens(); 364f388f5efSDag-Erling Smørgrav #endif 36509958426SBrian Feldman } 36609958426SBrian Feldman } 36709958426SBrian Feldman 36809958426SBrian Feldman /* Cleanly shutdown PAM */ 36909958426SBrian Feldman void finish_pam(void) 37009958426SBrian Feldman { 3712c917d39SAlfred Perlstein do_pam_cleanup_proc(NULL); 3722c917d39SAlfred Perlstein fatal_remove_cleanup(&do_pam_cleanup_proc, NULL); 37309958426SBrian Feldman } 37409958426SBrian Feldman 37509958426SBrian Feldman /* Start PAM authentication for specified account */ 376989dd127SDag-Erling Smørgrav void start_pam(const char *user) 37709958426SBrian Feldman { 37809958426SBrian Feldman int pam_retval; 379989dd127SDag-Erling Smørgrav extern ServerOptions options; 380989dd127SDag-Erling Smørgrav extern u_int utmp_len; 381989dd127SDag-Erling Smørgrav const char *rhost; 38209958426SBrian Feldman 383989dd127SDag-Erling Smørgrav debug("Starting up PAM with username \"%.200s\"", user); 38409958426SBrian Feldman 385989dd127SDag-Erling Smørgrav pam_retval = pam_start(SSHD_PAM_SERVICE, user, &conv, &__pamh); 38609958426SBrian Feldman 387989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 38809958426SBrian Feldman fatal("PAM initialisation failed[%d]: %.200s", 389989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 39009958426SBrian Feldman 391989dd127SDag-Erling Smørgrav rhost = get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping); 392989dd127SDag-Erling Smørgrav debug("PAM setting rhost to \"%.200s\"", rhost); 393989dd127SDag-Erling Smørgrav 394989dd127SDag-Erling Smørgrav pam_retval = pam_set_item(__pamh, PAM_RHOST, rhost); 395989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 396989dd127SDag-Erling Smørgrav fatal("PAM set rhost failed[%d]: %.200s", pam_retval, 397989dd127SDag-Erling Smørgrav PAM_STRERROR(__pamh, pam_retval)); 39809958426SBrian Feldman #ifdef PAM_TTY_KLUDGE 39909958426SBrian Feldman /* 40009958426SBrian Feldman * Some PAM modules (e.g. pam_time) require a TTY to operate, 40109958426SBrian Feldman * and will fail in various stupid ways if they don't get one. 40209958426SBrian Feldman * sshd doesn't set the tty until too late in the auth process and may 40309958426SBrian Feldman * not even need one (for tty-less connections) 40409958426SBrian Feldman * Kludge: Set a fake PAM_TTY 40509958426SBrian Feldman */ 406989dd127SDag-Erling Smørgrav pam_retval = pam_set_item(__pamh, PAM_TTY, "NODEVssh"); 407989dd127SDag-Erling Smørgrav if (pam_retval != PAM_SUCCESS) 40809958426SBrian Feldman fatal("PAM set tty failed[%d]: %.200s", 409989dd127SDag-Erling Smørgrav pam_retval, PAM_STRERROR(__pamh, pam_retval)); 41009958426SBrian Feldman #endif /* PAM_TTY_KLUDGE */ 41109958426SBrian Feldman 4122c917d39SAlfred Perlstein fatal_add_cleanup(&do_pam_cleanup_proc, NULL); 41309958426SBrian Feldman } 41409958426SBrian Feldman 415f388f5efSDag-Erling Smørgrav /* Return list of PAM environment strings */ 41609958426SBrian Feldman char **fetch_pam_environment(void) 41709958426SBrian Feldman { 41809958426SBrian Feldman #ifdef HAVE_PAM_GETENVLIST 419989dd127SDag-Erling Smørgrav return(pam_getenvlist(__pamh)); 42009958426SBrian Feldman #else /* HAVE_PAM_GETENVLIST */ 42109958426SBrian Feldman return(NULL); 42209958426SBrian Feldman #endif /* HAVE_PAM_GETENVLIST */ 42309958426SBrian Feldman } 42409958426SBrian Feldman 425f388f5efSDag-Erling Smørgrav void free_pam_environment(char **env) 426f388f5efSDag-Erling Smørgrav { 427f388f5efSDag-Erling Smørgrav int i; 428f388f5efSDag-Erling Smørgrav 429f388f5efSDag-Erling Smørgrav if (env != NULL) { 430f388f5efSDag-Erling Smørgrav for (i = 0; env[i] != NULL; i++) 431f388f5efSDag-Erling Smørgrav xfree(env[i]); 432f388f5efSDag-Erling Smørgrav } 433f388f5efSDag-Erling Smørgrav } 434f388f5efSDag-Erling Smørgrav 43509958426SBrian Feldman /* Print any messages that have been generated during authentication */ 43609958426SBrian Feldman /* or account checking to stderr */ 43709958426SBrian Feldman void print_pam_messages(void) 43809958426SBrian Feldman { 439989dd127SDag-Erling Smørgrav if (__pam_msg != NULL) 440989dd127SDag-Erling Smørgrav fputs(__pam_msg, stderr); 44109958426SBrian Feldman } 44209958426SBrian Feldman 443989dd127SDag-Erling Smørgrav /* Append a message to buffer */ 444989dd127SDag-Erling Smørgrav void message_cat(char **p, const char *a) 44509958426SBrian Feldman { 446989dd127SDag-Erling Smørgrav char *cp; 447989dd127SDag-Erling Smørgrav size_t new_len; 44809958426SBrian Feldman 449989dd127SDag-Erling Smørgrav new_len = strlen(a); 45009958426SBrian Feldman 451989dd127SDag-Erling Smørgrav if (*p) { 452989dd127SDag-Erling Smørgrav size_t len = strlen(*p); 45309958426SBrian Feldman 454989dd127SDag-Erling Smørgrav *p = xrealloc(*p, new_len + len + 2); 455989dd127SDag-Erling Smørgrav cp = *p + len; 456989dd127SDag-Erling Smørgrav } else 457989dd127SDag-Erling Smørgrav *p = cp = xmalloc(new_len + 2); 45809958426SBrian Feldman 459989dd127SDag-Erling Smørgrav memcpy(cp, a, new_len); 460989dd127SDag-Erling Smørgrav cp[new_len] = '\n'; 461989dd127SDag-Erling Smørgrav cp[new_len + 1] = '\0'; 46209958426SBrian Feldman } 46309958426SBrian Feldman 46409958426SBrian Feldman #endif /* USE_PAM */ 465