From: Paul Mackerras Date: Wed, 25 Mar 1998 01:26:03 +0000 (+0000) Subject: PAM fixes from Al Longyear. X-Git-Tag: RELEASE_2_3_6~112 X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=963a3b2de4193800c5549ca4a326e1dee99fc077;ds=sidebyside PAM fixes from Al Longyear. Use script_setenv to pass peer name to scripts. --- diff --git a/pppd/auth.c b/pppd/auth.c index 2e00b41..457fa1c 100644 --- a/pppd/auth.c +++ b/pppd/auth.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: auth.c,v 1.35 1997/11/27 06:49:15 paulus Exp $"; +static char rcsid[] = "$Id: auth.c,v 1.36 1998/03/25 01:26:03 paulus Exp $"; #endif #include @@ -58,14 +58,10 @@ static char rcsid[] = "$Id: auth.c,v 1.35 1997/11/27 06:49:15 paulus Exp $"; #ifdef USE_PAM #include -#include #endif #ifdef HAS_SHADOW #include -#ifndef SVR4 -#include -#endif #ifndef PW_PPP #define PW_PPP PW_LOGIN #endif @@ -356,6 +352,7 @@ auth_peer_success(unit, protocol, name, namelen) namelen = sizeof(peer_authname) - 1; BCOPY(name, peer_authname, namelen); peer_authname[namelen] = 0; + script_setenv("PEERNAME", peer_authname); /* * If there is no more authentication still to be done, @@ -586,7 +583,6 @@ auth_reset(unit) if (!have_chap_secret(remote_name, our_name, remote)) go->neg_chap = 0; } - } @@ -695,15 +691,65 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) } /* - * This function is needed for PAM. However, it should not be called. - * If it is, return the error code. + * This function is needed for PAM. */ #ifdef USE_PAM -static int pam_conv(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr) +static char *PAM_username = ""; +static char *PAM_password = ""; + +#ifdef PAM_ESTABLISH_CRED /* new PAM defines :(^ */ +#define MY_PAM_STRERROR(err_code) (char *) pam_strerror(pamh,err_code) +#else +#define MY_PAM_STRERROR(err_code) (char *) pam_strerror(err_code) +#endif + +static int pam_conv (int num_msg, + const struct pam_message **msg, + struct pam_response **resp, + void *appdata_ptr) { - return PAM_CONV_ERR; + int count = 0, replies = 0; + struct pam_response *reply = NULL; + int size = 0; + + for (count = 0; count < num_msg; count++) + { + size += sizeof (struct pam_response); + reply = realloc (reply, size); /* ANSI: is malloc() if reply==NULL */ + if (!reply) + return PAM_CONV_ERR; + + switch (msg[count]->msg_style) + { + case PAM_PROMPT_ECHO_ON: + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies++].resp = strdup(PAM_username); /* never NULL */ + break; + + case PAM_PROMPT_ECHO_OFF: + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies++].resp = strdup(PAM_password); /* never NULL */ + break; + + case PAM_TEXT_INFO: + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies++].resp = NULL; + break; + + case PAM_ERROR_MSG: + default: + free (reply); + return PAM_CONV_ERR; + } + } + + if (resp) + *resp = reply; + else + free (reply); + + return PAM_SUCCESS; } #endif @@ -724,14 +770,12 @@ plogin(user, passwd, msg, msglen) char **msg; int *msglen; { - char *tty; #ifdef USE_PAM + struct pam_conv pam_conversation; pam_handle_t *pamh; int pam_error; - char *pass; - char *dev; /* * Fill the pam_conversion structure */ @@ -739,23 +783,33 @@ plogin(user, passwd, msg, msglen) pam_conversation.conv = &pam_conv; pam_error = pam_start ("ppp", user, &pam_conversation, &pamh); + if (pam_error != PAM_SUCCESS) { - *msg = (char *) pam_strerror (pam_error); + *msg = MY_PAM_STRERROR (pam_error); return UPAP_AUTHNAK; } /* * Define the fields for the credintial validation */ - (void) pam_set_item (pamh, PAM_AUTHTOK, passwd); - (void) pam_set_item (pamh, PAM_TTY, devnam); + (void) pam_set_item (pamh, PAM_TTY, devnam); + PAM_username = user; + PAM_password = passwd; /* * Validate the user */ pam_error = pam_authenticate (pamh, PAM_SILENT); - if (pam_error == PAM_SUCCESS) + if (pam_error == PAM_SUCCESS) { pam_error = pam_acct_mgmt (pamh, PAM_SILENT); - *msg = (char *) pam_strerror (pam_error); + /* start a session for this user. Session closed when link ends. */ + if (pam_error == PAM_SUCCESS) + (void) pam_open_session (pamh, PAM_SILENT); + } + + *msg = MY_PAM_STRERROR (pam_error); + + PAM_username = + PAM_password = ""; /* * Clean up the mess */ @@ -769,14 +823,15 @@ plogin(user, passwd, msg, msglen) #else /* #ifdef USE_PAM */ struct passwd *pw; + char *tty; #ifdef HAS_SHADOW struct spwd *spwd; struct spwd *getspnam(); - extern int isexpired (struct passwd *, struct spwd *); /* in libshadow.a */ #endif pw = getpwnam(user); + endpwent(); if (pw == NULL) { return (UPAP_AUTHNAK); } @@ -786,8 +841,13 @@ plogin(user, passwd, msg, msglen) endspent(); if (spwd) { /* check the age of the password entry */ - if (isexpired(pw, spwd)) { - syslog(LOG_WARNING,"Expired password for %s",user); + long now = time(NULL) / 86400L; + + if ((spwd->sp_expire > 0 && now >= spwd->sp_expire) + || ((spwd->sp_max >= 0 && spwd->sp_max < 10000) + && spwd->sp_lstchg >= 0 + && now >= spwd->sp_lstchg + spwd->sp_max)) { + syslog(LOG_WARNING, "Password for %s has expired", user); return (UPAP_AUTHNAK); } pw->pw_passwd = spwd->sp_pwdp; @@ -801,19 +861,22 @@ plogin(user, passwd, msg, msglen) || strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) != 0) return (UPAP_AUTHNAK); -#endif /* #ifdef USE_PAM */ - - syslog(LOG_INFO, "user %s logged in", user); + /* These functions are not enabled for PAM. The reason for this is that */ + /* there is not necessarily a "passwd" entry for this user. That is */ + /* real purpose of 'PAM' -- to virtualize the account data from the */ + /* application. If you want to do the same thing, write the entry in */ + /* the 'session' hook. */ /* * Write a wtmp entry for this user. */ + tty = devnam; if (strncmp(tty, "/dev/", 5) == 0) tty += 5; logwtmp(tty, user, remote_name); /* Add wtmp login entry */ -#ifdef _PATH_LASTLOG +#if defined(_PATH_LASTLOG) { struct lastlog ll; int fd; @@ -828,6 +891,10 @@ plogin(user, passwd, msg, msglen) } } #endif + +#endif /* #ifdef USE_PAM */ + + syslog(LOG_INFO, "user %s logged in", user); logged_in = TRUE; return (UPAP_AUTHACK); @@ -839,12 +906,34 @@ plogin(user, passwd, msg, msglen) static void plogout() { +#ifdef USE_PAM + struct pam_conv pam_conversation; + pam_handle_t *pamh; + int pam_error; +/* + * Fill the pam_conversion structure. The PAM specification states that the + * session must be able to be closed by a totally different handle from which + * it was created. Hold the PAM group to their own specification! + */ + memset (&pam_conversation, '\0', sizeof (struct pam_conv)); + pam_conversation.conv = &pam_conv; + + pam_error = pam_start ("ppp", user, &pam_conversation, &pamh); + if (pam_error == PAM_SUCCESS) { + (void) pam_set_item (pamh, PAM_TTY, devnam); + (void) pam_close_session (pamh, PAM_SILENT); + (void) pam_end (pamh, PAM_SUCCESS); + } + +#else char *tty; tty = devnam; if (strncmp(tty, "/dev/", 5) == 0) tty += 5; - logwtmp(tty, "", ""); /* Wipe out wtmp logout entry */ + logwtmp(tty, "", ""); /* Wipe out utmp logout entry */ +#endif + logged_in = FALSE; } @@ -1062,8 +1151,7 @@ set_allowed_addrs(unit, addrs) u_int32_t a; struct hostent *hp; - if (wo->hisaddr == 0 && *p != '!' && *p != '-' - && strchr(p, '/') == NULL) { + if (*p != '!' && *p != '-' && strchr(p, '/') == NULL) { hp = gethostbyname(p); if (hp != NULL && hp->h_addrtype == AF_INET) a = *(u_int32_t *)hp->h_addr;