Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
21
cde/lib/pam/pam_modules/Imakefile
Normal file
21
cde/lib/pam/pam_modules/Imakefile
Normal 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))
|
||||
48
cde/lib/pam/pam_modules/dce/Imakefile
Normal file
48
cde/lib/pam/pam_modules/dce/Imakefile
Normal 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()
|
||||
179
cde/lib/pam/pam_modules/dce/dce_acct_mgmt.c
Normal file
179
cde/lib/pam/pam_modules/dce/dce_acct_mgmt.c
Normal 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);
|
||||
}
|
||||
434
cde/lib/pam/pam_modules/dce/dce_authenticate.c
Normal file
434
cde/lib/pam/pam_modules/dce/dce_authenticate.c
Normal file
@@ -0,0 +1,434 @@
|
||||
/* $XConsortium: dce_authenticate.c /main/5 1996/05/09 04:26:26 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)dce_authenticate.c 1.34 96/02/14 SMI"
|
||||
|
||||
#include <dce/nbase.h>
|
||||
#include <dce/sec_login.h>
|
||||
#include <dce/dce_error.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <rpc/des_crypt.h>
|
||||
#include <pwd.h>
|
||||
#include <syslog.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#include "pam_impl.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
#include "xfn_mapping.h"
|
||||
#endif /* XFN_MAPPING */
|
||||
|
||||
#define SLEEPTIME 4
|
||||
|
||||
/* maxmimum DCE_PASSWD_LENGTH. We need to pick something for
|
||||
* __pam_get_authtok to use.
|
||||
*/
|
||||
|
||||
#define DCE_PASSWD_LENGTH 256
|
||||
|
||||
static int
|
||||
attempt_dce_login(
|
||||
void *pamh,
|
||||
dce_module_data_t *dsd,
|
||||
error_status_t *st,
|
||||
char *user,
|
||||
char *dce_pass
|
||||
);
|
||||
|
||||
void
|
||||
dce_cleanup(
|
||||
pam_handle_t *pamh,
|
||||
void *data,
|
||||
int pam_status
|
||||
);
|
||||
|
||||
/*
|
||||
* pam_sm_authenticate - Authenticate user
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_authenticate(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
char *user;
|
||||
int err, result = PAM_AUTH_ERR;
|
||||
char messages[1][PAM_MAX_MSG_SIZE];
|
||||
error_status_t st;
|
||||
char *defpass;
|
||||
int num_msg = 0;
|
||||
int debug = 0;
|
||||
int warn = 1;
|
||||
int passwd_flag = 0;
|
||||
int try_first_pass = 0;
|
||||
int use_first_pass = 0;
|
||||
int ignore = 0;
|
||||
int invalid_user = 0;
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
int try_mapped_pass = 0;
|
||||
int use_mapped_pass = 0;
|
||||
#endif
|
||||
int i;
|
||||
char *firstpass = NULL, *password = NULL;
|
||||
uid_t pw_uid;
|
||||
dce_module_data_t *dsd = NULL;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcmp(argv[i], "try_first_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
try_first_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
} else if (strcmp(argv[i], "use_first_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
use_first_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
#ifdef XFN_MAPPING
|
||||
} else if (strcmp(argv[i], "try_mapped_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
try_mapped_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
} else if (strcmp(argv[i], "use_mapped_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
use_mapped_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
#endif
|
||||
} else if (strcmp(argv[i], "nowarn") == 0) {
|
||||
warn = 0;
|
||||
} else {
|
||||
syslog(LOG_ERR, "illegal module option %s", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & PAM_SILENT) warn = 0;
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE pam_sm_authenticate");
|
||||
|
||||
err = pam_get_user(pamh, &user, NULL);
|
||||
|
||||
if (err != PAM_SUCCESS)
|
||||
return (err);
|
||||
|
||||
if (user == NULL || !user[0])
|
||||
return (PAM_AUTH_ERR);
|
||||
|
||||
/* Don't bother to authenticate root in DCE */
|
||||
|
||||
if (strcmp(user, "root") == 0)
|
||||
ignore = 1;
|
||||
|
||||
/* make sure a password entry exists for this user */
|
||||
/* we also need the uid for XFN */
|
||||
|
||||
if (!get_pw_uid(user, &pw_uid)) {
|
||||
invalid_user = 1;
|
||||
}
|
||||
|
||||
if (pam_get_data(pamh, DCE_DATA, (void**)&dsd) != PAM_SUCCESS ||
|
||||
dsd == NULL) {
|
||||
|
||||
dsd = calloc(1, sizeof (dce_module_data_t));
|
||||
if (dsd == NULL) {
|
||||
result = PAM_BUF_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((err = pam_set_data(pamh, DCE_DATA, dsd, &dce_cleanup))
|
||||
!= PAM_SUCCESS) {
|
||||
free(dsd);
|
||||
result = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (dsd->login_context != sec_login_default_handle) {
|
||||
error_status_t st;
|
||||
sec_login_purge_context(&dsd->login_context, &st);
|
||||
}
|
||||
}
|
||||
|
||||
dsd->login_context = sec_login_default_handle;
|
||||
dsd->auth_status = PAM_AUTH_ERR;
|
||||
dsd->debug = debug;
|
||||
dsd->warn = warn;
|
||||
dsd->reset_passwd = 0;
|
||||
dsd->passwd_expired = 0;
|
||||
dsd->auth_src = sec_login_auth_src_network;
|
||||
|
||||
/* see if a legitimate DCE user */
|
||||
|
||||
if (!sec_login_setup_identity((unsigned char *)user,
|
||||
sec_login_no_flags, &dsd->login_context, &st)) {
|
||||
if (debug) {
|
||||
dce_error_string_t text;
|
||||
syslog(LOG_DEBUG,
|
||||
"PAM: DCE sec_login_setup_identity: %s",
|
||||
get_dce_error_message(st, text));
|
||||
}
|
||||
if (st == sec_rgy_object_not_found) {
|
||||
/* mask the unknown user case */
|
||||
invalid_user = 1;
|
||||
} else {
|
||||
result = PAM_AUTH_ERR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
err = pam_get_item(pamh, PAM_AUTHTOK, (void **) &firstpass);
|
||||
|
||||
if (err != PAM_SUCCESS && (use_first_pass || use_mapped_pass)) {
|
||||
result = PAM_AUTH_ERR;
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "PAM: DCE goto out!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (firstpass != NULL && (ignore || invalid_user))
|
||||
goto out;
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
|
||||
if (firstpass == NULL) {
|
||||
if (use_mapped_pass) goto out;
|
||||
} else if (try_mapped_pass || use_mapped_pass) {
|
||||
char dcepass[MAP_PASSLEN+1];
|
||||
uid_t saved_uid;
|
||||
int got_mapped_pass;
|
||||
|
||||
saved_uid = geteuid();
|
||||
|
||||
if (saved_uid != pw_uid && getuid() == 0 &&
|
||||
seteuid(pw_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd: seteuid: %m");
|
||||
/* continue since we might be able to get mapping */
|
||||
}
|
||||
|
||||
got_mapped_pass = xfn_get_mapped_password(
|
||||
debug ? XFN_MAP_DEBUG : 0, user, DCE_XFN_PASS_ATTR,
|
||||
firstpass, dcepass, sizeof (dcepass));
|
||||
|
||||
if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd seteuid restore: %m");
|
||||
/* XXX: what should we do here? */
|
||||
}
|
||||
|
||||
if (got_mapped_pass) {
|
||||
|
||||
result =
|
||||
attempt_dce_login(pamh, dsd, &st, user, dcepass);
|
||||
|
||||
memset(dcepass, 0, MAP_PASSLEN);
|
||||
|
||||
if (result == PAM_SUCCESS ||
|
||||
st == sec_login_s_acct_invalid) goto out;
|
||||
}
|
||||
if (use_mapped_pass) goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (firstpass == NULL) {
|
||||
if (use_first_pass) goto out;
|
||||
} else if (use_first_pass || try_first_pass) {
|
||||
|
||||
result = attempt_dce_login(pamh, dsd, &st,
|
||||
user, firstpass);
|
||||
|
||||
if (result == PAM_SUCCESS ||
|
||||
st == sec_login_s_acct_invalid ||
|
||||
use_first_pass) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the password from the user
|
||||
*/
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE pam_sm_auth prompting for password");
|
||||
|
||||
if (firstpass == NULL &&
|
||||
!(try_first_pass||try_mapped_pass||invalid_user))
|
||||
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 10,
|
||||
"Password: "));
|
||||
else
|
||||
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 11,
|
||||
"DCE Password: "));
|
||||
|
||||
num_msg = 1;
|
||||
|
||||
err = __pam_get_authtok(pamh, PAM_PROMPT, PAM_AUTHTOK,
|
||||
DCE_PASSWD_LENGTH,messages[0], &password);
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE __pam_get_authtok = %d", err);
|
||||
|
||||
if (err != PAM_SUCCESS) {
|
||||
result = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (password == NULL) {
|
||||
/* Need a password to proceed */
|
||||
result = PAM_AUTH_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (firstpass == NULL) {
|
||||
/* this is the first password, stash it away */
|
||||
pam_set_item(pamh, PAM_AUTHTOK, password);
|
||||
}
|
||||
|
||||
/* one last ditch attempt to login to DCE */
|
||||
|
||||
if (invalid_user || ignore)
|
||||
goto out;
|
||||
|
||||
result = attempt_dce_login(pamh, dsd, &st, user, password);
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
/* we had to prompt for DCE password, so attempt to */
|
||||
/* update mapping iff we got a good DCE password */
|
||||
|
||||
if (try_mapped_pass && result == PAM_SUCCESS && firstpass) {
|
||||
uid_t saved_uid;
|
||||
|
||||
saved_uid = geteuid();
|
||||
|
||||
if (saved_uid != pw_uid && seteuid(pw_uid) < 0) {
|
||||
syslog(LOG_ERR, "xfn_get_mapped_passwd: seteuid: %m");
|
||||
goto out;
|
||||
}
|
||||
|
||||
xfn_update_mapped_password(debug ? XFN_MAP_DEBUG : 0,
|
||||
user, DCE_XFN_PASS_ATTR, firstpass, password);
|
||||
|
||||
if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd seteuid restore: %m");
|
||||
/* XXX: what should we do here? */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
out:
|
||||
|
||||
if (ignore) {
|
||||
result = PAM_IGNORE;
|
||||
}
|
||||
|
||||
if (password != NULL)
|
||||
memset(password, 0, strlen(password));
|
||||
|
||||
if (invalid_user)
|
||||
result = PAM_USER_UNKNOWN;
|
||||
|
||||
if (dsd)
|
||||
dsd->auth_status = result;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
attempt_dce_login(
|
||||
void *pamh,
|
||||
dce_module_data_t *dsd,
|
||||
error_status_t *st,
|
||||
char *user,
|
||||
char *dce_pass)
|
||||
{
|
||||
sec_passwd_rec_t passwd_rec;
|
||||
boolean32 login_valid = 0;
|
||||
error_status_t set_st;
|
||||
|
||||
/* have to strdup password because the call clears it */
|
||||
passwd_rec.key.tagged_union.plain = (idl_char *) strdup(dce_pass);
|
||||
if (passwd_rec.key.tagged_union.plain == NULL) {
|
||||
return (PAM_BUF_ERR);
|
||||
}
|
||||
passwd_rec.key.key_type = sec_passwd_plain;
|
||||
passwd_rec.pepper = NULL;
|
||||
passwd_rec.version_number = sec_passwd_c_version_none;
|
||||
|
||||
login_valid = sec_login_valid_and_cert_ident(dsd->login_context,
|
||||
&passwd_rec, &dsd->reset_passwd, &dsd->auth_src, st);
|
||||
|
||||
if (dsd->debug) {
|
||||
dce_error_string_t text;
|
||||
|
||||
syslog(LOG_DEBUG, "sec_login_valid_and_cert_ident: %s",
|
||||
get_dce_error_message(*st, text));
|
||||
}
|
||||
|
||||
if (*st == sec_login_s_acct_invalid && dsd->warn) {
|
||||
char messages[1][PAM_MAX_MSG_SIZE];
|
||||
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 12, "Error: Your DCE Account has expired.\n"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
|
||||
}
|
||||
|
||||
/* the call to sec_login_valid_and_cert_ident already zeros */
|
||||
/* out the password, so we just free it */
|
||||
|
||||
free(passwd_rec.key.tagged_union.plain);
|
||||
|
||||
return (login_valid ? PAM_SUCCESS : PAM_AUTH_ERR);
|
||||
}
|
||||
|
||||
void
|
||||
dce_cleanup(
|
||||
pam_handle_t *pamh,
|
||||
void *data,
|
||||
int pam_status)
|
||||
{
|
||||
error_status_t st;
|
||||
dce_module_data_t *dsd = (dce_module_data_t *) data;
|
||||
int status;
|
||||
|
||||
if (dsd->debug) {
|
||||
syslog(LOG_DEBUG, "DCE dce_cleanup pam_sm_auth_status(%d)",
|
||||
dsd->auth_status);
|
||||
}
|
||||
|
||||
if (!dsd->login_context != sec_login_default_handle) {
|
||||
free(dsd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* if pam_end as PAM_SUCCESS, clean up based on value in */
|
||||
/* auth_status, otherwise just purge the context */
|
||||
|
||||
if (pam_status == PAM_SUCCESS) {
|
||||
pam_sec_login_free_context(dsd->auth_status,
|
||||
&dsd->login_context, &st);
|
||||
} else {
|
||||
sec_login_purge_context(&dsd->login_context, &st);
|
||||
if (dsd->debug) {
|
||||
dce_error_string_t text;
|
||||
syslog(LOG_DEBUG, "sec_login_purge_context: %s",
|
||||
get_dce_error_message(st, text));
|
||||
}
|
||||
}
|
||||
|
||||
free(dsd);
|
||||
}
|
||||
475
cde/lib/pam/pam_modules/dce/dce_password.c
Normal file
475
cde/lib/pam/pam_modules/dce/dce_password.c
Normal 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);
|
||||
}
|
||||
49
cde/lib/pam/pam_modules/dce/dce_session.c
Normal file
49
cde/lib/pam/pam_modules/dce/dce_session.c
Normal 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);
|
||||
}
|
||||
125
cde/lib/pam/pam_modules/dce/dce_setcred.c
Normal file
125
cde/lib/pam/pam_modules/dce/dce_setcred.c
Normal 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);
|
||||
}
|
||||
}
|
||||
22
cde/lib/pam/pam_modules/dce/libpam_cde.elist
Normal file
22
cde/lib/pam/pam_modules/dce/libpam_cde.elist
Normal 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
|
||||
71
cde/lib/pam/pam_modules/dce/pam_dce.msg
Normal file
71
cde/lib/pam/pam_modules/dce/pam_dce.msg
Normal 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
|
||||
|
||||
96
cde/lib/pam/pam_modules/dce/utils.c
Normal file
96
cde/lib/pam/pam_modules/dce/utils.c
Normal 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);
|
||||
}
|
||||
58
cde/lib/pam/pam_modules/dce/utils.h
Normal file
58
cde/lib/pam/pam_modules/dce/utils.h
Normal 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 */
|
||||
287
cde/lib/pam/pam_modules/dce/xfn_mapping.c
Normal file
287
cde/lib/pam/pam_modules/dce/xfn_mapping.c
Normal 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);
|
||||
}
|
||||
}
|
||||
46
cde/lib/pam/pam_modules/dce/xfn_mapping.h
Normal file
46
cde/lib/pam/pam_modules/dce/xfn_mapping.h
Normal 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
|
||||
32
cde/lib/pam/pam_modules/dial_auth/Imakefile
Normal file
32
cde/lib/pam/pam_modules/dial_auth/Imakefile
Normal 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()
|
||||
139
cde/lib/pam/pam_modules/dial_auth/dial_auth.c
Normal file
139
cde/lib/pam/pam_modules/dial_auth/dial_auth.c
Normal 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);
|
||||
}
|
||||
18
cde/lib/pam/pam_modules/dial_auth/libpam_dial_auth.elist
Normal file
18
cde/lib/pam/pam_modules/dial_auth/libpam_dial_auth.elist
Normal 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
|
||||
92
cde/lib/pam/pam_modules/dial_auth/unix_headers.h
Normal file
92
cde/lib/pam/pam_modules/dial_auth/unix_headers.h
Normal 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 */
|
||||
32
cde/lib/pam/pam_modules/rhosts_auth/Imakefile
Normal file
32
cde/lib/pam/pam_modules/rhosts_auth/Imakefile
Normal 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()
|
||||
18
cde/lib/pam/pam_modules/rhosts_auth/libpam_rhosts_auth.elist
Normal file
18
cde/lib/pam/pam_modules/rhosts_auth/libpam_rhosts_auth.elist
Normal 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
|
||||
83
cde/lib/pam/pam_modules/rhosts_auth/rhosts_auth.c
Normal file
83
cde/lib/pam/pam_modules/rhosts_auth/rhosts_auth.c
Normal 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);
|
||||
}
|
||||
69
cde/lib/pam/pam_modules/rhosts_auth/unix_headers.h
Normal file
69
cde/lib/pam/pam_modules/rhosts_auth/unix_headers.h
Normal 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 */
|
||||
46
cde/lib/pam/pam_modules/sample/Imakefile
Normal file
46
cde/lib/pam/pam_modules/sample/Imakefile
Normal 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()
|
||||
28
cde/lib/pam/pam_modules/sample/libpam_sample.elist
Normal file
28
cde/lib/pam/pam_modules/sample/libpam_sample.elist
Normal 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
|
||||
|
||||
127
cde/lib/pam/pam_modules/sample/sample_acct_mgmt.c
Normal file
127
cde/lib/pam/pam_modules/sample/sample_acct_mgmt.c
Normal 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);
|
||||
}
|
||||
168
cde/lib/pam/pam_modules/sample/sample_authenticate.c
Normal file
168
cde/lib/pam/pam_modules/sample/sample_authenticate.c
Normal 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);
|
||||
}
|
||||
21
cde/lib/pam/pam_modules/sample/sample_close_session.c
Normal file
21
cde/lib/pam/pam_modules/sample/sample_close_session.c
Normal 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);
|
||||
}
|
||||
21
cde/lib/pam/pam_modules/sample/sample_open_session.c
Normal file
21
cde/lib/pam/pam_modules/sample/sample_open_session.c
Normal 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);
|
||||
}
|
||||
27
cde/lib/pam/pam_modules/sample/sample_password.c
Normal file
27
cde/lib/pam/pam_modules/sample/sample_password.c
Normal 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);
|
||||
}
|
||||
32
cde/lib/pam/pam_modules/sample/sample_setcred.c
Normal file
32
cde/lib/pam/pam_modules/sample/sample_setcred.c
Normal 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);
|
||||
}
|
||||
174
cde/lib/pam/pam_modules/sample/sample_utils.c
Normal file
174
cde/lib/pam/pam_modules/sample/sample_utils.c
Normal 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);
|
||||
}
|
||||
51
cde/lib/pam/pam_modules/sample/sample_utils.h
Normal file
51
cde/lib/pam/pam_modules/sample/sample_utils.h
Normal 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 */
|
||||
66
cde/lib/pam/pam_modules/unix/Imakefile
Normal file
66
cde/lib/pam/pam_modules/unix/Imakefile
Normal 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()
|
||||
48
cde/lib/pam/pam_modules/unix/libpam_unix.elist
Normal file
48
cde/lib/pam/pam_modules/unix/libpam_unix.elist
Normal 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
|
||||
|
||||
414
cde/lib/pam/pam_modules/unix/npd_clnt.c
Normal file
414
cde/lib/pam/pam_modules/unix/npd_clnt.c
Normal 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, ®);
|
||||
}
|
||||
k = deskey->c;
|
||||
for (i = 0; i < 8; i++) {
|
||||
(void) sdiv(tmp, base, tmp, ®);
|
||||
*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 */
|
||||
213
cde/lib/pam/pam_modules/unix/pam_unix.msg
Normal file
213
cde/lib/pam/pam_modules/unix/pam_unix.msg
Normal 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:
|
||||
684
cde/lib/pam/pam_modules/unix/switch_utils.c
Normal file
684
cde/lib/pam/pam_modules/unix/switch_utils.c
Normal 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) */
|
||||
}
|
||||
313
cde/lib/pam/pam_modules/unix/unix_acct_mgmt.c
Normal file
313
cde/lib/pam/pam_modules/unix/unix_acct_mgmt.c
Normal 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);
|
||||
}
|
||||
355
cde/lib/pam/pam_modules/unix/unix_authenticate.c
Normal file
355
cde/lib/pam/pam_modules/unix/unix_authenticate.c
Normal 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);
|
||||
}
|
||||
}
|
||||
89
cde/lib/pam/pam_modules/unix/unix_chauthtok.c
Normal file
89
cde/lib/pam/pam_modules/unix/unix_chauthtok.c
Normal 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));
|
||||
}
|
||||
34
cde/lib/pam/pam_modules/unix/unix_close_session.c
Normal file
34
cde/lib/pam/pam_modules/unix/unix_close_session.c
Normal 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);
|
||||
}
|
||||
352
cde/lib/pam/pam_modules/unix/unix_get_authtokattr.c
Normal file
352
cde/lib/pam/pam_modules/unix/unix_get_authtokattr.c
Normal 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 */
|
||||
206
cde/lib/pam/pam_modules/unix/unix_headers.h
Normal file
206
cde/lib/pam/pam_modules/unix/unix_headers.h
Normal 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 */
|
||||
82
cde/lib/pam/pam_modules/unix/unix_open_session.c
Normal file
82
cde/lib/pam/pam_modules/unix/unix_open_session.c
Normal 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);
|
||||
}
|
||||
112
cde/lib/pam/pam_modules/unix/unix_set_authtokattr.c
Normal file
112
cde/lib/pam/pam_modules/unix/unix_set_authtokattr.c
Normal 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);
|
||||
}
|
||||
172
cde/lib/pam/pam_modules/unix/unix_setcred.c
Normal file
172
cde/lib/pam/pam_modules/unix/unix_setcred.c
Normal 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);
|
||||
}
|
||||
1519
cde/lib/pam/pam_modules/unix/unix_update_authtok.c
Normal file
1519
cde/lib/pam/pam_modules/unix/unix_update_authtok.c
Normal file
File diff suppressed because it is too large
Load Diff
637
cde/lib/pam/pam_modules/unix/unix_update_authtok_file.c
Normal file
637
cde/lib/pam/pam_modules/unix/unix_update_authtok_file.c
Normal 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);
|
||||
}
|
||||
326
cde/lib/pam/pam_modules/unix/unix_update_authtok_nis.c
Normal file
326
cde/lib/pam/pam_modules/unix/unix_update_authtok_nis.c
Normal 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 */
|
||||
1049
cde/lib/pam/pam_modules/unix/unix_update_authtok_nisplus.c
Normal file
1049
cde/lib/pam/pam_modules/unix/unix_update_authtok_nisplus.c
Normal file
File diff suppressed because it is too large
Load Diff
974
cde/lib/pam/pam_modules/unix/unix_utils.c
Normal file
974
cde/lib/pam/pam_modules/unix/unix_utils.c
Normal 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);
|
||||
}
|
||||
}
|
||||
68
cde/lib/pam/pam_modules/unix/yppasswdxdr.c
Normal file
68
cde/lib/pam/pam_modules/unix/yppasswdxdr.c
Normal 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 */
|
||||
Reference in New Issue
Block a user