Initial import of the CDE 2.1.30 sources from the Open Group.

This commit is contained in:
Peter Howkins
2012-03-10 18:21:40 +00:00
commit 83b6996daa
18978 changed files with 3945623 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
/* $XConsortium: Imakefile /main/3 1996/04/21 19:13:01 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#define IHaveSubdirs
#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
SUBDIRS = "unix" sample dial_auth rhosts_auth /*dce*/
LINTSUBDIRS = "unix" sample dial_auth rhosts_auth /*dce*/
MakeSubdirs($(SUBDIRS))
DependSubdirs($(SUBDIRS))
MakeLintLibSubdirs($(LINTLIBSUBDIRS))
LintSubdirs($(LINTSUBDIRS))

View File

@@ -0,0 +1,48 @@
/* $XConsortium: Imakefile /main/4 1996/04/21 19:13:14 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#define DoNormalLib NormalLibPam
#define DoSharedLib SharedLibPam
#define DoDebugLib DebugLibPam
#define DoProfileLib ProfileLibPam
#define LibName pam_dce
#define SoRev SOPAMREV
#define LibHeaders NO
#include <Threads.tmpl>
SRCS = \
dce_authenticate.c \
dce_setcred.c \
dce_acct_mgmt.c \
dce_password.c \
dce_session.c \
utils.c \
xfn_mapping.c
OBJS = \
dce_authenticate.o \
dce_setcred.o \
dce_acct_mgmt.o \
dce_password.o \
dce_session.o \
utils.o \
xfn_mapping.o
#ifdef SharedPamDceAuthReqs
REQUIREDLIBS = SharedPamDceAuthReqs
#endif
INCLUDES = -I../../libpam
#include <Library.tmpl>
DependTarget()

View File

@@ -0,0 +1,179 @@
/* $XConsortium: dce_acct_mgmt.c /main/5 1996/05/09 04:26:10 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)dce_acct_mgmt.c 1.3 95/08/02 SMI"
#include <syslog.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <libintl.h>
#include <dce/sec_login.h>
#include <dce/dce_error.h>
#include "pam_impl.h"
#include "utils.h"
/*
* pam_sm_acct_mgmt main account managment routine.
* XXX: The routine just prints out a warning message.
* It may need to force the user to change his/her
* passwd.
*/
#include <security/pam_appl.h>
#define SECS_PER_HOUR (60*60)
#define SECS_PER_DAY (SECS_PER_HOUR * 24)
static void
do_warn(pam_handle_t *pamh, time_t cur, time_t t, char *desc);
static void
do_warn_passwd(pam_handle_t *pamh);
int
pam_sm_acct_mgmt(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
dce_module_data_t *dsd;
sec_login_net_info_t net_info;
error_status_t st;
time_t curtime;
int result = PAM_AUTH_ERR;
int i, debug = 0;
int warn = 1;
int allow_expired_passwd = 0;
int err;
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0)
debug = 1;
else if (strcmp(argv[i], "allow_expired_passwd") == 0)
allow_expired_passwd = 1;
else if (strcmp(argv[i], "nowarn") == 0)
warn = 0;
else
syslog(LOG_ERR,
"illegal DCE acct_mgmt option %s", argv[i]);
}
if (flags & PAM_SILENT) warn = 0;
if (debug) syslog(LOG_DEBUG, "DCE pam_sm_acct_mgmt");
if (pam_get_data(pamh, DCE_DATA, (void**)&dsd) != PAM_SUCCESS ||
dsd == NULL) {
return (PAM_AUTH_ERR);
}
if (dsd->auth_status != PAM_SUCCESS)
return (dsd->auth_status);
if (dsd->auth_src == sec_login_auth_src_local) {
/* we can't call sec_login_inquire_net_info on locally */
/* authenticated contexts. Might want an option to dis-allow */
/* them. For now we just allow them. */
return (PAM_SUCCESS);
}
sec_login_inquire_net_info(dsd->login_context, &net_info, &st);
if (st != error_status_ok && st != sec_login_s_not_certified) {
if (debug) {
dce_error_string_t text;
syslog(LOG_DEBUG, "sec_login_inquire_net_info: %s",
get_dce_error_message(st, text));
}
return (PAM_PERM_DENIED);
}
time(&curtime);
if (warn) {
if (dsd->reset_passwd) {
do_warn_passwd(pamh);
} else {
do_warn(pamh, curtime,
(time_t) net_info.passwd_expiration_date,
"passwd");
}
}
if (warn) do_warn(pamh, curtime,
(time_t) net_info.acct_expiration_date, "account");
result = PAM_SUCCESS;
if ((net_info.passwd_expiration_date &&
net_info.passwd_expiration_date < curtime) ||
dsd->reset_passwd) {
result = PAM_AUTHTOKEN_REQD;
dsd->passwd_expired = 1;
}
/*
* I assume an expired account is worse then an expired password,
* so if both the password and account are expired we want to
* return PAM_ACCT_EXPIRED.
*/
if (net_info.acct_expiration_date &&
net_info.acct_expiration_date < curtime) {
result = PAM_ACCT_EXPIRED;
}
sec_login_free_net_info(&net_info);
return (result);
}
static void
do_warn(pam_handle_t *pamh, time_t cur, time_t t, char *desc)
{
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
if (t == 0)
return; /* unlimited */
if (cur > t) {
sprintf(messages[0],
PAM_MSG(pamh, 1, "Warning: Your DCE %s has expired.\n"), desc);
} else if ((cur + SECS_PER_DAY) > t) {
int hours;
hours = (t - cur) / (SECS_PER_HOUR);
hours = hours ? hours : 1;
sprintf(messages[0], PAM_MSG(pamh, 2,
"Warning: Your DCE %s will expire within %d hour%s.\n"),
desc, hours, (hours == 1) ? "" : "s");
} else if ((cur + (2*SECS_PER_DAY)) > t) {
sprintf(messages[0], PAM_MSG(pamh, 3,
"Warning: Your DCE %s will expire in 2 days.\n"), desc);
} else {
return;
}
__pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
}
static void
do_warn_passwd(pam_handle_t *pamh)
{
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
sprintf(messages[0],
PAM_MSG(pamh, 4, "Warning: Your DCE passwd has expired.\n"));
__pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
}

View 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);
}

View File

@@ -0,0 +1,475 @@
/* $XConsortium: dce_password.c /main/5 1996/05/09 04:26:43 drk $ */
/*
* Copyright (c) 1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)dce_password.c 1.22 96/02/14 SMI"
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <syslog.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#include <dce/acct.h>
#include <dce/uuid.h>
#include <dce/binding.h>
#include <dce/sec_login.h>
#include <dce/dce_error.h>
#include "utils.h"
#include "pam_impl.h"
#ifdef XFN_MAPPING
#include "xfn_mapping.h"
#endif
static int
dce_changepw(
char *account_name,
char *old_pass,
char *new_pass);
static char *
get_passwd(
pam_handle_t *pamh,
char *prompt);
/*
* XXX: This module is NOT finished!
*
*/
int
pam_sm_chauthtok(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
char *user;
int err, result = PAM_AUTH_ERR;
char *newpass = NULL, *vnewpass = NULL;
char *oldpass = NULL;
int try_first_pass = 0;
int use_first_pass = 0;
char *firstpass = NULL;
#ifdef XFN_MAPPING
int try_mapped_pass = 0;
int use_mapped_pass = 0;
uid_t saved_uid;
#endif
int i;
int debug = 0;
uid_t pw_uid;
dce_module_data_t *dsd = NULL;
error_status_t status;
if (debug)
syslog(LOG_DEBUG, "DCE Authentication\n");
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0)
debug = 1;
else if (strcmp(argv[i], "try_first_pass") == 0)
try_first_pass = 1;
else if (strcmp(argv[i], "use_first_pass") == 0)
use_first_pass = 1;
#ifdef XFN_MAPPING
else if (strcmp(argv[i], "try_mapped_pass") == 0)
try_mapped_pass = 1;
else if (strcmp(argv[i], "use_mapped_pass") == 0)
use_mapped_pass = 1;
#endif
else
syslog(LOG_DEBUG, "illegal scheme option %s", argv[i]);
}
if (flags & PAM_PRELIM_CHECK) {
/* try and bind to registry master of local cell */
sec_rgy_handle_t rh = sec_rgy_default_handle;
sec_rgy_site_open_update(NULL, &rh, &status);
if (status == error_status_ok) {
sec_rgy_site_close(rh, &status);
return (PAM_SUCCESS);
}
return (PAM_AUTHTOK_ERR);
}
/* make sure PAM framework is telling us to update passwords */
if (!(flags & PAM_UPDATE_AUTHTOK)) {
syslog(LOG_ERR, "dce pam_sm_chauthtok: bad flags: %d", flags);
return (PAM_SYSTEM_ERR);
}
if (flags & PAM_CHANGE_EXPIRED_AUTHTOK) {
if (pam_get_data(pamh, DCE_DATA, (void **)&dsd)
== PAM_SUCCESS) {
if (!dsd->passwd_expired)
return (PAM_IGNORE);
}
}
if ((err = pam_get_item(pamh, PAM_USER, (void **) &user)) < 0)
return (err);
/* Don't bother to handle root in DCE */
if (strcmp(user, "root") == 0)
return (PAM_IGNORE);
#ifdef XFN_MAPPING
if (use_mapped_pass || try_mapped_pass) {
int got_mapped = 0, updated_mapped = 0;
char dcepass[MAP_PASSLEN+1];
if ((err = pam_get_item(pamh, PAM_AUTHTOK,
(void **) &newpass)) < 0)
return (err);
if ((err = pam_get_item(pamh, PAM_OLDAUTHTOK,
(void **) &oldpass)) < 0)
return (err);
if (!get_pw_uid(user, &pw_uid)) {
return (PAM_AUTHTOK_ERR);
}
/* XXX: need to seteuid */
saved_uid = geteuid();
if (saved_uid != pw_uid && getuid() == 0 &&
seteuid(pw_uid) < 0) {
syslog(LOG_ERR,
"xfn_get_mapped_passwd: seteuid: %m");
return (PAM_AUTHTOK_ERR);
}
got_mapped = xfn_get_mapped_password(0, user,
DCE_XFN_PASS_ATTR, oldpass, dcepass, sizeof (dcepass));
if (got_mapped) {
updated_mapped = xfn_update_mapped_password(
0, user, DCE_XFN_PASS_ATTR, newpass,
dcepass);
memset(dcepass, 0, sizeof (dcepass));
} else {
/* probably should prompt for DCE password */
/* and attempt to update it */
}
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 (use_mapped_pass) {
if (updated_mapped)
return (PAM_SUCCESS);
else
return (PAM_AUTHTOK_ERR);
}
return (PAM_AUTHTOK_ERR);
}
#endif /* XFN_MAPPING */
if (try_first_pass || use_first_pass) {
if ((err = pam_get_item(pamh, PAM_AUTHTOK,
(void **) &newpass)) < 0)
return (err);
if ((err = pam_get_item(pamh, PAM_OLDAUTHTOK,
(void **) &oldpass)) < 0)
return (err);
result = dce_changepw(user, oldpass, newpass);
if (result == PAM_SUCCESS) {
/* might need to update PAM_OLDAUTHTOK and PAM_NEWAUTHTOK */
goto out;
}
/* assume we need to prompt for old DCE password? */
oldpass = get_passwd(pamh, PAM_MSG(pamh, 20,
"Old DCE password: "));
if (oldpass == NULL || oldpass[0] == '\0') {
/* Need a password to proceed */
result = PAM_AUTHTOK_ERR;
goto out;
}
result = dce_changepw(user, oldpass, newpass);
if (result == PAM_SUCCESS) {
/* might need to update PAM_OLDAUTHTOK and PAM_NEWAUTHTOK */
}
goto out;
}
/* prompt for both old and new passwords */
if (firstpass == NULL && !(try_first_pass||try_mapped_pass))
oldpass = get_passwd(pamh, PAM_MSG(pamh, 20,
"Old DCE password: "));
else
oldpass = get_passwd(pamh, PAM_MSG(pamh, 20,
"Old DCE password: "));
if (oldpass == NULL || oldpass[0] == '\0') {
/* Need a password to proceed */
result = PAM_AUTHTOK_ERR;
goto out;
}
if (firstpass == NULL && !(try_first_pass||try_mapped_pass))
newpass = get_passwd(pamh, PAM_MSG(pamh, 21,
"New DCE password: "));
else
newpass = get_passwd(pamh, PAM_MSG(pamh, 21,
"New DCE password: "));
if (newpass == NULL || newpass[0] == '\0') {
/* Need a password to proceed */
result = PAM_AUTHTOK_ERR;
goto out;
}
if (firstpass == NULL && !(try_first_pass||try_mapped_pass))
vnewpass = get_passwd(pamh,
PAM_MSG(pamh, 22,
"Re-enter new DCE password: "));
else
vnewpass = get_passwd(pamh,
PAM_MSG(pamh, 22,
"Re-enter new DCE password: "));
if (vnewpass == NULL || vnewpass[0] == '\0') {
/* Need a password to proceed */
result = PAM_AUTHTOK_ERR;
goto out;
}
if (strcmp(newpass, vnewpass)) {
result = PAM_AUTHTOK_ERR;
goto out;
}
result = dce_changepw(user, oldpass, newpass);
if (result == PAM_SUCCESS) {
/* might need to update PAM_OLDAUTHTOK and PAM_NEWAUTHTOK) */
}
out:
if (oldpass) {
memset(oldpass, 0, strlen(oldpass));
free(oldpass);
}
if (newpass) {
memset(newpass, 0, strlen(newpass));
free(newpass);
}
if (vnewpass) {
memset(vnewpass, 0, strlen(vnewpass));
free(vnewpass);
}
return (result);
}
static int
dce_changepw(
char *account_name,
char *old_pass,
char *new_pass)
{
error_status_t status;
sec_rgy_handle_t rgy_handle = sec_rgy_default_handle;
sec_rgy_login_name_t name_key;
sec_rgy_cursor_t account_cursor;
sec_rgy_login_name_t name_result;
sec_rgy_sid_t id_sid;
sec_rgy_unix_sid_t unix_sid;
sec_rgy_acct_key_t key_parts;
sec_rgy_acct_user_t user_part;
sec_rgy_acct_admin_t admin_part;
sec_passwd_rec_t new_key, caller_key;
sec_passwd_version_t new_key_version;
sec_login_handle_t login_context = sec_login_default_handle;
sec_passwd_rec_t passwd_rec;
boolean32 reset_pass = 0, login_valid = 0;
sec_login_auth_src_t auth_src;
char *env;
static char *krb5 = "KRB5CCNAME";
char *krb5_value = NULL;
/* stash away the value of KRB5CCNAME, if there is one set */
env = getenv(krb5);
if (env) {
krb5_value = malloc(strlen(krb5)+1+strlen(env)+1);
if (krb5_value)
sprintf(krb5_value, "%s=%s", krb5, env);
else {
status = sec_login_s_no_current_context;
goto out;
}
}
/* first we a get a login context. A future version should */
/* check and see if there is a current context with the */
/* same name as the user we are setting */
if (!sec_login_setup_identity((unsigned_char_p_t) account_name,
sec_login_no_flags, &login_context, &status)) {
goto out;
}
/* have to strdup password because the call clears it */
passwd_rec.key.tagged_union.plain =
(idl_char *) strdup(old_pass);
if (passwd_rec.key.tagged_union.plain == NULL) {
status = sec_login_s_no_current_context;
goto out;
}
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_validate_identity(login_context,
&passwd_rec, &reset_pass, &auth_src, &status);
free(passwd_rec.key.tagged_union.plain); /* already memset */
if (!login_valid)
goto out;
sec_login_set_context(login_context, &status);
if (status != error_status_ok)
goto out;
/* we now have a context with the same account as the one */
/* we are trying to change the password on. Lets talk to the */
/* registry... */
sec_rgy_site_open(NULL, &rgy_handle, &status);
if (status != error_status_ok) {
goto out;
}
caller_key.key.key_type = sec_passwd_plain;
caller_key.pepper = NULL;
caller_key.version_number = sec_passwd_c_version_none;
caller_key.key.tagged_union.plain = (idl_char *) old_pass;
sec_rgy_cursor_reset(&account_cursor);
strcpy((char *)name_key.pname, account_name);
name_key.gname[0] = '\0';
name_key.oname[0] = '\0';
/* need to do this in order to get the org and group for the */
/* account. All we want is name_result... */
sec_rgy_acct_lookup(
rgy_handle,
&name_key,
&account_cursor,
&name_result,
&id_sid,
&unix_sid,
&key_parts,
&user_part,
&admin_part,
&status);
if (status != error_status_ok)
goto out;
caller_key.key.key_type = sec_passwd_plain;
caller_key.pepper = NULL;
caller_key.version_number = sec_passwd_c_version_none;
caller_key.key.tagged_union.plain = (idl_char *) old_pass;
new_key.key.key_type = sec_passwd_plain;
new_key.pepper = NULL;
new_key.version_number = sec_passwd_c_version_none;
new_key.key.tagged_union.plain = (idl_char *) new_pass;
/* rock and roll. lets try to update the password... */
sec_rgy_acct_passwd(
rgy_handle,
&name_result,
&caller_key,
&new_key,
sec_passwd_des,
&new_key_version,
&status);
out:
/* restore the old KRB5CCNAME value */
if (krb5_value) {
putenv(krb5_value);
}
if (rgy_handle != sec_rgy_default_handle) {
error_status_t st; /* don't trash status */
sec_rgy_site_close(rgy_handle, &st);
}
if (login_context != sec_login_default_handle) {
error_status_t st; /* don't trash status */
sec_login_purge_context(&login_context, &st);
}
if (status == error_status_ok) {
return (PAM_SUCCESS);
} else {
return (PAM_AUTHTOK_ERR);
}
}
static char *
get_passwd(
pam_handle_t *pamh,
char *prompt)
{
int err;
char *p;
err = __pam_get_authtok(pamh, PAM_PROMPT, 0, 256, prompt, &p);
if (err != PAM_SUCCESS) {
return (NULL);
}
return (p);
}

View File

@@ -0,0 +1,49 @@
/* $XConsortium: dce_session.c /main/4 1996/05/09 04:27:00 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)dce_session.c 1.3 96/01/10 SMI"
#include <libintl.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <dce/sec_login.h>
#include <dce/dce_error.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <syslog.h>
#include <libintl.h>
#include "pam_impl.h"
#include "utils.h"
/*
* pam_sm_open_session
*/
int
pam_sm_open_session(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return (PAM_SUCCESS);
}
/*
* pam_sm_close_session
*/
int
pam_sm_close_session(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,125 @@
/* $XConsortium: dce_setcred.c /main/5 1996/05/09 04:27:17 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)dce_setcred.c 1.21 96/01/11 SMI"
#include <libintl.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <dce/sec_login.h>
#include <dce/dce_error.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <syslog.h>
#include <libintl.h>
#include "pam_impl.h"
#include "utils.h"
static void
do_cred_warn(void *pamh)
{
char messages[1][PAM_MAX_MSG_SIZE];
sprintf(messages[0],
PAM_MSG(pamh, 30, "warning: Unable to obtain DCE credentials.\n"));
(void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
}
/*
* pam_sm_setcred
*/
int
pam_sm_setcred(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int debug = 0;
int warn = 1;
int i;
dce_module_data_t *dsd;
error_status_t st;
int err;
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0)
debug = 1;
if (strcmp(argv[i], "nowarn") == 0)
warn = 0;
}
if (flags & PAM_SILENT) warn = 0;
if (debug)
syslog(LOG_DEBUG, "DCE pam_setcred");
if (pam_get_data(pamh, DCE_DATA, (void**)&dsd) != PAM_SUCCESS ||
dsd == NULL) {
if (flags & PAM_DELETE_CRED) {
sec_login_handle_t context;
/* attempt to get current context and purge */
sec_login_get_current_context(&context, &st);
if (st == error_status_ok) {
sec_login_purge_context(&context, &st);
}
return (st == error_status_ok ? PAM_SUCCESS :
PAM_CRED_UNAVAIL);
}
if (warn) do_cred_warn(pamh);
return (PAM_IGNORE); /* since pam_auth was never called */
}
if (dsd->auth_status != PAM_SUCCESS)
return (dsd->auth_status);
if (flags & PAM_DELETE_CRED) {
(void) sec_login_purge_context(dsd->login_context, &st);
if (debug) {
dce_error_string_t text;
syslog(LOG_DEBUG,
"PAM: DCE sec_login_purge_context: %s",
get_dce_error_message(st, text));
}
} else {
if (dsd->auth_src == sec_login_auth_src_local) {
/* we can't set_context on locally authenticated */
/* contexts */
st = sec_login_s_auth_local;
} else {
(void) sec_login_set_context(dsd->login_context, &st);
}
if (debug) {
dce_error_string_t text;
syslog(LOG_DEBUG, "PAM: DCE sec_login_set_context: %s",
get_dce_error_message(st, text));
}
}
/* might want an option to return success even if set_context failed */
if (st == error_status_ok) {
return (PAM_SUCCESS);
} else {
if (warn) do_cred_warn(pamh);
if (debug) syslog(LOG_DEBUG,
"Can't set user login context");
return (PAM_CRED_ERR);
}
}

View File

@@ -0,0 +1,22 @@
/****************************************************************************
* Export list for libpam_dce.
* This list *must* be updated whenever a change is made to the libpam_dce
* API.
*
* The syntax for the symbol declarations in this list is as follows:
* public sym => Public C symbol, i.e., publicised API
* private sym => Private C symbol, i.e., unpublicised API
* internal sym => Internal C symbol, i.e., not part of API
* publicC++ sym => Public C++ symbol, i.e., publicised API
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
* internalC++ sym => Internal C++ symbol, i.e., not part of API
*
* $TOG: libpam_cde.elist /main/1 1999/09/08 15:58:14 mgreess $
*****************************************************************************/
public pam_sm_authenticate
public pam_sm_setcred
public pam_sm_acct_mgmt
public pam_sm_open_session
public pam_sm_close_session
public pam_sm_chauthtok

View File

@@ -0,0 +1,71 @@
$ $XConsortium: pam_dce.msg /main/2 1996/07/24 19:04:00 drk $
$ *************************************<+>*************************************
$ *****************************************************************************
$ **
$ ** File: pam_dce.msg
$ **
$ ** Project: pam_dce
$ **
$ ** Description:
$ ** -----------
$ ** This file is the source for the message catalog for pam_unix module.
$ **
$ **
$ *****************************************************************************
$ **
$ ** (c) Copyright 1996 Sun Microsystems, Inc.
$ ** All Rights reserved
$ **
$ *****************************************************************************
$ *************************************<+>*************************************
$ *****************************************************************************
$
$ ***** NOTE FOR MESSAGE CATALOG TRANSLATORS *****
$
$ There may be three types of messages in this file:
$
$ 1. Messages that appear in dialogs or are displayed to the user.
$
$ These messages are the default and they should ALL BE LOCALIZED.
$ Note that these messages do NOT have any identification (see the
$ comments for type 2 and 3 below).
$
$ 2. Messages that only appear in the error log file.
$
$ The localization of these messages is OPTIONAL. These messages are
$ identified by the following:
$
$ MESSAGES xx-yy IN SET zz WILL ONLY APPEAR IN THE DT ERRORLOG FILE
$
$ 3. Messages that should not be localized.
$
$ These messages are identified by the following:
$
$ DO NOT TRANSLATE or CHANGE or LOCALIZE MESSAGES xx-yy from set zz
$
$ ***** END (NOTE FOR MESSAGE CATALOG TRANSLATORS) *****
$
$ ******************************************************************************
$set 1
$ dce_acct_mgmt.c
1 Warning: Your DCE %s has expired.
2 Warning: Your DCE %s will expire within %d hour%s.
3 Warning: Your DCE %s will expire in 2 days.\n
4 Warning: Your DCE passwd has expired.
$ dce_authenticate.c
10 Password:
11 DCE Password:
12 Error: Your DCE Account has expired.\n
$ dce_password.c
20 Old DCE password:
21 New DCE password:
22 Re-enter new DCE password:
$ dce_setcred.c
30 warning: Unable to obtain DCE credentials.\n

View File

