Import pam_deny, pam_permit and pam_unix from FreeBSD, use them instead
authorJoerg Sonnenberger <joerg@dragonflybsd.org>
Mon, 1 Aug 2005 16:15:19 +0000 (16:15 +0000)
committerJoerg Sonnenberger <joerg@dragonflybsd.org>
Mon, 1 Aug 2005 16:15:19 +0000 (16:15 +0000)
of the sample modules from OpenPAM. I should read release notes in
greater detail. Thanks to DES for pointing that out.

contrib/openpam/modules/pam_unix/pam_unix.c [deleted file]
lib/pam_module/pam_deny/Makefile
lib/pam_module/pam_deny/pam_deny.8 [new file with mode: 0644]
lib/pam_module/pam_deny/pam_deny.c [moved from contrib/openpam/modules/pam_deny/pam_deny.c with 58% similarity]
lib/pam_module/pam_permit/Makefile
lib/pam_module/pam_permit/pam_permit.8 [new file with mode: 0644]
lib/pam_module/pam_permit/pam_permit.c [moved from contrib/openpam/modules/pam_permit/pam_permit.c with 58% similarity]
lib/pam_module/pam_unix/Makefile
lib/pam_module/pam_unix/pam_unix.8 [new file with mode: 0644]
lib/pam_module/pam_unix/pam_unix.c [new file with mode: 0644]

