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 <shadow.h>
 #endif
 
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+extern void reopen_log(void);
+#endif
+
 #ifdef RADIUS
 #include <radiusclient.h>
 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.
  */