@@ -0,0 +1,96 @@
/* $XConsortium: utils.c /main/4 1996/05/09 04:27:30 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)utils.c 1.13 95/09/19 SMI"
#include <dce/sec_login.h>
#include <security/pam_appl.h>
#include <pwd.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include "utils.h"
/* ******************************************************************** */
/* */
/* Utilities Functions */
/* */
/* ******************************************************************** */
/* return a string given an error status */
unsigned char *
get_dce_error_message(
error_status_t status,
unsigned char *buffer
)
{
int s;
dce_error_inq_text(status, buffer, &s);
if (s)
sprintf((char *)buffer, "DCE error %u", status);
return (buffer);
}
/* release login_context resources. if we are returning PAM_SUCCESS */
/* we also have to save KRB5CCNAME and set it after calling release */
/* because s_l_release_c unset's it even though we still need it */
void
pam_sec_login_free_context(
int pam_status,
sec_login_handle_t *login_context,
error_status_t *st)
{
if (pam_status == PAM_SUCCESS) {
static char *krb5 = "KRB5CCNAME";
char *krb5_value = NULL;
char *env = getenv(krb5);
if (env) {
/* we MUST malloc this for the putenv to work! */
krb5_value = malloc(strlen(krb5)+1+strlen(env)+1);
if (krb5_value)
sprintf(krb5_value, "%s=%s", krb5, env);
}
sec_login_release_context(login_context, st);
if (krb5_value)
putenv(krb5_value);
} else { /* login failed. purge this context */
sec_login_purge_context(login_context, st);
}
}
/*
* get_pw_uid():
* To get the uid from the passwd entry for specified user
* It returns 0 if the user can't be found, otherwise returns 1.
*/
int
get_pw_uid(char *user, uid_t *uid)
{
struct passwd sp;
char buffer[1024];
if (getpwnam_r(user, &sp, buffer, sizeof (buffer)) == NULL) {
return (0);
}
*uid = sp.pw_uid;
return (1);
}

View File

@@ -0,0 +1,58 @@
/* $XConsortium: utils.h /main/5 1996/05/09 04:27:45 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _UTILS_H
#define _UTILS_H
#ident "@(#)utils.h 1.17 96/01/10 SMI"
#ifdef __cplusplus
extern "C" {
#endif
#include <security/pam_appl.h>
#include <dce/sec_login.h>
#define DCE_DATA "SUNW-DCE-AUTH-DATA"
/*
* PAM_MSG macro for return of internationalized text
*/
#define PAM_MSG(pamh, number, string)\
(char *) __pam_get_i18n_msg(pamh, "pam_dce", 1, number, string)
typedef struct {
sec_login_handle_t login_context;
int debug;
int warn;
int auth_status;
boolean32 reset_passwd;
boolean32 passwd_expired;
sec_login_auth_src_t auth_src;
} dce_module_data_t;
void
pam_sec_login_free_context(
int pam_status,
sec_login_handle_t *login_context,
error_status_t *st);
unsigned char *
get_dce_error_message(
error_status_t status,
unsigned char *buffer
);
int
get_pw_uid(char *user, uid_t *uid);
#ifdef __cplusplus
}
#endif
#endif /* _DCE_UTILS_H */

View File

@@ -0,0 +1,287 @@
/* $XConsortium: xfn_mapping.c /main/4 1996/05/09 04:28:00 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)xfn_mapping.c 1.6 95/09/19 SMI"
#include <security/pam_appl.h>
#include <xfn/xfn.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include "xfn_mapping.h"
static char hexval(char);
static int hex2bin(int, char *, char *);
static int bin2hex(int, unsigned char *, char *);
/*
* attempt to get mapped password from XFN
*/
int
xfn_get_mapped_password(
int flags,
char *user, /* xfn user */
char *xfn_attr, /* xfn attribute that holds the target pass */
char *key, /* key (password) encrypting target password */
char *out, /* un-encrypted target password */
int out_max) /* buffer size of out */
{
FN_status_t *status = NULL;
FN_composite_name_t *compname = NULL;
FN_ctx_t *ctx = NULL;
FN_string_t *str = NULL;
FN_attribute_t *attr = NULL;
const FN_attrvalue_t *attr_val = NULL;
FN_identifier_t attr_id; /* attr identifier */
FN_identifier_t attr_syn; /* attr syntax */
char hexpass[MAP_HEXLEN+1];
char pass[MAP_PASSLEN+1];
char composed_user[128]; /* XXX 128? */
int result = 0;
void *pos;
pass[0] = '\0';
status = fn_status_create(); /* free status */
if (status == NULL)
goto out;
ctx = fn_ctx_handle_from_initial(status); /* free ctx */
if (ctx == NULL)
goto out;
attr_id.format = FN_ID_STRING;
attr_id.length = strlen(xfn_attr);
attr_id.contents = xfn_attr;
if (strlen(user) > (sizeof (composed_user)-6))
goto out;
sprintf(composed_user, "user/%s", user);
str = fn_string_from_str(
(unsigned char *)composed_user); /* free str */
if (str == NULL)
goto out;
compname = fn_composite_name_from_string(str); /* free compname */
if (compname == NULL)
goto out;
attr = fn_attr_get(ctx, compname, &attr_id, status); /* free attr */
if (attr == NULL)
goto out;
attr_val = fn_attribute_first(attr, &pos); /* don't have to free */
if (attr_val == NULL)
goto out;
if (attr_val->length != MAP_HEXLEN)
goto out;
memcpy(hexpass, attr_val->contents, attr_val->length);
if (xdecrypt(hexpass, key) == 0)
goto out;
hexpass[MAP_HEXLEN] = '\0';
hex2bin(MAP_PASSLEN, hexpass, pass); /* we have the password!! */
memset(hexpass, 0, MAP_HEXLEN);
if (strlen(pass)+1 > out_max)
goto out; /* sigh... */
strcpy(out, pass);
memset(pass, 0, strlen(pass));
result = 1;
out:
if (pass[0])
memset(pass, 0, MAP_PASSLEN);
if (status)
fn_status_destroy(status);
if (ctx)
fn_ctx_handle_destroy(ctx);
if (str)
fn_string_destroy(str);
if (compname)
fn_composite_name_destroy(compname);
if (attr)
fn_attribute_destroy(attr);
return (result);
}
/*
* attempt to update mapped password from XFN
*/
int
xfn_update_mapped_password(
int flags, /* debug, etc */
char *user, /* xfn user */
char *xfn_attr, /* xfn attribute that holds the target pass */
char *key, /* key (password) encrypting target password */
char *password) /* un-encrypted target password */
{
FN_status_t *status = NULL;
FN_composite_name_t *compname = NULL;
FN_ctx_t *ctx = NULL;
FN_ref_t *ref = NULL;
FN_string_t *str = NULL;
FN_attribute_t *attr = NULL;
FN_identifier_t attr_id; /* attr identifier */
FN_identifier_t attr_syn; /* attr syntax */
FN_attrvalue_t attr_val;
char hexpass[MAP_HEXLEN+1];
char pass[MAP_PASSLEN+1];
char composed_user[128]; /* XXX 128? */
int result;
result = 0; /* guilty until proven innocent */
hexpass[0] = '\0';
if (strlen(pass) > MAP_PASSLEN)
goto out;
status = fn_status_create(); /* free status */
if (status == NULL)
goto out;
ctx = fn_ctx_handle_from_initial(status); /* free ctx */
if (ctx == NULL)
goto out;
attr_id.format = FN_ID_STRING;
attr_id.length = strlen(xfn_attr);
attr_id.contents = xfn_attr;
attr_syn.format = FN_ID_STRING;
#define PASSWD_ATTR_SYNTAX "fn_attr_syntax_ascii"
attr_syn.length = sizeof (PASSWD_ATTR_SYNTAX)-1; /* sizeof has null */
attr_syn.contents = PASSWD_ATTR_SYNTAX;
attr = fn_attribute_create(&attr_id, &attr_syn); /* free attr */
if (strlen(user) > (sizeof (composed_user)-6))
goto out;
sprintf(composed_user, "user/%s", user);
str = fn_string_from_str(
(unsigned char *)composed_user); /* free str */
if (str == NULL)
goto out;
compname = fn_composite_name_from_string(str); /* free compname */
if (compname == NULL)
goto out;
ref = fn_ctx_lookup(ctx, compname, status);
if (ref == NULL)
goto out;
strcpy(pass, password);
bin2hex(MAP_PASSLEN, (unsigned char *)pass, hexpass);
hexpass[MAP_HEXLEN] = '\0';
memset(pass, 0, sizeof (pass));
if (xencrypt(hexpass, key) == 0)
goto out;
attr_val.length = strlen(hexpass);
attr_val.contents = hexpass;
if (fn_attribute_add(attr, &attr_val, 1) == 0)
goto out;
if (fn_attr_modify(ctx, compname, FN_ATTR_OP_ADD, attr, status) == 0)
goto out;
result = 1;
out:
if (hexpass[0])
memset(hexpass, 0, MAP_HEXLEN);
if (status)
fn_status_destroy(status);
if (ctx)
fn_ctx_handle_destroy(ctx);
if (str)
fn_string_destroy(str);
if (compname)
fn_composite_name_destroy(compname);
if (attr)
fn_attribute_destroy(attr);
return (result);
}
/*
* Hex to binary conversion
*/
static
hex2bin(int len, char *hexnum, char *binnum)
{
int i;
char v1;
char v2;
for (i = 0; i < len; i++) {
v1 = hexval(hexnum[2 * i]);
if (v1 == -1)
return (0);
v2 = hexval(hexnum[2 * i + 1]);
if (v2 == -1)
return (0);
*binnum++ = (v1 << 4) + v2;
}
return (1);
}
/*
* Binary to hex conversion
*/
static
bin2hex(int len, unsigned char *binnum, char *hexnum)
{
int i;
unsigned val;
static char hex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
};
for (i = 0; i < len; i++) {
val = binnum[i];
hexnum[i*2] = hex[val >> 4];
hexnum[i*2+1] = hex[val & 0xf];
}
hexnum[len*2] = 0;
return (1);
}
static char
hexval(char c)
{
if (c >= '0' && c <= '9') {
return (c - '0');
} else if (c >= 'a' && c <= 'f') {
return (c - 'a' + 10);
} else if (c >= 'A' && c <= 'F') {
return (c - 'A' + 10);
} else {
return (-1);
}
}

View File

@@ -0,0 +1,46 @@
/* $XConsortium: xfn_mapping.h /main/4 1996/05/09 04:28:15 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _XFN_MAPPING_H
#define _XFN_MAPPING_H
#ident "@(#)xfn_mapping.h 1.6 95/09/19 SMI"
#ifdef __cplusplus
extern "C" {
#endif
#define MAP_PASSLEN 32 /* XXX max mapped passwd length */
#define MAP_HEXLEN (2*MAP_PASSLEN) /* XXX max passwd length in hex */
#define DCE_XFN_PASS_ATTR "onc_dce_passwd"
#define XFN_MAP_DEBUG 0x1 /* enable debugging */
int
xfn_get_mapped_password(
int flags, /* XFN_MAP_DEBUG, etc */
char *user, /* xfn user */
char *xfn_attr, /* xfn attribute that holds the target pass */
char *key, /* key (password) encrypting target password */
char *out, /* un-encrypted target password */
int max_out_len /* buffer size of out */
);
int
xfn_update_mapped_password(
int flags, /* XFN_MAP_DEBUG, etc */
char *user, /* xfn user */
char *xfn_attr, /* xfn attribute that holds the target pass */
char *key, /* key (password) encrypting target password */
char *password /* un-encrypted target password */
);
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,32 @@
/* $XConsortium: Imakefile /main/4 1996/04/21 19:13:07 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#define DoNormalLib NormalLibPam
#define DoSharedLib SharedLibPam
#define DoDebugLib DebugLibPam
#define DoProfileLib ProfileLibPam
#define LibName pam_dial_auth
#define SoRev SOPAMREV
#define LibHeaders NO
#include <Threads.tmpl>
SRCS = dial_auth.c
OBJS = dial_auth.o
#ifdef SharedPamDialAuthReqs
REQUIREDLIBS = SharedPamDialAuthReqs
#endif
#include <Library.tmpl>
DependTarget()

View File

@@ -0,0 +1,139 @@
/* $XConsortium: dial_auth.c /main/5 1996/05/09 04:28:31 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)dial_auth.c 1.20 96/02/09 SMI"
#include "unix_headers.h"
/*
* pam_sm_auth_port - This is the top level function in the
* module called by pam_auth_port in the framework
* Returns: PAM_SERVICE_ERR on failure, 0 on success
*/
int
pam_sm_authenticate(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
char *ttyn, *user;
struct pam_conv *pam_convp;
FILE *fp;
char defpass[30];
char line[80];
char *p1, *p2;
struct passwd pwd;
char pwd_buffer[1024];
char *password;
static struct pam_response *ret_resp;
int retcode;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
int num_msg;
int i;
int debug = 0;
for (i = 0; i < argc; i++) {
if (strcasecmp(argv[i], "debug") == 0)
debug = 1;
else
syslog(LOG_DEBUG, "illegal option %s", argv[i]);
}
if ((retcode = pam_get_user(pamh, &user, NULL))
!= PAM_SUCCESS ||
(retcode = pam_get_item(pamh, PAM_TTY, (void **)&ttyn))
!= PAM_SUCCESS ||
(retcode = pam_get_item(pamh, PAM_CONV, (void **)&pam_convp))
!= PAM_SUCCESS)
return (retcode);
if (debug) {
syslog(LOG_DEBUG,
"Dialpass authenticate user = %s, ttyn = %s",
user, ttyn);
}
if (getpwnam_r(user, &pwd, pwd_buffer, sizeof (pwd_buffer)) == NULL)
return (PAM_USER_UNKNOWN);
if ((fp = fopen(DIAL_FILE, "r")) == NULL) {
return (PAM_SUCCESS);
}
while ((p1 = fgets(line, sizeof (line), fp)) != NULL) {
while (*p1 != '\n' && *p1 != ' ' && *p1 != '\t')
p1++;
*p1 = '\0';
if (strcmp(line, ttyn) == 0)
break;
}
(void) fclose(fp);
if (p1 == NULL || (fp = fopen(DPASS_FILE, "r")) == NULL)
return (PAM_SUCCESS);
defpass[0] = '\0';
p2 = 0;
while ((p1 = fgets(line, sizeof (line)-1, fp)) != NULL) {
while (*p1 && *p1 != ':')
p1++;
*p1++ = '\0';
p2 = p1;
while (*p1 && *p1 != ':')
p1++;
*p1 = '\0';
if (pwd.pw_shell != NULL && strcmp(pwd.pw_shell, line) == 0)
break;
if (strcmp(SHELL, line) == 0)
SCPYN(defpass, p2);
p2 = 0;
}
(void) fclose(fp);
if (!p2)
p2 = defpass;
if (*p2 != '\0') {
strcpy(messages[0], PAM_MSG(pamh, 1, "Dialup Password: "));
num_msg = 1;
retcode = __pam_get_input(PAM_PROMPT_ECHO_OFF, pam_convp->conv,
num_msg, messages, NULL, &ret_resp);
if (retcode != PAM_SUCCESS)
return (retcode);
password = ret_resp->resp;
/* UNIX passwords can only be 8 characters long */
password[8] = '\0';
if (strcmp(crypt(password, p2), p2)) {
__pam_free_resp(num_msg, ret_resp);
return (PAM_SERVICE_ERR);
}
__pam_free_resp(num_msg, ret_resp);
}
return (PAM_SUCCESS);
}
/*
* dummy pam_sm_setcred - does nothing
*/
pam_sm_setcred(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,18 @@
/****************************************************************************
* Export list for libpam_dial_auth.
* This list *must* be updated whenever a change is made to the libpam_dial_auth
* API.
*
* The syntax for the symbol declarations in this list is as follows:
* public sym => Public C symbol, i.e., publicised API
* private sym => Private C symbol, i.e., unpublicised API
* internal sym => Internal C symbol, i.e., not part of API
* publicC++ sym => Public C++ symbol, i.e., publicised API
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
* internalC++ sym => Internal C++ symbol, i.e., not part of API
*
* $TOG: libpam_dial_auth.elist /main/1 1999/09/08 15:58:41 mgreess $
*****************************************************************************/
public pam_sm_authenticate
public pam_sm_setcred

View File

@@ -0,0 +1,92 @@
/* $XConsortium: unix_headers.h /main/4 1996/05/09 04:28:47 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _UNIX_HEADERS_H
#define _UNIX_HEADERS_H
#pragma ident "@(#)unix_headers.h 1.6 96/02/02 SMI" /* PAM 2.6 */
#ifdef __cplusplus
extern "C" {
#endif
/*
******************************************************************
PROPRIETARY NOTICE(Combined)
This source code is unpublished proprietary information
constituting, or derived under license from AT&T's UNIX(r) System V.
In addition, portions of such source code were derived from Berkeley
4.3 BSD under license from the Regents of the University of
California.
Copyright Notice
Notice of copyright on this source code product does not indicate
publication.
(c) 1986, 1987, 1988, 1989, 1990, 1991, 1992 Sun Microsystems, Inc
(c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T.
All rights reserved.
*******************************************************************
*/
/*
******************************************************************** *
* *
* Unix Scheme Header Files *
* *
* ******************************************************************** */
#include <sys/param.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <pwd.h>
#include <shadow.h>
#include <string.h>
#include <rpc/types.h>
#include <rpc/auth.h>
#include <locale.h>
#include <crypt.h>
#include <syslog.h>
/*
* Various useful files and string constants
*/
#define DIAL_FILE "/etc/dialups"
#define DPASS_FILE "/etc/d_passwd"
#define SHELL "/usr/bin/sh"
/*
* PAM_MSG macro for return of internationalized text
*/
#define PAM_MSG(pamh, number, string)\
(char *) __pam_get_i18n_msg(pamh, "pam_unix", 2, number, string)
/*
* Miscellaneous constants
*/
#define SLEEPTIME 4
#define ERROR 1
#define OK 0
#define MAXTRYS 5
#define ROOTUID 0
/*
* String manipulation macros: SCPYN, EQN and ENVSTRNCAT
*/
#define SCPYN(a, b) (void) strncpy(a, b, sizeof (a))
#ifdef __cplusplus
}
#endif
#endif /* _UNIX_HEADERS_H */

View File

@@ -0,0 +1,32 @@
/* $XConsortium: Imakefile /main/4 1996/04/21 19:13:11 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#define DoNormalLib NormalLibPam
#define DoSharedLib SharedLibPam
#define DoDebugLib DebugLibPam
#define DoProfileLib ProfileLibPam
#define LibName pam_rhosts_auth
#define SoRev SOPAMREV
#define LibHeaders NO
#include <Threads.tmpl>
SRCS = rhosts_auth.c
OBJS = rhosts_auth.o
#ifdef SharedPamRhostsAuthReqs
REQUIREDLIBS = SharedPamRhostsAuthReqs
#endif
#include <Library.tmpl>
DependTarget()

View File

@@ -0,0 +1,18 @@
/****************************************************************************
* Export list for libpam_rhosts_auth.
* This list *must* be updated whenever a change is made to the
* libpam_rhosts_auth API.
*
* The syntax for the symbol declarations in this list is as follows:
* public sym => Public C symbol, i.e., publicised API
* private sym => Private C symbol, i.e., unpublicised API
* internal sym => Internal C symbol, i.e., not part of API
* publicC++ sym => Public C++ symbol, i.e., publicised API
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
* internalC++ sym => Internal C++ symbol, i.e., not part of API
*
* $TOG: libpam_rhosts_auth.elist /main/1 1999/09/08 15:59:05 mgreess $
*****************************************************************************/
public pam_sm_authenticate
public pam_sm_setcred

View File

@@ -0,0 +1,83 @@
/* $XConsortium: rhosts_auth.c /main/5 1996/05/09 04:29:04 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)rhosts_auth.c 1.19 96/02/02 SMI"
#include "unix_headers.h"
/*
* pam_sm_auth_netuser - Checks if the user is allowed remote access
*/
int
pam_sm_authenticate(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
char *host = NULL, *lusername = NULL;
struct passwd pwd;
char pwd_buffer[1024];
int is_superuser;
char *rusername;
int err;
int i;
int debug = 0;
for (i = 0; i < argc; i++) {
if (strcasecmp(argv[i], "debug") == 0)
debug = 1;
else
syslog(LOG_DEBUG, "illegal option %s", argv[i]);
}
if (pam_get_item(pamh, PAM_USER, (void **) &lusername) != PAM_SUCCESS)
return (PAM_SERVICE_ERR);
if (pam_get_item(pamh, PAM_RHOST, (void **) &host) != PAM_SUCCESS)
return (PAM_SERVICE_ERR);
if (pam_get_item(pamh, PAM_RUSER, (void **)&rusername) != PAM_SUCCESS)
return (PAM_SERVICE_ERR);
if (debug) {
syslog(LOG_DEBUG,
"rhosts authenticate: user = %s, host = %s",
lusername, host);
}
if (getpwnam_r(lusername, &pwd, pwd_buffer, sizeof (pwd_buffer))
== NULL)
return (PAM_USER_UNKNOWN);
/*
* RHOST may not be set due to unknown USER or reset by previous
* authentication failure.
*/
if ((rusername == NULL) || (rusername[0] == '\0'))
return (PAM_AUTH_ERR);
if (pwd.pw_uid == 0)
is_superuser = 1;
else
is_superuser = 0;
return (ruserok(host, is_superuser, rusername, lusername)
== -1 ? PAM_AUTH_ERR : PAM_SUCCESS);
}
/*
* dummy pam_sm_setcred - does nothing
*/
pam_sm_setcred(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,69 @@
/* $XConsortium: unix_headers.h /main/4 1996/05/09 04:29:21 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _UNIX_HEADERS_H
#define _UNIX_HEADERS_H
#pragma ident "@(#)unix_headers.h 1.6 96/02/02 SMI" /* PAM 2.6 */
#ifdef __cplusplus
extern "C" {
#endif
/*
******************************************************************
PROPRIETARY NOTICE(Combined)
This source code is unpublished proprietary information
constituting, or derived under license from AT&T's UNIX(r) System V.
In addition, portions of such source code were derived from Berkeley
4.3 BSD under license from the Regents of the University of
California.
Copyright Notice
Notice of copyright on this source code product does not indicate
publication.
(c) 1986, 1987, 1988, 1989, 1990, 1991, 1992 Sun Microsystems, Inc
(c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T.
All rights reserved.
*******************************************************************
*/
/*
******************************************************************** *
* *
* Unix Scheme Header Files *
* *
* ******************************************************************** */
#include <sys/param.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <pwd.h>
#include <shadow.h>
#include <string.h>
#include <rpc/types.h>
#include <rpc/auth.h>
#include <locale.h>
#include <crypt.h>
#include <syslog.h>
/*
* Miscellaneous constants
*/
#define ROOTUID 0
#ifdef __cplusplus
}
#endif
#endif /* _UNIX_HEADERS_H */

View File

@@ -0,0 +1,46 @@
/* $XConsortium: Imakefile /main/2 1996/04/21 19:14:34 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#define DoNormalLib NormalLibPam
#define DoSharedLib SharedLibPam
#define DoDebugLib DebugLibPam
#define DoProfileLib ProfileLibPam
#define LibName pam_sample
#define SoRev SOPAMREV
#define LibHeaders NO
#include <Threads.tmpl>
SRCS = \
sample_acct_mgmt.c \
sample_authenticate.c \
sample_close_session.c \
sample_open_session.c \
sample_password.c \
sample_setcred.c \
sample_utils.c
OBJS = \
sample_acct_mgmt.o \
sample_authenticate.o \
sample_close_session.o \
sample_open_session.o \
sample_password.o \
sample_setcred.o \
sample_utils.o
#ifdef SharedPamSampleReqs
REQUIREDLIBS = SharedPamSampleReqs
#endif
#include <Library.tmpl>
DependTarget()

View File

@@ -0,0 +1,28 @@
/****************************************************************************
* Export list for libpam_sample.
* This list *must* be updated whenever a change is made to the libpam_sample
* API.
*
* The syntax for the symbol declarations in this list is as follows:
* public sym => Public C symbol, i.e., publicised API
* private sym => Private C symbol, i.e., unpublicised API
* internal sym => Internal C symbol, i.e., not part of API
* publicC++ sym => Public C++ symbol, i.e., publicised API
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
* internalC++ sym => Internal C++ symbol, i.e., not part of API
*
* $TOG: libpam_sample.elist /main/1 1999/09/08 15:59:30 mgreess $
*****************************************************************************/
public pam_sm_authenticate
public pam_sm_setcred
public pam_sm_acct_mgmt
public pam_sm_open_session
public pam_sm_close_session
public pam_sm_chauthtok
internal display_errmsg
internal get_authtok
internal free_msg
internal free_resp

View File

@@ -0,0 +1,127 @@
/* $XConsortium: sample_acct_mgmt.c /main/2 1996/05/09 04:29:37 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)sample_acct_mgmt.c 1.12 96/02/02 SMI"
#include <syslog.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <libintl.h>
static parse_allow_name(char *, char *);
/*
* pam_sm_acct_mgmt main account managment routine.
* It only checks the flag passed from pam_sm_auth_user().
* XXX: The routine just prints out a warning message.
* It may need to force the user to change his/her
* passwd.
*/
#include <security/pam_appl.h>
#define PAMTXD "SUNW_OST_SYSOSPAM"
int
pam_sm_acct_mgmt(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
char *user;
char *pg;
int i;
int debug = 0;
int nowarn = 0;
int error = 0;
if (argc == 0)
return (PAM_SUCCESS);
if (pam_get_item(pamh, PAM_USER, (void **)&user) != PAM_SUCCESS)
return (PAM_SERVICE_ERR);
if (pam_get_item(pamh, PAM_SERVICE, (void **)&pg) != PAM_SUCCESS)
return (PAM_SERVICE_ERR);
/*
* kludge alert. su needs to be handled specially for allow policy.
* we want to use the policy of the current user not the "destination"
* user. This will enable us to prevent su to root but not to rlogin,
* telnet, rsh, ftp to root.
*
* description of problem: user name is the "destination" name. not
* the current name. The allow policy needs to be applied to the
* current name in the case of su. user is "root" in this case and
* we will be getting the root policy instead of the user policy.
*/
if (strcmp(pg, "su") == 0) {
struct passwd *pw;
uid_t uid;
uid = getuid();
pw = getpwuid(uid);
if (pw == NULL)
return (PAM_SYSTEM_ERR);
user = pw->pw_name;
}
if (user == 0 || *user == '\0' || (strcmp(user, "root") == 0))
return (PAM_SUCCESS);
for (i = 0; i < argc; i++) {
if (strcasecmp(argv[i], "debug") == 0)
debug = 1;
else if (strcasecmp(argv[i], "nowarn") == 0) {
nowarn = 1;
flags = flags | PAM_SILENT;
} else if (strncmp(argv[i], "allow=", 6) == 0)
error |= parse_allow_name(user, (char *)(argv[i]+6));
else
syslog(LOG_DEBUG, "illegal option %s", argv[i]);
}
return (error?PAM_SUCCESS:PAM_AUTH_ERR);
}
static
parse_allow_name(char *who, char *cp)
{
char name[256];
static char *getname();
/* catch "allow=" */
if (*cp == '\0')
return (0);
while (cp) {
cp = getname(cp, name);
/* catch things such as =, and ,, */
if (*name == '\0')
continue;
if (strcmp(who, name) == 0)
return (1);
}
return (0);
}
static char *
getname(char *cp, char *name)
{
/* force name to be initially null string */
*name = '\0';
/* end of string? */
if (*cp == '\0')
return ((char *)0);
while (*cp) {
/* end of name? */
if (*cp == ',' || *cp == '\0')
break;
*name++ = *cp++;
}
/* make name into string */
*name++ = '\0';
return ((*cp == '\0')? (char *)0 : ++cp);
}

View File

@@ -0,0 +1,168 @@
/* $XConsortium: sample_authenticate.c /main/2 1996/05/09 04:29:50 drk $ */
/*
* Copyright (c) 1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)sample_authenticate.c 1.14 96/01/15 SMI"
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#include <syslog.h>
#include <libintl.h>
#include "sample_utils.h"
#define SLEEPTIME 4
/*
*
* Sample module for pam_sm_authenticate.
*
* options -
*
* debug
* use_first_pass
* try_first_pass
* first_pass_good (first password is always good when used with use/try)
* first_pass_bad (first password is always bad when used with use/try)
* pass=foobar (set good password to "foobar". default good password
* is test)
* always_fail always return PAM_AUTH_ERR
* always_succeed always return PAM_SUCCESS
* always_ignore
*
*
*/
/*
* pam_sm_authenticate - Authenticate user
*/
int
pam_sm_authenticate(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
char *user;
struct pam_conv *pam_convp;
int err, result = PAM_AUTH_ERR;
struct pam_response *ret_resp = (struct pam_response *)0;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
int debug = 0;
int try_first_pass = 0;
int use_first_pass = 0;
int first_pass_good = 0;
int first_pass_bad = 0;
int i, num_msg;
char *firstpass, *password;
char the_password[64];
if (debug)
syslog(LOG_DEBUG, "Sample Authentication\n");
strcpy(the_password, "test");
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0)
debug = 1;
else if (strcmp(argv[i], "try_first_pass") == 0)
try_first_pass = 1;
else if (strcmp(argv[i], "first_pass_good") == 0)
first_pass_good = 1;
else if (strcmp(argv[i], "first_pass_bad") == 0)
first_pass_bad = 1;
else if (strcmp(argv[i], "use_first_pass") == 0)
use_first_pass = 1;
else if (strcmp(argv[i], "always_fail") == 0)
return (PAM_AUTH_ERR);
else if (strcmp(argv[i], "always_succeed") == 0)
return (PAM_SUCCESS);
else if (strcmp(argv[i], "always_ignore") == 0)
return (PAM_IGNORE);
else if (sscanf(argv[i], "pass=%s", the_password) == 1) {
/* nothing */;
}
else
syslog(LOG_DEBUG, "illegal scheme option %s", argv[i]);
}
err = pam_get_item(pamh, PAM_USER, (void**) &user);
if (err != PAM_SUCCESS)
return (err);
err = pam_get_item(pamh, PAM_CONV, (void**) &pam_convp);
if (err != PAM_SUCCESS)
return (err);
(void) pam_get_item(pamh, PAM_AUTHTOK, (void **) &firstpass);
if (firstpass && (use_first_pass || try_first_pass)) {
if ((first_pass_good ||
strcmp(firstpass, the_password) == 0) &&
!first_pass_bad) {
result = PAM_SUCCESS;
goto out;
}
if (use_first_pass) goto out;
}
/*
* Get the password from the user
*/
if (firstpass) {
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 1,
"TEST Password: "));
} else {
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 2,
"Password: "));
}
num_msg = 1;
err = get_authtok(pam_convp->conv,
num_msg, messages, NULL, &ret_resp);
if (err != PAM_SUCCESS) {
result = err;
goto out;
}
password = ret_resp->resp;
if (password == NULL) {
result = PAM_AUTH_ERR;
goto out;
}
/* one last ditch attempt to "login" to TEST */
if (strcmp(password, the_password) == 0) {
result = PAM_SUCCESS;
if (firstpass == NULL) {
/* this is the first password, stash it away */
pam_set_item(pamh, PAM_AUTHTOK, password);
}
}
out:
if (num_msg > 0) {
if (ret_resp != 0) {
if (ret_resp->resp != 0) {
/* avoid leaving password cleartext around */
memset(ret_resp->resp, 0,
strlen(ret_resp->resp));
}
free_resp(num_msg, ret_resp);
ret_resp = 0;
}
}
return (result);
}