diff --git a/contrib/openpam/modules/pam_unix/pam_unix.c b/contrib/openpam/modules/pam_unix/pam_unix.c
deleted file mode 100644 (file)
index 259aa60..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*-
- * Copyright (c) 2002-2003 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * This software was developed for the FreeBSD Project by ThinkSec AS and
- * Network Associates Laboratories, the Security Research Division of
- * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $P4: //depot/projects/openpam/modules/pam_unix/pam_unix.c#6 $
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <sys/param.h>
-
-#include <pwd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#ifdef HAVE_CRYPT_H
-# include <crypt.h>
-#endif
-
-#include <security/pam_modules.h>
-#include <security/pam_appl.h>
-
-#ifndef _OPENPAM
-static char password_prompt[] = "Password:";
-#endif
-
-#ifndef PAM_EXTERN
-#define PAM_EXTERN
-#endif
-
-PAM_EXTERN int
-pam_sm_authenticate(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
-{
-#ifndef _OPENPAM
-       struct pam_conv *conv;
-       struct pam_message msg;
-       const struct pam_message *msgp;
-       struct pam_response *resp;
-#endif
-       struct passwd *pwd;
-       const char *user;
-       char *crypt_password, *password;
-       int pam_err, retry;
-
-       /* identify user */
-       if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
-               return (pam_err);
-       if ((pwd = getpwnam(user)) == NULL)
-               return (PAM_USER_UNKNOWN);
-
-       /* get password */
-#ifndef _OPENPAM
-       pam_err = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
-       if (pam_err != PAM_SUCCESS)
-               return (PAM_SYSTEM_ERR);
-       msg.msg_style = PAM_PROMPT_ECHO_OFF;
-       msg.msg = password_prompt;
-       msgp = &msg;
-#endif
-       for (retry = 0; retry < 3; ++retry) {
-#ifdef _OPENPAM
-               pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
-                   (const char **)&password, NULL);
-#else
-               resp = NULL;
-               pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
-               if (resp != NULL) {
-                       if (pam_err == PAM_SUCCESS)
-                               password = resp->resp;
-                       else
-                               free(resp->resp);
-                       free(resp);
-               }
-#endif
-               if (pam_err == PAM_SUCCESS)
-                       break;
-       }
-       if (pam_err == PAM_CONV_ERR)
-               return (pam_err);
-       if (pam_err != PAM_SUCCESS)
-               return (PAM_AUTH_ERR);
-
-       /* compare passwords */
-       if ((!pwd->pw_passwd[0] && (flags & PAM_DISALLOW_NULL_AUTHTOK)) ||
-           (crypt_password = crypt(password, pwd->pw_passwd)) == NULL ||
-           strcmp(crypt_password, pwd->pw_passwd) != 0)
-               pam_err = PAM_AUTH_ERR;
-       else
-               pam_err = PAM_SUCCESS;
-#ifndef _OPENPAM
-       free(password);
-#endif
-       return (pam_err);
-}
-
-PAM_EXTERN int
-pam_sm_setcred(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
-{
-
-       return (PAM_SUCCESS);
-}
-
-PAM_EXTERN int
-pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
-{
-
-       return (PAM_SUCCESS);
-}
-
-PAM_EXTERN int
-pam_sm_open_session(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
-{
-
-       return (PAM_SUCCESS);
-}
-
-PAM_EXTERN int
-pam_sm_close_session(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
-{
-
-       return (PAM_SUCCESS);
-}
-
-PAM_EXTERN int
-pam_sm_chauthtok(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
-{
-
-       return (PAM_SERVICE_ERR);
-}
-
-#ifdef PAM_MODULE_ENTRY
-PAM_MODULE_ENTRY("pam_unix");
-#endif
index 7ed36bd..591b41a 100644 (file)
@@ -1,10 +1,8 @@
-# $DragonFly: src/lib/pam_module/pam_deny/Makefile,v 1.1 2005/07/08 15:42:01 joerg Exp $
+# $DragonFly: src/lib/pam_module/pam_deny/Makefile,v 1.2 2005/08/01 16:15:19 joerg Exp $
 
 LIB=   pam_deny
 SRCS=  pam_deny.c
 WARNS?=        6
-WARNS_NO_UNUSED_PARAMETERS=
+MAN=   pam_deny.8
 
 .include <bsd.lib.mk>
-
-.PATH: ${OPENPAM_DIR}/modules/pam_deny
diff --git a/lib/pam_module/pam_deny/pam_deny.8 b/lib/pam_module/pam_deny/pam_deny.8
new file mode 100644 (file)
index 0000000..8ccc653
--- /dev/null
@@ -0,0 +1,81 @@
+.\" Copyright (c) 2001 Mark R V Murray
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libpam/modules/pam_deny/pam_deny.8,v 1.4 2001/08/15 20:05:30 markm Exp $
+.\" $DragonFly: src/lib/pam_module/pam_deny/pam_deny.8,v 1.1 2005/08/01 16:15:19 joerg Exp $
+.\"
+.Dd July 7, 2001
+.Dt PAM_DENY 8
+.Os
+.Sh NAME
+.Nm pam_deny
+.Nd Deny PAM module
+.Sh SYNOPSIS
+.Op Ar service-name
+.Ar module-type
+.Ar control-flag
+.Pa pam_deny
+.Op Ar options
+.Sh DESCRIPTION
+The Deny authentication service module for PAM,
+.Nm
+provides functionality for all the PAM categories:
+authentication,
+account management,
+session management and
+password management.
+In terms of the
+.Ar module-type
+parameter, these are the
+.Dq Li auth ,
+.Dq Li account ,
+.Dq Li session ,
+and
+.Dq Li password
+features.
+.Pp
+The Deny module
+will universally deny all requests.
+It is primarily of use during testing,
+and to
+.Dq null-out
+unwanted functionality.
+.Pp
+The following options may be passed to the module:
+.Bl -tag -width ".Cm no_warn"
+.It Cm debug
+.Xr syslog 3
+debugging information at
+.Dv LOG_DEBUG
+level.
+.It Cm no_warn
+suppress warning messages to the user.
+These messages include
+reasons why the user's
+authentication attempt was declined.
+.El
+.Sh SEE ALSO
+.Xr syslog 3 ,
+.Xr pam.conf 5 ,
+.Xr pam 8
similarity index 58%
rename from contrib/openpam/modules/pam_deny/pam_deny.c
rename to lib/pam_module/pam_deny/pam_deny.c
index e2d9a80..d881ec5 100644 (file)
@@ -1,12 +1,7 @@
 /*-
- * Copyright (c) 2002-2003 Networks Associates Technology, Inc.
+ * Copyright 2001 Mark R V Murray
  * All rights reserved.
  *
- * This software was developed for the FreeBSD Project by ThinkSec AS and
- * Network Associates Laboratories, the Security Research Division of
- * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -15,9 +10,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $P4: //depot/projects/openpam/modules/pam_deny/pam_deny.c#10 $
+ * $FreeBSD: src/lib/libpam/modules/pam_deny/pam_deny.c,v 1.10 2005/06/10 06:16:13 des Exp $
+ * $DragonFly: src/lib/pam_module/pam_deny/pam_deny.c,v 1.1 2005/08/01 16:15:19 joerg Exp $
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <stddef.h>
 
-#include <sys/param.h>
+#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
+#define PAM_SM_SESSION
+#define PAM_SM_PASSWORD
 
+#include <security/pam_appl.h>
 #include <security/pam_modules.h>
 
 PAM_EXTERN int
-pam_sm_authenticate(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
+       const char *user;
+       int r;
+
+       if ((r = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
+               return (r);
 
        return (PAM_AUTH_ERR);
 }
 
 PAM_EXTERN int
-pam_sm_setcred(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
        return (PAM_CRED_ERR);
 }
 
 PAM_EXTERN int
-pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_acct_mgmt(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
        return (PAM_AUTH_ERR);
 }
 
 PAM_EXTERN int
-pam_sm_open_session(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_chauthtok(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
-       return (PAM_SESSION_ERR);
+       return (PAM_AUTHTOK_ERR);
 }
 
 PAM_EXTERN int
-pam_sm_close_session(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_open_session(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
        return (PAM_SESSION_ERR);
 }
 
 PAM_EXTERN int
-pam_sm_chauthtok(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_close_session(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
-       return (PAM_AUTHTOK_ERR);
+       return (PAM_SESSION_ERR);
 }
 
 PAM_MODULE_ENTRY("pam_deny");
index f238915..d0417fd 100644 (file)
@@ -1,10 +1,8 @@
-# $DragonFly: src/lib/pam_module/pam_permit/Makefile,v 1.1 2005/07/08 15:42:01 joerg Exp $
+# $DragonFly: src/lib/pam_module/pam_permit/Makefile,v 1.2 2005/08/01 16:15:19 joerg Exp $
 
 LIB=   pam_permit
 SRCS=  pam_permit.c
-WARNS?=        2
-WARNS_NO_UNUSED_PARAMETERS=
+WARNS?=        6
+MAN=   pam_permit.8
 
 .include <bsd.lib.mk>
-
-.PATH: ${OPENPAM_DIR}/modules/pam_permit
diff --git a/lib/pam_module/pam_permit/pam_permit.8 b/lib/pam_module/pam_permit/pam_permit.8
new file mode 100644 (file)
index 0000000..05091ec
--- /dev/null
@@ -0,0 +1,76 @@
+.\" Copyright (c) 2001 Mark R V Murray
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libpam/modules/pam_permit/pam_permit.8,v 1.3 2001/07/13 09:09:50 ru Exp $
+.\" $DragonFly: src/lib/pam_module/pam_permit/pam_permit.8,v 1.1 2005/08/01 16:15:19 joerg Exp $
+.\"
+.Dd July 7, 2001
+.Dt PAM_PERMIT 8
+.Os
+.Sh NAME
+.Nm pam_permit
+.Nd Promiscuous PAM module
+.Sh SYNOPSIS
+.Op Ar service-name
+.Ar module-type
+.Ar control-flag
+.Pa pam_permit
+.Op Ar options
+.Sh DESCRIPTION
+The Promiscuous authentication service module for PAM,
+.Nm
+provides functionality for all the PAM categories:
+authentication,
+account management,
+session management and
+password management.
+In terms of the
+.Ar module-type
+parameter, these are the
+.Dq Li auth ,
+.Dq Li account ,
+.Dq Li session ,
+and
+.Dq Li password
+features.
+.Pp
+The Promiscuous module
+will universally allow all requests.
+It is primarily of use during testing,
+and to silence
+.Dq noisy
+PAM-enabled applications.
+.Pp
+The following options may be passed to the module:
+.Bl -tag -width ".Cm debug"
+.It Cm debug
+.Xr syslog 3
+debugging information at
+.Dv LOG_DEBUG
+level.
+.El
+.Sh SEE ALSO
+.Xr syslog 3 ,
+.Xr pam.conf 5 ,
+.Xr pam 8
similarity index 58%
rename from contrib/openpam/modules/pam_permit/pam_permit.c
rename to lib/pam_module/pam_permit/pam_permit.c
index 802450e..1079776 100644 (file)
@@ -1,12 +1,7 @@
 /*-
- * Copyright (c) 2002-2003 Networks Associates Technology, Inc.
+ * Copyright 2001 Mark R V Murray
  * All rights reserved.
  *
- * This software was developed for the FreeBSD Project by ThinkSec AS and
- * Network Associates Laboratories, the Security Research Division of
- * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -15,9 +10,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $P4: //depot/projects/openpam/modules/pam_permit/pam_permit.c#9 $
+ * $FreeBSD: src/lib/libpam/modules/pam_permit/pam_permit.c,v 1.8 2002/04/12 22:27:22 des Exp $
+ * $DragonFly: src/lib/pam_module/pam_permit/pam_permit.c,v 1.1 2005/08/01 16:15:19 joerg Exp $
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <stddef.h>
 
-#include <sys/param.h>
+#define        PAM_SM_AUTH
+#define        PAM_SM_ACCOUNT
+#define        PAM_SM_SESSION
+#define        PAM_SM_PASSWORD
 
+#include <security/pam_appl.h>
 #include <security/pam_modules.h>
 
 PAM_EXTERN int
-pam_sm_authenticate(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
+       const char *user;
+       int r;
+
+       if ((r = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
+               return (r);
 
        return (PAM_SUCCESS);
 }
 
 PAM_EXTERN int
-pam_sm_setcred(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
        return (PAM_SUCCESS);
 }
 
 PAM_EXTERN int
-pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_acct_mgmt(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
        return (PAM_SUCCESS);
 }
 
 PAM_EXTERN int
-pam_sm_open_session(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_chauthtok(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
        return (PAM_SUCCESS);
 }
 
 PAM_EXTERN int
-pam_sm_close_session(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_open_session(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
        return (PAM_SUCCESS);
 }
 
 PAM_EXTERN int
-pam_sm_chauthtok(pam_handle_t *pamh, int flags,
-       int argc, const char *argv[])
+pam_sm_close_session(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
 {
 
        return (PAM_SUCCESS);
index 4d2ba2d..bbd1675 100644 (file)
@@ -1,9 +1,9 @@
-# $DragonFly: src/lib/pam_module/pam_unix/Makefile,v 1.3 2005/07/28 19:25:41 joerg Exp $
+# $DragonFly: src/lib/pam_module/pam_unix/Makefile,v 1.4 2005/08/01 16:15:19 joerg Exp $
 
 LIB=   pam_unix
 SRCS=  pam_unix.c
-WARNS?=        2
-WARNS_NO_UNUSED_PARAMETERS=
+WARNS?=        6
+MAN=   pam_unix.8
 
 DPADD= ${LIBCRYPT}
 LDADD= -lcrypt
diff --git a/lib/pam_module/pam_unix/pam_unix.8 b/lib/pam_module/pam_unix/pam_unix.8
new file mode 100644 (file)
index 0000000..6f11b2f
--- /dev/null
@@ -0,0 +1,202 @@
+.\" Copyright (c) 2001 Mark R V Murray
+.\" All rights reserved.
+.\" Copyright (c) 2001 Networks Associates Technology, Inc.
+.\" All rights reserved.
+.\"
+.\" This software was developed for the FreeBSD Project by ThinkSec AS and
+.\" NAI Labs, the Security Research Division of Network Associates, Inc.
+.\" under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
+.\" DARPA CHATS research program.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. The name of the author may not be used to endorse or promote
+.\"    products derived from this software without specific prior written
+.\"    permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libpam/modules/pam_unix/pam_unix.8,v 1.11 2005/01/21 10:44:10 ru Exp $
+.\" $DragonFly: src/lib/pam_module/pam_unix/pam_unix.8,v 1.1 2005/08/01 16:15:19 joerg Exp $
+.\"
+.Dd November 26, 2001
+.Dt PAM_UNIX 8
+.Os
+.Sh NAME
+.Nm pam_unix
+.Nd UNIX PAM module
+.Sh SYNOPSIS
+.Op Ar service-name
+.Ar module-type
+.Ar control-flag
+.Pa pam_unix
+.Op Ar options
+.Sh DESCRIPTION
+The
+.Ux
+authentication service module for PAM,
+.Nm
+provides functionality for two PAM categories:
+authentication
+and account management.
+In terms of the
+.Ar module-type
+parameter, they are the
+.Dq Li auth
+and
+.Dq Li account
+features.
+It also provides a null function for session management.
+.Ss Ux Ss Authentication Module
+The
+.Ux
+authentication component
+provides functions to verify the identity of a user
+.Pq Fn pam_sm_authenticate ,
+which obtains the relevant
+.Xr passwd 5
+entry.
+It prompts the user for a password
+and verifies that this is correct with
+.Xr crypt 3 .
+.Pp
+The following options may be passed to the authentication module:
+.Bl -tag -width ".Cm use_first_pass"
+.It Cm debug
+.Xr syslog 3
+debugging information at
+.Dv LOG_DEBUG
+level.
+.It Cm use_first_pass
+If the authentication module
+is not the first in the stack,
+and a previous module
+obtained the user's password,
+that password is used
+to authenticate the user.
+If this fails,
+the authentication module returns failure
+without prompting the user for a password.
+This option has no effect
+if the authentication module
+is the first in the stack,
+or if no previous modules
+obtained the user's password.
+.It Cm try_first_pass
+This option is similar to the
+.Cm use_first_pass
+option,
+except that if the previously obtained password fails,
+the user is prompted for another password.
+.It Cm auth_as_self
+This option will require the user
+to authenticate himself as the user
+given by
+.Xr getlogin 2 ,
+not as the account they are attempting to access.
+This is primarily for services like
+.Xr su 1 ,
+where the user's ability to retype
+their own password
+might be deemed sufficient.
+.It Cm nullok
+If the password database
+has no password
+for the entity being authenticated,
+then this option
+will forgo password prompting,
+and silently allow authentication to succeed.
+.It Cm local_pass
+Use only the local password database,
+even if NIS is in use.
+This will cause an authentication failure
+if the system is configured
+to only use NIS.
+.It Cm nis_pass
+Use only the NIS password database.
+This will cause an authentication failure
+if the system is not configured
+to use NIS.
+.El
+.Ss Ux Ss Account Management Module
+The
+.Ux
+account management component
+provides a function to perform account management,
+.Fn pam_sm_acct_mgmt .
+The function verifies
+that the authenticated user
+is allowed to login to the local user account
+by checking the password expiry date.
+.Pp
+The following options may be passed to the management module:
+.Bl -tag -width ".Cm use_first_pass"
+.It Cm debug
+.Xr syslog 3
+debugging information at
+.Dv LOG_DEBUG
+level.
+.El
+.Ss Ux Ss Password Management Module
+The
+.Ux
+password management component
+provides a function to perform account management,
+.Fn pam_sm_chauthtok .
+The function changes
+the user's password.
+.Pp
+The following options may be passed to the password module:
+.Bl -tag -width ".Cm use_first_pass"
+.It Cm debug
+.Xr syslog 3
+debugging information at
+.Dv LOG_DEBUG
+level.
+.It Cm no_warn
+suppress warning messages to the user.
+These messages include
+reasons why the user's
+authentication attempt was declined.
+.It Cm local_pass
+forces the password module
+to change a local password
+in favour of a NIS one.
+.It Cm nis_pass
+forces the password module
+to change a NIS password
+in favour of a local one.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /etc/master.passwd" -compact
+.It Pa /etc/master.passwd
+default
+.Ux
+password database.
+.El
+.Sh SEE ALSO
+.Xr passwd 1 ,
+.Xr getlogin 2 ,
+.Xr crypt 3 ,
+.Xr getpwent 3 ,
+.Xr syslog 3 ,
+.Xr nsswitch.conf 5 ,
+.Xr passwd 5 ,
+.Xr pam 8 ,
+.Xr yp 8
diff --git a/lib/pam_module/pam_unix/pam_unix.c b/lib/pam_module/pam_unix/pam_unix.c
new file mode 100644 (file)
index 0000000..7c06779
--- /dev/null
@@ -0,0 +1,470 @@
+/*-
+ * Copyright 1998 Juniper Networks, Inc.
+ * All rights reserved.
+ * Copyright (c) 2002-2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software was developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libpam/modules/pam_unix/pam_unix.c,v 1.51 2005/07/05 18:42:18 des Exp $
+ * $DragonFly: src/lib/pam_module/pam_unix/pam_unix.c,v 1.1 2005/08/01 16:15:19 joerg Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <login_cap.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <libutil.h>
+
+#ifdef YP
+#include <ypclnt.h>
+#endif
+
+#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
+#define        PAM_SM_PASSWORD
+
+#include <security/pam_appl.h>
+#include <security/pam_modules.h>
+#include <security/pam_mod_misc.h>
+
+#define PASSWORD_HASH          "md5"
+#define DEFAULT_WARN           (2L * 7L * 86400L)  /* Two weeks */
+#define        SALTSIZE                32
+
+static void makesalt(char []);
+
+static char password_hash[] =          PASSWORD_HASH;
+
+#define PAM_OPT_LOCAL_PASS     "local_pass"
+#define PAM_OPT_NIS_PASS       "nis_pass"
+
+char *tempname = NULL;
+
+/*
+ * authentication management
+ */
+PAM_EXTERN int
+pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
+{
+       login_cap_t *lc;
+       struct passwd *pwd;
+       int retval;
+       const char *pass, *user, *realpw, *prompt;
+
+       if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) {
+               pwd = getpwnam(getlogin());
+       } else {
+               retval = pam_get_user(pamh, &user, NULL);
+               if (retval != PAM_SUCCESS)
+                       return (retval);
+               pwd = getpwnam(user);
+       }
+
+       PAM_LOG("Got user: %s", user);
+
+       if (pwd != NULL) {
+               PAM_LOG("Doing real authentication");
+               realpw = pwd->pw_passwd;
+               if (realpw[0] == '\0') {
+                       if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) &&
+                           openpam_get_option(pamh, PAM_OPT_NULLOK))
+                               return (PAM_SUCCESS);
+                       realpw = "*";
+               }
+               lc = login_getpwclass(pwd);
+       } else {
+               PAM_LOG("Doing dummy authentication");
+               realpw = "*";
+               lc = login_getclass(NULL);
+       }
+       prompt = login_getcapstr(lc, "passwd_prompt", NULL, NULL);
+       retval = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, prompt);
+       login_close(lc);
+       if (retval != PAM_SUCCESS)
+               return (retval);
+       PAM_LOG("Got password");
+       if (strcmp(crypt(pass, realpw), realpw) == 0)
+               return (PAM_SUCCESS);
+
+       return (PAM_AUTH_ERR);
+}
+
+PAM_EXTERN int
+pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
+{
+
+       return (PAM_SUCCESS);
+}
+
+/*
+ * account management
+ */
+PAM_EXTERN int
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused,
+    int argc __unused, const char *argv[] __unused)
+{
+       struct addrinfo hints, *res;
+       struct passwd *pwd;
+       struct timeval tp;
+       login_cap_t *lc;
+       time_t warntime;
+       int retval;
+       const char *user;
+       const void *rhost, *tty;
+       char rhostip[MAXHOSTNAMELEN] = "";
+
+       retval = pam_get_user(pamh, &user, NULL);
+       if (retval != PAM_SUCCESS)
+               return (retval);
+
+       if (user == NULL || (pwd = getpwnam(user)) == NULL)
+               return (PAM_SERVICE_ERR);
+
+       PAM_LOG("Got user: %s", user);
+
+       retval = pam_get_item(pamh, PAM_RHOST, &rhost);
+       if (retval != PAM_SUCCESS)
+               return (retval);
+
+       retval = pam_get_item(pamh, PAM_TTY, &tty);
+       if (retval != PAM_SUCCESS)
+               return (retval);
+
+       if (*pwd->pw_passwd == '\0' &&
+           (flags & PAM_DISALLOW_NULL_AUTHTOK) != 0)
+               return (PAM_NEW_AUTHTOK_REQD);
+
+       lc = login_getpwclass(pwd);
+       if (lc == NULL) {
+               PAM_LOG("Unable to get login class for user %s", user);
+               return (PAM_SERVICE_ERR);
+       }
+
+       PAM_LOG("Got login_cap");
+
+       if (pwd->pw_change || pwd->pw_expire)
+               gettimeofday(&tp, NULL);
+
+       /*
+        * Check pw_expire before pw_change - no point in letting the
+        * user change the password on an expired account.
+        */
+
+       if (pwd->pw_expire) {
+               warntime = login_getcaptime(lc, "warnexpire",
+                   DEFAULT_WARN, DEFAULT_WARN);
+               if (tp.tv_sec >= pwd->pw_expire) {
+                       login_close(lc);
+                       return (PAM_ACCT_EXPIRED);
+               } else if (pwd->pw_expire - tp.tv_sec < warntime &&
+                   (flags & PAM_SILENT) == 0) {
+                       pam_error(pamh, "Warning: your account expires on %s",
+                           ctime(&pwd->pw_expire));
+               }
+       }
+
+       retval = PAM_SUCCESS;
+       if (pwd->pw_change) {
+               warntime = login_getcaptime(lc, "warnpassword",
+                   DEFAULT_WARN, DEFAULT_WARN);
+               if (tp.tv_sec >= pwd->pw_change) {
+                       retval = PAM_NEW_AUTHTOK_REQD;
+               } else if (pwd->pw_change - tp.tv_sec < warntime &&
+                   (flags & PAM_SILENT) == 0) {
+                       pam_error(pamh, "Warning: your password expires on %s",
+                           ctime(&pwd->pw_change));
+               }
+       }
+
+       /*
+        * From here on, we must leave retval untouched (unless we
+        * know we're going to fail), because we need to remember
+        * whether we're supposed to return PAM_SUCCESS or
+        * PAM_NEW_AUTHTOK_REQD.
+        */
+
+       if (rhost && *(const char *)rhost != '\0') {
+               memset(&hints, 0, sizeof(hints));
+               hints.ai_family = AF_UNSPEC;
+               if (getaddrinfo(rhost, NULL, &hints, &res) == 0) {
+                       getnameinfo(res->ai_addr, res->ai_addrlen,
+                           rhostip, sizeof(rhostip), NULL, 0,
+                           NI_NUMERICHOST);
+               }
+               if (res != NULL)
+                       freeaddrinfo(res);
+       }
+
+       /*
+        * Check host / tty / time-of-day restrictions
+        */
+
+       if (!auth_hostok(lc, rhost, rhostip) ||
+           !auth_ttyok(lc, tty) ||
+           !auth_timeok(lc, time(NULL)))
+               retval = PAM_AUTH_ERR;
+
+       login_close(lc);
+
+       return (retval);
+}
+
+/*
+ * password management
+ *
+ * standard Unix and NIS password changing
+ */
+PAM_EXTERN int
+pam_sm_chauthtok(pam_handle_t *pamh, int flags,
+    int argc __unused, const char *argv[] __unused)
+{
+#ifdef YP
+       struct ypclnt *ypclnt;
+       void *yp_domain, *yp_server;
+#endif
+       char salt[SALTSIZE + 1];
+       login_cap_t * lc;
+       struct passwd *pwd, *old_pwd;
+       const char *user, *old_pass, *new_pass;
+       char *encrypted;
+       int pfd, tfd, retval = PAM_ABORT;
+
+       if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF))
+               pwd = getpwnam(getlogin());
+       else {
+               retval = pam_get_user(pamh, &user, NULL);
+               if (retval != PAM_SUCCESS)
+                       return (retval);
+               pwd = getpwnam(user);
+       }
+
+       if (pwd == NULL)
+               return (PAM_AUTHTOK_RECOVERY_ERR);
+
+       PAM_LOG("Got user: %s", user);
+
+       if (flags & PAM_PRELIM_CHECK) {
+
+               PAM_LOG("PRELIM round");
+
+               if (getuid() == 0
+#if 0
+                   && (pwd->pw_fields & _PWF_SOURCE) == _PWF_FILES
+#endif
+                   )
+                       /* root doesn't need the old password */
+                       return (pam_set_item(pamh, PAM_OLDAUTHTOK, ""));
+#ifdef YP
+               if (getuid() == 0
+#if 0
+                   && (pwd->pw_fields & _PWF_SOURCE) == _PWF_NIS
+#endif
+                   ) {
+
+                       yp_domain = yp_server = NULL;
+                       (void)pam_get_data(pamh, "yp_domain", &yp_domain);
+                       (void)pam_get_data(pamh, "yp_server", &yp_server);
+
+                       ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_server);
+                       if (ypclnt == NULL)
+                               return (PAM_BUF_ERR);
+
+                       if (ypclnt_connect(ypclnt) == -1) {
+                               ypclnt_free(ypclnt);
+                               return (PAM_SERVICE_ERR);
+                       }
+
+                       retval = ypclnt_havepasswdd(ypclnt);
+                       ypclnt_free(ypclnt);
+                       if (retval == 1)
+                               return (pam_set_item(pamh, PAM_OLDAUTHTOK, ""));
+                       else if (retval == -1)
+                               return (PAM_SERVICE_ERR);
+               }
+#endif
+               if (pwd->pw_passwd[0] == '\0'
+                   && openpam_get_option(pamh, PAM_OPT_NULLOK)) {
+                       /*
+                        * No password case. XXX Are we giving too much away
+                        * by not prompting for a password?
+                        * XXX check PAM_DISALLOW_NULL_AUTHTOK
+                        */
+                       old_pass = "";
+               } else {
+                       retval = pam_get_authtok(pamh,
+                           PAM_OLDAUTHTOK, &old_pass, NULL);
+                       if (retval != PAM_SUCCESS)
+                               return (retval);
+               }
+               PAM_LOG("Got old password");
+               /* always encrypt first */
+               encrypted = crypt(old_pass, pwd->pw_passwd);
+               if (old_pass[0] == '\0' &&
+                   !openpam_get_option(pamh, PAM_OPT_NULLOK))
+                       return (PAM_PERM_DENIED);
+               if (strcmp(encrypted, pwd->pw_passwd) != 0)
+                       return (PAM_PERM_DENIED);
+       }
+       else if (flags & PAM_UPDATE_AUTHTOK) {
+               PAM_LOG("UPDATE round");
+
+               retval = pam_get_authtok(pamh,
+                   PAM_OLDAUTHTOK, &old_pass, NULL);
+               if (retval != PAM_SUCCESS)
+                       return (retval);
+               PAM_LOG("Got old password");
+
+               /* get new password */
+               for (;;) {
+                       retval = pam_get_authtok(pamh,
+                           PAM_AUTHTOK, &new_pass, NULL);
+                       if (retval != PAM_TRY_AGAIN)
+                               break;
+                       pam_error(pamh, "Mismatch; try again, EOF to quit.");
+               }
+               PAM_LOG("Got new password");
+               if (retval != PAM_SUCCESS) {
+                       PAM_VERBOSE_ERROR("Unable to get new password");
+                       return (retval);
+               }
+
+               if (getuid() != 0 && new_pass[0] == '\0' &&
+                   !openpam_get_option(pamh, PAM_OPT_NULLOK))
+                       return (PAM_PERM_DENIED);
+
+               if ((old_pwd = pw_dup(pwd)) == NULL)
+                       return (PAM_BUF_ERR);
+
+               pwd->pw_change = 0;
+               lc = login_getclass(pwd->pw_class);
+               if (login_setcryptfmt(lc, password_hash, NULL) == NULL)
+                       openpam_log(PAM_LOG_ERROR,
+                           "can't set password cipher, relying on default");
+               login_close(lc);
+               makesalt(salt);
+               pwd->pw_passwd = crypt(new_pass, salt);
+#ifdef YP
+               switch (old_pwd->pw_fields & _PWF_SOURCE) {
+               case _PWF_FILES:
+#endif
+                       retval = PAM_SERVICE_ERR;
+                       if (pw_init(NULL, NULL))
+                               openpam_log(PAM_LOG_ERROR, "pw_init() failed");
+                       else if ((pfd = pw_lock()) == -1)
+                               openpam_log(PAM_LOG_ERROR, "pw_lock() failed");
+                       else if ((tfd = pw_tmp(-1)) == -1)
+                               openpam_log(PAM_LOG_ERROR, "pw_tmp() failed");
+                       else if (pw_copy(pfd, tfd, pwd, old_pwd) == -1)
+                               openpam_log(PAM_LOG_ERROR, "pw_copy() failed");
+                       else if (pw_mkdb(pwd->pw_name) == -1)
+                               openpam_log(PAM_LOG_ERROR, "pw_mkdb() failed");
+                       else
+                               retval = PAM_SUCCESS;
+                       pw_fini();
+#ifdef YP
+                       break;
+               case _PWF_NIS:
+                       yp_domain = yp_server = NULL;
+                       (void)pam_get_data(pamh, "yp_domain", &yp_domain);
+                       (void)pam_get_data(pamh, "yp_server", &yp_server);
+                       ypclnt = ypclnt_new(yp_domain,
+                           "passwd.byname", yp_server);
+                       if (ypclnt == NULL) {
+                               retval = PAM_BUF_ERR;
+                       } else if (ypclnt_connect(ypclnt) == -1 ||
+                           ypclnt_passwd(ypclnt, pwd, old_pass) == -1) {
+                               openpam_log(PAM_LOG_ERROR, "%s", ypclnt->error);
+                               retval = PAM_SERVICE_ERR;
+                       } else {
+                               retval = PAM_SUCCESS;
+                       }
+                       ypclnt_free(ypclnt);
+                       break;
+               default:
+                       openpam_log(PAM_LOG_ERROR, "unsupported source 0x%x",
+                           pwd->pw_fields & _PWF_SOURCE);
+                       retval = PAM_SERVICE_ERR;
+               }
+#endif
+               free(old_pwd);
+       }
+       else {
+               /* Very bad juju */
+               retval = PAM_ABORT;
+               PAM_LOG("Illegal 'flags'");
+       }
+
+       return (retval);
+}
+
+/* Mostly stolen from passwd(1)'s local_passwd.c - markm */
+
+static unsigned char itoa64[] =                /* 0 ... 63 => ascii - 64 */
+       "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void
+to64(char *s, long v, int n)
+{
+       while (--n >= 0) {
+               *s++ = itoa64[v&0x3f];
+               v >>= 6;
+       }
+}
+
+/* Salt suitable for traditional DES and MD5 */
+void
+makesalt(char salt[SALTSIZE])
+{
+       int i;
+
+       /* These are not really random numbers, they are just
+        * numbers that change to thwart construction of a
+        * dictionary. This is exposed to the public.
+        */
+       for (i = 0; i < SALTSIZE; i += 4)
+               to64(&salt[i], arc4random(), 4);
+       salt[SALTSIZE] = '\0';
+}
+
+PAM_MODULE_ENTRY("pam_unix");