diff -urN isdn4k-utils-clean/ipppd/auth.c isdn4k-utils_pam/ipppd/auth.c --- isdn4k-utils-clean/ipppd/auth.c 2002-07-06 02:34:08.000000000 +0200 +++ isdn4k-utils_pam/ipppd/auth.c 2003-02-11 10:01:46.000000000 +0100 @@ -63,6 +63,11 @@ #include #endif +#ifdef USE_PAM +#include +extern void reopen_log(void); +#endif + #ifdef RADIUS #include int radius_pap_auth __P((int, char *, char *, char **, int *)); @@ -730,6 +735,71 @@ return ret; } +#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 passord. + */ + +static int PAM_conv (int num_msg, const 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: + 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 a 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 */ + #ifdef RADIUS /* * Name: radius_check_passwd @@ -828,9 +898,57 @@ */ static int check_login(char *user,char *passwd,char **msg,int *msglen,int unit) { + char *tty; + +#ifdef USE_PAM + int pam_error; + + pam_error = pam_start("ippp", 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 + */ + + tty = lns[unit].devnam; + if (strncmp(tty, "/dev/", 5) == 0) + tty += 5; + + PAM_username = user; + PAM_password = passwd; + PAM_error = 0; + pam_set_item(pamh, PAM_TTY, tty); /* 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_open_session(pamh, PAM_SILENT); + } + + /* + * Clean up the mess + */ + reopen_log(); /* apparently PAM calls closelog() */ + PAM_username = NULL; + PAM_password = NULL; + if (pam_error != PAM_SUCCESS) + return UPAP_AUTHNAK; +#else /* USE_PAM */ + +/* + * Use the non-PAM methods directly + */ struct passwd *pw; char *epasswd; - char *tty; #ifdef HAVE_SHADOW_H struct spwd *spwd; @@ -855,20 +973,20 @@ endspent(); #endif - /* - * XXX If no passwd, let them login without one. - */ - if (!pw->pw_passwd || *pw->pw_passwd == '\0') { - return (UPAP_AUTHACK); - } - - epasswd = crypt(passwd, pw->pw_passwd); - if (strcmp(epasswd, pw->pw_passwd)) { - return (UPAP_AUTHNAK); + /* + * If no passwd, let them login without one. + */ + if (pw->pw_passwd && *pw->pw_passwd != '\0') { + epasswd = crypt(passwd, pw->pw_passwd); + if (strcmp(epasswd, pw->pw_passwd)) { + return (UPAP_AUTHNAK); + } } +#endif /* USE_PAM */ syslog(LOG_INFO, "user %s logged in", user); +#ifndef USE_PAM /* * Write a wtmp entry for this user. */ @@ -876,6 +994,7 @@ if (strncmp(tty, "/dev/", 5) == 0) tty += 5; logwtmputmp(unit, tty, user, ""); /* Add wtmp login entry */ +#endif /* USE_PAM */ return (UPAP_AUTHACK); } @@ -885,12 +1004,24 @@ */ static void do_logout(int unit) { +#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 pam does closelog() */ + reopen_log(); +#else /* USE_PAM */ char *tty; tty = lns[unit].devnam; if (strncmp(tty, "/dev/", 5) == 0) tty += 5; logwtmputmp(unit, tty, "", ""); /* Wipe out wtmp logout entry */ +#endif } diff -urN isdn4k-utils-clean/ipppd/configure.in isdn4k-utils_pam/ipppd/configure.in --- isdn4k-utils-clean/ipppd/configure.in 2002-07-19 20:51:41.000000000 +0200 +++ isdn4k-utils_pam/ipppd/configure.in 2003-02-11 09:53:54.000000000 +0100 @@ -28,6 +28,7 @@ AC_CHECK_HEADERS(fcntl.h limits.h paths.h sys/file.h sys/ioctl.h sys/time.h syslog.h unistd.h) AC_CHECK_HEADER(shadow.h, HAVE_SHADOW_H=1; AC_DEFINE(HAVE_SHADOW_H)) AC_CHECK_HEADER(linux/isdn_lzscomp.h, HAVE_LZSCOMP_H=1; AC_DEFINE(HAVE_LZSCOMP_H)) +AC_CHECK_HEADER(security/pam_appl.h, HAVE_LIBPAM_H=1; AC_DEFINE(HAVE_LIBPAM_H)) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -105,6 +106,7 @@ AC_SUBST(HAVE_LIBBSD) AC_SUBST(HAVE_SHADOW_H) AC_SUBST(HAVE_LZSCOMP_H) +AC_SUBST(HAVE_LIBPAM_H) AC_SUBST(CONFIG_RUNDIR) AC_SUBST(CONFIG_SBINDIR) AC_SUBST(CONFIG_MANDIR) diff -urN isdn4k-utils-clean/ipppd/Makefile.in isdn4k-utils_pam/ipppd/Makefile.in --- isdn4k-utils-clean/ipppd/Makefile.in 2002-07-19 21:03:53.000000000 +0200 +++ isdn4k-utils_pam/ipppd/Makefile.in 2003-02-11 09:54:46.000000000 +0100 @@ -7,6 +7,7 @@ HAVE_LIBCRYPT := @HAVE_LIBCRYPT@ HAVE_SHADOW_H := @HAVE_SHADOW_H@ HAVE_LZSCOMP_H:= @HAVE_LZSCOMP_H@ +HAVE_LIBPAM_H := @HAVE_LIBPAM_H@ SBINDIR := @CONFIG_SBINDIR@ MANDIR := @CONFIG_MANDIR@ CC := @CC@ @@ -113,6 +114,11 @@ CFLAGS += -DHAVE_LZSCOMP_H endif +ifeq ($(HAVE_LIBPAM_H),1) + CFLAGS += -DUSE_PAM + LIBS += -lpam -ldl +endif + %.8: %.man cp $< $@ diff -urN isdn4k-utils-clean/ipppd/sys-linux.c isdn4k-utils_pam/ipppd/sys-linux.c --- isdn4k-utils-clean/ipppd/sys-linux.c 2000-10-05 22:45:25.000000000 +0200 +++ isdn4k-utils_pam/ipppd/sys-linux.c 2003-01-23 16:56:07.000000000 +0100 @@ -208,6 +208,16 @@ } } +#ifdef USE_PAM +void reopen_log(void) +{ + openlog("ipppd", LOG_PID | LOG_NDELAY, LOG_PPP); + setlogmask(LOG_UPTO(LOG_INFO)); + if (debug) + setlogmask(LOG_UPTO(LOG_DEBUG)); +} +#endif + /* * note_debug_level - note a change in the debug level. */