View File

@@ -0,0 +1,21 @@
/* $XConsortium: sample_close_session.c /main/2 1996/05/09 04:30:08 drk $ */
/*
* Copyright (c) 1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)sample_close_session.c 1.8 96/01/12 SMI"
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <syslog.h>
int
pam_sm_close_session(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,21 @@
/* $XConsortium: sample_open_session.c /main/2 1996/05/09 04:30:22 drk $ */
/*
* Copyright (c) 1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)sample_open_session.c 1.8 96/01/12 SMI"
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <syslog.h>
int
pam_sm_open_session(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,27 @@
/* $XConsortium: sample_password.c /main/2 1996/05/09 04:30:43 drk $ */
/*
* Copyright (c) 1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)sample_password.c 1.10 96/01/15 SMI"
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <syslog.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
int
pam_sm_chauthtok(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,32 @@
/* $XConsortium: sample_setcred.c /main/2 1996/05/09 04:31:02 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)sample_setcred.c 1.9 96/01/12 SMI"
#include <libintl.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#define PAMTXD "SUNW_OST_SYSOSPAM"
/*
* pam_sm_setcred
*/
int
pam_sm_setcred(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
/*
* Set the credentials
*/
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,174 @@
/* $XConsortium: sample_utils.c /main/2 1996/05/09 04:31:21 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)sample_utils.c 1.8 96/01/12 SMI"
#include <security/pam_appl.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include "sample_utils.h"
/* ******************************************************************** */
/* */
/* Utilities Functions */
/* */
/* ******************************************************************** */
/*
* free_msg():
* free storage for messages used in the call back "pam_conv" functions
*/
void
free_msg(num_msg, msg)
int num_msg;
struct pam_message *msg;
{
int i;
struct pam_message *m;
if (msg) {
m = msg;
for (i = 0; i < num_msg; i++, m++) {
if (m->msg)
free(m->msg);
}
free(msg);
}
}
/*
* free_resp():
* free storage for responses used in the call back "pam_conv" functions
*/
void
free_resp(num_msg, resp)
int num_msg;
struct pam_response *resp;
{
int i;
struct pam_response *r;
if (resp) {
r = resp;
for (i = 0; i < num_msg; i++, r++) {
if (r->resp)
free(r->resp);
}
free(resp);
}
}
/*
* display_errmsg():
* display error message by calling the call back functions
* provided by the application through "pam_conv" structure
*/
int
display_errmsg(conv_funp, num_msg, messages, conv_apdp)
int (*conv_funp)();
int num_msg;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
void *conv_apdp;
{
struct pam_message *msg;
struct pam_message *m;
struct pam_response *resp;
int i;
int k;
int retcode;
msg = (struct pam_message *)calloc(num_msg,
sizeof (struct pam_message));
if (msg == NULL) {
return (PAM_CONV_ERR);
}
m = msg;
i = 0;
k = num_msg;
resp = NULL;
while (k--) {
/*
* fill out the pam_message structure to display error message
*/
m->msg_style = PAM_ERROR_MSG;
m->msg = (char *)malloc(PAM_MAX_MSG_SIZE);
if (m->msg != NULL)
(void) strcpy(m->msg, (const char *)messages[i]);
else
continue;
m++;
i++;
}
/*
* Call conv function to display the message,
* ignoring return value for now
*/
retcode = conv_funp(num_msg, &msg, &resp, conv_apdp);
free_msg(num_msg, msg);
free_resp(num_msg, resp);
return (retcode);
}
/*
* get_authtok():
* get authentication token by calling the call back functions
* provided by the application through "pam_conv" structure
*/
int
get_authtok(conv_funp, num_msg, messages, conv_apdp, ret_respp)
int (*conv_funp)();
int num_msg;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
void *conv_apdp;
struct pam_response **ret_respp;
{
struct pam_message *msg;
struct pam_message *m;
int i;
int k;
int retcode;
i = 0;
k = num_msg;
msg = (struct pam_message *)calloc(num_msg,
sizeof (struct pam_message));
if (msg == NULL) {
return (PAM_CONV_ERR);
}
m = msg;
while (k--) {
/*
* fill out the message structure to display error message
*/
m->msg_style = PAM_PROMPT_ECHO_OFF;
m->msg = (char *)malloc(PAM_MAX_MSG_SIZE);
if (m->msg != NULL)
(void) strcpy(m->msg, (char *)messages[i]);
else
continue;
m++;
i++;
}
/*
* Call conv function to display the prompt,
* ignoring return value for now
*/
retcode = conv_funp(num_msg, &msg, ret_respp, conv_apdp);
free_msg(num_msg, msg);
return (retcode);
}

View File

@@ -0,0 +1,51 @@
/* $XConsortium: sample_utils.h /main/2 1996/05/09 04:31:40 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _TEST_UTILS_H
#define _TEST_UTILS_H
#pragma ident "@(#)sample_utils.h 1.7 96/02/02 SMI" /* PAM 2.6 */
#ifdef __cplusplus
extern "C" {
#endif
void
free_msg(int num_msg, struct pam_message *msg);
void
free_resp(int num_msg, struct pam_response *resp);
int
display_errmsg(
int (*conv_funp)(),
int num_msg,
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE],
void *conv_apdp
);
int
get_authtok(
int (*conv_funp)(),
int num_msg,
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE],
void *conv_apdp,
struct pam_response **ret_respp
);
/*
* PAM_MSG macro for return of internationalized text
*/
#define PAM_MSG(pamh, number, string)\
(char *) __pam_get_i18n_msg(pamh, "pam_unix", 3, number, string)
#ifdef __cplusplus
}
#endif
#endif /* _TEST_UTILS_H */

View File

@@ -0,0 +1,66 @@
/* $XConsortium: Imakefile /main/4 1996/04/21 19:13:04 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#define DoNormalLib NormalLibPam
#define DoSharedLib SharedLibPam
#define DoDebugLib DebugLibPam
#define DoProfileLib ProfileLibPam
#define LibName pam_unix
#define SoRev SOPAMREV
#define LibHeaders NO
#include <Threads.tmpl>
SRCS = unix_acct_mgmt.c \
unix_authenticate.c \
unix_chauthtok.c \
unix_close_session.c \
unix_get_authtokattr.c \
unix_open_session.c \
unix_set_authtokattr.c \
npd_clnt.c \
unix_setcred.c \
unix_update_authtok.c \
unix_update_authtok_file.c \
unix_update_authtok_nis.c \
unix_update_authtok_nisplus.c \
switch_utils.c \
unix_utils.c \
yppasswdxdr.c
OBJS = unix_acct_mgmt.o \
unix_authenticate.o \
unix_chauthtok.o \
unix_close_session.o \
unix_get_authtokattr.o \
unix_open_session.o \
unix_set_authtokattr.o \
npd_clnt.o \
unix_setcred.o \
unix_update_authtok.o \
unix_update_authtok_file.o \
unix_update_authtok_nis.o \
unix_update_authtok_nisplus.o \
switch_utils.o \
unix_utils.o \
yppasswdxdr.o
#ifdef SharedPamUnixReqs
REQUIREDLIBS = SharedPamUnixReqs
#endif
#ifdef PamUnixDefines
DEFINES = PamUnixDefines
#endif
#include <Library.tmpl>
DependTarget()

View File

@@ -0,0 +1,48 @@
/****************************************************************************
* Export list for libpam_unix.
* This list *must* be updated whenever a change is made to the libpam_unix API.
*
* The syntax for the symbol declarations in this list is as follows:
* public sym => Public C symbol, i.e., publicised API
* private sym => Private C symbol, i.e., unpublicised API
* internal sym => Internal C symbol, i.e., not part of API
* publicC++ sym => Public C++ symbol, i.e., publicised API
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
* internalC++ sym => Internal C++ symbol, i.e., not part of API
*
* $TOG: libpam_unix.elist /main/1 1999/09/08 15:59:55 mgreess $
*****************************************************************************/
public pam_sm_authenticate
public pam_sm_setcred
public pam_sm_acct_mgmt
public pam_sm_open_session
public pam_sm_close_session
public pam_sm_chauthtok
internal get_ns
internal __set_authtoken_attr
internal defcntl
internal defopen
internal ck_perm
internal gethomedir
internal str2spwd
internal xdr_yppasswd
internal getspnam_from
internal update_authtok_file
internal setup_attr
internal getfingerinfo
internal free_setattr
internal defread
internal repository_to_string
internal _priv_lock
internal getpwnam_from
internal update_authtok_nis
internal attr_find
internal getloginshell
internal xdr_passwd
internal attr_match
internal __update_authtok
internal free_passwd_structs
internal __get_authtoken_attr

View File

@@ -0,0 +1,414 @@
/* $TOG: npd_clnt.c /main/5 1999/10/15 17:23:53 mgreess $ */
/*
* npd_clnt.c
* Contains all the client-side routines to communicate
* with the NIS+ passwd update deamon.
*
* Copyright (c) 1992-5 Sun Microsystems Inc
* All Rights Reserved.
*/
#ident "@(#)npd_clnt.c 1.11 95/09/19 SMI"
#ifdef PAM_NISPLUS
#include <syslog.h>
#include <string.h>
#include <shadow.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <rpc/des_crypt.h>
#include <mp.h>
#include <rpc/key_prot.h>
#include <rpcsvc/nis.h>
#include <rpcsvc/nispasswd.h>
#include <memory.h>
#include <sys/time.h>
#define _NPD_PASSMAXLEN 16
extern int pow(); /* from libmp.so (undocumented) */
extern int _mp_move(); /* from libmp.so (undocumented) */
extern int sdiv(); /* from libmp.so (undocumented) */
extern bool_t __npd_ecb_crypt();
extern bool_t __npd_cbc_crypt();
extern void *calloc();
extern void free();
/*
* given the domain return the client handle to the rpc.nispasswdd
* that I need to contact and the master_servers' publickey.
* returns TRUE on success and FALSE on failure.
*/
bool_t
npd_makeclnthandle(domain, clnt, srv_pubkey, keysize)
char *domain;
CLIENT **clnt; /* returned */
char *srv_pubkey; /* buf to hold the pubkey; returned */
int keysize; /* size of buffer */
{
nis_server **srvs; /* servers that serve 'domain' */
nis_server *master_srv;
char buf[NIS_MAXNAMELEN];
CLIENT *tmpclnt = NULL;
if (domain == NULL || *domain == '\0')
domain = nis_local_directory();
/* strlen("org_dir.") + null + "." = 10 */
if ((strlen(domain) + 10) > (size_t) NIS_MAXNAMELEN)
return (FALSE);
(void) sprintf(buf, "org_dir.%s", domain);
if (buf[strlen(buf) - 1] != '.')
(void) strcat(buf, ".");
srvs = nis_getservlist(buf);
if (srvs == NULL) {
/* can't find any of the servers that serve this domain */
/* something is very wrong ! */
syslog(LOG_ERR,
"can't get a list of servers for %s domain",
domain);
return (FALSE);
}
master_srv = srvs[0]; /* the first one is always the master */
/*
* copy the publickey -- should be safe to assume there is one,
* BUT just in case lets check first !
*/
switch (master_srv->key_type) {
case NIS_PK_DH:
if (keysize < master_srv->pkey.n_len) {
syslog(LOG_ERR,
"buf is %d bytes only, need %d bytes for the key",
keysize, master_srv->pkey.n_len);
(void) nis_freeservlist(srvs);
return (FALSE);
}
(void) strcpy(srv_pubkey, master_srv->pkey.n_bytes);
break;
case NIS_PK_NONE:
default:
/* server does not have a D-H key-pair */
syslog(LOG_ERR, "no publickey for %s", master_srv->name);
(void) nis_freeservlist(srvs);
return (FALSE);
}
/*
* now that we have the universal addr for the master server,
* lets create the client handle to rpc.nispasswdd.
* always use VC and attempt to create an authenticated handle.
* nis_make_rpchandle() will attempt to use auth_des first,
* if user does not have D-H keys, then it will try auth_sys.
* sendsz and recvsz are 0 ==> choose defaults.
*/
tmpclnt = nis_make_rpchandle(master_srv, 0, NISPASSWD_PROG,
NISPASSWD_VERS, ZMH_VC+ZMH_AUTH, 0, 0);
/* done with server list */
(void) nis_freeservlist(srvs);
if (tmpclnt == NULL) {
/*
* error syslog'd by nis_make_rpchandle()
*/
return (FALSE);
}
*clnt = tmpclnt;
return (TRUE);
}
/*
* generate a common DES key with the publickey I give and
* my secret key -- used by the client-side because the secret
* key is not cached with keyserv.
* returns TRUE on success and FALSE on failure.
*/
bool_t
__get_cmnkey(public, secret, deskey)
char *public;
char *secret;
des_block *deskey;
{
MINT *pub;
MINT *sec;
MINT *cmn;
MINT *tmp;
short reg;
short base = (1 << 8);
int i;
char *k;
pub = xtom(public);
sec = xtom(secret);
if ((pub == NULL) || (sec == NULL))
return (FALSE);
cmn = itom(0);
(void) pow(pub, sec, xtom(HEXMODULUS), cmn);
/*
* Choose middle 64 bits of the common key to use as our des
* key, possibly overwriting the lower order bits by setting
* parity.
*/
tmp = itom(0);
(void) _mp_move(cmn, tmp);
for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
(void) sdiv(tmp, base, tmp, &reg);
}
k = deskey->c;
for (i = 0; i < 8; i++) {
(void) sdiv(tmp, base, tmp, &reg);
*k++ = reg;
}
des_setparity((char *)deskey);
mfree(tmp);
mfree(sec);
mfree(pub);
mfree(cmn);
return (TRUE);
}
/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 55, 0 };
/*
* initiate the passwd update request session by sending
* username, domainname, the generated public key and
* the callers' old passwd encrypted with the common DES key.
* if it succeeds, decrypt the identifier and randval sent in
* the response; otherwise return an appropriate error code.
*/
nispasswd_status
nispasswd_auth(user, domain, oldpass, u_pubkey, deskey, clnt,
ident, randval, err)
char *user; /* user name */
char *domain; /* domain */
char *oldpass; /* clear old password */
unsigned char *u_pubkey; /* users' public key */
des_block *deskey; /* the common DES key */
CLIENT *clnt; /* client handle to rpc.nispasswdd */
unsigned long *ident; /* ID, returned on first attempt */
unsigned long *randval; /* R, returned on first attempt */
int *err; /* error code, returned */
{
npd_request req_arg;
nispasswd_authresult res;
des_block ivec;
unsigned char xpass[_NPD_PASSMAXLEN];
des_block cryptbuf;
int cryptstat;
int i;
char *keystr = "DES";
if ((user == NULL || *user == '\0') ||
(domain == NULL || *domain == '\0') ||
(oldpass == NULL || *oldpass == '\0') ||
(u_pubkey == NULL || *u_pubkey == '\0') ||
(deskey == (des_block *) NULL) ||
(clnt == (CLIENT *) NULL)) {
*err = NPD_INVALIDARGS;
return (NPD_FAILED);
}
(void) memset((char *)&req_arg, 0, sizeof (req_arg));
(void) memset((char *)&res, 0, sizeof (res));
/* encrypt the passwd with the common des key */
if (strlen(oldpass) > (size_t) _NPD_PASSMAXLEN) {
*err = NPD_BUFTOOSMALL;
return (NPD_FAILED);
}
(void) strcpy((char *)xpass, oldpass);
for (i = strlen(oldpass); i < _NPD_PASSMAXLEN; i++)
xpass[i] = '\0';
ivec.key.high = ivec.key.low = 0;
cryptstat = cbc_crypt((char *) deskey, (char *) xpass,
_NPD_PASSMAXLEN, DES_ENCRYPT | DES_HW,
(char *) &ivec);
if (DES_FAILED(cryptstat)) {
*err = NPD_ENCRYPTFAIL;
return (NPD_FAILED);
}
req_arg.username = user;
req_arg.domain = domain;
req_arg.key_type = keystr;
req_arg.user_pub_key.user_pub_key_len =
strlen((char *)u_pubkey) + 1;
req_arg.user_pub_key.user_pub_key_val = u_pubkey;
req_arg.npd_authpass.npd_authpass_len = _NPD_PASSMAXLEN;
req_arg.npd_authpass.npd_authpass_val = xpass;
req_arg.ident = *ident; /* on re-tries ident is non-zero */
if (clnt_call(clnt, NISPASSWD_AUTHENTICATE,
(xdrproc_t) xdr_npd_request, (caddr_t) &req_arg,
(xdrproc_t) xdr_nispasswd_authresult, (caddr_t) &res,
TIMEOUT) != RPC_SUCCESS) {
/* following msg is printed on stderr */
(void) clnt_perror(clnt, "call to rpc.nispasswdd failed");
*err = NPD_SRVNOTRESP;
return (NPD_FAILED);
}
switch (res.status) {
case NPD_SUCCESS:
case NPD_TRYAGAIN:
/*
* decrypt the ident & randval
*/
cryptbuf.key.high =
ntohl(res.nispasswd_authresult_u.npd_verf.npd_xid);
cryptbuf.key.low =
ntohl(res.nispasswd_authresult_u.npd_verf.npd_xrandval);
if (! __npd_ecb_crypt(ident, randval, &cryptbuf,
sizeof (des_block), DES_DECRYPT, deskey)) {
*err = NPD_DECRYPTFAIL;
return (NPD_FAILED);
}
return (res.status);
case NPD_FAILED:
*err = res.nispasswd_authresult_u.npd_err;
return (NPD_FAILED);
default:
/*
* should never reach this case !
*/
*err = NPD_SYSTEMERR;
return (NPD_FAILED);
}
/* NOTREACHED */
}
/*
* authenticated the caller, now send the identifier; and the
* new password and the random value encrypted with the common
* DES key. Send any other changed password information in the
* clear.
*/
int
nispasswd_pass(clnt, ident, randval, deskey, newpass, gecos, shell, err, errlst)
CLIENT *clnt; /* client handle to rpc.nispasswdd */
unsigned long ident; /* ID */
unsigned long randval; /* R */
des_block *deskey; /* common DES key */
char *newpass; /* clear new password */
char *gecos; /* gecos */
char *shell; /* shell */
int *err; /* error code, returned */
nispasswd_error **errlst; /* error list on partial success, returned */
{
npd_update send_arg;
nispasswd_updresult result;
npd_newpass cryptbuf;
unsigned long tmp_xrval;
nispasswd_error *errl = NULL, *p;
if ((clnt == (CLIENT *) NULL) ||
(deskey == (des_block *) NULL) ||
(newpass == NULL || *newpass == '\0')) {
*err = NPD_INVALIDARGS;
return (NPD_FAILED);
}
(void) memset((char *)&send_arg, 0, sizeof (send_arg));
(void) memset((char *)&result, 0, sizeof (result));
send_arg.ident = ident;
if (! __npd_cbc_crypt(&randval, newpass, strlen(newpass),
&cryptbuf, _NPD_PASSMAXLEN, DES_ENCRYPT, deskey)) {
*err = NPD_ENCRYPTFAIL;
return (NPD_FAILED);
}
tmp_xrval = cryptbuf.npd_xrandval;
cryptbuf.npd_xrandval = htonl(tmp_xrval);
send_arg.xnewpass = cryptbuf;
/* gecos */
send_arg.pass_info.pw_gecos = gecos;
/* shell */
send_arg.pass_info.pw_shell = shell;
if (clnt_call(clnt, NISPASSWD_UPDATE,
(xdrproc_t) xdr_npd_update, (caddr_t) &send_arg,
(xdrproc_t) xdr_nispasswd_updresult, (caddr_t) &result,
TIMEOUT) != RPC_SUCCESS) {
/* printed to stderr */
(void) clnt_perror(clnt, "call to rpc.nispasswdd failed");
*err = NPD_SRVNOTRESP;
return (NPD_FAILED);
}
switch (result.status) {
case NPD_SUCCESS:
return (NPD_SUCCESS);
case NPD_PARTIALSUCCESS:
/* need to assign field/err code */
errl = &result.nispasswd_updresult_u.reason;
if (errl == (struct nispasswd_error *) NULL) {
*err = NPD_SYSTEMERR;
return (NPD_FAILED);
}
*errlst = (nispasswd_error *)
calloc(1, sizeof (nispasswd_error));
if (*errlst == (struct nispasswd_error *) NULL) {
*err = NPD_SYSTEMERR;
return (NPD_FAILED);
}
for (p = *errlst; errl != NULL; errl = errl->next) {
p->npd_field = errl->npd_field;
p->npd_code = errl->npd_code;
if (errl->next != NULL) {
p->next = (nispasswd_error *)
calloc(1, sizeof (nispasswd_error));
p = p->next;
} else
p->next = (nispasswd_error *) NULL;
}
return (NPD_PARTIALSUCCESS);
case NPD_FAILED:
*err = result.nispasswd_updresult_u.npd_err;
return (NPD_FAILED);
default:
/*
* should never reach this case !
*/
*err = NPD_SYSTEMERR;
return (NPD_FAILED);
}
}
void
__npd_free_errlist(list)
nispasswd_error *list;
{
nispasswd_error *p;
if (list == NULL)
return;
for (; list != NULL; list = p) {
p = list->next;
free(list);
}
list = NULL;
}
#else
#if defined(sun)
/* Quiet warnings */
static int dummy;
#endif /* sun */
#endif /* PAM_NISPLUS */

