/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
*/
+#include <afsconfig.h>
+#include <afs/param.h>
+
+#include <roken.h>
+
#include <security/pam_appl.h>
#include <security/pam_modules.h>
-#include <syslog.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pwd.h>
-#include <unistd.h>
-#include <afs/param.h>
-#include <sys/param.h>
+
#include <afs/kautils.h>
+
#include "afs_message.h"
#include "afs_util.h"
#endif
extern int
-pam_sm_setcred(
- pam_handle_t *pamh,
- int flags,
- int argc,
- const char **argv)
+pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char **argv)
{
int retcode = PAM_SUCCESS;
int errcode = PAM_SUCCESS;
int origmask;
int logmask = LOG_UPTO(LOG_INFO);
int nowarn = 0;
- int use_first_pass = 1; /* use the password passed in by auth */
+ int use_first_pass = 1; /* use the password passed in by auth */
int try_first_pass = 0;
int got_authtok = 0;
- int ignore_root = 0;
- int trust_root = 0;
- int set_expires = 0; /* the default is to not to set the env variable */
+ int ignore_uid = 0;
+ int no_unlog = 0;
+ uid_t ignore_uid_id = 0;
+ int refresh_token = 0;
+ int set_expires = 0; /* the default is to not to set the env variable */
+ int use_klog = 0;
int i;
- struct pam_conv *pam_convp = NULL;
+ PAM_CONST struct pam_conv *pam_convp = NULL;
char my_password_buf[256];
+ char *cell_ptr = NULL;
char sbuffer[100];
- char *password = NULL;
int torch_password = 1;
int auth_ok = 0;
- char* lh;
- char *user = NULL;
- long password_expires= -1;
- char* reason = NULL;
+ char *lh;
+ PAM_CONST char *user = NULL;
+ const char *password = NULL;
+ int password_expires = -1;
+ char *reason = NULL;
struct passwd unix_pwd, *upwd = NULL;
- char upwd_buf[2048]; /* size is a guess. */
+ char upwd_buf[2048]; /* size is a guess. */
#ifndef AFS_SUN56_ENV
openlog(pam_afs_ident, LOG_CONS, LOG_AUTH);
* Parse the user options. Log an error for any unknown options.
*/
for (i = 0; i < argc; i++) {
- if ( strcasecmp(argv[i], "debug" ) == 0) {
+ if (strcasecmp(argv[i], "debug") == 0) {
logmask |= LOG_MASK(LOG_DEBUG);
- (void) setlogmask(logmask);
- } else if (strcasecmp(argv[i], "nowarn" ) == 0) {
+ (void)setlogmask(logmask);
+ } else if (strcasecmp(argv[i], "nowarn") == 0) {
nowarn = 1;
} else if (strcasecmp(argv[i], "use_first_pass") == 0) {
- use_first_pass = 1; /* practically redundant */
+ use_first_pass = 1; /* practically redundant */
} else if (strcasecmp(argv[i], "try_first_pass") == 0) {
try_first_pass = 1;
- } else if (strcasecmp(argv[i], "ignore_root" ) == 0) {
- ignore_root = 1;
- } else if (strcasecmp(argv[i], "trust_root" ) == 0) {
- trust_root = 1;
- } else if (strcasecmp(argv[i], "catch_su" ) == 0) {
- use_first_pass = 0;
- } else if (strcasecmp(argv[i], "setenv_password_expires")==0) {
+ } else if (strcasecmp(argv[i], "ignore_root") == 0) {
+ ignore_uid = 1;
+ ignore_uid_id = 0;
+ } else if (strcasecmp(argv[i], "ignore_uid") == 0) {
+ i++;
+ if (i == argc) {
+ pam_afs_syslog(LOG_ERR, PAMAFS_IGNOREUID,
+ "ignore_uid missing argument");
+ ignore_uid = 0;
+ } else {
+ ignore_uid = 1;
+ ignore_uid_id = (uid_t) strtol(argv[i], (char **)NULL, 10);
+ if ((0 > ignore_uid_id) || (ignore_uid_id > IGNORE_MAX)) {
+ ignore_uid = 0;
+ pam_afs_syslog(LOG_ERR, PAMAFS_IGNOREUID, argv[i]);
+ }
+ }
+ } else if (strcasecmp(argv[i], "cell") == 0) {
+ i++;
+ if (i == argc) {
+ pam_afs_syslog(LOG_ERR, PAMAFS_OTHERCELL,
+ "cell missing argument");
+ } else {
+ cell_ptr = (char *)argv[i];
+ pam_afs_syslog(LOG_INFO, PAMAFS_OTHERCELL, cell_ptr);
+ }
+ } else if (strcasecmp(argv[i], "no_unlog") == 0) {
+ no_unlog = 1;
+ } else if (strcasecmp(argv[i], "refresh_token") == 0) {
+ refresh_token = 1;
+ } else if (strcasecmp(argv[i], "set_token") == 0) {
+ ;
+ } else if (strcasecmp(argv[i], "dont_fork") == 0) {
+ ;
+ } else if (strcasecmp(argv[i], "use_klog") == 0) {
+ use_klog = 1;
+ } else if (strcasecmp(argv[i], "setenv_password_expires") == 0) {
set_expires = 1;
} else {
pam_afs_syslog(LOG_ERR, PAMAFS_UNKNOWNOPT, argv[i]);
}
}
- if (use_first_pass) try_first_pass = 0;
+ if (use_first_pass)
+ try_first_pass = 0;
- pam_afs_syslog(LOG_DEBUG, PAMAFS_OPTIONS, nowarn, use_first_pass, try_first_pass);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_OPTIONS, nowarn, use_first_pass,
+ try_first_pass, ignore_uid, ignore_uid_id, 8, 8, 8, 8);
/* Try to get the user-interaction info, if available. */
- errcode = pam_get_item(pamh, PAM_CONV, (void **) &pam_convp);
+ errcode = pam_get_item(pamh, PAM_CONV, (PAM_CONST void **)&pam_convp);
if (errcode != PAM_SUCCESS) {
- pam_afs_syslog(LOG_DEBUG, PAMAFS_NO_USER_INT);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_NO_USER_INT);
pam_convp = NULL;
}
/* Who are we trying to authenticate here? */
- if ((errcode = pam_get_user(pamh, &user, "AFS username:")) != PAM_SUCCESS) {
- pam_afs_syslog(LOG_ERR, PAMAFS_NOUSER, errcode);
- RET(PAM_USER_UNKNOWN);
+ if ((errcode =
+ pam_get_user(pamh, (PAM_CONST char **)&user,
+ "AFS username:")) != PAM_SUCCESS) {
+ pam_afs_syslog(LOG_ERR, PAMAFS_NOUSER, errcode);
+ RET(PAM_USER_UNKNOWN);
}
/*
* If the user has a "local" (or via nss, possibly nss_dce) pwent,
* and its uid==0, and "ignore_root" was given in pam.conf,
* ignore the user.
*/
-#if defined(AFS_HPUX_ENV)
-#if defined(AFS_HPUX110_ENV)
+ /* enhanced: use "ignore_uid <number>" to specify the largest uid
+ * which should be ignored by this module
+ */
+#if defined(AFS_HPUX_ENV) || defined(AFS_DARWIN100_ENV) || defined(AFS_SUN58_ENV)
+#if defined(AFS_HPUX110_ENV) || defined(AFS_DARWIN100_ENV) || defined(AFS_SUN58_ENV)
i = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf), &upwd);
-#else /* AFS_HPUX110_ENV */
+#else /* AFS_HPUX110_ENV */
i = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf));
- if ( i == 0 ) /* getpwnam_r success */
- upwd = &unix_pwd;
-#endif /* AFS_HPUX110_ENV */
- if (ignore_root && i == 0 && upwd->pw_uid == 0) {
- pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
- RET(PAM_AUTH_ERR);
+ if (i == 0) /* getpwnam_r success */
+ upwd = &unix_pwd;
+#endif /* AFS_HPUX110_ENV */
+ if (ignore_uid && i == 0 && upwd && upwd->pw_uid <= ignore_uid_id) {
+ pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
+ RET(PAM_AUTH_ERR);
}
#else
-#ifdef AFS_LINUX20_ENV
+#if defined(AFS_LINUX20_ENV) || defined(AFS_FBSD_ENV) || defined(AFS_DFBSD_ENV) || defined(AFS_NBSD_ENV)
upwd = getpwnam(user);
#else
upwd = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf));
#endif
- if (upwd != NULL && upwd->pw_uid == 0) {
- if (ignore_root) {
- pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
- RET(PAM_AUTH_ERR);
- } else if (trust_root) {
- pam_afs_syslog(LOG_INFO, PAMAFS_TRUSTROOT, user);
- RET(PAM_SUCCESS);
- }
+ if (ignore_uid && upwd != NULL && upwd->pw_uid <= ignore_uid_id) {
+ pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
+ RET(PAM_AUTH_ERR);
}
#endif
if (flags & PAM_DELETE_CRED) {
- pam_afs_syslog(LOG_DEBUG, PAMAFS_DELCRED, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_DELCRED, user);
RET(PAM_SUCCESS);
} else if (flags & PAM_REINITIALIZE_CRED) {
- pam_afs_syslog(LOG_DEBUG, PAMAFS_REINITCRED, user);
- RET(PAM_SUCCESS);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_REINITCRED, user);
+ RET(PAM_SUCCESS);
- } else { /* flags are PAM_REFRESH_CRED, PAM_ESTABLISH_CRED, unknown */
+ } else { /* flags are PAM_REFRESH_CRED, PAM_ESTABLISH_CRED, unknown */
- pam_afs_syslog(LOG_DEBUG, PAMAFS_ESTABCRED, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_ESTABCRED, user);
- errcode = pam_get_data(pamh, pam_afs_lh, (const void **) &password);
+ errcode = pam_get_data(pamh, pam_afs_lh, (const void **)&password);
if (errcode != PAM_SUCCESS || password == NULL) {
if (use_first_pass) {
pam_afs_syslog(LOG_ERR, PAMAFS_PASSWD_REQ, user);
RET(PAM_AUTH_ERR);
}
password = NULL; /* In case it isn't already NULL */
- pam_afs_syslog(LOG_DEBUG, PAMAFS_NOFIRSTPASS, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_NOFIRSTPASS, user);
} else if (password[0] == '\0') {
/* Actually we *did* get one but it was empty. */
got_authtok = 1;
pam_afs_syslog(LOG_ERR, PAMAFS_PASSWD_REQ, user);
RET(PAM_NEW_AUTHTOK_REQD);
}
- pam_afs_syslog(LOG_DEBUG, PAMAFS_NILPASSWORD, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_NILPASSWORD, user);
} else {
- pam_afs_syslog(LOG_DEBUG, PAMAFS_GOTPASS, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_GOTPASS, user);
torch_password = 0;
got_authtok = 1;
}
password = NULL;
}
- try_auth:
+ try_auth:
if (password == NULL) {
+ char *prompt_password;
torch_password = 1;
RET(PAM_AUTH_ERR); /* shouldn't happen */
if (try_first_pass)
try_first_pass = 0; /* we come back if try_first_pass==1 below */
-
+
if (pam_convp == NULL || pam_convp->conv == NULL) {
pam_afs_syslog(LOG_ERR, PAMAFS_CANNOT_PROMPT);
RET(PAM_AUTH_ERR);
}
-
- errcode = pam_afs_prompt(pam_convp, &password, 0, PAMAFS_PWD_PROMPT);
- if (errcode != PAM_SUCCESS || password == NULL) {
+
+ errcode =
+ pam_afs_prompt(pam_convp, &prompt_password, 0, PAMAFS_PWD_PROMPT);
+ if (errcode != PAM_SUCCESS || prompt_password == NULL) {
pam_afs_syslog(LOG_ERR, PAMAFS_GETPASS_FAILED);
RET(PAM_AUTH_ERR);
}
- if (password[0] == '\0') {
- pam_afs_syslog(LOG_DEBUG, PAMAFS_NILPASSWORD);
+ if (prompt_password[0] == '\0') {
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_NILPASSWORD);
RET(PAM_NEW_AUTHTOK_REQD);
}
/*
* this storage, copy it to a buffer that won't need to be freed
* later, and free this storage now.
*/
- strncpy(my_password_buf, password, sizeof(my_password_buf));
- my_password_buf[sizeof(my_password_buf)-1] = '\0';
- memset(password, 0, strlen(password));
- free(password);
+
+ strncpy(my_password_buf, prompt_password, sizeof(my_password_buf));
+ my_password_buf[sizeof(my_password_buf) - 1] = '\0';
+ memset(prompt_password, 0, strlen(prompt_password));
+ free(prompt_password);
password = my_password_buf;
}
+ /*
+ * We only set a PAG here, if we haven't got one before in
+ * pam_sm_authenticate() or if it was destroyed by the application
+ */
+ if ((!refresh_token) && (getPAG() == -1)) {
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "New PAG created in pam_setcred()");
+ setpag();
+#ifdef AFS_KERBEROS_ENV
+ ktc_newpag();
+#endif
+ }
- if ( flags & PAM_REFRESH_CRED ) {
- if ( ka_VerifyUserPassword(
- KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
- user, /* kerberos name */
- (char *)0, /* instance */
- (char *)0, /* realm */
- password, /* password */
- 0, /* spare 2 */
- &reason /* error string */
- )) {
- pam_afs_syslog(LOG_ERR, PAMAFS_LOGIN_FAILED, user, reason);
+ if (flags & PAM_REFRESH_CRED) {
+ if (use_klog) {
+ auth_ok = !do_klog(user, password, "00:00:01", cell_ptr);
+ ktc_ForgetAllTokens();
} else {
- auth_ok = 1;
- }
+ if (ka_VerifyUserPassword(KA_USERAUTH_VERSION, (char *)user, /* kerberos name */
+ NULL, /* instance */
+ cell_ptr, /* realm */
+ (char*)password, /* password */
+ 0, /* spare 2 */
+ &reason /* error string */
+ )) {
+ pam_afs_syslog(LOG_ERR, PAMAFS_LOGIN_FAILED, user,
+ reason);
+ } else {
+ auth_ok = 1;
+ }
+ }
}
-
- if ( flags & PAM_ESTABLISH_CRED ) {
- if ( ka_UserAuthenticateGeneral(
- KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
- user, /* kerberos name */
- (char *)0, /* instance */
- (char *)0, /* realm */
- password, /* password */
- 0, /* default lifetime */
- &password_expires,
- 0, /* spare 2 */
- &reason /* error string */
- )) {
- pam_afs_syslog(LOG_ERR, PAMAFS_LOGIN_FAILED, user, reason);
- } else {
- auth_ok = 1;
+
+ if (flags & PAM_ESTABLISH_CRED) {
+ if (use_klog)
+ auth_ok = !do_klog(user, password, NULL, cell_ptr);
+ else {
+ if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION, (char *)user, /* kerberos name */
+ NULL, /* instance */
+ cell_ptr, /* realm */
+ (char*)password, /* password */
+ 0, /* default lifetime */
+ &password_expires, 0, /* spare 2 */
+ &reason /* error string */
+ )) {
+ pam_afs_syslog(LOG_ERR, PAMAFS_LOGIN_FAILED, user,
+ reason);
+ } else {
+ auth_ok = 1;
+ }
}
}
goto try_auth;
}
- if (auth_ok && !got_authtok) {
- torch_password = 0;
- (void) pam_set_item(pamh, PAM_AUTHTOK, password);
- }
+ /* pam_sm_authenticate should have set this
+ * if (auth_ok && !got_authtok) {
+ * torch_password = 0;
+ * (void) pam_set_item(pamh, PAM_AUTHTOK, password);
+ * }
+ */
if (auth_ok) {
- if (set_expires && (password_expires >= 0) ) {
+ if (set_expires && !use_klog && (password_expires >= 0)) {
strcpy(sbuffer, "PASSWORD_EXPIRES=");
strcat(sbuffer, cv2string(&sbuffer[100], password_expires));
- errcode = pam_putenv( pamh, sbuffer);
- if ( errcode != PAM_SUCCESS )
+ errcode = pam_putenv(pamh, sbuffer);
+ if (errcode != PAM_SUCCESS)
pam_afs_syslog(LOG_ERR, PAMAFS_PASSEXPFAIL, user);
}
#if defined(AFS_KERBEROS_ENV)
- if (upwd)
- {
- if ( chown(ktc_tkt_string(), upwd->pw_uid, upwd->pw_gid) < 0 )
+ if (upwd) {
+ if (chown(ktc_tkt_string(), upwd->pw_uid, upwd->pw_gid) < 0)
pam_afs_syslog(LOG_ERR, PAMAFS_CHOWNKRB, user);
sprintf(sbuffer, "KRBTKFILE=%s", ktc_tkt_string());
- errcode = pam_putenv( pamh, sbuffer);
- if ( errcode != PAM_SUCCESS )
- pam_afs_syslog(LOG_ERR, PAMAFS_KRBFAIL, user);
- }
+ errcode = pam_putenv(pamh, sbuffer);
+ if (errcode != PAM_SUCCESS)
+ pam_afs_syslog(LOG_ERR, PAMAFS_KRBFAIL, user);
+ }
#endif
RET(PAM_SUCCESS);
}
}
- out:
- if (password && torch_password) memset(password, 0, strlen(password));
- (void) setlogmask(origmask);
+ out:
+ if (password && torch_password)
+ memset((char*)password, 0, strlen(password));
+ (void)setlogmask(origmask);
#ifndef AFS_SUN56_ENV
closelog();
#endif