summaryrefslogtreecommitdiff
path: root/contrib/libpam/modules/pam_unix/pam_unix_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpam/modules/pam_unix/pam_unix_auth.c')
-rw-r--r--contrib/libpam/modules/pam_unix/pam_unix_auth.c347
1 files changed, 132 insertions, 215 deletions
diff --git a/contrib/libpam/modules/pam_unix/pam_unix_auth.c b/contrib/libpam/modules/pam_unix/pam_unix_auth.c
index 95f13d0abdc69..f08ea515b4d48 100644
--- a/contrib/libpam/modules/pam_unix/pam_unix_auth.c
+++ b/contrib/libpam/modules/pam_unix/pam_unix_auth.c
@@ -1,8 +1,7 @@
-/* $Header: /home/morgan/pam/Linux-PAM-0.59/modules/pam_unix/RCS/pam_unix_auth.c,v 1.1 1996/11/09 19:44:35 morgan Exp morgan $ */
-
/*
* Copyright Alexander O. Yuriev, 1996. All rights reserved.
* NIS+ support by Thorsten Kukuk <kukuk@weber.uni-paderborn.de>
+ * Copyright Jan Rêkorajski, 1999. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,217 +34,145 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-/*
- * $Log: pam_unix_auth.c,v $
- *
- * Revision 1.9 1996/05/26 04:13:04 morgan
- * added static support
- *
- * Revision 1.8 1996/05/21 03:51:58 morgan
- * added "const" to rcsid[] definition
- *
- * Revision 1.7 1996/04/19 03:25:57 alex
- * minor corrections.
- *
- * Revision 1.6 1996/04/17 01:05:05 alex
- * _pam_auth_unix() cleaned up - non-authentication code is made into funcs
- * and mostly moved out to support.c.
- *
- * Revision 1.5 1996/04/16 21:12:46 alex
- * unix authentication works on Bach again. This is a tranitional stage.
- * I really don't like that _pam_unix_auth() grew into a monster that does
- * prompts etc etc. They should go into other functions.
- *
- * Revision 1.4 1996/04/07 08:06:12 morgan
- * tidied up a little
- *
- * Revision 1.3 1996/04/07 07:34:07 morgan
- * added conversation support. Now the module is capable of obtaining a
- * username and a password all by itself.
- *
- * Revision 1.2 1996/03/29 02:31:19 morgan
- * Marek Michalkiewicz's small patches for shadow support.
- *
- * Revision 1.1 1996/03/09 09:10:57 morgan
- * Initial revision
- *
- */
-#ifdef linux
-# define _GNU_SOURCE
-# include <features.h>
-#endif
+/* #define DEBUG */
+
+#include <security/_pam_aconf.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
-#define __USE_BSD
#include <unistd.h>
-#include <pwd.h>
+#include <fcntl.h>
+#include <ctype.h>
#include <sys/types.h>
+#include <sys/stat.h>
-#ifndef NDEBUG
-
-#include <syslog.h>
-
-#endif /* NDEBUG */
-
-#ifdef HAVE_SHADOW_H
-
-#include <shadow.h>
-
-#endif /* HAVE_SHADOW_H */
-
-#ifndef LINUX
-
-#include <security/pam_appl.h>
+/* indicate the following groups are defined */
-#endif /* LINUX */
+#define PAM_SM_AUTH
#define _PAM_EXTERN_FUNCTIONS
+#include <security/_pam_macros.h>
#include <security/pam_modules.h>
-static const char rcsid[] = "$Id: pam_unix_auth.c,v 1.1 1996/11/09 19:44:35 morgan Exp morgan $ pam_unix authentication functions. alex@bach.cis.temple.edu";
-
-/* Define function phototypes */
-
-extern char *crypt(const char *key, const char *salt); /* This should have
- been in unistd.h
- but it is not */
-extern int converse( pam_handle_t *pamh,
- int nargs,
- struct pam_message **message,
- struct pam_response **response );
-
-extern int _set_auth_tok( pam_handle_t *pamh,
- int flags, int argc,
- const char **argv );
-
-static int _pam_auth_unix( pam_handle_t *pamh,
- int flags, int argc,
- const char **argv );
+#ifndef LINUX_PAM
+#include <security/pam_appl.h>
+#endif /* LINUX_PAM */
-static int _pam_set_credentials_unix ( pam_handle_t *pamh,
- int flags,
- int argc,
- const char ** argv ) ;
+#include "support.h"
+/*
+ * PAM framework looks for these entry-points to pass control to the
+ * authentication module.
+ */
/* Fun starts here :)
- *
- * _pam_auth_unix() actually performs UNIX/shadow authentication
+
+ * pam_sm_authenticate() performs UNIX/shadow authentication
*
- * First, if shadow support is available, attempt to perform
- * authentication using shadow passwords. If shadow is not
- * available, or user does not have a shadow password, fallback
- * onto a normal UNIX authentication
+ * First, if shadow support is available, attempt to perform
+ * authentication using shadow passwords. If shadow is not
+ * available, or user does not have a shadow password, fallback
+ * onto a normal UNIX authentication
*/
-static int _pam_auth_unix( pam_handle_t *pamh,
- int flags,
- int argc,
- const char **argv )
+#define _UNIX_AUTHTOK "-UN*X-PASS"
+
+#define AUTH_RETURN \
+{ \
+ if (on(UNIX_LIKE_AUTH, ctrl) && ret_data) { \
+ D(("recording return code for next time [%d]", \
+ retval)); \
+ pam_set_data(pamh, "unix_setcred_return", \
+ (void *) retval, NULL); \
+ } \
+ D(("done. [%s]", pam_strerror(pamh, retval))); \
+ return retval; \
+}
+
+PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags
+ ,int argc, const char **argv)
{
- int retval;
- struct passwd *pw;
- const char *name;
- char *p, *pp;
- const char *salt;
+ unsigned int ctrl;
+ int retval, *ret_data = NULL;
+ const char *name, *p;
-#ifdef HAVE_SHADOW_H
+ D(("called."));
- struct spwd *sp;
+ ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
-#endif
+ /* Get a few bytes so we can pass our return value to
+ pam_sm_setcred(). */
+ ret_data = malloc(sizeof(int));
/* get the user'name' */
- if ( (retval = pam_get_user( pamh, &name, "login: ") ) != PAM_SUCCESS )
- return retval;
-
- /*
- * at some point we will have to make this module pay
- * attention to arguments, like 'pam_first_pass' etc...
- */
-
- pw = getpwnam ( name );
+ retval = pam_get_user(pamh, &name, "login: ");
+ if (retval == PAM_SUCCESS) {
+ /*
+ * Various libraries at various times have had bugs related to
+ * '+' or '-' as the first character of a user name. Don't take
+ * any chances here. Require that the username starts with an
+ * alphanumeric character.
+ */
+ if (name == NULL || !isalnum(*name)) {
+ _log_err(LOG_ERR, pamh, "bad username [%s]", name);
+ retval = PAM_USER_UNKNOWN;
+ AUTH_RETURN
+ }
+ if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
+ D(("username [%s] obtained", name));
+ } else {
+ D(("trouble reading username"));
+ if (retval == PAM_CONV_AGAIN) {
+ D(("pam_get_user/conv() function is not ready yet"));
+ /* it is safe to resume this function so we translate this
+ * retval to the value that indicates we're happy to resume.
+ */
+ retval = PAM_INCOMPLETE;
+ }
+ AUTH_RETURN
+ }
- /* For NIS+, root cannot get password for lesser user */
- if (pw) {
- uid_t save_euid, save_uid;
+ /* if this user does not have a password... */
- save_uid = getuid ();
- save_euid = geteuid();
- if (setreuid (0,pw->pw_uid) >= 0) {
- pw = getpwnam ( name );
- setreuid (save_uid,save_euid);
- }
+ if (_unix_blankpasswd(ctrl, name)) {
+ D(("user '%s' has blank passwd", name));
+ name = NULL;
+ retval = PAM_SUCCESS;
+ AUTH_RETURN
}
-
- if ( pw && (!pw->pw_passwd || pw->pw_passwd[0] == '\0') &&
- !(flags & PAM_DISALLOW_NULL_AUTHTOK)) {
- return PAM_SUCCESS;
+ /* get this user's authentication token */
+
+ retval = _unix_read_password(pamh, ctrl, NULL, "Password: ", NULL
+ ,_UNIX_AUTHTOK, &p);
+ if (retval != PAM_SUCCESS) {
+ if (retval != PAM_CONV_AGAIN) {
+ _log_err(LOG_CRIT, pamh, "auth could not identify password for [%s]"
+ ,name);
+ } else {
+ D(("conversation function is not ready yet"));
+ /*
+ * it is safe to resume this function so we translate this
+ * retval to the value that indicates we're happy to resume.
+ */
+ retval = PAM_INCOMPLETE;
+ }
+ name = NULL;
+ AUTH_RETURN
}
- pam_get_item( pamh, PAM_AUTHTOK, (void*) &p );
-
- if ( !p )
- {
- retval = _set_auth_tok( pamh, flags, argc, argv );
- if ( retval != PAM_SUCCESS )
- return retval;
- }
-
- /*
- We have to call pam_get_item() again because value of p should
- change
- */
-
- pam_get_item( pamh, PAM_AUTHTOK, (void*) &p );
+ D(("user=%s, password=[%s]", name, p));
+ /* verify the password of this user */
+ retval = _unix_verify_password(pamh, name, p, ctrl);
+ name = p = NULL;
- if (pw)
- {
-
-#ifdef HAVE_SHADOW_H
-
- /*
- * Support for shadow passwords on Linux and SVR4-based
- * systems. Shadow passwords are optional on Linux - if
- * there is no shadow password, use the non-shadow one.
- */
-
- sp = getspnam( name );
- if (sp && (!strcmp(pw->pw_passwd,"x")))
- {
- /* TODO: check if password has expired etc. */
- salt = sp->sp_pwdp;
- }
- else
-#endif
- salt = pw->pw_passwd;
- }
- else
- return PAM_USER_UNKNOWN;
-
- /* The 'always-encrypt' method does not make sense in PAM
- because the framework requires return of a different
- error code for non-existant users -- alex */
-
- if ( ( !pw->pw_passwd ) && ( !p ) )
- if ( flags && PAM_DISALLOW_NULL_AUTHTOK )
- return PAM_SUCCESS;
- else
- return PAM_AUTH_ERR;
-
- pp = crypt(p, salt);
-
- if ( strcmp( pp, salt ) == 0 )
- return PAM_SUCCESS;
-
- return PAM_AUTH_ERR;
+ AUTH_RETURN
}
+
/*
* The only thing _pam_set_credentials_unix() does is initialization of
* UNIX group IDs.
@@ -255,45 +182,35 @@ static int _pam_auth_unix( pam_handle_t *pamh,
* warned you. -- AOY
*/
-static int _pam_set_credentials_unix ( pam_handle_t *pamh,
- int flags,
- int argc,
- const char **argv )
-
-{ /* FIX ME: incorrect error code */
-
- return PAM_SUCCESS; /* This is a wrong result code. From what I
- remember from reafing one of the guides
- there's an error-level saying 'N/A func'
- -- AOY
- */
-}
-
-/*
- * PAM framework looks for these entry-points to pass control to the
- * authentication module.
- */
-
-PAM_EXTERN
-int pam_sm_authenticate( pam_handle_t *pamh,
- int flags,
- int argc,
- const char **argv )
-{
- return _pam_auth_unix( pamh, flags, argc, argv );
-}
-
-PAM_EXTERN
-int pam_sm_setcred( pam_handle_t *pamh,
- int flags,
- int argc,
- const char **argv)
+PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags
+ ,int argc, const char **argv)
{
- return _pam_set_credentials_unix ( pamh, flags, argc, argv ) ;
+ unsigned int ctrl;
+ int retval;
+
+ D(("called."));
+
+ /* FIXME: it shouldn't be necessary to parse the arguments again. The
+ only argument we need is UNIX_LIKE_AUTH: if it was set,
+ pam_get_data will succeed. If it wasn't, it will fail, and we
+ return PAM_SUCCESS. -SRL */
+ ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
+ retval = PAM_SUCCESS;
+
+ if (on(UNIX_LIKE_AUTH, ctrl)) {
+ int *pretval = NULL;
+
+ D(("recovering return code from auth call"));
+ pam_get_data(pamh, "unix_setcred_return", (const void **) pretval);
+ if(pretval) {
+ retval = *pretval;
+ free(pretval);
+ D(("recovered data indicates that old retval was %d", retval));
+ }
+ }
+ return retval;
}
-
-/* static module data */
#ifdef PAM_STATIC
struct pam_module _pam_unix_auth_modstruct = {
"pam_unix_auth",