View File

@@ -0,0 +1,213 @@
$ $XConsortium: pam_unix.msg /main/2 1996/07/24 19:04:15 drk $
$ *************************************<+>*************************************
$ *****************************************************************************
$ **
$ ** File: pam_unix.msg
$ **
$ ** Project: pam
$ **
$ ** Description:
$ ** -----------
$ ** This file is the source for the pam_unix message catalog.
$ **
$ ** It contains messages for the pam_unix service module (set 1).
$ **
$ ** Also contains messages for pam_dial (set 2) and pam_test (set 3) modules.
$ **
$ *****************************************************************************
$ **
$ ** (c) Copyright 1996 Sun Microsystems, Inc.
$ ** All Rights reserved
$ **
$ *****************************************************************************
$ *************************************<+>*************************************
$ *****************************************************************************
$
$ ***** NOTE FOR MESSAGE CATALOG TRANSLATORS *****
$
$ There may be three types of messages in this file:
$
$ 1. Messages that appear in dialogs or are displayed to the user.
$
$ These messages are the default and they should ALL BE LOCALIZED.
$ Note that these messages do NOT have any identification (see the
$ comments for type 2 and 3 below).
$
$ 2. Messages that only appear in the error log file.
$
$ The localization of these messages is OPTIONAL. These messages are
$ identified by the following:
$
$ MESSAGES xx-yy IN SET zz WILL ONLY APPEAR IN THE DT ERRORLOG FILE
$
$ 3. Messages that should not be localized.
$
$ These messages are identified by the following:
$
$ DO NOT TRANSLATE or CHANGE or LOCALIZE MESSAGES xx-yy from set zz
$
$ ***** END (NOTE FOR MESSAGE CATALOG TRANSLATORS) *****
$
$ ******************************************************************************
$ unix module messages
$set 1
$ switch_utils.c
$ Msg 1 thru 8 print on consecutive lines.
$ Keep intentation for "passwd:" in messages 2 thru 7
1 Supported configurations for passwd management are as follows:
2 passwd: files
3 passwd: files nis
4 passwd: files nisplus
5 passwd: compat
6 passwd: compat AND
7 passwd_compat: nisplus
8 Please check your /etc/nsswitch.conf file
9 Can't find name service for passwd
10 You may not use nisplus repository
11 Your specified repository is not defined in the nsswitch file!
$ unix_acct_mgmt.c
20 Your password has been expired for too long.
21 Please contact the system administrator
22 Your password will expire within 24 hours.
23 Your password will expire in %d day.
24 Your password will expire in %d days.
$ unix_authenticate.c
30 UNIX Password:
31 Password:
$ unix_get_authtokattr.c
40 You must specify repository when displaying passwd attributes
$ leave "%s" unchanged
41 %s: System error: repository out of range
42 Unable to retrieve username.
$ leave "%s" unchanged
43 %s: Unexpected failure. Password database unchanged.
$ unix_setcred.c
$ translate 50-51 as a single sentence
50 Removing root credentials would break the rpc services that
51 use secure rpc on this host!
52 Root may use keylogout -f to do this (at your own risk)!
53 Could not unset your secret key.
54 Maybe the keyserver is down?
55 Warning: NFS credentials not destroyed
56 Password does not decrypt secret key for %s.
57 Could not set secret key for %s. The key server may be down.
$ unix_update_authtok.c
60 %s%s: %s does not exist
61 %s%s: user must have NIS+ credential
62 Enter login(NIS) password:
63 Enter login(NIS+) password:
64 Enter login password:
65 %s%s: Sorry.
66 %s%s: Sorry, wrong passwd
67 This password differs from your secure RPC password.
68 Please enter your old Secure RPC password:
69 This password does not decrypt your secure RPC credentials. Try again:
70 Please enter your old Secure RPC password:
71 %s%s: Sorry: less than %ld days since the last change.
72 %s%s: You may not change this password.
73 %s%s: can't create process
74 New password:
75 Re-enter new password:
76 %s%s: Too many tries; try again later
77 %s%s: They don't match; try again.
78 %s%s: Too many failures - try later.
79 %s%s: Password too short - must be at least 6 characters.
80 %s%s: Password cannot be circular shift of logonid.
81 %s%s: The first %d characters of the password
82 must contain at least two alphabetic characters and at least
83 one numeric or special character.
84 %s%s: Passwords must differ by at least 3 positions
85 nispasswd: user must have LOCAL credential
86 %s: invalid LOCAL credential
$ unix_update_authtok_file.c
90 %s%s: Password database busy. Try again later.
91 %s%s: Unexpected failure. Password database unchanged.
92 %s%s: Unexpected failure. Password database missing.
93 %s%s: passwd successfully changed for %s
94 %s: No local passwd record
$ unix_update_authtok_nis.c
100 %s%s: couldn't change passwd/attributes
101 %s%s: Couldn't change passwd/attributes for %s
102 NIS(YP) passwd/attributes changed on %s
103 System error: no NIS passwd record for %s
104 %s: System error%s: shell is set illegally
105 System error%s: homedir is set illegally.
106 System error: gecos is set illegally.
107 %s: secret key reencrypted for %s on %s
$ unix_update_authtok_nisplus.c
108 NIS+ password information changed for %s
109 NIS+ credential information changed for %s
110 Unable to reencrypt NIS+ credentials for %s;
111 %s%s: Password information update failed
112 NIS+ password information changed for %s
113 The NIS+ credential information for %s will not be changed.
114 User %s must do the following to update his/her
115 credential information:
116 Use NEW passwd for login and OLD passwd for keylogin.
$ translate 117-118 as a single sentance.
117 Use \"chkey -p\" to reencrypt the credentials with the
118 new login passwd.
119 The user must keylogin explicitly after their next login.
120 WARNING: Could not reencrypt NIS+ credentials for %s;
121 login and keylogin passwords differ.
122 Use NEW passwd for login and OLD passwd for keylogin.
123 You must keylogin explicitly after your next login.
124 %s%s: couldn't change password for %s.
125 Reason: failed to update the cred table with reencrypted credentials.
126 Please notify your System Administrator.
127 NIS+ Password incorrect: try again
128 NIS+ password information update failed while talking to NIS+ passwd daemon
129 GECOS information was not updated: check NIS+ permissions.
130 SHELL information was not updated: check NIS+ permissions.
131 NIS+ Credential information was not updated.
132 No NIS+ record
133 NIS+ password information update failed (update_attr)
$ unix_utils.c
140 %s%s: Permission denied
141 %s%s: Can't change local passwd file\n
142 %s%s: System error: repository out of range
143 Cannot change from restricted shell %s
144 Old shell: %s
145 New shell:
146 Login shell unchanged.
147 %s is unacceptable as a new shell
148 warning: %s is unavailable on this machine
149 Default values are printed inside of '[]'.
150 To accept the default, type <return>.
151 To have a blank entry, type the word 'none'.
152 Name [%s]:
153 Finger information unchanged.
154 Home Directory [%s]:
155 Homedir information unchanged.
156 ':' is not allowed.
157 Maximum number of characters allowed is %d.
158 Control characters are not allowed.
$ dialup password module messages
$set 2
1 Dialup Password:
$ dialup password module messages
$set 3
1 TEST Password:
2 Password:

View File

@@ -0,0 +1,684 @@
/* $XConsortium: switch_utils.c /main/5 1996/05/09 04:32:20 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)switch_utils.c 1.31 96/02/02 SMI"
#include "unix_headers.h"
/*
* XXX
* This file relies on the fact that you are using NSS_SWITCH.
* If PAM_NIS or PAM_NISPLUS is defined, then the
* include files for nss_switch are included.
* Otherwise, the repository is assumed to be FILES,
* and NSS_SWITCH is not used.
*/
static void pr_config();
/*
* The following is similar to getpwnam() except that it specifies
* where to get the information. This is modeled after getpwnam_r().
*/
#ifdef PAM_NIS
static void
nss_nis_passwd(p)
nss_db_params_t *p;
{
p->name = NSS_DBNAM_PASSWD;
p->flags |= NSS_USE_DEFAULT_CONFIG;
p->default_config = "nis";
}
static void
nss_nis_shadow(p)
nss_db_params_t *p;
{
p->name = NSS_DBNAM_SHADOW;
p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */
p->flags |= NSS_USE_DEFAULT_CONFIG;
p->default_config = "nis";
}
#endif /* PAM_NIS */
#ifdef PAM_NISPLUS
static void
nss_nisplus_passwd(p)
nss_db_params_t *p;
{
p->name = NSS_DBNAM_PASSWD;
p->flags |= NSS_USE_DEFAULT_CONFIG;
p->default_config = "nisplus";
}
static void
nss_nisplus_shadow(p)
nss_db_params_t *p;
{
p->name = NSS_DBNAM_SHADOW;
p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */
p->flags |= NSS_USE_DEFAULT_CONFIG;
p->default_config = "nisplus";
}
#endif /* PAM_NISPLUS */
static char *
gettok(nextpp)
char **nextpp;
{
char *p = *nextpp;
char *q = p;
char c;
if (p == 0) {
return (0);
}
while ((c = *q) != '\0' && c != ':') {
q++;
}
if (c == '\0') {
*nextpp = 0;
} else {
*q++ = '\0';
*nextpp = q;
}
return (p);
}
#if (PAM_NIS || PAM_NISPLUS)
/*
* Return values: 0 = success, 1 = parse error, 2 = erange ...
* The structure pointer passed in is a structure in the caller's space
* wherein the field pointers would be set to areas in the buffer if
* need be. instring and buffer should be separate areas.
*/
static int
str2passwd(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
{
struct passwd *passwd = (struct passwd *)ent;
char *p, *next;
int black_magic; /* "+" or "-" entry */
if (lenstr + 1 > buflen) {
return (NSS_STR_PARSE_ERANGE);
}
/*
* We copy the input string into the output buffer and
* operate on it in place.
*/
(void) memcpy(buffer, instr, lenstr);
buffer[lenstr] = '\0';
next = buffer;
passwd->pw_name = p = gettok(&next); /* username */
if (*p == '\0') {
/* Empty username; not allowed */
return (NSS_STR_PARSE_PARSE);
}
black_magic = (*p == '+' || *p == '-');
if (black_magic) {
passwd->pw_uid = UID_NOBODY;
passwd->pw_gid = GID_NOBODY;
/*
* pwconv tests pw_passwd and pw_age == NULL
*/
passwd->pw_passwd = "";
passwd->pw_age = "";
/*
* the rest of the passwd entry is "optional"
*/
passwd->pw_comment = "";
passwd->pw_gecos = "";
passwd->pw_dir = "";
passwd->pw_shell = "";
}
passwd->pw_passwd = p = gettok(&next); /* password */
if (p == 0) {
if (black_magic)
return (NSS_STR_PARSE_SUCCESS);
else
return (NSS_STR_PARSE_PARSE);
}
for (; *p != '\0'; p++) { /* age */
if (*p == ',') {
*p++ = '\0';
break;
}
}
passwd->pw_age = p;
p = next; /* uid */
if (p == 0 || *p == '\0') {
if (black_magic)
return (NSS_STR_PARSE_SUCCESS);
else
return (NSS_STR_PARSE_PARSE);
}
if (!black_magic) {
passwd->pw_uid = strtol(p, &next, 10);
if (next == p) {
/* uid field should be nonempty */
return (NSS_STR_PARSE_PARSE);
}
/*
* The old code (in 2.0 thru 2.5) would check
* for the uid being negative, or being greater
* than 60001 (the rfs limit). If it met either of
* these conditions, the uid was translated to 60001.
*
* Now we just check for negative uids; anything else
* is administrative policy
*/
if (passwd->pw_uid < 0)
passwd->pw_uid = UID_NOBODY;
}
if (*next++ != ':') {
if (black_magic)
p = gettok(&next);
else
return (NSS_STR_PARSE_PARSE);
}
p = next; /* gid */
if (p == 0 || *p == '\0') {
if (black_magic)
return (NSS_STR_PARSE_SUCCESS);
else
return (NSS_STR_PARSE_PARSE);
}
if (!black_magic) {
passwd->pw_gid = strtol(p, &next, 10);
if (next == p) {
/* gid field should be nonempty */
return (NSS_STR_PARSE_PARSE);
}
/*
* gid should be non-negative; anything else
* is administrative policy.
*/
if (passwd->pw_gid < 0)
passwd->pw_gid = GID_NOBODY;
}
if (*next++ != ':') {
if (black_magic)
p = gettok(&next);
else
return (NSS_STR_PARSE_PARSE);
}
passwd->pw_gecos = passwd->pw_comment = p = gettok(&next);
if (p == 0) {
if (black_magic)
return (NSS_STR_PARSE_SUCCESS);
else
return (NSS_STR_PARSE_PARSE);
}
passwd->pw_dir = p = gettok(&next);
if (p == 0) {
if (black_magic)
return (NSS_STR_PARSE_SUCCESS);
else
return (NSS_STR_PARSE_PARSE);
}
passwd->pw_shell = p = gettok(&next);
if (p == 0) {
if (black_magic)
return (NSS_STR_PARSE_SUCCESS);
else
return (NSS_STR_PARSE_PARSE);
}
/* Better not be any more fields... */
if (next == 0) {
/* Successfully parsed and stored */
return (NSS_STR_PARSE_SUCCESS);
}
return (NSS_STR_PARSE_PARSE);
}
typedef const char *constp;
static bool_t /* 1 means success and more input, 0 means error or no more */
getfield(nextp, limit, uns, valp)
constp *nextp;
constp limit;
int uns;
void *valp;
{
constp p = *nextp;
char *endfield;
char numbuf[12]; /* Holds -2^31 and trailing \0 */
int len;
if (p == 0 || p >= limit) {
return (0);
}
if (*p == ':') {
p++;
*nextp = p;
return (p < limit);
}
if ((len = limit - p) > sizeof (numbuf) - 1) {
len = sizeof (numbuf) - 1;
}
/*
* We want to use strtol() and we have a readonly non-zero-terminated
* string, so first we copy and terminate the interesting bit.
* Ugh. (It's convenient to terminate with a colon rather than \0).
*/
if ((endfield = memccpy(numbuf, p, ':', len)) == 0) {
if (len != limit - p) {
/* Error -- field is too big to be a legit number */
return (0);
}
numbuf[len] = ':';
p = limit;
} else {
p += (endfield - numbuf);
}
if (uns) {
*((unsigned long *)valp) = strtoul(numbuf, &endfield, 10);
} else {
*((long *)valp) = strtol(numbuf, &endfield, 10);
}
if (*endfield != ':') {
/* Error -- expected <integer><colon>, got something else */
return (0);
}
*nextp = p;
return (p < limit);
}
/*
* str2spwd() -- convert a string to a shadow passwd entry. The parser is
* more liberal than the passwd or group parsers; since it's legitimate
* for almost all the fields here to be blank, the parser lets one omit
* any number of blank fields at the end of the entry. The acceptable
* forms for '+' and '-' entries are the same as those for normal entries.
* === Is this likely to do more harm than good?
*
* Return values: 0 = success, 1 = parse error, 2 = erange ...
* The structure pointer passed in is a structure in the caller's space
* wherein the field pointers would be set to areas in the buffer if
* need be. instring and buffer should be separate areas.
*/
int
str2spwd(instr, lenstr, ent, buffer, buflen)
const char *instr;
int lenstr;
void *ent; /* really (struct spwd *) */
char *buffer;
int buflen;
{
struct spwd *shadow = (struct spwd *)ent;
const char *p = instr, *limit;
char *bufp;
int lencopy, black_magic;
limit = p + lenstr;
if ((p = memchr(instr, ':', lenstr)) == 0 ||
++p >= limit ||
(p = memchr(p, ':', limit - p)) == 0) {
lencopy = lenstr;
p = 0;
} else {
lencopy = p - instr;
p++;
}
if (lencopy + 1 > buflen) {
return (NSS_STR_PARSE_ERANGE);
}
(void) memcpy(buffer, instr, lencopy);
buffer[lencopy] = 0;
black_magic = (*instr == '+' || *instr == '-');
shadow->sp_namp = bufp = buffer;
shadow->sp_pwdp = 0;
shadow->sp_lstchg = -1;
shadow->sp_min = -1;
shadow->sp_max = -1;
shadow->sp_warn = -1;
shadow->sp_inact = -1;
shadow->sp_expire = -1;
shadow->sp_flag = 0;
if ((bufp = strchr(bufp, ':')) == 0) {
if (black_magic)
return (NSS_STR_PARSE_SUCCESS);
else
return (NSS_STR_PARSE_PARSE);
}
*bufp++ = '\0';
shadow->sp_pwdp = bufp;
if (instr == 0) {
if ((bufp = strchr(bufp, ':')) == 0) {
if (black_magic)
return (NSS_STR_PARSE_SUCCESS);
else
return (NSS_STR_PARSE_PARSE);
}
*bufp++ = '\0';
p = bufp;
} /* else p was set when we copied name and passwd into the buffer */
if (!getfield(&p, limit, 0, &shadow->sp_lstchg))
return (NSS_STR_PARSE_SUCCESS);
if (!getfield(&p, limit, 0, &shadow->sp_min))
return (NSS_STR_PARSE_SUCCESS);
if (!getfield(&p, limit, 0, &shadow->sp_max))
return (NSS_STR_PARSE_SUCCESS);
if (!getfield(&p, limit, 0, &shadow->sp_warn))
return (NSS_STR_PARSE_SUCCESS);
if (!getfield(&p, limit, 0, &shadow->sp_inact))
return (NSS_STR_PARSE_SUCCESS);
if (!getfield(&p, limit, 0, &shadow->sp_expire))
return (NSS_STR_PARSE_SUCCESS);
if (!getfield(&p, limit, 1, &shadow->sp_flag))
return (NSS_STR_PARSE_SUCCESS);
if (p != limit) {
/* Syntax error -- garbage at end of line */
return (NSS_STR_PARSE_PARSE);
}
return (NSS_STR_PARSE_SUCCESS);
}
static nss_XbyY_buf_t *buffer;
static DEFINE_NSS_DB_ROOT(db_root);
#define GETBUF() \
NSS_XbyY_ALLOC(&buffer, sizeof (struct passwd), NSS_BUFLEN_PASSWD)
struct passwd *
getpwnam_from(name, rep)
const char *name;
int rep;
{
nss_XbyY_buf_t *b = GETBUF();
nss_XbyY_args_t arg;
if (b == 0)
return (0);
NSS_XbyY_INIT(&arg, b->result, b->buffer, b->buflen, str2passwd);
arg.key.name = name;
switch (rep) {
#ifdef PAM_NISPLUS
case PAM_REP_NISPLUS:
nss_search(&db_root, nss_nisplus_passwd, NSS_DBOP_PASSWD_BYNAME,
&arg);
break;
#endif
#ifdef PAM_NIS
case PAM_REP_NIS:
nss_search(&db_root, nss_nis_passwd, NSS_DBOP_PASSWD_BYNAME,
&arg);
break;
#endif
default:
return (NULL);
}
return (struct passwd *) NSS_XbyY_FINI(&arg);
}
static nss_XbyY_buf_t *spbuf;
static DEFINE_NSS_DB_ROOT(spdb_root);
#define GETSPBUF() \
NSS_XbyY_ALLOC(&spbuf, sizeof (struct spwd), NSS_BUFLEN_SHADOW)
struct spwd *
getspnam_from(name, rep)
const char *name;
int rep;
{
nss_XbyY_buf_t *b = GETSPBUF();
nss_XbyY_args_t arg;
if (b == 0)
return (0);
NSS_XbyY_INIT(&arg, b->result, b->buffer, b->buflen, str2spwd);
arg.key.name = name;
switch (rep) {
#ifdef PAM_NISPLUS
case PAM_REP_NISPLUS:
nss_search(&spdb_root, nss_nisplus_shadow,
NSS_DBOP_SHADOW_BYNAME, &arg);
break;
#endif
#ifdef PAM_NIS
case PAM_REP_NIS:
nss_search(&spdb_root, nss_nis_shadow,
NSS_DBOP_SHADOW_BYNAME, &arg);
break;
#endif
default:
return (NULL);
}
return (struct spwd *) NSS_XbyY_FINI(&arg);
}
#endif /* (PAM_NIS || PAM_NISPLUS) */
static void
pr_config(pamh)
pam_handle_t *pamh;
{
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
sprintf(messages[0], PAM_MSG(pamh, 1,
"Supported configurations for passwd management are as follows:"));
sprintf(messages[1], PAM_MSG(pamh, 2, " passwd: files"));
sprintf(messages[2], PAM_MSG(pamh, 3, " passwd: files nis"));
sprintf(messages[3], PAM_MSG(pamh, 4, " passwd: files nisplus"));
sprintf(messages[4], PAM_MSG(pamh, 5, " passwd: compat"));
sprintf(messages[5], PAM_MSG(pamh, 6, " passwd: compat AND"));
sprintf(messages[6], PAM_MSG(pamh, 7, " passwd_compat: nisplus"));
sprintf(messages[7],
PAM_MSG(pamh, 8, "Please check your /etc/nsswitch.conf file"));
/* display the above 8 messages */
(void) __pam_display_msg(pamh, PAM_ERROR_MSG, 8, messages, NULL);
}
/*
* get name services (or repositories) of passwd.
* o_rep: the specified respository in command line. If no repository is
* specified in the command line, o_rep is equal to PAM_REP_DEFAULT.
* return value: new repositories
* 1. In the case of PAM_REP_DEFAULT, new repositories are from nsswitch
* file (as long as it represents a valid and supported configuration).
* 2. In the case of specified repository, it should be present as one
* of the valid services (or repositories) in nsswitch file.
* A warning is printed if this happens. Operation is continued.
*/
int
get_ns(pamh, o_rep, debug, nowarn)
pam_handle_t *pamh;
int o_rep;
int debug;
int nowarn;
{
#if (PAM_NIS || PAM_NISPLUS)
struct __nsw_switchconfig *conf = NULL;
struct __nsw_switchconfig *confcomp = NULL;
enum __nsw_parse_err pserr;
struct __nsw_lookup *lkp;
struct __nsw_lookup *lkp2;
int rep = 0;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
/* yppasswd/nispasswd doesn't care about nsswitch file */
if (IS_OPWCMD(o_rep))
return (o_rep);
conf = __nsw_getconfig("passwd", &pserr);
if (conf == NULL) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 9,
"Can't find name service for passwd"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
if (IS_NISPLUS(o_rep)) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 10,
"You may not use nisplus repository"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (-1);
} else if (o_rep != PAM_REP_DEFAULT) {
/*
* The user specified a repository:
* Allow the user to try to change the passwd
* even though the specified repository is
* not listed in nsswitch.conf
*/
return (o_rep);
} else {
/*
* The user did not specify a repository:
* Allow the user to try to change the passwd
* in the default repositories (files and nis)
* even though we can not find the name service
* switch entry.
*/
rep = PAM_REP_FILES | PAM_REP_NIS;
return (rep); /* default */
}
}
if (debug)
syslog(LOG_DEBUG, "number of services is %d",
conf->num_lookups);
lkp = conf->lookups;
/*
* XXX: Currently we do now support more than 2 services
*/
if (conf->num_lookups > 2) {
pr_config(pamh);
return (-1);
} else if (conf->num_lookups == 1) {
/* files or compat */
if (strcmp(lkp->service_name, "files") == 0) {
rep |= PAM_REP_FILES;
if (o_rep == PAM_REP_NIS || o_rep == PAM_REP_NISPLUS) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 11,
"Your specified repository is not defined in the nsswitch file!"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (o_rep);
}
return (rep);
} else if (strcmp(lkp->service_name, "compat") == 0) {
/* get passwd_compat */
confcomp = __nsw_getconfig("passwd_compat", &pserr);
if (confcomp == NULL) {
rep = PAM_REP_FILES | PAM_REP_NIS;
if (o_rep == PAM_REP_NISPLUS) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 11,
"Your specified repository is not defined in the nsswitch file!"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (o_rep);
} else if (o_rep != PAM_REP_DEFAULT)
return (o_rep);
else
return (rep);
} else {
/* check the service: nisplus? */
if (strcmp(confcomp->lookups->service_name,
"nisplus") == 0) {
rep = PAM_REP_FILES | PAM_REP_NISPLUS;
if (o_rep == PAM_REP_NIS) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 11,
"Your specified repository is not defined in the nsswitch file!"));
__pam_display_msg(pamh,
PAM_ERROR_MSG,
1, messages, NULL);
}
return (o_rep);
} else if (o_rep != PAM_REP_DEFAULT)
return (o_rep);
else
return (rep);
} else {
/* passwd_compat must be nisplus?? */
return (-1);
}
}
} else {
pr_config(pamh);
return (-1);
}
} else { /* two services */
lkp = conf->lookups;
lkp2 = lkp->next;
if (strcmp(lkp->service_name, "files") == 0) {
/* files nis, or files nisplus */
rep |= PAM_REP_FILES;
/* continue */
} else {
pr_config(pamh);
return (-1);
}
if (strcmp(lkp2->service_name, "nis") == 0) {
rep |= PAM_REP_NIS;
if (o_rep == PAM_REP_NISPLUS) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 11,
"Your specified repository is not defined in the nsswitch file!"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (o_rep);
} else if (o_rep != PAM_REP_DEFAULT)
return (o_rep);
else
return (rep);
} else if (strcmp(lkp2->service_name, "nisplus") == 0) {
rep |= PAM_REP_NISPLUS;
if (o_rep == PAM_REP_NIS) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 11,
"Your specified repository is not defined in the nsswitch file!"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (o_rep);
} else if (o_rep != PAM_REP_DEFAULT)
return (o_rep);
else
return (rep);
} else {
pr_config(pamh);
return (-1);
}
}
#else
return (PAM_REP_FILES);
#endif /* (PAM_NIS || PAM_NISPLUS) */
}

