Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
434
cde/lib/pam/pam_modules/dce/dce_authenticate.c
Normal file
434
cde/lib/pam/pam_modules/dce/dce_authenticate.c
Normal file
@@ -0,0 +1,434 @@
|
||||
/* $XConsortium: dce_authenticate.c /main/5 1996/05/09 04:26:26 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)dce_authenticate.c 1.34 96/02/14 SMI"
|
||||
|
||||
#include <dce/nbase.h>
|
||||
#include <dce/sec_login.h>
|
||||
#include <dce/dce_error.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <rpc/des_crypt.h>
|
||||
#include <pwd.h>
|
||||
#include <syslog.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#include "pam_impl.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
#include "xfn_mapping.h"
|
||||
#endif /* XFN_MAPPING */
|
||||
|
||||
#define SLEEPTIME 4
|
||||
|
||||
/* maxmimum DCE_PASSWD_LENGTH. We need to pick something for
|
||||
* __pam_get_authtok to use.
|
||||
*/
|
||||
|
||||
#define DCE_PASSWD_LENGTH 256
|
||||
|
||||
static int
|
||||
attempt_dce_login(
|
||||
void *pamh,
|
||||
dce_module_data_t *dsd,
|
||||
error_status_t *st,
|
||||
char *user,
|
||||
char *dce_pass
|
||||
);
|
||||
|
||||
void
|
||||
dce_cleanup(
|
||||
pam_handle_t *pamh,
|
||||
void *data,
|
||||
int pam_status
|
||||
);
|
||||
|
||||
/*
|
||||
* pam_sm_authenticate - Authenticate user
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_authenticate(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
char *user;
|
||||
int err, result = PAM_AUTH_ERR;
|
||||
char messages[1][PAM_MAX_MSG_SIZE];
|
||||
error_status_t st;
|
||||
char *defpass;
|
||||
int num_msg = 0;
|
||||
int debug = 0;
|
||||
int warn = 1;
|
||||
int passwd_flag = 0;
|
||||
int try_first_pass = 0;
|
||||
int use_first_pass = 0;
|
||||
int ignore = 0;
|
||||
int invalid_user = 0;
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
int try_mapped_pass = 0;
|
||||
int use_mapped_pass = 0;
|
||||
#endif
|
||||
int i;
|
||||
char *firstpass = NULL, *password = NULL;
|
||||
uid_t pw_uid;
|
||||
dce_module_data_t *dsd = NULL;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcmp(argv[i], "try_first_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
try_first_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
} else if (strcmp(argv[i], "use_first_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
use_first_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
#ifdef XFN_MAPPING
|
||||
} else if (strcmp(argv[i], "try_mapped_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
try_mapped_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
} else if (strcmp(argv[i], "use_mapped_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
use_mapped_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
#endif
|
||||
} else if (strcmp(argv[i], "nowarn") == 0) {
|
||||
warn = 0;
|
||||
} else {
|
||||
syslog(LOG_ERR, "illegal module option %s", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & PAM_SILENT) warn = 0;
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE pam_sm_authenticate");
|
||||
|
||||
err = pam_get_user(pamh, &user, NULL);
|
||||
|
||||
if (err != PAM_SUCCESS)
|
||||
return (err);
|
||||
|
||||
if (user == NULL || !user[0])
|
||||
return (PAM_AUTH_ERR);
|
||||
|
||||
/* Don't bother to authenticate root in DCE */
|
||||
|
||||
if (strcmp(user, "root") == 0)
|
||||
ignore = 1;
|
||||
|
||||
/* make sure a password entry exists for this user */
|
||||
/* we also need the uid for XFN */
|
||||
|
||||
if (!get_pw_uid(user, &pw_uid)) {
|
||||
invalid_user = 1;
|
||||
}
|
||||
|
||||
if (pam_get_data(pamh, DCE_DATA, (void**)&dsd) != PAM_SUCCESS ||
|
||||
dsd == NULL) {
|
||||
|
||||
dsd = calloc(1, sizeof (dce_module_data_t));
|
||||
if (dsd == NULL) {
|
||||
result = PAM_BUF_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((err = pam_set_data(pamh, DCE_DATA, dsd, &dce_cleanup))
|
||||
!= PAM_SUCCESS) {
|
||||
free(dsd);
|
||||
result = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (dsd->login_context != sec_login_default_handle) {
|
||||
error_status_t st;
|
||||
sec_login_purge_context(&dsd->login_context, &st);
|
||||
}
|
||||
}
|
||||
|
||||
dsd->login_context = sec_login_default_handle;
|
||||
dsd->auth_status = PAM_AUTH_ERR;
|
||||
dsd->debug = debug;
|
||||
dsd->warn = warn;
|
||||
dsd->reset_passwd = 0;
|
||||
dsd->passwd_expired = 0;
|
||||
dsd->auth_src = sec_login_auth_src_network;
|
||||
|
||||
/* see if a legitimate DCE user */
|
||||
|
||||
if (!sec_login_setup_identity((unsigned char *)user,
|
||||
sec_login_no_flags, &dsd->login_context, &st)) {
|
||||
if (debug) {
|
||||
dce_error_string_t text;
|
||||
syslog(LOG_DEBUG,
|
||||
"PAM: DCE sec_login_setup_identity: %s",
|
||||
get_dce_error_message(st, text));
|
||||
}
|
||||
if (st == sec_rgy_object_not_found) {
|
||||
/* mask the unknown user case */
|
||||
invalid_user = 1;
|
||||
} else {
|
||||
result = PAM_AUTH_ERR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
err = pam_get_item(pamh, PAM_AUTHTOK, (void **) &firstpass);
|
||||
|
||||
if (err != PAM_SUCCESS && (use_first_pass || use_mapped_pass)) {
|
||||
result = PAM_AUTH_ERR;
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "PAM: DCE goto out!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (firstpass != NULL && (ignore || invalid_user))
|
||||
goto out;
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
|
||||
if (firstpass == NULL) {
|
||||
if (use_mapped_pass) goto out;
|
||||
} else if (try_mapped_pass || use_mapped_pass) {
|
||||
char dcepass[MAP_PASSLEN+1];
|
||||
uid_t saved_uid;
|
||||
int got_mapped_pass;
|
||||
|
||||
saved_uid = geteuid();
|
||||
|
||||
if (saved_uid != pw_uid && getuid() == 0 &&
|
||||
seteuid(pw_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd: seteuid: %m");
|
||||
/* continue since we might be able to get mapping */
|
||||
}
|
||||
|
||||
got_mapped_pass = xfn_get_mapped_password(
|
||||
debug ? XFN_MAP_DEBUG : 0, user, DCE_XFN_PASS_ATTR,
|
||||
firstpass, dcepass, sizeof (dcepass));
|
||||
|
||||
if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd seteuid restore: %m");
|
||||
/* XXX: what should we do here? */
|
||||
}
|
||||
|
||||
if (got_mapped_pass) {
|
||||
|
||||
result =
|
||||
attempt_dce_login(pamh, dsd, &st, user, dcepass);
|
||||
|
||||
memset(dcepass, 0, MAP_PASSLEN);
|
||||
|
||||
if (result == PAM_SUCCESS ||
|
||||
st == sec_login_s_acct_invalid) goto out;
|
||||
}
|
||||
if (use_mapped_pass) goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (firstpass == NULL) {
|
||||
if (use_first_pass) goto out;
|
||||
} else if (use_first_pass || try_first_pass) {
|
||||
|
||||
result = attempt_dce_login(pamh, dsd, &st,
|
||||
user, firstpass);
|
||||
|
||||
if (result == PAM_SUCCESS ||
|
||||
st == sec_login_s_acct_invalid ||
|
||||
use_first_pass) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the password from the user
|
||||
*/
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE pam_sm_auth prompting for password");
|
||||
|
||||
if (firstpass == NULL &&
|
||||
!(try_first_pass||try_mapped_pass||invalid_user))
|
||||
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 10,
|
||||
"Password: "));
|
||||
else
|
||||
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 11,
|
||||
"DCE Password: "));
|
||||
|
||||
num_msg = 1;
|
||||
|
||||
err = __pam_get_authtok(pamh, PAM_PROMPT, PAM_AUTHTOK,
|
||||
DCE_PASSWD_LENGTH,messages[0], &password);
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE __pam_get_authtok = %d", err);
|
||||
|
||||
if (err != PAM_SUCCESS) {
|
||||
result = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (password == NULL) {
|
||||
/* Need a password to proceed */
|
||||
result = PAM_AUTH_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (firstpass == NULL) {
|
||||
/* this is the first password, stash it away */
|
||||
pam_set_item(pamh, PAM_AUTHTOK, password);
|
||||
}
|
||||
|
||||
/* one last ditch attempt to login to DCE */
|
||||
|
||||
if (invalid_user || ignore)
|
||||
goto out;
|
||||
|
||||
result = attempt_dce_login(pamh, dsd, &st, user, password);
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
/* we had to prompt for DCE password, so attempt to */
|
||||
/* update mapping iff we got a good DCE password */
|
||||
|
||||
if (try_mapped_pass && result == PAM_SUCCESS && firstpass) {
|
||||
uid_t saved_uid;
|
||||
|
||||
saved_uid = geteuid();
|
||||
|
||||
if (saved_uid != pw_uid && seteuid(pw_uid) < 0) {
|
||||
syslog(LOG_ERR, "xfn_get_mapped_passwd: seteuid: %m");
|
||||
goto out;
|
||||
}
|
||||
|
||||
xfn_update_mapped_password(debug ? XFN_MAP_DEBUG : 0,
|
||||
user, DCE_XFN_PASS_ATTR, firstpass, password);
|
||||
|
||||
if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd seteuid restore: %m");
|
||||
/* XXX: what should we do here? */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
out:
|
||||
|
||||
if (ignore) {
|
||||
result = PAM_IGNORE;
|
||||
}
|
||||
|
||||
if (password != NULL)
|
||||
memset(password, 0, strlen(password));
|
||||
|
||||
if (invalid_user)
|
||||
result = PAM_USER_UNKNOWN;
|
||||
|
||||
if (dsd)
|
||||
dsd->auth_status = result;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
attempt_dce_login(
|
||||
void *pamh,
|
||||
dce_module_data_t *dsd,
|
||||
error_status_t *st,
|
||||
char *user,
|
||||
char *dce_pass)
|
||||
{
|
||||
sec_passwd_rec_t passwd_rec;
|
||||
boolean32 login_valid = 0;
|
||||
error_status_t set_st;
|
||||
|
||||
/* have to strdup password because the call clears it */
|
||||
passwd_rec.key.tagged_union.plain = (idl_char *) strdup(dce_pass);
|
||||
if (passwd_rec.key.tagged_union.plain == NULL) {
|
||||
return (PAM_BUF_ERR);
|
||||
}
|
||||
passwd_rec.key.key_type = sec_passwd_plain;
|
||||
passwd_rec.pepper = NULL;
|
||||
passwd_rec.version_number = sec_passwd_c_version_none;
|
||||
|
||||
login_valid = sec_login_valid_and_cert_ident(dsd->login_context,
|
||||
&passwd_rec, &dsd->reset_passwd, &dsd->auth_src, st);
|
||||
|
||||
if (dsd->debug) {
|
||||
dce_error_string_t text;
|
||||
|
||||
syslog(LOG_DEBUG, "sec_login_valid_and_cert_ident: %s",
|
||||
get_dce_error_message(*st, text));
|
||||
}
|
||||
|
||||
if (*st == sec_login_s_acct_invalid && dsd->warn) {
|
||||
char messages[1][PAM_MAX_MSG_SIZE];
|
||||
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 12, "Error: Your DCE Account has expired.\n"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
|
||||
}
|
||||
|
||||
/* the call to sec_login_valid_and_cert_ident already zeros */
|
||||
/* out the password, so we just free it */
|
||||
|
||||
free(passwd_rec.key.tagged_union.plain);
|
||||
|
||||
return (login_valid ? PAM_SUCCESS : PAM_AUTH_ERR);
|
||||
}
|
||||
|
||||
void
|
||||
dce_cleanup(
|
||||
pam_handle_t *pamh,
|
||||
void *data,
|
||||
int pam_status)
|
||||
{
|
||||
error_status_t st;
|
||||
dce_module_data_t *dsd = (dce_module_data_t *) data;
|
||||
int status;
|
||||
|
||||
if (dsd->debug) {
|
||||
syslog(LOG_DEBUG, "DCE dce_cleanup pam_sm_auth_status(%d)",
|
||||
dsd->auth_status);
|
||||
}
|
||||
|
||||
if (!dsd->login_context != sec_login_default_handle) {
|
||||
free(dsd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* if pam_end as PAM_SUCCESS, clean up based on value in */
|
||||
/* auth_status, otherwise just purge the context */
|
||||
|
||||
if (pam_status == PAM_SUCCESS) {
|
||||
pam_sec_login_free_context(dsd->auth_status,
|
||||
&dsd->login_context, &st);
|
||||
} else {
|
||||
sec_login_purge_context(&dsd->login_context, &st);
|
||||
if (dsd->debug) {
|
||||
dce_error_string_t text;
|
||||
syslog(LOG_DEBUG, "sec_login_purge_context: %s",
|
||||
get_dce_error_message(st, text));
|
||||
}
|
||||
}
|
||||
|
||||
free(dsd);
|
||||
}
|
||||
Reference in New Issue
Block a user