-/*
- * This function is needed for PAM.
- */
-
-#ifdef USE_PAM
-/* Static variables used to communicate between the conversation function
- * and the server_login function
- */
-static char *PAM_username;
-static char *PAM_password;
-static int PAM_error = 0;
-static pam_handle_t *pamh = NULL;
-
-/* PAM conversation function
- * Here we assume (for now, at least) that echo on means login name, and
- * echo off means password.
- */
-
-static int PAM_conv (int num_msg,
-#ifndef SOL2
- const
-#endif
- struct pam_message **msg,
- struct pam_response **resp, void *appdata_ptr)
-{
- int replies = 0;
- struct pam_response *reply = NULL;
-
-#define COPY_STRING(s) (s) ? strdup(s) : NULL
-
- reply = malloc(sizeof(struct pam_response) * num_msg);
- if (!reply) return PAM_CONV_ERR;
-
- for (replies = 0; replies < num_msg; replies++) {
- switch (msg[replies]->msg_style) {
- case PAM_PROMPT_ECHO_ON:
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = COPY_STRING(PAM_username);
- /* PAM frees resp */
- break;
- case PAM_PROMPT_ECHO_OFF:
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = COPY_STRING(PAM_password);
- /* PAM frees resp */
- break;
- case PAM_TEXT_INFO:
- /* fall through */
- case PAM_ERROR_MSG:
- /* ignore it, but pam still wants a NULL response... */
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = NULL;
- break;
- default:
- /* Must be an error of some sort... */
- free (reply);
- PAM_error = 1;
- return PAM_CONV_ERR;
- }
- }
- *resp = reply;
- return PAM_SUCCESS;
-}
-
-static struct pam_conv PAM_conversation = {
- &PAM_conv,
- NULL
-};
-#endif /* USE_PAM */
-
-/*
- * plogin - Check the user name and password against the system
- * password database, and login the user if OK.
- *
- * returns:
- * UPAP_AUTHNAK: Login failed.
- * UPAP_AUTHACK: Login succeeded.
- * In either case, msg points to an appropriate message.
- */
-
-static int
-plogin(user, passwd, msg)
- char *user;
- char *passwd;
- char **msg;
-{
- char *tty;
-
-#ifdef USE_PAM
- int pam_error;
-
- pam_error = pam_start ("ppp", user, &PAM_conversation, &pamh);
- if (pam_error != PAM_SUCCESS) {
- *msg = (char *) pam_strerror (pamh, pam_error);
- reopen_log();
- return UPAP_AUTHNAK;
- }
- /*
- * Define the fields for the credential validation
- */
-
- PAM_username = user;
- PAM_password = passwd;
- PAM_error = 0;
- pam_set_item (pamh, PAM_TTY, devnam); /* this might be useful to some modules */
-
- /*
- * Validate the user
- */
- pam_error = pam_authenticate (pamh, PAM_SILENT);
- if (pam_error == PAM_SUCCESS && !PAM_error) {
- pam_error = pam_acct_mgmt (pamh, PAM_SILENT);
- if (pam_error == PAM_SUCCESS)
- pam_error = pam_open_session (pamh, PAM_SILENT);
- }
-
- *msg = (char *) pam_strerror (pamh, pam_error);
-
- /*
- * Clean up the mess
- */
- reopen_log(); /* apparently the PAM stuff does closelog() */
- PAM_username = NULL;
- PAM_password = NULL;
- if (pam_error != PAM_SUCCESS)
- return UPAP_AUTHNAK;
-#else /* #ifdef USE_PAM */
-
-/*
- * Use the non-PAM methods directly
- */
-
-#ifdef HAS_SHADOW
- struct spwd *spwd;
- struct spwd *getspnam();
-#endif
- struct passwd *pw = getpwnam(user);
-
- endpwent();
- if (pw == NULL)
- return (UPAP_AUTHNAK);
-
-#ifdef HAS_SHADOW
- spwd = getspnam(user);
- endspent();
- if (spwd) {
- /* check the age of the password entry */
- 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)) {
- warn("Password for %s has expired", user);
- return (UPAP_AUTHNAK);
- }
- pw->pw_passwd = spwd->sp_pwdp;
- }
-#endif
-
- /*
- * If no passwd, don't let them login.
- */
- if (pw->pw_passwd == NULL || strlen(pw->pw_passwd) < 2
- || strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) != 0)
- return (UPAP_AUTHNAK);
-
-#endif /* #ifdef USE_PAM */
-
- /*
- * Write a wtmp entry for this user.
- */
-
- tty = devnam;
- if (strncmp(tty, "/dev/", 5) == 0)
- tty += 5;
- logwtmp(tty, user, ifname); /* Add wtmp login entry */
-
-#if defined(_PATH_LASTLOG) && !defined(USE_PAM)
- if (pw != (struct passwd *)NULL) {
- struct lastlog ll;
- int fd;
-
- if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
- (void)lseek(fd, (off_t)(pw->pw_uid * sizeof(ll)), SEEK_SET);
- memset((void *)&ll, 0, sizeof(ll));
- (void)time(&ll.ll_time);
- (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
- (void)write(fd, (char *)&ll, sizeof(ll));
- (void)close(fd);
- }
- }
-#endif /* _PATH_LASTLOG and not USE_PAM */
-
- info("user %s logged in", user);
- logged_in = 1;
-
- return (UPAP_AUTHACK);
-}
-
-/*
- * plogout - Logout the user.
- */
-static void
-plogout()
-{
- char *tty;
-#ifdef USE_PAM
- int pam_error;
-
- if (pamh != NULL) {
- pam_error = pam_close_session (pamh, PAM_SILENT);
- pam_end (pamh, pam_error);
- pamh = NULL;
- }
- /* Apparently the pam stuff does closelog(). */
- reopen_log();
-#endif /* USE_PAM */
-
- tty = devnam;
- if (strncmp(tty, "/dev/", 5) == 0)
- tty += 5;
- logwtmp(tty, "", ""); /* Wipe out utmp logout entry */
- logged_in = 0;
-}
-
-