View File

@@ -0,0 +1,313 @@
/* $XConsortium: unix_acct_mgmt.c /main/5 1996/05/09 04:32:39 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_acct_mgmt.c 1.35 95/12/08 SMI"
#include "unix_headers.h"
static void
unix_cleanup(
pam_handle_t *pamh,
void *data,
int pam_status)
{
free((unix_authtok_data *)data);
}
/*
* check_for_login_inactivity - Check for login inactivity
*
*/
static int
check_for_login_inactivity(
struct passwd pwd,
struct spwd shpwd)
{
int fdl;
struct lastlog ll;
int retval;
long long offset;
offset = (long long) pwd.pw_uid * (long long) sizeof (struct lastlog);
if ((fdl = open(LASTLOG, O_RDWR|O_CREAT, 0444)) >= 0) {
/*
* Read the last login (ll) time
*/
if (llseek(fdl, offset, SEEK_SET) != offset) {
/*
* XXX uid too large for database
*/
return (0);
}
retval = read(fdl, (char *)&ll, sizeof (ll));
/* Check for login inactivity */
if ((shpwd.sp_inact > 0) && (retval == sizeof (ll)) &&
ll.ll_time) {
if (((ll.ll_time / DAY) + shpwd.sp_inact) < DAY_NOW) {
/*
* Account inactive for too long
*/
(void) close(fdl);
return (1);
}
}
(void) close(fdl);
}
return (0);
}
/*
* new_password_check()
*
* check to see if the user needs to change their password
*/
static int
new_password_check(pwd, shpwd, flags)
struct passwd *pwd;
struct spwd *shpwd;
int flags;
{
int now = DAY_NOW;
/*
* We want to make sure that we change the password only if
* passwords are required for the system, the user does not
* have a password, AND the user's NULL password can be changed
* according to its password aging information
*/
if ((flags & PAM_DISALLOW_NULL_AUTHTOK) != 0) {
if (shpwd->sp_pwdp[0] == '\0') {
if ((pwd->pw_uid != 0) &&
((shpwd->sp_max == -1) ||
(shpwd->sp_lstchg > now) ||
((now >= shpwd->sp_lstchg + shpwd->sp_min) &&
(shpwd->sp_max >= shpwd->sp_min)))) {
return (PAM_NEW_AUTHTOK_REQD);
}
}
}
return (PAM_SUCCESS);
}
/*
* perform_passwd_aging_check
* - Check for password exipration.
*/
static int
perform_passwd_aging_check(
pam_handle_t *pamh,
struct spwd shpwd,
int flags)
{
int now = DAY_NOW;
int Idleweeks = -1;
char *ptr;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
if (defopen(LOGINADMIN) == 0) {
if ((ptr = defread("IDLEWEEKS=")) != NULL)
Idleweeks = atoi(ptr);
(void) defopen(NULL);
}
if ((shpwd.sp_lstchg == 0) ||
((shpwd.sp_max >= 0) &&
(now > (shpwd.sp_lstchg + shpwd.sp_max)) &&
(shpwd.sp_max >= shpwd.sp_min))) {
if ((Idleweeks == 0) ||
((Idleweeks > 0) &&
(now > (shpwd.sp_lstchg + (7 * Idleweeks))))) {
if (!(flags & PAM_SILENT)) {
strcpy(messages[0], PAM_MSG(pamh, 20,
"Your password has been expired for too long."));
strcpy(messages[1], PAM_MSG(pamh, 21,
"Please contact the system administrator"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
2, messages, NULL);
}
return (PAM_AUTHTOK_EXPIRED);
} else {
return (PAM_NEW_AUTHTOK_REQD);
}
}
return (PAM_SUCCESS);
}
/*
* warn_user_passwd_will_expire - warn the user when the password will
* expire.
*/
static void
warn_user_passwd_will_expire(
pam_handle_t *pamh,
struct spwd shpwd)
{
int now = DAY_NOW;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
int days;
if ((shpwd.sp_warn > 0) && (shpwd.sp_max > 0) &&
(now + shpwd.sp_warn) >= (shpwd.sp_lstchg + shpwd.sp_max)) {
days = (shpwd.sp_lstchg + shpwd.sp_max) - now;
if (days <= 0)
sprintf(messages[0], PAM_MSG(pamh, 22,
"Your password will expire within 24 hours."));
else if (days == 1)
sprintf(messages[0], PAM_MSG(pamh, 23,
"Your password will expire in %d day."), days);
else
sprintf(messages[0], PAM_MSG(pamh, 24,
"Your password will expire in %d days."), days);
__pam_display_msg(pamh, PAM_TEXT_INFO, 1, messages, NULL);
}
}
/*
* pam_sm_acct_mgmt - main account managment routine.
* Returns: module error or specific error on failure
*/
int
pam_sm_acct_mgmt(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
struct spwd shpwd;
struct passwd pwd;
char pwd_buf[1024];
char shpwd_buf[1024];
int error = PAM_ACCT_EXPIRED;
char *user;
int i;
int debug = 0;
int nowarn = 0;
uid_t orig_uid;
unix_authtok_data *status;
for (i = 0; i < argc; i++) {
if (strcasecmp(argv[i], "debug") == 0)
debug = 1;
else if (strcasecmp(argv[i], "nowarn") == 0) {
nowarn = 1;
flags = flags | PAM_SILENT;
} else {
syslog(LOG_ERR,
"UNIX pam_sm_acct_mgmt: illegal option %s",
argv[i]);
}
}
if ((error = pam_get_item(pamh, PAM_USER, (void **)&user))
!= PAM_SUCCESS)
goto out;
if (user == NULL) {
error = PAM_USER_UNKNOWN;
goto out;
}
/*
* Get the password and shadow password entries
*/
if (getpwnam_r(user, &pwd, pwd_buf, sizeof (pwd_buf)) == NULL ||
getspnam_r(user, &shpwd, shpwd_buf, sizeof (shpwd_buf)) == NULL) {
error = PAM_USER_UNKNOWN;
goto out;
}
if (shpwd.sp_pwdp != NULL && strcmp(shpwd.sp_pwdp, "*NP*") == 0) {
orig_uid = geteuid();
seteuid(pwd.pw_uid);
memset(pwd_buf, 0, sizeof (pwd_buf));
memset(shpwd_buf, 0, sizeof (shpwd_buf));
if (getpwnam_r(user, &pwd, pwd_buf, sizeof (pwd_buf)) == NULL ||
getspnam_r(user, &shpwd, shpwd_buf, sizeof (shpwd_buf))
== NULL) {
error = PAM_USER_UNKNOWN;
seteuid(orig_uid);
goto out;
}
seteuid(orig_uid);
}
/*
* Check for account expiration
*/
if (shpwd.sp_expire > 0 &&
shpwd.sp_expire < DAY_NOW) {
error = PAM_ACCT_EXPIRED;
goto out;
}
/*
* Check for excessive login account inactivity
*/
if (check_for_login_inactivity(pwd, shpwd)) {
error = PAM_PERM_DENIED;
goto out;
}
/*
* Check to see if the user needs to change their password
*/
if (error = new_password_check(&pwd, &shpwd, flags)) {
goto out;
}
/*
* Check to make sure password aging information is okay
*/
if ((error = perform_passwd_aging_check(pamh, shpwd, flags))
!= PAM_SUCCESS) {
goto out;
}
/*
* Finally, warn the user if their password is about to expire.
*/
if (!(flags & PAM_SILENT)) {
warn_user_passwd_will_expire(pamh, shpwd);
}
/*
* All done, return Success
*/
error = PAM_SUCCESS;
out:
memset(shpwd_buf, 0, sizeof (shpwd_buf));
/* store the password aging status in the pam handle */
if (pam_get_data(pamh, UNIX_AUTHTOK_DATA, (void **)&status)
!= PAM_SUCCESS) {
if ((status = (unix_authtok_data *)calloc
(1, sizeof (unix_authtok_data))) == NULL) {
return (PAM_BUF_ERR);
}
}
status->age_status = error;
if (pam_set_data(pamh, UNIX_AUTHTOK_DATA, status, unix_cleanup)
!= PAM_SUCCESS) {
free(status);
return (PAM_SERVICE_ERR);
}
return (error);
}

View File

@@ -0,0 +1,355 @@
/* $XConsortium: unix_authenticate.c /main/5 1996/05/09 04:32:58 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_authenticate.c 1.58 96/02/09 SMI"
#include "unix_headers.h"
#ifdef PAM_SECURE_RPC
static void
unix_cleanup(
pam_handle_t *pamh,
void *data,
int pam_status)
{
free((unix_auth_data *)data);
}
#endif
static int attempt_authentication(char *, char *, char *, uid_t, int, int);
/*
* pam_sm_authenticate - Authenticate user
*/
int
pam_sm_authenticate(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
struct spwd shpwd; /* Shadow password structure */
struct passwd pwd; /* password structure */
char shpwd_buf[1024];
char pwd_buf[1024];
char *password = NULL;
char *dummy_passwd = "no:password";
int err = PAM_SUCCESS;
int retcode;
int debug = 0;
int try_first_pass = 0;
int use_first_pass = 0;
int i;
uid_t uid;
char *service, *user;
#ifdef PAM_SECURE_RPC
unix_auth_data *status;
char netname[MAXNETNAMELEN+1];
int estkey_stat;
#endif
for (i = 0; i < argc; i++) {
if (strcasecmp(argv[i], "debug") == 0)
debug = 1;
else if (strcasecmp(argv[i], "nowarn") == 0)
flags = flags | PAM_SILENT;
else if (strcmp(argv[i], "try_first_pass") == 0)
try_first_pass = 1;
else if (strcmp(argv[i], "use_first_pass") == 0)
use_first_pass = 1;
else {
syslog(LOG_ERR, "illegal option %s", argv[i]);
}
}
if ((err = pam_get_item(pamh, PAM_SERVICE, (void **)&service))
!= PAM_SUCCESS ||
(err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
return (err);
if (debug)
syslog(LOG_DEBUG,
"unix pam_sm_authenticate(%s %s), flags = %x ",
service, (user)?user:"no-user", flags);
if (!user) {
return (PAM_USER_UNKNOWN);
}
/*
* Get the password and shadow password entry
*/
memset(pwd_buf, 0, sizeof (pwd_buf));
memset(shpwd_buf, 0, sizeof (shpwd_buf));
if (getpwnam_r(user, &pwd, pwd_buf, sizeof (pwd_buf)) == NULL ||
getspnam_r(user, &shpwd, shpwd_buf, sizeof (shpwd_buf)) == NULL) {
err = PAM_USER_UNKNOWN;
/*
* Mask unknown users.
* Set up a dummy password.
*/
shpwd.sp_pwdp = dummy_passwd;
}
/*
* Is a password check required?
*/
/* Is there anything there to check? */
if ((shpwd.sp_pwdp == 0) || (*shpwd.sp_pwdp == '\0')) {
/*
* The /etc/default/login file will specify if passwords
* are required. If not, then simply return SUCCESS.
* Otherwise, flag the error, but still prompt the user
* for a password to mask the failure.
*/
if ((flags & PAM_DISALLOW_NULL_AUTHTOK) == 0)
goto out;
err = PAM_SERVICE_ERR;
goto prompt;
}
if ((err = __pam_get_authtok(pamh, PAM_HANDLE, PAM_AUTHTOK,
PASSWORD_LEN, NULL, &password)) != PAM_SUCCESS)
goto out;
if (try_first_pass) {
/*
* Try to login using the password from the first
* scheme, e.g. DCE password. If anything goes wrong,
* then simply prompt users for password.
*/
retcode = attempt_authentication(user, password,
shpwd.sp_pwdp, pwd.pw_uid,
flags, debug);
if (err != PAM_USER_UNKNOWN)
err = retcode;
if (err == PAM_SUCCESS)
goto post_prompt;
else
goto prompt;
} else if (use_first_pass) {
/*
* Try to login using the password from the first
* scheme, e.g. DCE password. If anything goes wrong,
* quit, and return the error;
*/
retcode = attempt_authentication(user, password,
shpwd.sp_pwdp, pwd.pw_uid,
flags, debug);
if (err != PAM_USER_UNKNOWN)
err = retcode;
if (err == PAM_SUCCESS)
goto post_prompt;
else
goto out;
}
prompt:
/*
* Get the password from the user
*/
if ((password != NULL && password[0] != '\0') || try_first_pass) {
if (password) {
memset(password, 0, strlen(password));
free(password);
password = NULL;
}
if ((retcode = __pam_get_authtok(pamh, PAM_PROMPT,
PAM_AUTHTOK, PASSWORD_LEN,
PAM_MSG(pamh, 30, "UNIX Password: "),
&password)) != PAM_SUCCESS) {
if (err != PAM_USER_UNKNOWN)
err = retcode;
goto out;
}
} else {
if (password) {
memset(password, 0, strlen(password));
free(password);
password = NULL;
}
if ((retcode = __pam_get_authtok(pamh, PAM_PROMPT,
PAM_AUTHTOK, PASSWORD_LEN,
PAM_MSG(pamh, 31, "Password: "),
&password)) != PAM_SUCCESS) {
if (err != PAM_USER_UNKNOWN)
err = retcode;
goto out;
}
}
retcode = attempt_authentication(user, password,
shpwd.sp_pwdp, pwd.pw_uid, flags, debug);
if (err != PAM_USER_UNKNOWN)
err = retcode;
if (err != PAM_SUCCESS)
goto out;
post_prompt:
#ifdef PAM_SECURE_RPC
/*
* Do a keylogin if the password is
* not null and its not a root login.
* This code used to be in pam_setcred().
*/
uid = pwd.pw_uid;
if (password != NULL &&
password[0] != '\0' &&
uid != 0) {
/*
* we always ask to reestablish the private key with
* keyserv to solve the problem that the keys may have
* changed and a re-keylogin not done
*/
estkey_stat = establish_key(uid, password, 1, netname);
/*
* Store the return value as module specific data
* to be printed out later in pam_setcred().
*/
if (pam_get_data(pamh, UNIX_AUTH_DATA, (void**)&status)
!= PAM_SUCCESS) {
if ((status = (unix_auth_data *)calloc
(1, sizeof (unix_auth_data)))
== NULL) {
err = PAM_BUF_ERR;
goto out;
}
}
status->key_status = estkey_stat;
strcpy(status->netname, netname);
if (pam_set_data(pamh, UNIX_AUTH_DATA, status, unix_cleanup)
!= PAM_SUCCESS) {
err = PAM_SERVICE_ERR;
goto out;
}
}
#endif /* PAM_SECURE_RPC */
out:
if (password) {
memset(password, 0, strlen(password));
free(password);
}
return (err);
}
static int
attempt_authentication(char *user, char *password, char *enc_passwd,
uid_t uid, int flags, int debug)
{
struct passwd pwd;
struct spwd shpwd;
char shpwd_buf[1024];
char pwd_buf[1024];
int estkey_stat;
uid_t orig_uid;
int err = 0;
if (password == NULL || password[0] == '\0') {
if (debug)
syslog(LOG_DEBUG,
"unix_auth: NULL passwd in attempt_authenticate()");
return (PAM_AUTH_ERR);
} else {
/*
* Yes, there is some string in the sp_pwdp field.
* We have one of the following two situations:
* 1) the sp_pwdp string is actually the encrypted
* user's password,
* or 2) the sp_pwdp string is "*NP*", which means we
* didn't actually have permission to read the
* password field in the name service.
*
* In either case, we must obtain the password from the
* user. In situation 2, we can't actually tell yet
* whether the unix password is present or not. We must
* get the password from the user, just to establish
* the user's secure RPC credentials. Then, having
* established the user's Secure RPC credentials, we
* need to re-obtain the shpwd structure. At that point,
* if the unix password is present there, we check it
* against that too.
*/
if (strcmp(enc_passwd, "*NP*") == 0) {
#ifdef PAM_SECURE_RPC
estkey_stat = establish_key(uid,
password, 1, NULL);
if (estkey_stat != ESTKEY_SUCCESS) {
/* Failed to establish secret key. */
switch (estkey_stat) {
case ESTKEY_BADPASSWD:
err = PAM_AUTH_ERR;
break;
case ESTKEY_NOCREDENTIALS:
/*
* user requires credentials to
* read passwd field but doesn't
* have any should syslog() a
* message for admin
*/
syslog(LOG_ALERT,
"User %s needs Secure RPC \
credentials to login.", user);
err = PAM_SERVICE_ERR;
break;
default:
err = PAM_SERVICE_ERR;
}
return (err);
}
orig_uid = geteuid();
seteuid(uid);
memset(pwd_buf, 0, sizeof (pwd_buf));
memset(shpwd_buf, 0, sizeof (shpwd_buf));
if (getpwnam_r(user, &pwd, pwd_buf,
sizeof (pwd_buf)) == NULL ||
getspnam_r(user, &shpwd, shpwd_buf,
sizeof (shpwd_buf)) == NULL) {
seteuid(orig_uid);
return (PAM_USER_UNKNOWN);
}
seteuid(orig_uid);
if ((shpwd.sp_pwdp != 0) &&
(strcmp(shpwd.sp_pwdp, "*NP*") == 0)) {
syslog(LOG_ALERT,
"Permissions on the password database may be too restrictive");
return (PAM_AUTH_ERR);
}
enc_passwd = shpwd.sp_pwdp;
#else
return (PAM_AUTH_ERR);
#endif /* PAM_SECURE_RPC */
}
if ((enc_passwd == 0) ||
(*enc_passwd == '\0')) {
if (flags & PAM_DISALLOW_NULL_AUTHTOK)
return (PAM_AUTH_ERR);
/* return success if passwords are not required */
return (PAM_SUCCESS);
}
if (strcmp(crypt(password, enc_passwd),
enc_passwd) != 0) {
return (PAM_AUTH_ERR);
}
/* success! */
return (PAM_SUCCESS);
}
}

View File

@@ -0,0 +1,89 @@
/* $XConsortium: unix_chauthtok.c /main/5 1996/05/09 04:33:18 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_chauthtok.c 1.83 95/12/12 SMI"
#include "unix_headers.h"
/*
* pam_sm_chauthtok():
* To change authentication token.
*
* This function handles all requests from the "passwd" command
* to change a user's password in all repositories specified
* in nsswitch.conf.
*/
int
pam_sm_chauthtok(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int i;
int debug = 0; /* debug option from pam.conf */
int authtok_aged = 0; /* flag to check if password expired */
unix_authtok_data *status; /* status in pam handle stating if */
/* password aged */
/*
* Only check for debug here - parse remaining options
* in __update_authtok();
*/
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0)
debug = 1;
}
if (flags & PAM_PRELIM_CHECK) {
/* do not do any prelim check at this time */
if (debug)
syslog(LOG_DEBUG,
"unix pam_sm_chauthtok(): prelim check");
return (PAM_SUCCESS);
}
/* make sure PAM framework is telling us to update passwords */
if (!(flags & PAM_UPDATE_AUTHTOK)) {
syslog(LOG_ERR, "unix pam_sm_chauthtok: bad flags: %d", flags);
return (PAM_SYSTEM_ERR);
}
if (flags & PAM_CHANGE_EXPIRED_AUTHTOK) {
if (pam_get_data(pamh, UNIX_AUTHTOK_DATA, (void **)&status)
== PAM_SUCCESS) {
switch (status->age_status) {
case PAM_NEW_AUTHTOK_REQD:
if (debug)
syslog(LOG_DEBUG,
"pam_sm_chauthtok: UNIX password aged");
authtok_aged = 1;
break;
default:
/* UNIX authtok did not expire */
if (debug)
syslog(LOG_DEBUG,
"pam_sm_chauthtok: UNIX password young");
authtok_aged = 0;
break;
}
}
if (!authtok_aged)
return (PAM_IGNORE);
}
/*
* This function calls __update_authtok() to change passwords.
* By passing PAM_REP_DEFAULT, the repository will be determined
* by looking in nsswitch.conf.
*
* To obtain the domain name (passed as NULL), __update_authtok()
* will call: nis_local_directory();
*/
return (__update_authtok(pamh, flags, PAM_REP_DEFAULT, NULL,
argc, argv));
}

View File

@@ -0,0 +1,34 @@
/* $XConsortium: unix_close_session.c /main/5 1996/05/09 04:33:38 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_close_session.c 1.26 95/12/12 SMI"
#include "unix_headers.h"
/*
* pam_sm_close_session - Terminate a PAM authenticated session
*/
int
pam_sm_close_session(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int i;
int debug = 0;
for (i = 0; i < argc; i++) {
if (strcasecmp(argv[i], "debug") == 0)
debug = 1;
else
syslog(LOG_ERR, "illegal option %s", argv[i]);
}
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,352 @@
/* $XConsortium: unix_get_authtokattr.c /main/8 1996/11/21 20:00:50 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_get_authtokattr.c 1.59 96/01/07 SMI"
#include "unix_headers.h"
#define XOS_USE_NO_LOCKING
#define X_INCLUDE_TIME_H
#include <X11/Xos_r.h>
#ifdef PAM_NISPLUS
static void _np_nss_initf_shadow(nss_db_params_t *);
static void _np_setspent();
static void _np_endspent();
static struct spwd * _np_getspent_r(struct spwd *, char *, int);
static struct spwd * _np_getspent();
#endif
/*
* __get_authtoken_attr():
* To get authentication token attribute values.
*
* This function calls ck_perm() first to check the caller's
* permission. If the check succeeds, it will read the
* attribute/value pairs from the shadow password entry of
* the user specified by the authentication handle "pamh"
* and store them into a character array and return.
*/
/*
* XXX: We use our own version of the shadow passwd getent routine.
* See below for details. Compatible with version 2 of the name service
* switch. In the future, the name service switch implementation may
* change and these functions and the Makefile may have to
* be modified.
*/
int
__get_authtoken_attr(
pam_handle_t *pamh,
char ***ga_getattr,
int repository,
const char *domain,
int argc,
const char **argv)
{
register int k;
char value[PAM_MAX_ATTR_SIZE];
int retcode;
long lstchg;
char *usrname;
char *prognamep;
char **get_attributes;
struct passwd *pwd;
struct spwd *shpwd;
int found = 0;
struct spwd *psp;
struct tm *tmp;
int privileged = 0;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
int debug = 0;
int nowarn = 0;
int i;
void *passwd_res;
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0)
debug = 1;
else if (strcmp(argv[i], "nowarn") == 0)
nowarn = 1;
else
syslog(LOG_ERR, "illegal UNIX module option %s",
argv[i]);
}
if (debug)
syslog(LOG_DEBUG,
"__get_authtoken_attr(): repository=%s",
repository_to_string(repository));
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
!= PAM_SUCCESS ||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
!= PAM_SUCCESS)
return (retcode);
if ((get_attributes = (char **)
calloc(PAM_MAX_NUM_ATTR, sizeof (char *))) == NULL)
return (PAM_BUF_ERR);
/* repository must be specified in the command line. */
if (repository == PAM_REP_DEFAULT) {
sprintf(messages[0], PAM_MSG(pamh, 40,
"You must specify repository when displaying passwd attributes"));
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
return (PAM_AUTHTOK_ERR);
}
if (!IS_FILES(repository) && !IS_NIS(repository) &&
!IS_NISPLUS(repository)) {
sprintf(messages[0], PAM_MSG(pamh, 41,
"%s: System error: repository out of range"), prognamep);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1,
messages, NULL);
return (PAM_SYSTEM_ERR);
}
#ifdef PAM_NISPLUS
if (usrname == NULL || *usrname == NULL) {
/* print nis+ table */
/*
* Cat the table using our private _np_getspent()
*/
if (!IS_NISPLUS(repository)) {
sprintf(messages[0], PAM_MSG(pamh, 42,
"Unable to retrieve username."));
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
return (PAM_AUTHTOK_RECOVERY_ERR);
}
(void) _np_setspent();
while ((psp = _np_getspent()) != NULL) {
found++;
sprintf(value, "%s ", psp->sp_namp);
if (psp->sp_pwdp == NULL) {
sprintf(messages[0],
"%s NP ", value);
} else if ((int)strlen(psp->sp_pwdp) < NUMCP) {
sprintf(messages[0],
"%s LK ", value);
} else {
sprintf(messages[0],
"%s PS ", value);
}
if (psp->sp_max != -1) {
_Xgtimeparams gmtime_buf;
strcpy(value, messages[0]);
if (psp->sp_lstchg) {
lstchg = psp->sp_lstchg * DAY;
tmp = _XGmtime(&lstchg, gmtime_buf);
sprintf(messages[0],
"%s %.2d/%.2d/%.2d ",
value,
(tmp->tm_mon + 1),
tmp->tm_mday, tmp->tm_year);
} else
sprintf(messages[0],
"%s 00/00/00 ",
value);
strcpy(value, messages[0]);
if ((psp->sp_min >= 0) && (psp->sp_warn > 0)) {
sprintf(messages[0],
"%s %d %d %d ",
value,
psp->sp_min, psp->sp_max,
psp->sp_warn);
} else if (psp->sp_min >= 0) {
sprintf(messages[0],
"%s %d %d ", value,
psp->sp_min, psp->sp_max);
} else if (psp->sp_warn > 0) {
sprintf(messages[0],
"%s %d %d ", value,
psp->sp_max, psp->sp_warn);
} else {
sprintf(messages[0],
"%s %d ",
value, psp->sp_max);
}
}
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
1, messages, NULL);
}
(void) _np_endspent();
/*
* If password table does not have any entries or is missing,
* return fatal error.
*/
if (found == 0) {
sprintf(messages[0],
PAM_MSG(pamh, 43,
"%s: Unexpected failure. Password database unchanged."),
prognamep);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
return (PAM_SYSTEM_ERR);
}
return (PAM_SUCCESS);
}
#endif /* PAM_NISPLUS */
retcode = ck_perm(pamh, repository,
(char *)domain, &pwd, &shpwd, &privileged,
(void **)&passwd_res, getuid(), debug, nowarn);
if (retcode != 0) {
return (retcode);
}
k = 0;
/* get attribute "AUTHTOK_STATUS" */
if (shpwd->sp_pwdp == NULL)
(void) strcpy(value, "NP ");
else if ((int)strlen(shpwd->sp_pwdp) < NUMCP)
(void) strcpy(value, "LK ");
else
(void) strcpy(value, "PS ");
setup_attr(get_attributes, k++, "AUTHTOK_STATUS=", value);
if (shpwd->sp_max != -1) {
/* get attribute "AUTHTOK_LASTCHANGE" */
if (shpwd->sp_lstchg) {
lstchg = shpwd->sp_lstchg * DAY;
sprintf(value, "%d", lstchg);
} else {
sprintf(value, "%d", shpwd->sp_lstchg);
}
setup_attr(get_attributes, k++,
"AUTHTOK_LASTCHANGE=", value);
/* get attribute "AUTHTOK_MINAGE" */
/* "AUTHTOK_MAXAGE", and "AUTHTOK_WARNDATE" */
if ((shpwd->sp_min >= 0) && (shpwd->sp_warn > 0)) {
sprintf(value, "%d", shpwd->sp_min);
setup_attr(get_attributes, k++,
"AUTHTOK_MINAGE=", value);
sprintf(value, "%d", shpwd->sp_max);
setup_attr(get_attributes, k++,
"AUTHTOK_MAXAGE=", value);
sprintf(value, "%d", shpwd->sp_warn);
setup_attr(get_attributes, k++,
"AUTHTOK_WARNDATE=", value);
} else {
if (shpwd->sp_min >= 0) {
sprintf(value, "%d", shpwd->sp_min);
setup_attr(get_attributes, k++,
"AUTHTOK_MINAGE=", value);
sprintf(value, "%d", shpwd->sp_max);
setup_attr(get_attributes, k++,
"AUTHTOK_MAXAGE=", value);
} else {
if (shpwd->sp_warn > 0) {
sprintf(value, "%d", shpwd->sp_max);
setup_attr(get_attributes, k++,
"AUTHTOK_MAXAGE=", value);
sprintf(value, "%d", shpwd->sp_warn);
setup_attr(get_attributes, k++,
"AUTHTOK_WARNDATE=", value);
} else {
sprintf(value, "%d", shpwd->sp_max);
setup_attr(get_attributes, k++,
"AUTHTOK_MAXAGE=", value);
}
}
}
}
/* terminate with NULL */
setup_attr(get_attributes, k, NULL, NULL);
*ga_getattr = &get_attributes[0];
free_passwd_structs(pwd, shpwd);
return (PAM_SUCCESS);
}
#ifdef PAM_NISPLUS
/*
* XXX Our private version of the switch frontend for getspent. We want to
* search just the nisplus sp file, so we want to bypass normal nsswitch.conf
* based processing. This implementation compatible with version 2 of the
* name service switch.
*/
#define NSS_NISPLUS_ONLY "nisplus"
int str2spwd(const char *, int, void *, char *, int);
static DEFINE_NSS_DB_ROOT(db_root);
static DEFINE_NSS_GETENT(context);
static void
_np_nss_initf_shadow(p)
nss_db_params_t *p;
{
p->name = NSS_DBNAM_SHADOW;
p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */
p->default_config = NSS_NISPLUS_ONLY; /* Use nisplus only */
p->flags = NSS_USE_DEFAULT_CONFIG;
}
static void
_np_setspent()
{
nss_setent(&db_root, _np_nss_initf_shadow, &context);
}
static void
_np_endspent()
{
nss_endent(&db_root, _np_nss_initf_shadow, &context);
nss_delete(&db_root);
}
static struct spwd *
_np_getspent_r(result, buffer, buflen)
struct spwd *result;
char *buffer;
int buflen;
{
nss_XbyY_args_t arg;
char *nam;
/* In getXXent_r(), protect the unsuspecting caller from +/- entries */
do {
NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
/* No key to fill in */
nss_getent(&db_root, _np_nss_initf_shadow, &context, &arg);
} while (arg.returnval != 0 &&
(nam = ((struct spwd *)arg.returnval)->sp_namp) != 0 &&
(*nam == '+' || *nam == '-'));
return (struct spwd *) NSS_XbyY_FINI(&arg);
}
static nss_XbyY_buf_t *buffer;
static struct spwd *
_np_getspent()
{
nss_XbyY_buf_t *b;
b = NSS_XbyY_ALLOC(&buffer, sizeof (struct spwd), NSS_BUFLEN_SHADOW);
return (b == 0 ? 0 : _np_getspent_r(b->result, b->buffer, b->buflen));
}
#endif /* PAM_NISPLUS */

View File

@@ -0,0 +1,206 @@
/* $XConsortium: unix_headers.h /main/5 1996/05/09 04:34:13 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _UNIX_HEADERS_H
#define _UNIX_HEADERS_H
#pragma ident "@(#)unix_headers.h 1.61 96/02/02 SMI" /* PAM 2.6 */
#ifdef __cplusplus
extern "C" {
#endif
/*
*******************************************************************
*
* PROPRIETARY NOTICE(Combined)
*
* This source code is unpublished proprietary information
* constituting, or derived under license from AT&T's UNIX(r) System V.
* In addition, portions of such source code were derived from Berkeley
* 4.3 BSD under license from the Regents of the University of
* California.
*
*
*
* Copyright Notice
*
* Notice of copyright on this source code product does not indicate
* publication.
*
* (c) 1986, 1987, 1988, 1989, 1990, 1991, 1992 Sun Microsystems, Inc
* (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T.
* All rights reserved.
*******************************************************************
*/
/*
********************************************************************** *
* *
* Unix Scheme Header Files *
* *
********************************************************************** */
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include "../../libpam/pam_impl.h"
#include <syslog.h>
#include <pwd.h>
#include <shadow.h>
#include <lastlog.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <libintl.h>
#include <thread.h>
#include <synch.h>
#include <errno.h>
#include <time.h>
#include <sys/fcntl.h>
#include <string.h>
#include <crypt.h>
#ifdef PAM_NISPLUS
#include <rpcsvc/nis.h>
#include <rpcsvc/nispasswd.h>
#endif
#if (PAM_NIS || PAM_NISPLUS)
#include <rpcsvc/yppasswd.h>
#include <rpcsvc/ypclnt.h>
#include <nss_dbdefs.h>
#include <nsswitch.h>
#include <rpc/key_prot.h>
#include <rpc/rpc.h>
#include <nfs/nfs.h>
#include <nfs/nfssys.h>
#endif
/*
* Various useful files and string constants
*/
#define SHELL "/usr/bin/sh"
#define DEFSHELL "/bin/sh"
#define LASTLOG "/var/adm/lastlog"
#define PWADMIN "/etc/default/passwd"
#define LOGINADMIN "/etc/default/login"
#define PASSWD "/etc/passwd"
#define SHADOW "/etc/shadow"
#define UNIX_AUTH_DATA "SUNW-UNIX-AUTH-DATA"
#define UNIX_AUTHTOK_DATA "SUNW-UNIX-AUTHTOK-DATA"
#define UNIX_MSG "(Unix)"
#define NIS_MSG "(NIS)"
#define NISPLUS_MSG "(NIS+)"
#define PASSWORD_LEN 8
#define PAM_NISPLUS_PARTIAL_SUCCESS -1
/*
* PAM_MSG macro for return of internationalized text
*/
#define PAM_MSG(pamh, number, string)\
(char *) __pam_get_i18n_msg(pamh, "pam_unix", 1, number, string)
/*
* Returned status codes for establish_key () utility function
*/
#define ESTKEY_SUCCESS 0
#define ESTKEY_NOCREDENTIALS 1
#define ESTKEY_BADPASSWD 2
#define ESTKEY_CANTSETKEY 3
#define ESTKEY_ALREADY 4
/*
* Miscellaneous constants
*/
#define ROOTUID 0
#define MINWEEKS -1 /* minimum weeks before next password change */
#define MAXWEEKS -1 /* maximum weeks before password change */
#define WARNWEEKS -1 /* number weeks before password expires */
/* to warn the user */
#define MINLENGTH 6 /* minimum length for passwords */
#define MAXLENGTH 8 /* maximum length for passwords */
#define NUMCP 13 /* number of characters for valid password */
#define MAX_CHANCES 3 /* 3 chances to enter new passwd */
/*
* variables declarations
*/
mutex_t _priv_lock;
/*
* nis+ definition
*/
#define PKTABLE "cred.org_dir"
#define PKTABLELEN 12
#define PASSTABLE "passwd.org_dir"
#define PASSTABLELEN 14
#define PKMAP "publickey.byname"
/* define error messages */
#define NULLSTRING ""
/*
* Function Declarations
*/
extern int defopen();
extern char *defread();
extern int key_setnet();
/* from unix_utils.c */
extern int ck_perm(pam_handle_t *, int,
char *, struct passwd **, struct spwd **,
int *, void **, uid_t, int, int);
extern char *attr_match(register char *, register char *);
extern char *getloginshell(pam_handle_t *, char *, int, int);
extern char *gethomedir(pam_handle_t *, char *, int);
extern char *getfingerinfo(pam_handle_t *, char *, int);
extern char *repository_to_string(int);
extern void free_passwd_structs(struct passwd *, struct spwd *);
/* from switch_utils.c */
extern int str2spwd(const char *, int, void *, char *, int);
extern struct passwd *getpwnam_from(const char *, int);
extern struct spwd *getspnam_from(const char *, int);
extern int get_ns(pam_handle_t *, int, int, int);
/* from update_authtok_<repository> */
extern int update_authtok_file(pam_handle_t *, char *, char **,
struct passwd *, int, int);
#ifdef PAM_NIS
extern int update_authtok_nis(pam_handle_t *, char *, char **,
char *, char *,
struct passwd *, int, int);
#endif
#ifdef PAM_NISPLUS
extern int update_authtok_nisplus(pam_handle_t *, char *, char *,
char **, char *, char *,
char *, int, struct passwd *, char *,
int, nis_result *, nis_result *, int, int);
#endif
#ifdef PAM_SECURE_RPC
extern int establish_key(uid_t, char *, int, char *);
typedef struct _unix_auth_data_ {
int key_status;
char netname[MAXNETNAMELEN+1];
}unix_auth_data;
#endif
typedef struct _unix_authtok_data_ {
int age_status;
}unix_authtok_data;
#ifdef __cplusplus
}
#endif
#endif /* _UNIX_HEADERS_H */

View File

@@ -0,0 +1,82 @@
/* $XConsortium: unix_open_session.c /main/5 1996/05/09 04:34:32 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_open_session.c 1.32 95/12/08 SMI"
/*
* pam_sm_open_session - session management for individual users
*/
#include "unix_headers.h"
int
pam_sm_open_session(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int error;
char *ttyn, *rhost, *user;
int fdl;
struct lastlog newll;
struct passwd pwd;
char buffer[2048];
int i;
int debug = 0;
long long offset;
for (i = 0; i < argc; i++) {
if (strcasecmp(argv[i], "debug") == 0)
debug = 1;
else
syslog(LOG_ERR, "illegal option %s", argv[i]);
}
if ((error = pam_get_item(pamh, PAM_TTY, (void **)&ttyn))
!= PAM_SUCCESS ||
(error = pam_get_item(pamh, PAM_USER, (void **)&user))
!= PAM_SUCCESS ||
(error = pam_get_item(pamh, PAM_RHOST, (void **)&rhost))
!= PAM_SUCCESS) {
return (error);
}
if (getpwnam_r(user, &pwd, buffer, sizeof (buffer)) == NULL) {
return (PAM_USER_UNKNOWN);
}
if ((fdl = open(LASTLOG, O_RDWR|O_CREAT, 0444)) >= 0) {
/*
* The value of lastlog is read by the UNIX
* account management module
*/
offset = (long long) pwd.pw_uid *
(long long) sizeof (struct lastlog);
if (llseek(fdl, offset, SEEK_SET) != offset) {
/*
* XXX uid too large for database
*/
return (PAM_SUCCESS);
}
(void) time(&newll.ll_time);
strncpy(newll.ll_line,
(ttyn + sizeof ("/dev/")-1),
sizeof (newll.ll_line));
strncpy(newll.ll_host, rhost, sizeof (newll.ll_host));
(void) write(fdl, (char *)&newll, sizeof (newll));
(void) close(fdl);
}
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,112 @@
/* $XConsortium: unix_set_authtokattr.c /main/5 1996/05/09 04:34:50 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)__set_authtoken_attr.c 1.33 95/09/11 SMI"
#include "unix_headers.h"
/*
* __set_authtoken_attr():
* To set authentication token attribute values.
*
* This function calls ck_perm() to check the caller's
* permission. If the check succeeds, It will
* call update_authentok_file() and passes attributes/value
* pairs pointed by "sa_setattr" to set the authentication
* token attribute values of the user specified by the
* authentication handle "pamh".
*/
int
__set_authtoken_attr(
pam_handle_t *pamh,
const char **sa_setattr,
int repository,
const char *domain,
int argc,
const char **argv)
{
register int i;
int retcode;
char *usrname;
char *prognamep;
struct passwd *pwd = NULL;
struct spwd *shpwd = NULL;
int privileged = 0;
int debug = 0;
int nowarn = 0;
void *passwd_res;
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0)
debug = 1;
else if (strcmp(argv[i], "nowarn") == 0)
nowarn = 1;
else
syslog(LOG_ERR, "illegal UNIX module option %s",
argv[i]);
}
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
!= PAM_SUCCESS ||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
!= PAM_SUCCESS)
return (retcode);
if (debug)
syslog(LOG_DEBUG,
"__set_authtoken_attr(): repository %x, usrname %s",
repository, usrname);
retcode = ck_perm(pamh, repository,
(char *)domain, &pwd, &shpwd, &privileged,
(void **)&passwd_res, getuid(), debug, nowarn);
if (retcode != 0) {
return (retcode);
}
/*
* XXX: why do this???
* ignore all the signals
*/
for (i = 1; i < NSIG; i++)
(void) sigset(i, SIG_IGN);
/* update authentication token file */
/* make sure the user exists before we update the repository */
#ifdef PAM_NIS
if (IS_NIS(repository) && (pwd != NULL)) {
retcode = update_authtok_nis(pamh, "attr",
(char **)sa_setattr, NULL, NULL, pwd,
privileged, nowarn);
free_passwd_structs(pwd, shpwd);
return (retcode);
} else
#endif
#ifdef PAM_NISPLUS
if (IS_NISPLUS(repository) && (pwd != NULL)) {
/* nis+ needs clear versions of old and new passwds */
retcode = update_authtok_nisplus(pamh,
(char *)domain, "attr", (char **)sa_setattr,
NULL, NULL, NULL, IS_OPWCMD(repository) ? 1 : 0, pwd,
NULL, privileged, (nis_result *)passwd_res, NULL,
debug, nowarn);
free_passwd_structs(pwd, shpwd);
return (retcode);
} else
#endif
if (IS_FILES(repository) && (pwd != NULL)) {
retcode = update_authtok_file(pamh, "attr",
(char **)sa_setattr, pwd,
privileged, nowarn);
free_passwd_structs(pwd, shpwd);
return (retcode);
}
return (PAM_SUCCESS);
}

View File

@@ -0,0 +1,172 @@
/* $XConsortium: unix_setcred.c /main/5 1996/05/09 04:35:09 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_setcred.c 1.51 95/12/12 SMI"
#include "unix_headers.h"
/*
* pam_sm_setcred - Set the process credentials
*
* XXX: If this module succeeds when invoked with PAM_ESTABLISH_CREd,
* and a subsequent module in the stack fails, then there is no way
* to delete the user's Secure RPC credentials (keylogout). Currently
* there is no way for PAM to correct this problem.
*/
int
pam_sm_setcred(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int i;
int debug = 0;
int err = 0;
struct pam_conv *pam_convp;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
#ifdef PAM_SECURE_RPC
unix_auth_data *status;
char secret[HEXKEYBYTES + 1];
struct nfs_revauth_args nra; /* revoking kernel NFS creds */
#endif
for (i = 0; i < argc; i++) {
if (strcasecmp(argv[i], "debug") == 0)
debug = 1;
else if (strcasecmp(argv[i], "nowarn") == 0)
flags = flags | PAM_SILENT;
}
/* make sure flags are valid */
if (flags &&
!(flags & PAM_ESTABLISH_CRED) &&
!(flags & PAM_REINITIALIZE_CRED) &&
!(flags & PAM_REFRESH_CRED) &&
!(flags & PAM_DELETE_CRED) &&
!(flags & PAM_SILENT)) {
syslog(LOG_ERR, "unix setcred: illegal flag %d", flags);
err = PAM_SYSTEM_ERR;
goto out;
}
if (pam_get_item(pamh, PAM_CONV, (void **) &pam_convp) !=
PAM_SUCCESS) {
if (debug) {
syslog(LOG_DEBUG,
"pam_sm_setcred(): unable to get conv structure");
}
err = PAM_SERVICE_ERR;
goto out;
}
if ((flags & PAM_REINITIALIZE_CRED) ||
(flags & PAM_REFRESH_CRED)) {
/* For unix, these flags are not applicable */
err = PAM_SUCCESS;
} else if (flags & PAM_DELETE_CRED) {
#ifdef PAM_SECURE_RPC
/* do a keylogout */
memset(secret, 0, sizeof (secret));
if (geteuid() == 0) {
if (!(flags & PAM_SILENT)) {
sprintf(messages[0], PAM_MSG(pamh, 50,
"removing root credentials would break the rpc services that"));
sprintf(messages[1], PAM_MSG(pamh, 51,
"use secure rpc on this host!"));
sprintf(messages[2], PAM_MSG(pamh, 52,
"root may use keylogout -f to do this (at your own risk)!"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
3, messages, NULL);
}
err = PAM_PERM_DENIED;
goto out;
}
if (key_setsecret(secret) < 0) {
if (!(flags & PAM_SILENT)) {
sprintf(messages[0], PAM_MSG(pamh, 53,
"Could not unset your secret key."));
sprintf(messages[1], PAM_MSG(pamh, 54,
"Maybe the keyserver is down?"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
2, messages, NULL);
}
err = PAM_AUTH_ERR;
goto out;
}
nra.authtype = AUTH_DES; /* only revoke DES creds */
nra.uid = getuid(); /* use the real uid */
if (_nfssys(NFS_REVAUTH, &nra) < 0) {
if (!(flags & PAM_SILENT)) {
sprintf(messages[0], PAM_MSG(pamh, 55,
"Warning: NFS credentials not destroyed"));
__pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
err = PAM_AUTH_ERR;
goto out;
}
#endif
err = PAM_SUCCESS;
} else {
#ifdef PAM_SECURE_RPC
/*
* Default case: PAM_ESTABLISH_CRED
* For unix, the keylogin was already done in
* unix_authenticate.c. Only print out the
* keylogin status here.
*/
if (!(flags & PAM_SILENT)) {
if (pam_get_data(pamh, UNIX_AUTH_DATA,
(void**)&status) == PAM_SUCCESS) {
switch (status->key_status) {
case ESTKEY_SUCCESS:
if (debug)
syslog(LOG_DEBUG,
"unix setcred successful");
case ESTKEY_ALREADY:
case ESTKEY_NOCREDENTIALS:
break;
case ESTKEY_BADPASSWD:
if (!(flags & PAM_SILENT)) {
sprintf(messages[0],
PAM_MSG(pamh, 56,
"Password does not decrypt secret key for %s."),
status->netname);
__pam_display_msg(
pamh,
PAM_ERROR_MSG, 1,
messages, NULL);
}
break;
case ESTKEY_CANTSETKEY:
if (!(flags & PAM_SILENT)) {
sprintf(messages[0],
PAM_MSG(pamh, 57,
"Could not set secret key for %s. The key server may be down."),
status->netname);
__pam_display_msg(
pamh,
PAM_ERROR_MSG, 1,
messages, NULL);
}
break;
}
} else {
if (debug)
syslog(LOG_DEBUG,
"pam_sm_setcred(): no module data");
}
}
#endif
err = PAM_SUCCESS;
}
out:
return (err);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,637 @@
/* $XConsortium: unix_update_authtok_file.c /main/5 1996/05/09 04:35:55 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_update_authtok_file.c 1.26 95/09/11 SMI"
#include "unix_headers.h"
static int update_spent(pam_handle_t *, char *, char **,
struct passwd *, struct spwd *, int *, int, int);
static int process_passwd(pam_handle_t *, char *, char *,
struct passwd *, int);
/*
* update_authtok_file():
* To update the authentication token file.
*
* This function is called by either __set_authtoken_attr() to
* update the token attributes or pam_chauthtok() to update the
* authentication token. The parameter "field" has to be specified
* as "attr" if the caller wants to update token attributes, and
* the attribute-value pairs to be set needs to be passed in by parameter
* "data". If the function is called to update authentication
* token itself, then "field" needs to be specified as "passwd"
* and the new authentication token has to be passed in by "data".
*/
int
update_authtok_file(pamh, field, data, unix_pwd, privileged, nowarn)
pam_handle_t *pamh;
char *field;
char *data[];
struct passwd *unix_pwd;
int privileged;
int nowarn;
{
char *prognamep;
char *usrname;
struct stat buf;
register int found = 0;
FILE *tsfp, *spfp;
struct spwd unix_sp;
char spbuf[1024];
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
int passwd_flag = 0; /* attrs in shadow or passwd file */
int retcode;
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
!= PAM_SUCCESS ||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
!= PAM_SUCCESS)
return (retcode);
/*
* XXX:
* Assume effective UID already set to 0
* so we can update the passwd file.
*
* This will be the last update (after nis/nis+)
*/
errno = 0;
/* lock the password file */
if (lckpwdf() != 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 90,
"%s%s: Password database busy. Try again later."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (PAM_AUTHTOK_LOCK_BUSY);
}
/* Mode of the shadow file should be 400 or 000 */
if (stat(SHADOW, &buf) < 0) {
syslog(LOG_ERR, "%s: stat of shadow file failed",
prognamep);
(void) ulckpwdf();
return (PAM_AUTHTOK_ERR);
}
(void) umask(S_IAMB & ~(buf.st_mode & S_IRUSR));
if ((tsfp = fopen(SHADTEMP, "w")) == NULL) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
(void) ulckpwdf();
return (PAM_AUTHTOK_ERR);
}
/*
* copy passwd files to temps, replacing matching lines
* with new password attributes.
*/
if ((spfp = fopen(SHADOW, "r")) == NULL) {
fclose(tsfp);
goto err;
}
while (fgetspent_r(spfp, &unix_sp, spbuf, sizeof (spbuf)) != NULL) {
if (strcmp(unix_sp.sp_namp, usrname) == 0) {
found = 1;
retcode = update_spent(pamh, field, data,
unix_pwd, &unix_sp, &passwd_flag,
privileged, nowarn);
if (retcode != PAM_SUCCESS) {
fclose(tsfp);
fclose(spfp);
goto err;
}
if (passwd_flag) {
/* The attributes are in passwd file */
if ((retcode = process_passwd(pamh,
prognamep, usrname, unix_pwd,
nowarn)) != PAM_SUCCESS) {
fclose(tsfp);
fclose(spfp);
goto err;
}
}
}
if (putspent(&unix_sp, tsfp) != 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
fclose(tsfp);
fclose(spfp);
goto err;
}
memset(spbuf, 0, sizeof (spbuf));
} /* end of while */
if ((fclose(tsfp)) || (fclose(spfp))) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
/* Check if user name exists */
if (found == 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
/*
* Rename temp file back to appropriate passwd file.
*/
/* remove old shadow file */
if (unlink(OSHADOW) && access(OSHADOW, 0) == 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
/* rename shadow file to old shadow file */
if (rename(SHADOW, OSHADOW) == -1) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
/* rename temparory shadow file to shadow file */
if (rename(SHADTEMP, SHADOW) == -1) {
(void) unlink(SHADOW);
if (link(OSHADOW, SHADOW)) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 92,
"%s%s: Unexpected failure. Password database missing."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
(void) ulckpwdf();
memset(spbuf, 0, sizeof (spbuf));
if (strcmp(field, "passwd") == 0) {
sprintf(messages[0], PAM_MSG(pamh, 93,
"%s%s: passwd successfully changed for %s"),
prognamep, UNIX_MSG, usrname);
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
1, messages, NULL);
}
return (PAM_SUCCESS);
err:
unlink(SHADTEMP);
(void) ulckpwdf();
memset(spbuf, 0, sizeof (spbuf));
return (PAM_AUTHTOK_ERR);
}
/*
* update_spent():
* To update a shadow password file entry in the Unix
* authentication token file.
* This function is called by update_authtok_file() to
* update the token to token attributes.
* The parameter "field" indicates whenther token attributes or
* token itself will be changes, and the parameter "data" has
* the new values for the attributes or token.
*
*/
static int
update_spent(pamh, field, data, unix_pwd, unix_sp,
passwd_flag, privileged, nowarn)
pam_handle_t *pamh;
char *field;
char **data;
struct passwd *unix_pwd;
struct spwd *unix_sp;
int *passwd_flag;
int privileged;
int nowarn;
{
char *value;
char *char_p;
char *tmp_pwd_entry;
char **data_p = data;
int mindate;
int maxdate;
int warndate;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
static char *lkstring = "*LK*"; /* lock string to lock */
/* user's password */
if (strcmp(field, "attr") == 0) {
while (*data != NULL) {
/* check attribute: AUTHTOK_DEL */
if ((value =
attr_match("AUTHTOK_DEL", *data))
!= NULL) {
if (strcmp(value, "1") == 0) {
/* delete password */
if (unix_sp->sp_pwdp)
memset(unix_sp->sp_pwdp, 0,
strlen(unix_sp->sp_pwdp));
/*
* set "AUTHTOK_EXT" will clear
* the sp_lstchg field. We do not
* want sp_lstchg field to be set
* if one execute passwd -d -f
* name or passwd -l -f name.
*/
if (attr_find("AUTHTOK_EXP",
data_p) == 0)
unix_sp->sp_lstchg = DAY_NOW;
}
data++;
continue;
}
/* check attribute: AUTHTOK_LK */
if ((value = attr_match("AUTHTOK_LK", *data))
!= NULL) {
if (strcmp(value, "1") == 0) {
memset(unix_sp->sp_pwdp, 0,
strlen(unix_sp->sp_pwdp));
/* lock password */
unix_sp->sp_pwdp = lkstring;
if (attr_find("AUTHTOK_EXP",
data_p) == 0)
unix_sp->sp_lstchg = DAY_NOW;
}
data++;
continue;
}
/* check attribute: AUTHTOK_EXP */
if ((value = attr_match("AUTHTOK_EXP", *data))
!= NULL) {
if (strcmp(value, "1") == 0) {
/* expire password */
unix_sp->sp_lstchg = (long) 0;
}
data++;
continue;
}
/* check attribute: AUTHTOK_MAXAGE */
if ((value = attr_match("AUTHTOK_MAXAGE", *data))
!= NULL) {
/* set max field */
maxdate = (int)strtol(value, &char_p, 10);
if ((attr_find("AUTHTOK_MINAGE", data_p) ==
0) && unix_sp->sp_min == -1)
unix_sp->sp_min = 0;
if (maxdate == -1) { /* turn off aging */
unix_sp->sp_min = -1;
unix_sp->sp_warn = -1;
} else if (unix_sp->sp_max == -1)
/*
* It was set to 0 before. That
* will force passwd change at the
* next login. There are several
* ways to force passwd change. I don't
* think turning on aging should imply
* that.
*/
unix_sp->sp_lstchg = DAY_NOW;
unix_sp->sp_max = maxdate;
data++;
continue;
}
/* check attribute: AUTHTOK_MINAGE */
if ((value = attr_match("AUTHTOK_MINAGE", *data))
!= NULL) {
/* set min field */
mindate = (int)strtol(value, &char_p, 10);
if ((attr_find("AUTHTOK_MAXAGE", data_p) ==
0) &&
unix_sp->sp_max == -1 && mindate != -1) {
return (PAM_AUTHTOK_DISABLE_AGING);
}
unix_sp->sp_min = mindate;
data++;
continue;
}
/* check attribute: AUTHTOK_WARNDATE */
if ((value =
attr_match
("AUTHTOK_WARNDATE", *data)) != NULL) {
/* set warn field */
warndate = (int)strtol(value, &char_p, 10);
if (unix_sp->sp_max == -1 && warndate != -1) {
return (PAM_AUTHTOK_DISABLE_AGING);
}
unix_sp->sp_warn = warndate;
data++;
continue;
}
/* new shell */
if ((value = attr_match("AUTHTOK_SHELL", *data))
!= NULL) {
if (unix_pwd == NULL) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 94,
"%s: No local passwd record"),
UNIX_MSG);
(void) __pam_display_msg(
pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (PAM_AUTHTOK_RECOVERY_ERR);
}
tmp_pwd_entry = unix_pwd->pw_shell;
unix_pwd->pw_shell =
getloginshell(pamh, unix_pwd->pw_shell,
privileged, nowarn);
if (tmp_pwd_entry)
free(tmp_pwd_entry);
/* if NULL, shell unchanged */
if (unix_pwd->pw_shell == NULL)
return (PAM_SUCCESS);
*passwd_flag = 1;
data++;
continue;
}
/* new homedir */
if ((value = attr_match("AUTHTOK_HOMEDIR", *data))
!= NULL) {
if (unix_pwd == NULL) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 94,
"%s: No local passwd record"),
UNIX_MSG);
(void) __pam_display_msg(
pamh, PAM_ERROR_MSG, 1,
messages, NULL);
}
return (PAM_AUTHTOK_RECOVERY_ERR);
}
tmp_pwd_entry = unix_pwd->pw_dir;
unix_pwd->pw_dir =
gethomedir(pamh, unix_pwd->pw_dir,
nowarn);
if (tmp_pwd_entry)
free(tmp_pwd_entry);
/* if NULL, homedir unchanged */
if (unix_pwd->pw_dir == NULL)
return (PAM_SUCCESS);
*passwd_flag = 1;
data++;
continue;
}
/* new gecos */
if ((value = attr_match("AUTHTOK_GECOS", *data))
!= NULL) {
if (unix_pwd == NULL) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 94,
"%s: No local passwd record"),
UNIX_MSG);
(void) __pam_display_msg(
pamh, PAM_ERROR_MSG, 1,
messages, NULL);
}
return (PAM_AUTHTOK_RECOVERY_ERR);
}
tmp_pwd_entry = unix_pwd->pw_gecos;
unix_pwd->pw_gecos =
getfingerinfo(pamh, unix_pwd->pw_gecos,
nowarn);
if (tmp_pwd_entry)
free(tmp_pwd_entry);
/* if NULL, gecos unchanged */
if (unix_pwd->pw_gecos == NULL)
return (PAM_SUCCESS);
*passwd_flag = 1;
data++;
continue;
}
}
} else {
if (strcmp(field, "passwd") == 0) { /* change password */
unix_sp->sp_pwdp = *data_p;
/* update the last change field */
unix_sp->sp_lstchg = DAY_NOW;
if (unix_sp->sp_max == 0) { /* turn off aging */
unix_sp->sp_max = -1;
unix_sp->sp_min = -1;
}
}
}
return (PAM_SUCCESS);
}
/*
* shell, homedir and gecos are in passwd file. The update is modeled
* after shadow file.
*/
static int
process_passwd(pamh, prognamep, usrname, unix_pwd, nowarn)
pam_handle_t *pamh;
char *prognamep;
char *usrname;
struct passwd *unix_pwd;
int nowarn;
{
FILE *tpfp; /* tmp passwd file pointer */
FILE *pwfp; /* passwd file pointer */
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
struct passwd *unix_p;
struct passwd unix_tmp;
int found;
char buf[4 * BUFSIZ];
struct stat stat_buf;
if (stat(PASSWD, &stat_buf) < 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (PAM_AUTHTOK_ERR);
}
(void) umask(S_IAMB & ~(stat_buf.st_mode & S_IRUSR));
if ((tpfp = fopen(PASSTEMP, "w")) == NULL) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (PAM_AUTHTOK_ERR);
}
if ((pwfp = fopen(PASSWD, "r")) == NULL) {
fclose(tpfp);
goto err;
}
while ((unix_p = fgetpwent_r(pwfp, &unix_tmp, buf, 4*BUFSIZ)) != NULL) {
if (strcmp(unix_p->pw_name, usrname) == 0) {
found = 1;
unix_p->pw_gecos = unix_pwd->pw_gecos;
unix_p->pw_dir = unix_pwd->pw_dir;
unix_p->pw_shell = unix_pwd->pw_shell;
}
if (putpwent(unix_p, tpfp) != 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
fclose(tpfp);
fclose(pwfp);
goto err;
}
memset(buf, 0, 4 * BUFSIZ);
} /* end of while */
if ((fclose(tpfp)) || (fclose(pwfp))) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
/* Check if user name exists */
if (found == 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
/*
* Rename temp file back to appropriate passwd file.
*/
/* remove old passwd file */
if (unlink(OPASSWD) && access(OPASSWD, 0) == 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: %s"),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
/* rename password file to old password file */
if (rename(PASSWD, OPASSWD) == -1) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
/* rename temporary password file to password file */
if (rename(PASSTEMP, PASSWD) == -1) {
(void) unlink(PASSWD);
if (link(OPASSWD, PASSWD)) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 91,
"%s%s: Unexpected failure. Password database unchanged."),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
goto err;
}
(void) chmod(PASSWD, 0644);
return (PAM_SUCCESS);
err:
(void) unlink(PASSTEMP);
return (PAM_AUTHTOK_ERR);
}

View File

@@ -0,0 +1,326 @@
/* $XConsortium: unix_update_authtok_nis.c /main/5 1996/05/09 04:36:14 drk $ */
/*
* Copyright (c) 1992-1996, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_update_authtok_nis.c 1.43 96/02/02 SMI"
#include "unix_headers.h"
#ifdef PAM_NIS
static void reencrypt_secret(pam_handle_t *, char *, char *, char *,
int);
static int update_nisattr(pam_handle_t *, char *, char **,
struct passwd *, int, int);
int
update_authtok_nis(
pam_handle_t *pamh,
char *field,
char *data[], /* encrypted new passwd */
/* or new attribute info */
char *old, /* old passwd: clear */
char *new, /* new passwd: clear */
struct passwd *nis_pwd, /* password structure */
int privileged,
int nowarn) /* no compat mode: npd and yp server */
/* take the same protocol */
{
int ok;
enum clnt_stat ans;
char *domain;
char *master;
CLIENT *client;
struct timeval timeout;
char *prognamep;
char *usrname;
int retcode = PAM_SYSTEM_ERR;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
struct yppasswd yppasswd;
/* initialize this */
yppasswd.oldpass = NULL;
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
!= PAM_SUCCESS ||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
!= PAM_SUCCESS)
goto out;
if (strcmp(field, "passwd") == 0) {
/*
* ck_passwd() already checked the old passwd. It won't get here
* if the old passwd is not matched.
* We are just preparing the passwd update packet here.
*/
if ((yppasswd.oldpass = strdup(old)) == NULL) {
retcode = PAM_BUF_ERR;
goto out;
}
if (nis_pwd->pw_passwd) {
memset(nis_pwd->pw_passwd, 0,
strlen(nis_pwd->pw_passwd));
free(nis_pwd->pw_passwd);
}
nis_pwd->pw_passwd = *data; /* encrypted new passwd */
} else {
/*
* prompt for passwd: required for the options
* nis_pwd struct will be modified by update_nisattr().
* The encrypted passwd remains the same because we are not
* changing passwd here.
*/
retcode = __pam_get_authtok(pamh, PAM_PROMPT, 0, PASSWORD_LEN,
PAM_MSG(pamh, 62, "Enter login(NIS) password: "),
&(yppasswd.oldpass));
if (retcode != PAM_SUCCESS)
goto out;
if ((retcode = update_nisattr(pamh, field, data,
nis_pwd, privileged, nowarn)) != PAM_SUCCESS) {
if (retcode == -1) {
/* finger, shell, or gecos info unchanged */
retcode = PAM_SUCCESS;
}
goto out;
}
}
yppasswd.newpw = *nis_pwd;
if (yp_get_default_domain(&domain) != 0) {
syslog(LOG_ERR, "%s%s: can't get domain",
prognamep, NIS_MSG);
retcode = PAM_SYSTEM_ERR;
goto out;
}
if (yp_master(domain, "passwd.byname", &master) != 0) {
syslog(LOG_ERR, "%s%s: can't get master for passwd map",
prognamep, NIS_MSG);
retcode = PAM_SYSTEM_ERR;
goto out;
}
client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
if (client == NULL) {
syslog(LOG_ERR,
"%s%s: couldn't create client to YP master",
prognamep, NIS_MSG);
retcode = PAM_SYSTEM_ERR;
goto out;
}
timeout.tv_usec = 0;
timeout.tv_sec = 55; /* npd uses 55 seconds */
ans = CLNT_CALL(client, YPPASSWDPROC_UPDATE, xdr_yppasswd,
(char *)&yppasswd, xdr_int, (char *)&ok, timeout);
(void) clnt_destroy(client);
if (ans != RPC_SUCCESS) {
sprintf(messages[0], PAM_MSG(pamh, 100,
"%s%s: couldn't change passwd/attributes"),
prognamep, NIS_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
retcode = PAM_PERM_DENIED;
goto out;
}
if (ok != 0) {
sprintf(messages[0], PAM_MSG(pamh, 101,
"%s%s: Couldn't change passwd/attributes for %s"),
prognamep, NIS_MSG, usrname);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
retcode = PAM_PERM_DENIED;
goto out;
}
sprintf(messages[0], PAM_MSG(pamh, 102,
"NIS(YP) passwd/attributes changed on %s"),
master);
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
1, messages, NULL);
reencrypt_secret(pamh, domain, old, new, nowarn);
retcode = PAM_SUCCESS;
out:
if (yppasswd.oldpass) {
memset(yppasswd.oldpass, 0, strlen(yppasswd.oldpass));
free(yppasswd.oldpass);
}
return (retcode);
}
static int
update_nisattr(pam_handle_t *pamh, char *field, char **data,
struct passwd *nis_pwd, int privileged, int nowarn)
{
char *username;
char *value;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
if (nis_pwd == NULL) {
if (!nowarn) {
pam_get_item(pamh, PAM_USER, (void **)&username);
sprintf(messages[0], PAM_MSG(pamh, 103,
"System error: no NIS passwd record for %s"),
username);
(void) __pam_display_msg(pamh,
PAM_ERROR_MSG, 1, messages, NULL);
}
return (PAM_USER_UNKNOWN);
}
if (strcmp(field, "attr") == 0) {
while (*data != NULL) {
/* AUTHTOK_DEL: not applicable */
if ((value = attr_match("AUTHTOK_SHELL", *data))
!= NULL) {
if (strcmp(value, "1") != 0) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 104,
"%s: System error%s: shell is set illegally"),
value, NIS_MSG);
(void) __pam_display_msg(pamh,
PAM_ERROR_MSG, 1,
messages, NULL);
}
return (PAM_SYSTEM_ERR);
}
nis_pwd->pw_shell =
getloginshell(pamh, nis_pwd->pw_shell,
privileged, nowarn);
/* if NULL, shell unchanged */
if (nis_pwd->pw_shell == NULL)
return (-1);
data++;
continue;
}
if ((value = attr_match("AUTHTOK_HOMEDIR", *data))
!= NULL) {
/* home directory */
if (strcmp(value, "1") != 0) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 105,
"System error%s: homedir is set illegally."),
NIS_MSG);
(void) __pam_display_msg(
pamh,
PAM_ERROR_MSG, 1,
messages, NULL);
}
return (PAM_SYSTEM_ERR);
}
nis_pwd->pw_dir =
gethomedir(pamh, nis_pwd->pw_dir, nowarn);
/* if NULL, homedir unchanged */
if (nis_pwd->pw_dir == NULL)
return (-1);
data++;
continue;
}
if ((value = attr_match("AUTHTOK_GECOS", *data))
!= NULL) {
/* finger information */
if (strcmp(value, "1") != 0) {
if (!nowarn) {
sprintf(messages[0],
PAM_MSG(pamh, 106,
"System error: gecos is set illegally."));
(void) __pam_display_msg(
pamh,
PAM_ERROR_MSG, 1,
messages, NULL);
}
return (PAM_SYSTEM_ERR);
}
nis_pwd->pw_gecos =
getfingerinfo(pamh, nis_pwd->pw_gecos,
nowarn);
/* if NULL, gecos unchanged */
if (nis_pwd->pw_gecos == NULL)
return (-1);
data++;
continue;
}
} /* while */
return (PAM_SUCCESS);
}
return (PAM_AUTHTOK_ERR);
/* NOTREACHED */
}
/*
* If the user has a secret key, reencrypt it.
* Otherwise, be quiet.
*/
static void
reencrypt_secret(pam_handle_t *pamh, char *domain, char *oldpass,
char *newpass, int nowarn)
{
#ifdef PAM_SECURE_RPC
char who[MAXNETNAMELEN+1];
char secret[HEXKEYBYTES+1];
char public[HEXKEYBYTES+1];
char crypt[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
char pkent[sizeof (crypt) + sizeof (public) + 1];
char *master;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
getnetname(who);
if (!getsecretkey(who, secret, oldpass)) {
/*
* Quiet: net is not running secure RPC
*/
return;
}
if (secret[0] == 0) {
/*
* Quiet: user has no secret key
*/
return;
}
if (getpublickey(who, public) == FALSE) {
return;
}
(void) memcpy(crypt, secret, HEXKEYBYTES);
(void) memcpy(crypt + HEXKEYBYTES, secret, KEYCHECKSUMSIZE);
crypt[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
(void) xencrypt(crypt, newpass);
(void) sprintf(pkent, "%s:%s", public, crypt);
if (yp_update(domain, PKMAP, YPOP_STORE,
who, strlen(who), pkent, strlen(pkent)) != 0) {
return;
}
if (yp_master(domain, PKMAP, &master) != 0) {
master = "yp master"; /* should never happen */
}
sprintf(messages[0], PAM_MSG(pamh, 107,
"%s: secret key reencrypted for %s on %s"),
NIS_MSG, who, master);
__pam_display_msg(pamh, PAM_TEXT_INFO, 1, messages, NULL);
#else
return;
#endif /* PAM_SECURE_RPC */
}
#endif /* PAM_NIS */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,974 @@
/* $XConsortium: unix_utils.c /main/5 1996/05/09 04:36:55 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)unix_utils.c 1.53 95/09/11 SMI"
#include "unix_headers.h"
static char *spskip();
static int special_case();
static int illegal_input();
static int copy_passwd_structs(struct passwd **, struct passwd *,
struct spwd **, struct spwd *);
void free_passwd_structs(struct passwd *, struct spwd *);
/* ******************************************************************** */
/* */
/* Utilities Functions */
/* */
/* ******************************************************************** */
#ifdef PAM_SECURE_RPC
/*
* Establish the Secure RPC secret key for the given uid using
* the given password to decrypt the secret key, and store it with
* the key service.
*
* If called with a nonzero 'reestablish' parameter, the key
* is obtained from the name service, decrypted, and stored
* even if the keyserver already has a key stored for the uid.
* If the 'reestablish' parameter is zero, the function will not
* try to reset the key. It will return immediately with
* ESTKEY_ALREADY.
*
* Returns one of the following codes:
* ESTKEY_ALREADY - reestablish flag was zero, and key was already set.
* ESTKEY_SUCCESS - successfully obtained, decrypted, and set the key
* ESTKEY_NOCREDENTIALS - the user has no credentials.
* ESTKEY_BADPASSWD - the password supplied didn't decrypt the key
* ESTKEY_CANTSETKEY - decrypted the key, but couldn't store key with
* the key service.
*
* If netnamebuf is a non-NULL pointer, the netname will be returned in
* netnamebuf, provided that the return status is not
* ESTKEY_NOCREDENTIALS or ESTKEY_ALREADY. If non-NULL, the
* netnamebuf pointer must point to a buffer of length at least
* MAXNETNAMELEN+1 characters.
*/
int
establish_key(uid, password, reestablish, netnamebuf)
uid_t uid;
char *password;
int reestablish;
char *netnamebuf;
{
char netname[MAXNETNAMELEN+1];
struct key_netstarg netst;
uid_t orig_uid;
orig_uid = geteuid();
if (seteuid(uid) == -1)
/* can't set uid */
return (ESTKEY_NOCREDENTIALS);
if (!reestablish && key_secretkey_is_set()) {
/* key is already established and we are not to reestablish */
(void) seteuid(orig_uid);
return (ESTKEY_ALREADY);
}
if (!getnetname(netname)) {
/* can't construct netname */
(void) seteuid(orig_uid);
return (ESTKEY_NOCREDENTIALS);
}
if (!getsecretkey(netname, (char *) &(netst.st_priv_key), password)) {
/* no secret key */
(void) seteuid(orig_uid);
return (ESTKEY_NOCREDENTIALS);
}
if (netnamebuf) {
/* return copy of netname in caller's buffer */
(void) strcpy(netnamebuf, netname);
}
if (netst.st_priv_key[0] == 0) {
/* password does not decrypt secret key */
(void) seteuid(orig_uid);
return (ESTKEY_BADPASSWD);
}
/* secret key successfully decrypted at this point */
/* store with key service */
if ((netst.st_netname = strdup(netname)) == NULL) {
(void) seteuid(orig_uid);
return (PAM_BUF_ERR);
}
(void) memset(netst.st_pub_key, 0, HEXKEYBYTES);
if (key_setnet(&netst) < 0) {
free(netst.st_netname);
(void) seteuid(orig_uid);
return (ESTKEY_CANTSETKEY);
}
free(netst.st_netname);
(void) seteuid(orig_uid);
return (ESTKEY_SUCCESS);
}
#endif /* PAM_SECURE_RPC */
/* ******************************************************************** */
/* */
/* Utilities Functions */
/* */
/* ******************************************************************** */
/*
* ck_perm():
* Check the permission of the user specified by "usrname".
*
* It returns PAM_PERM_DENIED if (1) the user has a NULL pasword or
* shadow password file entry, or (2) the caller is not root and
* its uid is not equivalent to the uid specified by the user's
* password file entry.
*/
int
ck_perm(pamh, repository, domain, pwd, shpwd, privileged, passwd_res, uid,
debug, nowarn)
pam_handle_t *pamh;
int repository;
char *domain;
struct passwd **pwd;
struct spwd **shpwd;
int *privileged;
void **passwd_res;
uid_t uid;
int debug;
int nowarn;
{
FILE *pwfp, *spfp;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
struct passwd local_pwd, *local_pwdp;
struct spwd local_shpwd, *local_shpwdp;
char pwdbuf[1024], shpwdbuf[1024];
char *prognamep;
char *usrname;
int retcode = 0;
#ifdef PAM_NISPLUS
char buf[NIS_MAXNAMELEN+1];
nis_name local_principal;
nis_name pwd_domain;
#endif
if (debug)
syslog(LOG_DEBUG,
"ck_perm() called: repository=%s",
repository_to_string(repository));
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
!= PAM_SUCCESS ||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
!= PAM_SUCCESS) {
*pwd = NULL; *shpwd = NULL;
return (retcode);
}
if (repository == PAM_REP_FILES) {
if (((pwfp = fopen(PASSWD, "r")) == NULL) ||
((spfp = fopen(SHADOW, "r")) == NULL)) {
*pwd = NULL; *shpwd = NULL;
syslog(LOG_ERR,
"ck_perm: can not open passwd/shadow file");
return (PAM_PERM_DENIED);
}
while ((local_pwdp = fgetpwent_r(pwfp, &local_pwd, pwdbuf,
sizeof (pwdbuf))) != NULL)
if (strcmp(local_pwd.pw_name, usrname) == 0)
break;
while ((local_shpwdp = fgetspent_r(spfp, &local_shpwd,
shpwdbuf, sizeof (shpwdbuf))) != NULL)
if (strcmp(local_shpwd.sp_namp, usrname) == 0)
break;
(void) fclose(pwfp);
(void) fclose(spfp);
if (local_pwdp == NULL || local_shpwdp == NULL) {
*pwd = NULL; *shpwd = NULL;
return (PAM_USER_UNKNOWN);
}
if (uid != 0 && uid != local_pwd.pw_uid) {
/*
* Change passwd for another person:
* Even if you are nis+ admin, you can't do anything
* locally. Don't bother to continue.
*/
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 140,
"%s%s: Permission denied"), prognamep,
UNIX_MSG);
sprintf(messages[1], PAM_MSG(pamh, 141,
"%s%s: Can't change local passwd file\n"),
prognamep, UNIX_MSG);
(void) __pam_display_msg(
pamh, PAM_ERROR_MSG, 2,
messages, NULL);
}
*pwd = NULL; *shpwd = NULL;
return (PAM_PERM_DENIED);
}
return (copy_passwd_structs(pwd, local_pwdp,
shpwd, local_shpwdp));
}
#ifdef PAM_NIS
if (repository == PAM_REP_NIS) {
/*
* Special case root: don't bother to get root from nis(yp).
*/
if (strcmp(usrname, "root") == 0) {
*pwd = NULL; *shpwd = NULL;
return (PAM_USER_UNKNOWN);
}
/* get pwd struct from yp */
local_pwdp = getpwnam_from(usrname, PAM_REP_NIS);
local_shpwdp = getspnam_from(usrname, PAM_REP_NIS);
if (local_pwdp == NULL || local_shpwdp == NULL)
return (PAM_USER_UNKNOWN);
if (uid != local_pwdp->pw_uid) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 140,
"%s%s: Permission denied"), prognamep,
NIS_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
*pwd = NULL; *shpwd = NULL;
return (PAM_PERM_DENIED);
}
return (copy_passwd_structs(pwd, local_pwdp,
shpwd, local_shpwdp));
}
#endif /* PAM_NIS */
#ifdef PAM_NISPLUS
if (repository == PAM_REP_NISPLUS) {
/*
* Special case root: don't bother to get root from nis+.
*/
if (strcmp(usrname, "root") == 0) {
*pwd = NULL; *shpwd = NULL;
return (PAM_USER_UNKNOWN);
}
if (debug)
syslog(LOG_DEBUG, "ck_perm(): NIS+ domain=%s", domain);
/*
* We need to use user id to
* make any nis+ request. But don't give up the super
* user power yet. It may be needed elsewhere.
*/
(void) setuid(0); /* keep real user id as root */
(void) seteuid(uid);
local_shpwdp = getspnam_from(usrname, PAM_REP_NISPLUS);
local_pwdp = getpwnam_from(usrname, PAM_REP_NISPLUS);
if (local_pwdp == NULL || local_shpwdp == NULL)
return (PAM_USER_UNKNOWN);
/*
* local_principal is internal, it is not meant to be free()ed
*/
local_principal = nis_local_principal();
if ((9 + strlen(usrname) + strlen(domain) + PASSTABLELEN) >
(size_t) NIS_MAXNAMELEN) {
sprintf(messages[0], PAM_MSG(pamh, 140,
"%s%s: Permission denied"), prognamep, NISPLUS_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
*pwd = NULL; *shpwd = NULL;
return (PAM_PERM_DENIED);
}
sprintf(buf, "[name=%s],%s.%s", usrname, PASSTABLE, domain);
if (buf[strlen(buf) - 1] != '.')
(void) strcat(buf, ".");
/*
* We must use an authenticated handle to get the cred
* table information for the user we want to modify the
* cred info for. If we can't even read that info, we
* definitely wouldn't have modify permission. Well..
*/
*passwd_res = (void *) nis_list(buf,
USE_DGRAM+FOLLOW_LINKS+FOLLOW_PATH+MASTER_ONLY,
NULL, NULL);
if (((nis_result *)(*passwd_res))->status != NIS_SUCCESS) {
sprintf(messages[0], PAM_MSG(pamh, 140,
"%s%s: Permission denied"), prognamep, NISPLUS_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
*pwd = NULL; *shpwd = NULL;
return (PAM_PERM_DENIED);
}
pwd_domain =
NIS_RES_OBJECT((nis_result *)(*passwd_res))->zo_domain;
if (strcmp(nis_leaf_of(pwd_domain), "org_dir") == 0) {
pwd_domain = nis_domain_of(
NIS_RES_OBJECT((nis_result *)(*passwd_res))->zo_domain);
}
*privileged = __nis_isadmin(local_principal, "passwd",
pwd_domain);
return (copy_passwd_structs(pwd, local_pwdp,
shpwd, local_shpwdp));
}
#endif /* PAM_NISPLUS */
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 142,
"%s%s: System error: repository out of range"),
prognamep, UNIX_MSG);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1,
messages, NULL);
}
*pwd = NULL; *shpwd = NULL;
return (PAM_PERM_DENIED);
}
/*
* attr_match():
*
* Check if the attribute name in string s1 is equivalent to
* that in string s2.
* s1 is either name, or name=value
* s2 is name=value
* if names match, return value of s2, else NULL
*/
char *
attr_match(s1, s2)
register char *s1, *s2;
{
while (*s1 == *s2++)
if (*s1++ == '=')
return (s2);
if (*s1 == '\0' && *(s2-1) == '=')
return (s2);
return (NULL);
}
/*
* attr_find():
*
* Check if the attribute name in string s1 is present in the
* attribute=value pairs array pointed by s2.
* s1 is name
* s2 is an array of name=value pairs
* if s1 match the name of any one of the name in the name=value pairs
* pointed by s2, then 1 is returned; else 0 is returned
*/
int
attr_find(s1, s2)
register char *s1, *s2[];
{
int i;
char *sa, *sb;
i = 0;
while (s2[i] != NULL) {
sa = s1;
sb = s2[i];
while (*sa++ == *sb++) {
if ((*sa == '\0') && (*sb == '='))
return (1); /* find */
}
i++;
}
return (0); /* not find */
}
/*
* free_setattr():
* free storage pointed by "setattr"
*/
void
free_setattr(setattr)
char * setattr[];
{
int i;
for (i = 0; setattr[i] != NULL; i++)
free(setattr[i]);
}
/*
* setup_attr():
* allocate memory and copy in attribute=value pair
* into the array of attribute=value pairs pointed to
* by "dest_attr"
*/
void
setup_attr(dest_attr, k, attr, value)
char *dest_attr[];
int k;
char attr[];
char value[];
{
if (attr != NULL) {
dest_attr[k] = (char *)calloc(PAM_MAX_ATTR_SIZE, sizeof (char));
(void) strncpy(dest_attr[k], attr, PAM_MAX_ATTR_SIZE);
(void) strncat(dest_attr[k], value, PAM_MAX_ATTR_SIZE);
} else
dest_attr[k] = NULL;
}
#ifdef PAM_NISPLUS
static char *
spskip(p)
register char *p;
{
while (*p && *p != ':' && *p != '\n')
++p;
if (*p == '\n')
*p = '\0';
else if (*p)
*p++ = '\0';
return (p);
}
void
nisplus_populate_age(enobj, sp)
struct nis_object *enobj;
struct spwd *sp;
{
char *oldage, *p, *end;
long x;
/*
* shadow (col 7)
*/
sp->sp_lstchg = -1;
sp->sp_min = -1;
sp->sp_max = -1;
sp->sp_warn = -1;
sp->sp_inact = -1;
sp->sp_expire = -1;
sp->sp_flag = 0;
if ((p = ENTRY_VAL(enobj, 7)) == NULL)
return;
oldage = strdup(p);
p = oldage;
x = strtol(p, &end, 10);
if (end != memchr(p, ':', strlen(p)))
return;
if (end != p)
sp->sp_lstchg = x;
p = spskip(p);
x = strtol(p, &end, 10);
if (end != memchr(p, ':', strlen(p)))
return;
if (end != p)
sp->sp_min = x;
p = spskip(p);
x = strtol(p, &end, 10);
if (end != memchr(p, ':', strlen(p)))
return;
if (end != p)
sp->sp_max = x;
p = spskip(p);
x = strtol(p, &end, 10);
if (end != memchr(p, ':', strlen(p)))
return;
if (end != p)
sp->sp_warn = x;
p = spskip(p);
x = strtol(p, &end, 10);
if (end != memchr(p, ':', strlen(p)))
return;
if (end != p)
sp->sp_inact = x;
p = spskip(p);
x = strtol(p, &end, 10);
if (end != memchr(p, ':', strlen(p)))
return;
if (end != p)
sp->sp_expire = x;
p = spskip(p);
x = strtol(p, &end, 10);
if ((end != memchr(p, ':', strlen(p))) &&
(end != memchr(p, '\n', strlen(p))))
return;
if (end != p)
sp->sp_flag = x;
free(oldage);
}
#endif /* PAM_NISPLUS */
/*
* getloginshell() displays old login shell and asks for new login shell.
* The new login shell is then returned to calling function.
*/
char *
getloginshell(pamh, oldshell, privileged, nowarn)
pam_handle_t *pamh;
char *oldshell;
int privileged;
int nowarn;
{
char newshell[PAM_MAX_MSG_SIZE];
char *cp, *valid, *getusershell();
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
struct pam_response *ret_resp = (struct pam_response *)0;
if (oldshell == 0 || *oldshell == '\0')
oldshell = DEFSHELL;
if (privileged == 0) {
mutex_lock(&_priv_lock);
setusershell();
for (valid = getusershell(); valid; valid = getusershell())
if (strcmp(oldshell, valid) == 0)
break;
mutex_unlock(&_priv_lock);
if (valid == NULL) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 143,
"Cannot change from restricted shell %s"),
oldshell);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (NULL);
}
}
sprintf(messages[0],
PAM_MSG(pamh, 144, "Old shell: %s"), oldshell);
(void) __pam_display_msg(pamh, PAM_TEXT_INFO, 1, messages, NULL);
sprintf(messages[0],
PAM_MSG(pamh, 145, "New shell: "));
(void) __pam_get_input(pamh, PAM_PROMPT_ECHO_ON,
1, messages, NULL, &ret_resp);
strncpy(newshell, ret_resp->resp, PAM_MAX_MSG_SIZE);
newshell[PAM_MAX_RESP_SIZE-1] = '\0';
__pam_free_resp(1, ret_resp);
cp = strchr(newshell, '\n');
if (cp)
*cp = '\0';
if (newshell[0] == '\0' || (strcmp(newshell, oldshell) == 0)) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 146,
"Login shell unchanged."));
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
return (NULL);
}
/*
* XXX:
* Keep in mind that, for whatever this validation is worth,
* a root on a machine can edit /etc/shells and get any shell
* accepted as a valid shell in the NIS+ table.
*/
mutex_lock(&_priv_lock);
setusershell();
if (!privileged) {
for (valid = getusershell(); valid; valid = getusershell()) {
/*
* Allow user to give shell w/o preceding pathname.
*/
if (newshell[0] == '/') {
cp = valid;
} else {
cp = strrchr(valid, '/');
if (cp == 0)
cp = valid;
else
cp++;
}
if (strcmp(newshell, cp) == 0) {
strncpy(newshell, valid, strlen(valid));
break;
}
}
}
mutex_unlock(&_priv_lock);
if (newshell == 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 147,
"%s is unacceptable as a new shell"),
newshell);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
__pam_free_resp(1, ret_resp);
return (NULL);
}
if (access(newshell, X_OK) < 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 148,
"warning: %s is unavailable on this machine"),
newshell);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
}
return (strdup(newshell));
}
/*
* Get name.
*/
char *
getfingerinfo(pamh, old_gecos, nowarn)
pam_handle_t *pamh;
char *old_gecos;
int nowarn;
{
char new_gecos[PAM_MAX_MSG_SIZE];
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
struct pam_response *ret_resp = (struct pam_response *)0;
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 149,
"Default values are printed inside of '[]'."));
sprintf(messages[1], PAM_MSG(pamh, 150,
"To accept the default, type <return>."));
sprintf(messages[2], PAM_MSG(pamh, 151,
"To have a blank entry, type the word 'none'."));
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
3, messages, NULL);
}
/*
* Get name.
*/
do {
sprintf(messages[0], " ");
(void) __pam_display_msg(pamh, PAM_TEXT_INFO, 1,
messages, NULL);
sprintf(messages[0], PAM_MSG(pamh, 152,
"Name [%s]: "), old_gecos);
(void) __pam_get_input(pamh, PAM_PROMPT_ECHO_ON,
1, messages, NULL, &ret_resp);
strncpy(new_gecos, ret_resp->resp, PAM_MAX_MSG_SIZE);
new_gecos[PAM_MAX_MSG_SIZE-1] = '\0';
__pam_free_resp(1, ret_resp);
if (special_case(new_gecos, old_gecos))
break;
} while (illegal_input(pamh, new_gecos, nowarn));
if (strcmp(new_gecos, old_gecos) == 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 153,
"Finger information unchanged."));
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
1, messages, NULL);
}
return (NULL);
}
return (strdup(new_gecos));
}
/*
* Get Home Dir.
*/
char *
gethomedir(pamh, olddir, nowarn)
pam_handle_t *pamh;
char *olddir;
int nowarn;
{
char newdir[PAM_MAX_MSG_SIZE];
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
struct pam_response *ret_resp = (struct pam_response *)0;
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 149,
"Default values are printed inside of '[]'."));
sprintf(messages[1], PAM_MSG(pamh, 150,
"To accept the default, type <return>."));
sprintf(messages[2], PAM_MSG(pamh, 151,
"To have a blank entry, type the word 'none'."));
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
3, messages, NULL);
}
do {
sprintf(messages[0], " ");
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
1, messages, NULL);
sprintf(messages[0], PAM_MSG(pamh, 154,
"Home Directory [%s]: "), olddir);
(void) __pam_get_input(pamh, PAM_PROMPT_ECHO_ON,
1, messages, NULL, &ret_resp);
strncpy(newdir, ret_resp->resp, PAM_MAX_MSG_SIZE);
newdir[PAM_MAX_MSG_SIZE-1] = '\0';
__pam_free_resp(1, ret_resp);
if (special_case(newdir, olddir))
break;
} while (illegal_input(pamh, newdir, nowarn));
if (strcmp(newdir, olddir) == 0) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 155,
"Homedir information unchanged."));
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
1, messages, NULL);
}
return (NULL);
}
return (strdup(newdir));
}
char *
repository_to_string(int repository)
{
/* if NISPLUS and FILES */
switch (repository) {
case (PAM_REP_FILES | PAM_REP_NISPLUS):
return ("files and nisplus");
case (PAM_REP_FILES | PAM_REP_NIS):
return ("files and nis");
case PAM_REP_NISPLUS:
return ("nisplus");
case PAM_REP_NIS:
return ("nis");
case PAM_REP_FILES:
return ("files");
case PAM_REP_DEFAULT:
return ("default");
default:
return ("bad repository");
}
}
/*
* Prints an error message if a ':' or a newline is found in the string.
* A message is also printed if the input string is too long.
* The password sources use :'s as seperators, and are not allowed in the "gcos"
* field. Newlines serve as delimiters between users in the password source,
* and so, those too, are checked for. (I don't think that it is possible to
* type them in, but better safe than sorry)
*
* Returns '1' if a colon or newline is found or the input line is too long.
*/
static int
illegal_input(pamh, input_str, nowarn)
pam_handle_t *pamh;
char *input_str;
int nowarn;
{
char *ptr;
int error_flag = 0;
int length = (int)strlen(input_str);
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
if (strchr(input_str, ':')) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 156,
"':' is not allowed."));
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
error_flag = 1;
}
if (input_str[length-1] != '\n') {
/* the newline and the '\0' eat up two characters */
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 157,
"Maximum number of characters allowed is %d."),
PAM_MAX_MSG_SIZE-2);
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
error_flag = 1;
}
/*
* Delete newline by shortening string by 1.
*/
input_str[length-1] = '\0';
/*
* Don't allow control characters, etc in input string.
*/
for (ptr = input_str; *ptr != '\0'; ptr++) {
/* 040 is ascii char "space" */
if ((int) *ptr < 040) {
if (!nowarn) {
sprintf(messages[0], PAM_MSG(pamh, 158,
"Control characters are not allowed."));
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
1, messages, NULL);
}
error_flag = 1;
break;
}
}
return (error_flag);
}
/*
* special_case returns true when either the default is accepted
* (str = '\n'), or when 'none' is typed. 'none' is accepted in
* either upper or lower case (or any combination). 'str' is modified
* in these two cases.
*/
static int
special_case(str, default_str)
char *str, *default_str;
{
static char word[] = "none\n";
char *ptr, *wordptr;
/*
* If the default is accepted, then change the old string do the
* default string.
*/
if (*str == '\n') {
(void) strcpy(str, default_str);
return (1);
}
/*
* Check to see if str is 'none'. (It is questionable if case
* insensitivity is worth the hair).
*/
wordptr = word - 1;
for (ptr = str; *ptr != '\0'; ++ptr) {
++wordptr;
if (*wordptr == '\0') /* then words are different sizes */
return (0);
if (*ptr == *wordptr)
continue;
if (isupper(*ptr) && (tolower(*ptr) == *wordptr))
continue;
/*
* At this point we have a mismatch, so we return
*/
return (0);
}
/*
* Make sure that words are the same length.
*/
if (*(wordptr+1) != '\0')
return (0);
/*
* Change 'str' to be the null string
*/
*str = '\0';
return (1);
}
static int
copy_passwd_structs(struct passwd **pwd, struct passwd *local_pwd,
struct spwd **shpwd, struct spwd *local_shpwd)
{
/* copy the passwd information */
if ((*pwd = (struct passwd *)
calloc(1, sizeof (struct passwd))) == NULL)
return (PAM_BUF_ERR);
if (local_pwd->pw_name) {
if (((*pwd)->pw_name = strdup(local_pwd->pw_name)) == NULL)
goto out;
}
if (local_pwd->pw_passwd) {
if (((*pwd)->pw_passwd = strdup(local_pwd->pw_passwd)) == NULL)
goto out;
}
(*pwd)->pw_uid = local_pwd->pw_uid;
(*pwd)->pw_gid = local_pwd->pw_gid;
if (local_pwd->pw_gecos) {
if (((*pwd)->pw_gecos = strdup(local_pwd->pw_gecos)) == NULL)
goto out;
}
if (local_pwd->pw_dir) {
if (((*pwd)->pw_dir = strdup(local_pwd->pw_dir)) == NULL)
goto out;
}
if (local_pwd->pw_shell) {
if (((*pwd)->pw_shell = strdup(local_pwd->pw_shell)) == NULL)
goto out;
}
/* copy the shadow passwd information */
if ((*shpwd = (struct spwd *)
calloc(1, sizeof (struct spwd))) == NULL)
goto out;
**shpwd = *local_shpwd;
if (local_shpwd->sp_namp) {
if (((*shpwd)->sp_namp = strdup(local_shpwd->sp_namp)) == NULL)
goto out;
}
if (local_shpwd->sp_pwdp) {
if (((*shpwd)->sp_pwdp = strdup(local_shpwd->sp_pwdp)) == NULL)
goto out;
}
return (PAM_SUCCESS);
out:
free_passwd_structs(*pwd, *shpwd);
return (PAM_BUF_ERR);
}
void
free_passwd_structs(struct passwd *pwd, struct spwd *shpwd)
{
if (pwd) {
if (pwd->pw_name)
free(pwd->pw_name);
if (pwd->pw_passwd) {
memset(pwd->pw_passwd, 0, strlen(pwd->pw_passwd));
free(pwd->pw_passwd);
}
if (pwd->pw_gecos)
free(pwd->pw_gecos);
if (pwd->pw_dir)
free(pwd->pw_dir);
if (pwd->pw_shell)
free(pwd->pw_shell);
free(pwd);
}
if (shpwd) {
if (shpwd->sp_namp)
free(shpwd->sp_namp);
if (shpwd->sp_pwdp) {
memset(shpwd->sp_pwdp, 0, strlen(shpwd->sp_pwdp));
free(shpwd->sp_pwdp);
}
free(shpwd);
}
}

View File

@@ -0,0 +1,68 @@
/* $XConsortium: yppasswdxdr.c /main/2 1996/05/08 13:46:51 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
/*******************************************************************************
** yppasswd utilies
*******************************************************************************/
#if (PAM_NIS || PAM_NISPLUS)
#include "unix_headers.h"
bool_t
xdr_passwd(xdrs, pw)
XDR *xdrs;
struct passwd *pw;
{
if (!xdr_wrapstring(xdrs, &pw->pw_name)) {
return (FALSE);
}
if (!xdr_wrapstring(xdrs, &pw->pw_passwd)) {
return (FALSE);
}
if (!xdr_uid_t(xdrs, &pw->pw_uid)) {
return (FALSE);
}
if (!xdr_gid_t(xdrs, (&pw->pw_gid))){
return (FALSE);
}
if (!xdr_wrapstring(xdrs, &pw->pw_gecos)) {
return (FALSE);
}
if (!xdr_wrapstring(xdrs, &pw->pw_dir)) {
return (FALSE);
}
if (!xdr_wrapstring(xdrs, &pw->pw_shell)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_yppasswd(xdrs, yppw)
XDR *xdrs;
struct yppasswd *yppw;
{
if (!xdr_wrapstring(xdrs, &yppw->oldpass)) {
return (FALSE);
}
if (!xdr_passwd(xdrs, &yppw->newpw)) {
return (FALSE);
}
return (TRUE);
}
#else
/* Some compilers complain about empty compilation modules. */
static int dummy;
#endif /* PAM_NIS or PAM_NISPLUS */