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

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

21
cde/lib/pam/Imakefile Normal file
View File

@@ -0,0 +1,21 @@
/* $XConsortium: Imakefile /main/3 1996/04/21 19:12:55 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 = libpam pam_modules
LINTSUBDIRS = libpam pam_modules
MakeSubdirs($(SUBDIRS))
DependSubdirs($(SUBDIRS))
MakeLintLibSubdirs($(LINTLIBSUBDIRS))
LintSubdirs($(LINTSUBDIRS))

51052
cde/lib/pam/doc/pam.admin.mif Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
#ident "@(#)login.dfl 1.8 96/02/02 SMI" /* SVr4.0 1.1.1.1 */
# Set the TZ environment variable of the shell.
#
#TIMEZONE=EST5EDT
# Set the HZ environment variable of the shell.
#
HZ=100
# ULIMIT sets the file size limit for the login. Units are disk blocks.
# The default of zero means no limit.
#
#ULIMIT=0
# If CONSOLE is set, root can only login on that device.
# Comment this line out to allow remote login by root.
#
CONSOLE=/dev/console
# PASSREQ determines if login requires a password.
#
PASSREQ=YES
# ALTSHELL determines if the SHELL environment variable should be set
#
ALTSHELL=YES
# PATH sets the initial shell PATH variable
#
#PATH=/usr/bin:
# SUPATH sets the initial shell PATH variable for root
#
#SUPATH=/usr/sbin:/usr/bin
# TIMEOUT sets the number of seconds (between 0 and 900) to wait before
# abandoning a login session.
#
#TIMEOUT=300
# UMASK sets the initial shell file creation mode mask. See umask(1).
#
#UMASK=022
# SYSLOG determines whether the syslog(3) LOG_AUTH facility should be used
# to log all root logins at level LOG_NOTICE and multiple failed login
# attempts at LOG_CRIT.
#
SYSLOG=YES
# Set the number of weeks that the account is allowed to be
# idle before the system considers that your password has
# automatically expired
#
#IDLEWEEKS=

View File

@@ -0,0 +1,22 @@
#
# Copyright 1993, by Sun Microsystems, Inc.
#
#ident "@(#)logindevperm 1.1 93/08/16 SMI"
#
# /etc/logindevperm - login-based device permissions
#
# If the user is logging in on a device specified in the "console" field
# of any entry in this file, the owner/group of the devices listed in the
# "devices" field will be set to that of the user. Similarly, the mode
# will be set to the mode specified in the "mode" field.
#
# "devices" is a colon-separated list of device names. A device name
# ending in "/*", such as "/dev/fbs/*", specifies all entries (except "."
# and "..") in a directory. A '#' begins a comment and may appear
# anywhere in an entry.
#
# console mode devices
#
/dev/console 0600 /dev/mouse:/dev/kbd
/dev/console 0600 /dev/sound/* # audio devices
/dev/console 0600 /dev/fbs/* # frame buffers

View File

@@ -0,0 +1,36 @@
/* $XConsortium: Imakefile /main/4 1996/04/21 19:12:58 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
#define SoRev SOPAMREV
#define IncSubdir security
#include <Threads.tmpl>
HEADERS = pam_appl.h pam_modules.h
SRCS = pam_framework.c pam_framework_utils.c
OBJS = pam_framework.o pam_framework_utils.o
#ifdef SharedPamReqs
REQUIREDLIBS = SharedPamReqs
#endif
DEFINES = -DOPT_INCLUDE_XTHREADS_H
#include <Library.tmpl>
DependTarget()

View File

@@ -0,0 +1,35 @@
/****************************************************************************
* Export list for libpam.
* This list *must* be updated whenever a change is made to the libpam 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.elist /main/1 1999/09/08 15:03:20 mgreess $
*****************************************************************************/
public pam_start
public pam_end
public pam_set_item
public pam_get_item
public pam_get_user
public pam_set_data
public pam_get_data
public pam_strerror
public pam_authenticate
public pam_acct_mgmt
public pam_open_session
public pam_close_session
public pam_setcred
public pam_chauthtok
private __pam_free_resp
private __pam_display_msg
private __pam_get_input
private __pam_get_authtok
private __pam_get_i18n_msg

View File

@@ -0,0 +1,148 @@
$ $XConsortium: libpam.msg /main/3 1996/07/24 19:03:44 drk $
$ *************************************<+>*************************************
$ *****************************************************************************
$ **
$ ** File: libpam.msg
$ **
$ ** Project: libpam
$ **
$ ** Description:
$ ** -----------
$ ** This file is the source for the message catalog for libpam library.
$ **
$ **
$ *****************************************************************************
$ **
$ ** (c) Copyright 1995 Sun Microsystems, Inc.
$ ** (c) Copyright 1995 Hewlett-Packard Company
$ ** 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 2
$ PAM_SUCCESS
1 Success
$ PAM_OPEN_ERR
2 Dlopen failure
$ PAM_SYMBOL_ERR
3 Symbol not found
$ PAM_SERVICE_ERR
4 Error in underlying service module
$ PAM_SYSTEM_ERR
5 System error
$ PAM_BUF_ERR
6 Memory buffer error
$ PAM_CONV_ERR
7 Conversation failure
$ PAM_PERM_DENIED
8 Permission denied
$ PAM_MAXTRIES
9 Maximum number of attempts exceeded
$ PAM_AUTH_ERR
10 Authentication failed
$ PAM_AUTHTOKEN_REQD
11 Get new authentication token
$ PAM_CRED_INSUFFICIENT
12 Insufficient credentials
$ PAM_AUTHINFO_UNAVAIL
13 Can not retrieve authentication info
$ PAM_USER_UNKNOWN
14 No account present for user
$ PAM_CRED_UNAVAIL
15 Can not retrieve user credentials
$ PAM_CRED_EXPIRED
16 User credentials have expired
$ PAM_CRED_ERR
17 Failure setting user credentials
$ PAM_ACCT_EXPIRED
18 User account has expired
$ PAM_AUTHTOK_EXPIRED
19 User password has expired
$ PAM_SESSION_ERR
20 Can not make/remove entry for session
$ PAM_AUTHTOK_ERR
21 Authentication token manipulation error
$ PAM_AUTHTOK_RECOVERY_ERR
22 Authentication token can not be recovered
$ PAM_AUTHTOK_LOCK_BUSY
23 Authentication token lock busy
$ PAM_AUTHTOK_DISABLE_AGING
24 Authentication token aging disabled
$ PAM_NO_MODULE_DATA
25 Module specific data not found
$ PAM_IGNORE
26 Ignore module
$ PAM_ABORT
27 General PAM failure
$ Unknown Error
28 Unknown Error
$ Following messages are from pam_framework_util.c
29 pam_sm_setcred: %s
30 setproc_cred: %s
31 password:
$ from pam_framework.c, default prompt
32 Please enter user name:

View File

@@ -0,0 +1,27 @@
# $TOG: pam.conf /main/5 1999/02/04 16:16:12 mgreess $
#
# PAM configuration
#
# Authentication management
#
dtlogin auth required /usr/dt/lib/security/pam_unix.so.2.1
other auth required /usr/dt/lib/security/pam_unix.so.2.1
#rsh auth required /usr/dt/lib/security/pam_rhosts_auth.so.1
#rlogin auth sufficient /usr/dt/lib/security/pam_rhosts_auth.so.1
#rlogin auth required /usr/dt/lib/security/pam_rhosts_auth.so.1
#
# Account management
#
dtlogin account required /usr/dt/lib/security/pam_unix.so.2.1
other account required /usr/dt/lib/security/pam_unix.so.2.1
#
# Session management
#
other session required /usr/dt/lib/security/pam_unix.so.2.1
#
# Password management
#
other password required /usr/dt/lib/security/pam_unix.so.2.1

View File

@@ -0,0 +1,322 @@
/* $XConsortium: pam_appl.h /main/5 1996/05/09 04:24:28 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _PAM_APPL_H
#define _PAM_APPL_H
#pragma ident "@(#)pam_appl.h 1.45 96/02/15 SMI" /* PAM 2.6 */
#include <pwd.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Generic PAM errors */
#define PAM_SUCCESS 0 /* Normal function return */
#define PAM_OPEN_ERR 1 /* Dlopen failure */
#define PAM_SYMBOL_ERR 2 /* Symbol not found */
#define PAM_SERVICE_ERR 3 /* Error in underlying service module */
#define PAM_SYSTEM_ERR 4 /* System error */
#define PAM_BUF_ERR 5 /* Memory buffer error */
#define PAM_CONV_ERR 6 /* Conversation failure */
#define PAM_PERM_DENIED 7 /* Permission denied */
/* Errors returned by pam_authenticate, pam_acct_mgmt(), and pam_setcred() */
#define PAM_MAXTRIES 8 /* Maximum number of tries exceeded */
#define PAM_AUTH_ERR 9 /* Authentication failure */
#define PAM_NEW_AUTHTOK_REQD 10 /* Get new auth token from the user */
#define PAM_AUTHTOKEN_REQD PAM_NEW_AUTHTOK_REQD /* backward compatible */
#define PAM_CRED_INSUFFICIENT 11 /* can not access auth data b/c */
/* of insufficient credentials */
#define PAM_AUTHINFO_UNAVAIL 12 /* Can not retrieve auth information */
#define PAM_USER_UNKNOWN 13 /* No account present for user */
/* Errors returned by pam_setcred() */
#define PAM_CRED_UNAVAIL 14 /* can not retrieve user credentials */
#define PAM_CRED_EXPIRED 15 /* user credentials expired */
#define PAM_CRED_ERR 16 /* failure setting user credentials */
/* Errors returned by pam_acct_mgmt() */
#define PAM_ACCT_EXPIRED 17 /* user account has expired */
#define PAM_AUTHTOK_EXPIRED 18 /* Password expired and no longer */
/* usable */
/* Errors returned by pam_open/close_session() */
#define PAM_SESSION_ERR 19 /* can not make/remove entry for */
/* specified session */
/* Errors returned by pam_chauthtok() */
#define PAM_AUTHTOK_ERR 20 /* Authentication token */
/* manipulation error */
#define PAM_AUTHTOK_RECOVERY_ERR 21 /* Old authentication token */
/* cannot be recovered */
#define PAM_AUTHTOK_LOCK_BUSY 22 /* Authentication token */
/* lock busy */
#define PAM_AUTHTOK_DISABLE_AGING 23 /* Authentication token aging */
/* is disabled */
/* Errors returned by pam_get_data */
#define PAM_NO_MODULE_DATA 24 /* module data not found */
/* Errors returned by modules */
#define PAM_IGNORE 25 /* ignore module */
#define PAM_ABORT 26 /* General PAM failure */
#define PAM_TRY_AGAIN 27 /* Unable to update password */
/* Try again another time */
/*
* XXX: Make sure that PAM_TOTAL_ERRNUM = 28 in pam_impl.h
*/
/*
* structure pam_message is used to pass prompt, error message,
* or any text information from scheme to application/user.
*/
struct pam_message {
int msg_style; /* Msg_style - see below */
char *msg; /* Message string */
};
/*
* msg_style defines the interaction style between the
* scheme and the application.
*/
#define PAM_PROMPT_ECHO_OFF 1 /* Echo off when getting response */
#define PAM_PROMPT_ECHO_ON 2 /* Echo on when getting response */
#define PAM_ERROR_MSG 3 /* Error message */
#define PAM_TEXT_INFO 4 /* Textual information */
/* max # of authentication token attributes */
#define PAM_MAX_NUM_ATTR 10
/* max size (in chars) of an authentication token attribute */
#define PAM_MAX_ATTR_SIZE 80
/*
* max # of messages passed to the application through the
* conversation function call
*/
#define PAM_MAX_NUM_MSG 32
/*
* max size (in chars) of each messages passed to the application
* through the conversation function call
*/
#define PAM_MAX_MSG_SIZE 512
/*
* max size (in chars) of each response passed from the application
* through the conversation function call
*/
#define PAM_MAX_RESP_SIZE 512
/*
* structure pam_response is used by the scheme to get the user's
* response back from the application/user.
*/
struct pam_response {
char *resp; /* Response string */
int resp_retcode; /* Return code - for future use */
};
/*
* structure pam_conv is used by authentication applications for passing
* call back function pointers and application data pointers to the scheme
*/
struct pam_conv {
int (*conv)(int, struct pam_message **,
struct pam_response **, void *);
void *appdata_ptr; /* Application data ptr */
};
/* the pam handle */
typedef struct pam_handle pam_handle_t;
/*
* pam_start() is called to initiate an authentication exchange
* with PAM.
*/
extern int
pam_start(
const char *service_name, /* Service Name */
const char *user, /* User Name */
const struct pam_conv *pam_conv, /* Conversation structure */
pam_handle_t **pamh /* Address to store handle */
);
/*
* pam_end() is called to end an authentication exchange with PAM.
*/
extern int
pam_end(
pam_handle_t *pamh, /* handle from pam_start() */
int status /* the final status value that */
/* gets passed to cleanup functions */
);
/*
* pam_set_item is called to store an object in PAM handle.
*/
extern int
pam_set_item(
pam_handle_t *pamh, /* PAM handle */
int item_type, /* Type of object - see below */
const void *item /* Address of place to put pointer */
/* to object */
);
/*
* pam_get_item is called to retrieve an object from the static data area
*/
extern int
pam_get_item(
const pam_handle_t *pamh, /* PAM handle */
int item_type, /* Type of object - see below */
void ** item /* Address of place to put pointer */
/* to object */
);
/* Items supported by pam_[sg]et_item() calls */
#define PAM_SERVICE 1 /* The program/service name */
#define PAM_USER 2 /* The user name */
#define PAM_TTY 3 /* The tty name */
#define PAM_RHOST 4 /* The remote host name */
#define PAM_CONV 5 /* The conversation structure */
#define PAM_AUTHTOK 6 /* The authentication token */
#define PAM_OLDAUTHTOK 7 /* Old authentication token */
#define PAM_RUSER 8 /* The remote user name */
#define PAM_USER_PROMPT 9 /* The user prompt */
/*
* pam_get_user is called to retrieve the user name (PAM_USER). If PAM_USER
* is not set then this call will prompt for the user name using the
* conversation function. This function should only be used by modules, not
* applications.
*/
extern int
pam_get_user(
pam_handle_t *pamh, /* PAM handle */
char **user, /* User Name */
const char *prompt /* Prompt */
);
/*
* pam_set_data is used to create module specific data, and
* to optionally add a cleanup handler that gets called by pam_end.
*
*/
extern int
pam_set_data(
pam_handle_t *pamh, /* PAM handle */
const char *module_data_name, /* unique module data name */
const void *data, /* the module specific data */
void (*cleanup)(pam_handle_t *pamh, void *data, int pam_end_status)
);
/*
* get module specific data set by pam_set_scheme_data.
* returns PAM_NO_MODULE_DATA if specified module data was not found.
*/
extern int
pam_get_data(
const pam_handle_t *pamh,
const char *module_data_name,
void **data
);
/*
* PAM equivalent to strerror();
*/
extern char *
pam_strerror(
pam_handle_t *pamh, /* pam handle */
int errnum /* error number */
);
/* general flag for pam_* functions */
#define PAM_SILENT 0x80000000
/*
* pam_authenticate is called to authenticate the current user.
*/
extern int
pam_authenticate(
pam_handle_t *pamh,
int flags
);
/*
* Flags for pam_authenticate
*/
#define PAM_DISALLOW_NULL_AUTHTOK 2 /* The password must be non-null */
/*
* pam_acct_mgmt is called to perform account management processing
*/
extern int
pam_acct_mgmt(
pam_handle_t *pamh,
int flags
);
/*
* pam_open_session is called to note the initiation of new session in the
* appropriate administrative data bases.
*/
extern int
pam_open_session(
pam_handle_t *pamh,
int flags
);
/*
* pam_close_session records the termination of a session.
*/
extern int
pam_close_session(
pam_handle_t *pamh,
int flags
);
/* pam_setcred is called to set the credentials of the current user */
extern int
pam_setcred(
pam_handle_t *pamh,
int flags
);
/* flags for pam_setcred() */
#define PAM_ESTABLISH_CRED 1 /* set scheme specific user id */
#define PAM_DELETE_CRED 2 /* unset scheme specific user id */
#define PAM_REINITIALIZE_CRED 4 /* reinitialize user credentials */
/* (after a password has changed */
#define PAM_REFRESH_CRED 8 /* extend lifetime of credentials */
/* pam_chauthtok is called to change authentication token */
extern int
pam_chauthtok(
pam_handle_t *pamh,
int flags
);
/*
* Be careful - there are flags defined for pam_sm_chauthtok() in
* pam_modules.h also.
*/
#define PAM_CHANGE_EXPIRED_AUTHTOK 4 /* update expired passwords only */
#ifdef __cplusplus
}
#endif
#endif /* _PAM_APPL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,866 @@
/* $XConsortium: pam_framework_utils.c /main/8 1996/11/20 11:07:39 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "@(#)pam_framework_utils.c 1.37 95/12/20 SMI" /* */
#include <syslog.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utmpx.h>
#include <string.h>
#include <malloc.h>
#include <unistd.h>
#include <libintl.h>
#include <synch.h>
#include <shadow.h>
#include <locale.h>
#include <stdio.h>
#include <nl_types.h>
#include <X11/Xthreads.h>
#include <X11/Xos.h>
#include <errno.h>
#ifdef X_NOT_STDC_ENV
extern int errno;
#endif
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include "pam_impl.h"
#include "pam_loc.h"
static void __pam_msg_destroy(void *);
static char * __pam_thread_backup(char *);
static int __pam_input_output(pam_handle_t *, int, int, char [][], void *,
struct pam_response **);
/*
* __pam_free_resp():
* free storage for responses used in the call back "pam_conv" functions
*/
void
__pam_free_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);
}
}
/*
* __pam_display_msg():
* display message by calling the call back functions
* provided by the application through "pam_conv" structure
*/
int
__pam_display_msg(pamh, msg_style, num_msg, messages, conv_apdp)
pam_handle_t *pamh;
int msg_style;
int num_msg;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
void *conv_apdp;
{
struct pam_response *ret_respp = NULL;
return (__pam_input_output(pamh, msg_style, num_msg, messages,
conv_apdp, &ret_respp));
}
int
__pam_get_input(pamh, msg_style, num_msg, messages, conv_apdp, ret_respp)
pam_handle_t *pamh;
int msg_style;
int num_msg;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
void *conv_apdp;
struct pam_response **ret_respp;
{
return (__pam_input_output(pamh, msg_style, num_msg, messages,
conv_apdp, ret_respp));
}
static int
__pam_input_output(pamh, msg_style, num_msg, messages, conv_apdp, ret_respp)
pam_handle_t *pamh;
int msg_style;
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;
struct pam_conv *pam_convp;
if ((retcode = pam_get_item(pamh, PAM_CONV, (void **)&pam_convp))
!= PAM_SUCCESS) {
return (retcode);
}
if (pam_convp == NULL)
return (PAM_SYSTEM_ERR);
i = 0;
k = num_msg;
msg = (struct pam_message *)calloc(num_msg,
sizeof (struct pam_message));
if (msg == NULL) {
return (PAM_BUF_ERR);
}
m = msg;
while (k--) {
/*
* fill out the message structure to display prompt message
*/
m->msg_style = msg_style;
m->msg = messages[i];
m++;
i++;
}
/*
* Call conv function to display the prompt.
*/
retcode = (pam_convp->conv)(num_msg, &msg, ret_respp, conv_apdp);
return (retcode);
}
/*
* __pam_get_authtok()
* retrieves a password of length "len" from the pam handle
* (pam_get_item) or from the input stream (pam_get_input).
*
* This function allocates memory for the new authtok.
* Applications calling this function are responsible for
* freeing this memory.
*
* If "source" is
* PAM_HANDLE
* and "type" is:
* PAM_AUTHTOK - password is taken from pam handle (PAM_AUTHTOK)
* PAM_OLDAUTHTOK - password is taken from pam handle (PAM_OLDAUTHTOK)
*
* If "source" is
* PAM_PROMPT
* and "type" is:
* 0: Prompt for new passwd, do not even attempt
* to store it in the pam handle.
* PAM_AUTHTOK: Prompt for new passwd, store in pam handle as
* PAM_AUTHTOK item if this value is not already set.
* PAM_OLDAUTHTOK: Prompt for new passwd, store in pam handle as
* PAM_OLDAUTHTOK item if this value is not
* already set.
*/
int
__pam_get_authtok(pam_handle_t *pamh, int source, int type, int len,
char *prompt, char **authtok)
{
int error = PAM_SYSTEM_ERR;
char *new_password = NULL;
struct pam_response *ret_resp = (struct pam_response *)0;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
char *backup_prompt = PAM_MSG(pamh, 31, "password: ");
if (len >= PAM_MAX_RESP_SIZE) {
syslog(LOG_ERR,
"__pam_get_authtok: requested passwd length too long");
return (PAM_BUF_ERR);
}
if ((*authtok = (char *)calloc(len + 1, sizeof (char))) == NULL) {
*authtok = NULL;
return (PAM_BUF_ERR);
}
if (prompt == NULL)
prompt = backup_prompt;
switch (source) {
case PAM_HANDLE:
/* get password from pam handle item list */
switch (type) {
case PAM_AUTHTOK:
case PAM_OLDAUTHTOK:
if ((error = pam_get_item(pamh, type,
(void **)&new_password)) != PAM_SUCCESS) {
free(*authtok);
*authtok = NULL;
return (error);
}
if (new_password == NULL || new_password[0] == '\0') {
free(*authtok);
*authtok = NULL;
} else {
strncpy(*authtok, new_password, len);
(*authtok)[len] = '\0';
}
break;
default:
syslog(LOG_ERR,
"__pam_get_authtok() invalid type: %d", type);
free(*authtok);
*authtok = NULL;
return (PAM_SYMBOL_ERR);
}
break;
case PAM_PROMPT:
/*
* Prompt for new password and save in pam handle item list
* if the that item is not already set.
*/
strncpy(messages[0], prompt, sizeof (messages[0]));
if ((error = __pam_get_input(pamh, PAM_PROMPT_ECHO_OFF,
1, messages, NULL, &ret_resp)) != PAM_SUCCESS) {
free(*authtok);
*authtok = NULL;
return (error);
}
/* save the new password if this item was NULL */
if (type) {
pam_get_item(pamh, type, (void **)&new_password);
if (new_password == NULL)
pam_set_item(pamh, type, ret_resp->resp);
}
strncpy(*authtok, ret_resp->resp, len);
(*authtok)[len] = '\0';
memset(ret_resp->resp, 0, strlen(ret_resp->resp));
__pam_free_resp(1, ret_resp);
break;
default:
syslog(LOG_ERR,
"__pam_get_authtok() invalid source: %d", source);
free(*authtok);
*authtok = NULL;
return (PAM_SYMBOL_ERR);
}
return (PAM_SUCCESS);
}
#if !defined(NL_CAT_LOCALE)
#define NL_CAT_LOCALE 0
#endif
typedef struct _pam_msg_data {
nl_catd fd;
} _pam_msg_data;
static void
__pam_msg_cleanup(
pam_handle_t *pamh,
void *data,
int pam_status)
{
_pam_msg_data *msg_data = (_pam_msg_data *) data;
catclose(msg_data->fd);
free(msg_data);
}
static void
__pam_msg_destroy(void *tsd)
{
if (tsd)
free((char *)tsd);
}
static char *
__pam_thread_backup(char *msg)
{
char *data_buffer = 0;
static xmutex_rec thread_lock = XMUTEX_INITIALIZER;
static xthread_key_t thread_key = 0;
static char fallback_buff[PAM_MAX_MSG_SIZE];
memset(fallback_buff, 0, sizeof (fallback_buff));
if (thread_key == 0) {
xmutex_lock(&thread_lock);
if (thread_key == 0)
xthread_key_create(&thread_key, __pam_msg_destroy);
xmutex_unlock(&thread_lock);
if (thread_key == 0) {
strncat(fallback_buff, msg, PAM_MAX_MSG_SIZE-1);
return (fallback_buff);
}
}
xthread_get_specific(thread_key, (void **)&data_buffer);
if (data_buffer == (char *)NULL) {
if ((data_buffer = (char *)calloc(PAM_MAX_MSG_SIZE,
sizeof (char))) == NULL) {
/* what else can i do? */
strncat(fallback_buff, msg, PAM_MAX_MSG_SIZE-1);
return (fallback_buff);
}
xthread_set_specific(thread_key, (void *)data_buffer);
}
/*
* Memset the buffer because we might have stale data from
* a previous thr_setspecific() call.
*/
memset(data_buffer, 0, PAM_MAX_MSG_SIZE);
strncat(data_buffer, msg, PAM_MAX_MSG_SIZE-1);
return (data_buffer);
}
/*
*
* Function: __pam_get_i18n_msg
*
*
* Parameters:
*
* int set - The message catalog set number.
*
* int n - The message number.
*
* char *s - The default message if the message is not
* retrieved from a message catalog.
*
* Returns: the string for set 'set' and number 'n'.
*
*/
char *
__pam_get_i18n_msg(
pam_handle_t *pamh,
char *filename,
int set,
int n,
char *s)
{
char *msg;
char *output_msg;
nl_catd nlmsg_fd;
/*
* If pam handle was supplied,
* look for stored message file descriptor.
*/
if (pamh != NULL) {
_pam_msg_data *msg_data;
int status = pam_get_data(pamh, filename, (void**) &msg_data);
if (status == PAM_SUCCESS) {
return (catgets(msg_data->fd, set, n, s));
}
if (status == PAM_NO_MODULE_DATA) {
/*
* No message file descriptor found, make and store one.
*/
nlmsg_fd = catopen(filename, NL_CAT_LOCALE);
msg = catgets(nlmsg_fd, set, n, s);
if ((msg_data = (_pam_msg_data *)
calloc(1, sizeof (_pam_msg_data))) == NULL) {
output_msg = __pam_thread_backup(msg);
catclose(nlmsg_fd);
return (output_msg);
}
msg_data->fd = nlmsg_fd;
pam_set_data(pamh, filename, msg_data, __pam_msg_cleanup);
return (msg);
}
}
/* NULL pamh */
nlmsg_fd = catopen(filename, NL_CAT_LOCALE);
msg = catgets(nlmsg_fd, set, n, s);
output_msg = __pam_thread_backup(msg);
catclose(nlmsg_fd);
return (output_msg);
}
#ifdef PAM_MAYBE_WILL_BE_USED_LATER
extern int pam_debug;
/* Errors returned by __setutmp_mgmt/__reset_utmp_mgmt() */
#define __NOENTRY 27 /* No entry found */
#define __ENTRYFAIL 28 /* Couldn't make/remove the entry */
/* Errors returned by __setproc_cred() */
#define __BAD_GID 29 /* Invalid Group ID */
#define __INITGROUP_FAIL 30 /* Initialization of group IDs failed */
#define __BAD_UID 31 /* Invaid User ID */
#define __SETGROUP_FAIL 32 /* Set of group IDs failed */
#define INIT_PROC_PID 1
#define PAMTXD "SUNW_OST_SYSOSPAM"
#define SCPYN(a, b) (void) strncpy(a, b, sizeof (a))
/* utility function to do UTMP/WTMP management */
int
__setutmp_mgmt(
char *user, /* user */
char *ttyn, /* ttyn */
char *rhost, /* remote hostname */
int flags, /* Flags - see below */
int type, /* type of utmp/wtmp entry */
char id[] /* 4 byte id field for utmp */
);
/* Flags for the flags field */
#define __UPDATE_ENTRY 1 /* Update an existing entry */
#define __NOLOG 2 /* Don't log the new session */
#define __LOGIN 4 /* login type entry (sigh...) */
/*
* __reset_utmp_mgmt is a utility function which terminates UTMP/WTMP mgmt
*/
int
__reset_utmp_mgmt(
char **user, /* user */
char **ttyn, /* tty name */
char **rhost, /* remote host */
int flags, /* flags - see below */
int status, /* logout process status */
char id[] /* logout ut_id (/etc/inittab id) */
);
/* flags for the flags field */
#define __NOOP 8 /* No utmp action desired */
/* __setproc_cred is a utility function to set process credentials */
int
__setproc_cred(
char *user, /* user */
int flags, /* flags - see below */
uid_t uid, /* User ID to set for this process */
gid_t gid, /* Group ID */
int ngroups, /* Number of groups */
gid_t *grouplist /* Group list */
);
/* flags indicates specific set credential actions */
#define __INITGROUPS 0x00000001 /* Request to initgroups() */
#define __SETGROUPS 0x00000002 /* Request to setgroups() */
#define __SETEGID 0x00000004 /* Set effective gid only */
#define __SETGID 0x00000008 /* Set real gid */
#define __SETEUID 0x00000010 /* Set effective uid only */
#define __SETUID 0x00000020 /* Set real uid */
#define __SETEID (__SETEGID|__SETEUID) /* Set effective ids only */
#define __SETRID (__SETGID|__SETUID) /* Set real ids */
/*
* __setutmp_mgmt - A utility function used to do UTMP/WTMP management.
* This function is NOT meant to be part of the official
* PAM API, and only serves as a convenience function.
*
* "user" is the current username.
* "ttyn" is the tty name.
* "rhost" is the remote hostname.
* The following flags may be set in the "flags" field:
*
* __UPDATE_ENTRY No new entry will be created if utmp
* entry not found - return __NOENTRY
* __NOLOG Generate a wtmp/wtmpx entry only
* __LOGIN Caller is a login application - update
* utmp entry accordingly
*
* "type" is used to indicate the type of utmp/wtmp entry written
* (see also utmp.h and utmpx.h)
* "id is an optional application-defined 4 byte array that represents
* the /sbin/inittab id (created by the process that puts an entry in
* utmp).
*
* Upon successful completion, PAM_SUCCESS is returned.
* Error values may include:
*
* __NOENTRY An entry for the specified process was not found
* __ENTRYFAIL Could not make/remove entry for specified process
*/
int
__setutmp_mgmt(
char *user,
char *ttyn,
char *rhost,
int flags,
int type,
char id[])
{
int tmplen;
struct utmpx *u = (struct utmpx *)0;
struct utmpx utmp;
char *ttyntail;
int err = PAM_SUCCESS;
if (pam_debug)
syslog(LOG_DEBUG, "pam_open_session(%d)\n", type);
(void) memset((void *)&utmp, 0, sizeof (utmp));
(void) time(&utmp.ut_tv.tv_sec);
utmp.ut_pid = getpid();
if (rhost != NULL && rhost[0] != '\0') {
(void) strcpy(utmp.ut_host, rhost);
tmplen = strlen(rhost) + 1;
if (tmplen < sizeof (utmp.ut_host))
utmp.ut_syslen = tmplen;
else
utmp.ut_syslen = sizeof (utmp.ut_host);
} else {
(void) memset(utmp.ut_host, 0, sizeof (utmp.ut_host));
utmp.ut_syslen = 0;
}
(void) strcpy(utmp.ut_user, user);
/*
* Copy in the name of the tty minus the "/dev/" if a /dev/ is
* in the path name.
*/
if (!(flags&__LOGIN))
SCPYN(utmp.ut_line, ttyn);
ttyntail = ttyn;
utmp.ut_type = type;
if (id != NULL)
(void) memcpy(utmp.ut_id, id, sizeof (utmp.ut_id));
if ((flags & __NOLOG) == __NOLOG) {
updwtmpx(WTMPX_FILE, &utmp);
} else {
/*
* Go through each entry one by one, looking only at INIT,
* LOGIN or USER Processes. Use the entry found if flags == 0
* and the line name matches, or if the process ID matches if
* the UPDATE_ENTRY flag is set. The UPDATE_ENTRY flag is
* mainly for login which normally only wants to update an
* entry if the pid fields matches.
*/
if (flags & __LOGIN) {
while ((u = getutxent()) != NULL) {
if ((u->ut_type == INIT_PROCESS ||
u->ut_type == LOGIN_PROCESS ||
u->ut_type == USER_PROCESS) &&
((flags == __LOGIN && ttyn != NULL &&
strncmp(u->ut_line, ttyntail,
sizeof (u->ut_line)) == 0) ||
u->ut_pid == utmp.ut_pid)) {
if (ttyn)
SCPYN(utmp.ut_line,
(ttyn + sizeof ("/dev/") - 1));
if (id == NULL) {
(void) memcpy(utmp.ut_id, u->ut_id,
sizeof (utmp.ut_id));
}
(void) pututxline(&utmp);
break;
}
} /* end while */
endutxent(); /* Close utmp file */
}
if (u == (struct utmpx *)NULL) {
/* audit_login_main11(); */
if (flags & __UPDATE_ENTRY)
err = __NOENTRY;
else
(void) makeutx(&utmp);
}
else
updwtmpx(WTMPX_FILE, &utmp);
}
return (err);
}
/*
* __reset_utmp_mgmt A utility function used to terminate UTMP/WTMP mgmt.
* This function is NOT meant to be part of the official
* PAM API, and only serves as a convenience function.
*
* "user" is the current username.
* "ttyn" is the tty name.
* "rhost" is the remote hostname.
* The following flags may be set in the "flags" field:
*
* __NOLOG Write a wtmp/wtmpx entry only
* __NOOP Ignore utmp/wtmp processing
*
* "status" is the logout process status.
* "id is an optional application-defined 4 byte array that represents
* the /sbin/inittab id (created by the process that puts an entry in
* utmp).
*
* Upon successful completion, PAM_SUCCESS is returned.
* Error values may include:
*
* __NOENTRY An entry for the specified process was not found
* __ENTRYFAIL Could not make/remove entry for specified process
*/
int
__reset_utmp_mgmt(
char **user,
char **ttyn,
char **rhost,
int flags,
int status,
char id[])
{
struct utmpx *up;
struct utmpx ut;
int err = 0;
int pid;
if (pam_debug)
syslog(LOG_DEBUG, "pam_close_session()\n");
/*
* do we want to do any utmp processing?
*/
if (flags & __NOOP) {
return (PAM_SUCCESS);
}
pid = (int) getpid();
if ((flags & __NOLOG) == __NOLOG) { /* only write to wtmp files */
/* clear utmpx entry */
(void) memset((char *)&ut, 0, sizeof (ut));
if (id != NULL)
(void) memcpy(ut.ut_id, id, sizeof (ut.ut_id));
if (*ttyn != NULL && **ttyn != '\0') {
if (strstr(*ttyn, "/dev/") != NULL)
(void) strncpy(ut.ut_line, (*ttyn+sizeof ("/dev/")-1),
sizeof (ut.ut_line));
else
(void) strncpy(ut.ut_line, *ttyn,
sizeof (ut.ut_line));
}
ut.ut_pid = pid;
ut.ut_type = DEAD_PROCESS;
ut.ut_exit.e_termination = 0;
ut.ut_exit.e_exit = 0;
ut.ut_syslen = 1;
(void) gettimeofday(&ut.ut_tv, NULL);
updwtmpx(WTMPX_FILE, &ut);
return (PAM_SUCCESS);
} else {
setutxent();
while (up = getutxent()) {
if (up->ut_pid == pid) {
if (up->ut_type == DEAD_PROCESS) {
/*
* Cleaned up elsewhere.
*/
endutxent();
return (0);
}
if ((*user = (char *) strdup(up->ut_user))
== NULL ||
(*ttyn = (char *) strdup(up->ut_line))
== NULL ||
(*rhost = (char *) strdup(up->ut_host))
== NULL ||)
return (PAM_BUF_ERR);
up->ut_type = DEAD_PROCESS;
up->ut_exit.e_termination = status & 0xff;
up->ut_exit.e_exit = (status >> 8) & 0xff;
if (id != NULL)
(void) memcpy(up->ut_id, id,
sizeof (up->ut_id));
(void) time(&up->ut_tv.tv_sec);
/*
* For init (Process ID 1) we don't write to
* init's pipe, since we are init.
*/
if (getpid() == INIT_PROC_PID) {
(void) pututxline(up);
/*
* Now attempt to add to the end of the
* wtmp and wtmpx files. Do not create
* if they don't already exist.
*/
updwtmpx("wtmpx", up);
} else {
if (modutx(up) == NULL) {
syslog(LOG_INFO,
"\tmodutx failed");
/*
* Since modutx failed we'll
* write out the new entry
* ourselves.
*/
(void) pututxline(up);
updwtmpx("wtmpx", up);
}
}
endutxent();
return (PAM_SUCCESS);
}
}
endutxent();
return (__NOENTRY);
}
}
/*
* __setproc_cred - A utility function used to set the unix credentials of the
* current process. This function is NOT meant to be part of
* the official PAM API, and only serves as a convenience
* function.
*
* "user" is the current username.
* The following flags may be set in the "flags" field:
*
* __INITGROUPS Initialize the supplementary group access list.
* __SETGROUPS Set the supplementary group access list.
* __SETEGID Set the effective group ID only.
* __SETGID Set the real and effective group IDs.
* __SETEUID Set the effective user ID only.
* __SETUID Set the real and effective user IDs.
* __SETEID Set the effective user and group IDs.
* __SETRID Set the real and effective user and group IDs.
*
* "uid" and "gid" are the values of the user ID and group ID respectively.
* "ngroups" is the number of supplementary groups.
* "grouplist" is a pointer to the list of supplementary groups.
*
* Upon successful completion, PAM_SUCCESS is returned.
* Error values may include:
*
* __BAD_GID Invalid group ID
* __INITGROUP_FAIL Initialization of group ID's failed
* __BAD_UID Invalid user ID
* __SETGROUP_FAIL Set of group ID's failed
*/
int
__setproc_cred(
char *user,
int flags,
uid_t uid,
gid_t gid,
int ngroups,
gid_t *grouplist)
{
int err = 0;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
/*
* Set the credentials
*/
/* set the effective GID */
if (flags & __SETEGID) {
if (setegid(gid) == -1) {
sprintf(messages[0], PAM_MSG(NULL, 29,
"pam_sm_setcred: %s\n"), strerror(errno));
return (__BAD_GID);
}
}
/* set the real (and effective) GID */
if (flags & __SETGID) {
if (setgid(gid) == -1) {
sprintf(messages[0], PAM_MSG(NULL, 30,
"setproc_cred: %s\n"), strerror(errno));
return (__BAD_GID);
}
}
/*
* Initialize the supplementary group access list.
*/
if (!user)
return (__INITGROUP_FAIL);
if (flags & __INITGROUPS) {
if (initgroups(user, gid) == -1) {
sprintf(messages[0], PAM_MSG(NULL, 29,
"pam_sm_setcred: %s\n"), strerror(errno));
return (__INITGROUP_FAIL);
}
}
/*
* Set the supplementary group access list.
*/
if (flags & __SETGROUPS) {
if (setgroups(ngroups, (gid_t *)grouplist) == -1) {
sprintf(messages[0], PAM_MSG(NULL, 29,
"pam_sm_setcred: %s\n"), strerror(errno));
return (__SETGROUP_FAIL);
}
}
/*
* Set the user id
*/
/* set the effective UID */
if (flags & __SETEUID) {
if (seteuid(uid) == -1) {
sprintf(messages[0], PAM_MSG(NULL, 29
"pam_sm_setcred: %s\n"), strerror(errno));
return (__BAD_UID);
}
}
/* set the real (and effective) UID */
if (flags & __SETUID) {
if (setuid(uid) == -1) {
sprintf(messages[0], PAM_MSG(NULL, 29,
"pam_sm_setcred: %s\n"), strerror(errno));
return (__BAD_UID);
}
}
return (PAM_SUCCESS);
}
#endif

View File

@@ -0,0 +1,191 @@
/* $XConsortium: pam_impl.h /main/4 1996/05/09 04:25:20 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _PAM_IMPL_H
#define _PAM_IMPL_H
#pragma ident "@(#)pam_impl.h 1.42 96/02/02 SMI" /* PAM 2.6 */
#ifdef __cplusplus
extern "C" {
#endif
#include <shadow.h>
#define PAMTXD "SUNW_OST_SYSOSPAM"
#define AUTH_LIB "/usr/lib/libpam.a"
#define PAM_CONFIG "/etc/pam.conf"
#define PAM_LIB_DIR "/usr/lib/security/"
#define PAM_AUTH_MODULE 0
#define PAM_ACCOUNT_MODULE 1
#define PAM_PASSWORD_MODULE 2
#define PAM_SESSION_MODULE 3
#define PAM_NUM_MODULE_TYPES 4
#define PAM_REQUIRED 1 /* required flag in config file */
#define PAM_OPTIONAL 2 /* optional flag in config file */
#define PAM_SUFFICIENT 4 /* sufficient flag in config file */
/* XXX: Make sure this is correct in pam_appl.h */
#define PAM_TOTAL_ERRNUM 28 /* total # PAM error numbers */
/* authentication module functions */
#define PAM_SM_AUTHENTICATE "pam_sm_authenticate"
#define PAM_SM_SETCRED "pam_sm_setcred"
/* session module functions */
#define PAM_SM_OPEN_SESSION "pam_sm_open_session"
#define PAM_SM_CLOSE_SESSION "pam_sm_close_session"
/* password module functions */
#define PAM_SM_CHAUTHTOK "pam_sm_chauthtok"
/* account module functions */
#define PAM_SM_ACCT_MGMT "pam_sm_acct_mgmt"
#define PAM_MAX_ITEMS 64 /* Max number of items */
/* for modules when calling __pam_get_authtok() */
#define PAM_PROMPT 1 /* prompt user for new password */
#define PAM_HANDLE 2 /* get password from pam handle (item) */
/* utility function prototypes */
extern void
__pam_free_resp(
int num_msg,
struct pam_response *resp
);
extern int
__pam_display_msg(
pam_handle_t *pamh,
int msg_style,
int num_msg,
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE],
void *conv_apdp
);
extern int
__pam_get_input(
pam_handle_t *pamh,
int msg_style,
int num_msg,
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE],
void *conv_apdp,
struct pam_response **ret_respp
);
extern int
__pam_get_authtok(
pam_handle_t *pamh,
int source,
int type,
int len,
char *prompt,
char **authtok
);
extern char *
__pam_get_i18n_msg(
pam_handle_t *pamh,
char *filename,
int set,
int n,
char *string
);
/* file handle for pam.conf */
struct pam_fh {
FILE *fconfig;
char line[256];
};
/* items that can be set/retrieved thru pam_[sg]et_item() */
struct pam_item {
void *pi_addr; /* pointer to item */
int pi_size; /* size of item */
};
/* module specific data stored in the pam handle */
struct pam_module_data {
char *module_data_name; /* unique module data name */
void *data; /* the module specific data */
void (*cleanup)(pam_handle_t *pamh, void *data, int pam_status);
struct pam_module_data *next; /* pointer to next module data */
};
/* each entry from pam.conf is stored here (in the pam handle) */
typedef struct pamtab {
char *pam_service; /* PAM service, e.g. login, rlogin */
int pam_type; /* AUTH, ACCOUNT, PASSWORD, SESSION */
int pam_flag; /* required, optional, sufficient */
char *module_path; /* module library */
int module_argc; /* module specific options */
char **module_argv;
void *function_ptr; /* pointer to struct holding function ptrs */
struct pamtab *next;
} pamtab;
/* the pam handle */
struct pam_handle {
struct pam_item ps_item[PAM_MAX_ITEMS]; /* array of PAM items */
pamtab *pam_conf_info[PAM_NUM_MODULE_TYPES]; /* pam.conf info */
struct pam_module_data *ssd; /* module specific data */
};
/*
* the function_ptr field in struct pamtab
* will point to one of these modules
*/
struct auth_module {
int (*pam_sm_authenticate)(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
int (*pam_sm_setcred)(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
};
struct password_module {
int (*pam_sm_chauthtok)(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
};
struct session_module {
int (*pam_sm_open_session)(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
int (*pam_sm_close_session)(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
};
struct account_module {
int (*pam_sm_acct_mgmt)(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
};
#ifdef __cplusplus
}
#endif
#endif /* _PAM_IMPL_H */

View File

@@ -0,0 +1,30 @@
/* $XConsortium: pam_loc.h /main/3 1996/05/09 04:25:37 drk $ */
/*
* "@(#)pam_loc.h 1.4 96/02/02
*
* Copyright 1996 Sun Microsystems, Inc.
*
* All Rights reserved
*/
#ifndef _PAM_LOC_H
#define _PAM_LOC_H
#pragma ident "@(#)pam_loc.h 1.4 96/02/02 SMI" /* PAM 2.6 */
#ifdef __cplusplus
extern "C" {
#endif
/*
* PAM_MSG macro for return of internationalized text
*/
#define PAM_MSG(pamh, number, string)\
(char *) __pam_get_i18n_msg(pamh, "libpam", 2, number, string)
#ifdef __cplusplus
}
#endif
#endif /* _PAM_LOC_H */

View File

@@ -0,0 +1,80 @@
/* $XConsortium: pam_modules.h /main/5 1996/05/09 04:25:54 drk $ */
/*
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
* All rights reserved.
*/
#ifndef _PAM_MODULES_H
#define _PAM_MODULES_H
#pragma ident "@(#)pam_modules.h 1.20 96/02/02 SMI" /* PAM 2.6 */
#ifdef __cplusplus
extern "C" {
#endif
extern int
pam_sm_authenticate(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
extern int
pam_sm_setcred(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
extern int
pam_sm_acct_mgmt(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
extern int
pam_sm_open_session(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
extern int
pam_sm_close_session(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
/*
* Be careful - there are flags defined for pam_chauthtok() in
* pam_appl.h also.
*/
#define PAM_PRELIM_CHECK 1
#define PAM_UPDATE_AUTHTOK 2
#define PAM_REP_DEFAULT 0x0
#define PAM_REP_FILES 0x01
#define PAM_REP_NIS 0x02
#define PAM_REP_NISPLUS 0x04
#define PAM_OPWCMD 0x08 /* for nispasswd, yppasswd */
#define IS_FILES(x) ((x & PAM_REP_FILES) == PAM_REP_FILES)
#define IS_NIS(x) ((x & PAM_REP_NIS) == PAM_REP_NIS)
#define IS_NISPLUS(x) ((x & PAM_REP_NISPLUS) == PAM_REP_NISPLUS)
#define IS_OPWCMD(x) ((x & PAM_OPWCMD) == PAM_OPWCMD)
extern int
pam_sm_chauthtok(
pam_handle_t *pamh,
int flags,
int argc,
const char **argv);
#ifdef __cplusplus
}
#endif
#endif /* _PAM_MODULES_H */

260
cde/lib/pam/man/man3/pam.3 Normal file
View File

@@ -0,0 +1,260 @@
.\" $XConsortium: pam.3 /main/5 1996/10/29 15:17:56 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam 3 "9 Jan 1996"
.SH NAME
PAM \- Pluggable Authentication Module
.SH SYNOPSIS
.LP
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.SH DESCRIPTION
.IX "PAM" "" "\fLPAM\fP \(em Pluggable Authentication Module"
.PP
.SM PAM
gives system administrators the flexibility of choosing any authentication
service available on the system to perform authentication. The framework
also allows new authentication service modules to be plugged in and made
available without modifying the applications.
.LP
The
.SM PAM
framework,
.B libpam,
consists of an interface library and multiple authentication
service modules. The
.SM PAM
interface library is the layer implementing the
Application Programming Interface (API). The authentication service modules
are a set of dynamically loadable objects invoked by the
.SM PAM
API to provide a particular type of user authentication.
.SS Interface Overview
The
.SM PAM
library interface
consists of functions which can be grouped into five categories. The
names for all the authentication library functions start with
.B pam_.
.PP
The first category contains functions for establishing and terminating an
authentication activity
(\f3pam_start\f1(3)
and
(\f3pam_end\f1(3)),
functions to maintain module specific data
(\f3pam_[sg]et_data\f1(3)),
functions to maintain state information
(\f3pam_[sg]et_item\f1(3)),
and a function to return error status information
(\f3pam_strerror\f1(3)).
.PP
The second category contains functions to authenticate an individual user
(\f3pam_authenticate\f1(3))
and to set the credentials of the user
(\f3pam_setcred\f1(3)).
.PP
The third category contains functions to do account management
(\f3pam_acct_mgmt\f1(3)).
This includes checking for password aging and access-hour restrictions.
.PP
The fourth category contains functions to perform session management
(\f3(pam_open_session\f1(3)
and
(\f3pam_close_session\f1(3))
after access to the system has been granted.
.PP
The fifth category consists of functions to change authentication tokens
.BR pam_chauthtok (3)).
An authentication token is the object used to verify the
identity of the user.
In
.SM UNIX,
an authentication
token is a user's password.
.PP
All the
.B pam_*(\|)
interfaces are implemented through the library
.B libpam.
For each of the categories listed above, excluding the first category
.BR pam_start(\|) ,
.BR pam_end(\|) ,
.BR pam_[sg]et_data(\|) ,
.BR pam_[sg]et_item(\|) ,
and
.BR pam_strerror(\|) )
there exists a dynamically loadable shared module
that provides the appropriate
service layer functionality upon demand.
The functional entry points in the
service layer start with the
.B pam_sm_
prefix. The only difference between the
.B pam_sm_*(\|)
interfaces and their corresponding
.B pam_
interfaces is that all the
.BR pam_sm_*(\|)
interfaces require extra parameters to pass service specific options
to the shared modules.
Please refer to
.BR pam_sm (3)
for an overview of the
.SM PAM
service module APIs.
.SS Stateful Interface
A sequence of calls sharing a common set of state information
is referred to as an authentication transaction. An authentication
transaction begins with a call to
.BR pam_start(\|).
.B pam_start(\|)
allocates space, performs various initialization activities,
and assigns a
.SM PAM
authentication handle to be used for subsequent calls
to the library.
.LP
After initiating an authentication transaction, applications can invoke
.B pam_authenticate(\|)
to authenticate a particular user, and
.B pam_acct_mgmt(\|)
to perform system entry management (the
application may want to determine if the user's
password has expired).
.LP
If the user has been successfully authenticated, applications call
.B pam_setcred(\|)
to set any user credentials associated with the authentication service.
Within one authentication transaction (between
.B pam_start(\|)
and
.BR pam_end(\|) ),
all calls to the
.SM PAM
interface should be made with the same authentication handle
returned by
.BR pam_start(\|) .
This is necessary because certain service modules
may store module-specific data in the handle
that is intended for use by other modules.
For example, during the call to
.BR pam_authenticate(\|) ,
service modules may store data in the handle
that is intended for use by
.BR pam_setcred(\|) .
.LP
To perform session management, applications call
.BR pam_open_session(\|) .
For example, the system may want to store
the total time for the session.
The function
.B pam_close_session(\|)
closes the current session.
.LP
When necessary, applications can call
.B pam_get_item(\|)
and
.B pam_set_item(\|)
to access and update specific authentication information.
Such information may include the current username.
.LP
To terminate an authentication transaction, the application simply calls
.BR pam_end(\|) ,
which frees previously allocated space used to store authentication information.
.PP
.SS Application - Authentication Service Interactive Interface
The authentication service in
.SM PAM
does not communicate directly with the user; instead it
relies on the application to perform all such interactions.
The application passes a pointer to the function,
.BR conv(\|) ,
along with any associated application data pointers, through a
.I pam_conv
structure to the authentication service when it initiates
an authentication transaction (via a call to
.BR pam_start(\|) ).
The service will then use the function,
.BR conv(\|) ,
to prompt the user for data,
output error messages, and display text information.
Refer to
.BR pam_start (3)
for more information.
.SS Stacking Multiple Schemes
The
.SM PAM
architecture enables authentication by multiple authentication services through
.I stacking.
System entry applications, such as
.BR login (1),
stack multiple service modules to authenticate users with multiple
authentication services.
The order in which authentication service
modules are stacked is specified in the configuration file,
.BR pam.conf (4).
A system administrator determines this ordering, and also determines
whether the same password can be used for all authentication services.
.SS Administrative Interface
The authentication library,
.BR /usr/lib/libpam.so.1 ,
implements the framework interface.
Various authentication services are
implemented by their own loadable modules
whose paths are specified through the
.BR pam.conf (4)
file.
.PP
.SH "RETURN VALUES"
.PP
The
.SM PAM
functions may return one of the following generic values,
or one of the values defined in the specific man pages:
.RS
.IP "PAM_SUCCESS" 22
Successful function return
.IP "PAM_OPEN_ERR" 22
.B dlopen(\|)
failure when dynamically loading a service module
.IP "PAM_SYMBOL_ERR" 22
Symbol not found
.IP "PAM_SERVICE_ERR" 22
Error in service module
.IP "PAM_SYSTEM_ERR" 22
System error
.IP "PAM_BUF_ERR" 22
Memory buffer error
.IP "PAM_CONV_ERR" 22
Conversation failure
.IP "PAM_PERM_DENIED
Permission denied
.RE
.SH "SEE ALSO"
.BR pam_authenticate (3),
.BR pam_open_session (3),
.BR pam_chauthtok (3),
.BR pam_set_item (3),
.BR pam_setcred (3),
.BR pam_sm (3),
.BR pam_start (3),
.BR pam_strerror (3),
.BR pam.conf (4)
.SH WARNING
Please note that all the
.SM PAM
APIs and the data structures are subject to
change without notice.

View File

@@ -0,0 +1,74 @@
.\" $XConsortium: pam_acct_mgmt.3 /main/5 1996/10/29 15:18:07 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.\" Don't forget to enter .IX index entries for each function.
.nr X
.TH pam_acct_mgmt 3 "9 Jan 1996"
.SH NAME
pam_acct_mgmt
\- perform PAM account validation procedures
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.BI "int pam_acct_mgmt(pam_handle_t *" "pamh" ,
.BI "int " "flags");
.SH DESCRIPTION
The function
.B pam_acct_mgmt(\|)
is called to determine if the current user's account is
valid. This includes checking for password and account expiration,
as well as verifying access hour restrictions. This function
is typically called after the user has been authenticated
with
.BR pam_authenticate (3).
.LP
The
.IR pamh
argument
is an authentication handle obtained by a prior call to
.BR pam_start(\|) .
The following flags may be set in the
.IR flags
field:
.RS
.IP PAM_SILENT 28
The account management service should not generate any messages
.IP PAM_DISALLOW_NULL_AUTHTOK 28
The account management service should return
.SM PAM_AUTHTOKEN_REQD
if the user has a null authentication token
.RE
.SH "RETURN VALUES"
.PP
Upon successful completion, PAM_SUCCESS is returned.
In addition to the error return values described in
.BR pam (3),
the following values may be returned:
.RS
.IP PAM_USER_UNKNOWN 28
User not known to underlying account management module
.IP PAM_AUTH_ERR 28
Authentication failure
.IP PAM_AUTHTOKEN_REQD 28
New authentication token required. This is normally returned if the machine
security policies require that the password should be changed because
the password is NULL or it has aged.
.IP PAM_ACCT_EXPIRED 28
User account has expired
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_start (3),
.BR pam_authenticate (3)

View File

@@ -0,0 +1,100 @@
.\" $XConsortium: pam_authenticate.3 /main/5 1996/10/29 15:18:17 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.\" Don't forget to enter .IX index entries for each function.
.nr X
.TH pam_authenticate 3 "9 Jan 1996"
.SH NAME
pam_authenticate
\- perform authentication within the PAM framework
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.BI "int pam_authenticate(pam_handle_t *" "pamh" ,
.BI "int " "flags");
.SH DESCRIPTION
.IX "pam_authenticate" "" "\fLpam_authenticate\fP \(em request authentication"
.B pam_authenticate(\|)
is called to authenticate the current user.
The user is usually required to enter
a password or similar authentication token depending upon
the authentication service configured within the system.
The user in question should have been specified by a prior call to
.B pam_start(\|)
or
.BR pam_set_item(\|) .
The following flags may be set in the
.IR flags
field:
.RS
.IP PAM_SILENT 35
Authentication service should not generate any messages
.IP PAM_DISALLOW_NULL_AUTHTOK 35
The authentication service should return PAM_AUTH_ERROR
if the user has a null authentication token
.RE
.SH NOTES
.PP
In the case of authentication failures due to an incorrect username
or password, it is the responsibility of the application to retry
.B pam_authenticate(\|)
and to maintain the retry count.
An authentication service module may implement an
internal retry count and return an error
PAM_MAXTRIES
if the module does not want the application to retry.
.LP
If the PAM framework can not load the authentication module, then
it will return PAM_ABORT.
This indicates a serious failure and that
the application should not attempt to retry the authentication.
.LP
For security reasons,
the location of authentication failures is hidden from the user.
Thus, if several authentication services are stacked and a single
service fails,
.B pam_authenticate(\|)
requires that the user re-authenticate to all the services.
.LP
A null authentication token in the authentication database will
result in successful authentication unless
.SM PAM_DISALLOW_NULL_AUTHTOK
was specified.
In such cases, there will not be any prompting
for the user to enter an authentication token.
.SH "RETURN VALUES"
.PP
Upon successful completion, PAM_SUCCESS is returned.
In addition to the error return values described in
.BR pam (3),
the following values may be returned:
.RS
.IP PAM_AUTH_ERR 29
Authentication failure
.IP PAM_CRED_INSUFFICIENT 29
Can not access authentication data due to insufficient credentials
.IP PAM_AUTHINFO_UNAVAIL 29
Underlying authentication service can not retrieve authentication information
.IP PAM_USER_UNKNOWN 29
User not known to the underlying authentication module
.IP PAM_MAXTRIES
An authentication service has maintained a retry count which
has been reached. No further retries should be attempted.
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_start (3),
.BR pam_open_session (3),
.BR pam_setcred (3)

View File

@@ -0,0 +1,100 @@
.\" $XConsortium: pam_chauthtok.3 /main/5 1996/10/29 15:18:27 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_chauthtok 3 "9 Jan 1996"
.SH NAME
pam_chauthtok
\- perform passord related functions within the PAM framework
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.BI "int pam_chauthtok(pam_handle_t " "*pamh" ,
.BI "const int" " flags");
.SH DESCRIPTION
.IX "pam_chauthtok" "" "\fLpam_chauthtok\fP \(em request changing authentication token or get/set authentication attributes"
.B pam_chauthtok(\|)
is called to change the authentication token
associated with a particular user
referenced by the authentication handle,
.IR pamh.
.LP
The following flag may be passed in to
.BR pam_chauthtok(\|) :
.RS
.IP PAM_SILENT 30
The password service should not generate any messages
.IP PAM_CHANGE_EXPIRED_AUTHTOK 30
The password service should only update those passwords that have aged.
If this flag is not passed,
all password services should update their passwords.
.RE
.LP
Upon successful completion of the call, the authentication
token of the user will be changed in accordance with the
password service configured in the system through
.BR pam.conf (4).
.SH NOTES
The flag
.SM PAM_CHANGE_EXPIRED_AUTHTOK
is typically used by a
.B login
application which has determined that the user's password has aged or expired.
Before allowing the user to login, the
.B login
application may invoke
.B pam_chauthtok(\|)
with this flag to allow the user to update the password.
Typically applications such as
.BR passwd (1)
should not use this flag.
.PP
.B pam_chauthtok(\|)
performs a preliminary check before attempting to update
passwords. This check is performed for each
password module in the stack as listed in
.BR pam.conf (4).
The check may include pinging remote name services to determine
if they are available. If
.B pam_chauthtok(\|)
returns
PAM_TRY_AGAIN,
then the check has failed, and passwords are not updated.
.SH "RETURN VALUES"
.PP
Upon successful completion, PAM_SUCCESS is returned.
In addition to the error return values described in
.BR pam (3),
the following values may be returned:
.RS
.IP PAM_PERM_DENIED 34
No permission
.IP PAM_AUTHTOK_ERR 34
Authentication token manipulation error
.IP PAM_AUTHTOK_RECOVERY_ERR 34
Authentication information cannot be recovered
.IP PAM_AUTHTOK_LOCK_BUSY 34
Authentication token lock busy
.IP PAM_AUTHTOK_DISABLE_AGING 34
Authentication token aging disabled
.IP PAM_USER_UNKNOWN 34
User unknown to password service
.IP PAM_TRY_AGAIN 34
Preliminary check by password service failed
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_start (3),
.BR pam_authenticate (3)

View File

@@ -0,0 +1,106 @@
.\" $XConsortium: pam_open_session.3 /main/5 1996/10/29 15:18:42 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_open_session 3 "9 Jan 1996"
.SH NAME
pam_open_session, pam_close_session \- perform PAM session creation and
termination operations
.SH SYNOPSIS
.LP
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.BI "int pam_open_session(pam_handle_t " "*pamh" ,
.BI "int " "flags");
.LP
.BI "int pam_close_session(pam_handle_t " "*pamh" ,
.BI "int " "flags");
.SH DESCRIPTION
.IX "pam_open_session" "" "\fLpam_open_session\fP \(em request authentication"
.B pam_open_session(\|)
is called after a user has been successfully authenticated (refer to
.BR pam_authenticate (3)
and
.BR pam_acct_mgmt (3))
and is used to notify the session modules that a new session
has been initiated. All programs that use the
.BR pam (3)
library should invoke
.B pam_open_session(\|)
when beginning a new session.
Upon termination of this activity,
.B pam_close_session(\|)
should be invoked to inform
.BR pam (3)
that the
session has terminated.
.LP
The
.I pamh
argument
is an authentication handle obtained by a prior call to
.B pam_start(\|).
The following flag may be set in the
.I flags
field for
.B pam_open_session(\|)
and
.BR pam_close_session(\|) :
.RS
.IP PAM_SILENT 16
The session service should not generate any messages
.RE
.SH NOTES
In many instances, the
.B pam_open_session(\|)
and
.B pam_close_session(\|)
calls may be made by different processes.
For example, in UNIX the
.B login
process opens a session, while the
.B init
process closes
the session. In this case,
UTMP/WTMP entries may be used to link the call to
.B pam_close_session(\|)
with an earlier call to
.BR pam_open_session(\|) .
This is possible because
UTMP/WTMP entries are uniquely identified by a combination of attributes,
including the user login name and device name, which are accessible
through the PAM handle,
.I pamh.
The call to
.B pam_open_session(\|)
should precede UTMP/WTMP entry management and the call to
.B pam_close_session(\|)
should follow UTMP/WTMP exit management.
.PP
.SH "RETURN VALUES"
.PP
Upon successful completion, PAM_SUCCESS is returned. In addition to the
return values defined in
.BR pam (3),
the following value may be returned on error:
.RS
.IP PAM_SESSION_ERR 22
Can not make/remove an entry for the specified session
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_start (3),
.BR pam_authenticate (3),
.BR pam_acct_mgmt (3),
.BR getutxent (3C)

View File

@@ -0,0 +1,108 @@
.\" $XConsortium: pam_set_data.3 /main/5 1996/10/29 15:19:01 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.\" Don't forget to enter .IX index entries for each function.
.nr X
.TH pam_set_data 3 "9 Jan 1996"
.SH NAME
pam_set_data, pam_get_data
\- PAM routines to maintain module specific state
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.BI "int pam_set_data(pam_handle_t " "*pamh" ,
.BI "const char *" "module_data_name" ,
.BI "const void *" "data" ,
.BI "void " "(*cleanup)(pam_handle_t *pamh, void *data, int pam_end_status)" );
.LP
.BI "int pam_get_data(const pam_handle_t " "*pamh" ,
.BI "const char *" "module_data_name" ,
.BI "void **" "data" );
.SH DESCRIPTION
.IX "pam_set_data" "" "\fLpam_set_data\fP \(em set module info"
.B pam_set_data(\|)
and
.B pam_set_data(\|)
allow
.SM PAM
service modules to access and update module specific information as needed.
These functions should not be used by applications.
.LP
.B pam_set_data(\|)
stores module specific data within the PAM handle,
.I pamh.
The
.I module_data_name
argument
uniquely identifies the data, and the
.I data
argument
represents the actual data.
.I module_data_name
should be unique across all services (UNIX, etc).
.LP
The
.I cleanup
function is used to free any memory used by the
.I data
after it is no longer needed, and is invoked by
.BR pam_end(\|) .
The
.I cleanup
function takes as its arguments a pointer to the PAM handle,
.I pamh,
a pointer to the actual data,
.I data,
and a status code,
.I pam_end_status.
The status code determines exactly what state information needs to be
purged, and is therefore specific to each module.
.LP
If
.B pam_set_data(\|)
is called and module data already exists under the same
.I module_data_name
(from a prior call to
.BR pam_set_data(\|) ),
then the existing
.I data
is replaced by the new
.I data,
and the existing
.I cleanup
function is replaced by the new
.I cleanup
function.
.LP
.B pam_get_data(\|)
retrieves module specific data stored in the PAM handle,
.I pamh,
identified by the unique name,
.I module_data_name.
The
.I data
argument is assigned the address of the requested data.
.SH "RETURN VALUES"
.PP
In addition to the return values listed in
.BR pam (3),
the following value may also be returned:
.RS
.IP PAM_NO_MODULE_DATA 28
No module specific data is present
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_end (3)

View File

@@ -0,0 +1,137 @@
.\" $XConsortium: pam_set_item.3 /main/5 1996/10/29 15:19:14 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.\" Don't forget to enter .IX index entries for each function.
.nr X
.TH pam_set_item 3 "9 Jan 1996"
.SH NAME
pam_set_item, pam_get_item
\- authentication information routines for PAM
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.BI "int pam_set_item(pam_handle_t " "*pamh" ,
.BI "int " "item_type" ,
.BI "const void *" "item" );
.LP
.BI "int pam_get_item(const pam_handle_t " "*pamh" ,
.BI "int " "item_type" ,
.BI "void **" "item" );
.SH DESCRIPTION
.IX "pam_set_item" "" "\fLpam_set_item\fP \(em set authentication info"
.B pam_get_item(\|)
and
.B pam_set_item(\|)
allow applications and PAM service modules to access and update
.SM PAM
information as needed. The information is specified by
.IR item_type,
and can be one of the following:
.RS
.IP "PAM_SERVICE" 25
The service name
.IP "PAM_USER" 25
The user name
.IP "PAM_AUTHTOK" 25
The user authentication token
.IP "PAM_OLDAUTHTOK" 25
The old user authentication token
.IP "PAM_TTY" 25
The tty name
.IP "PAM_RHOST" 25
The remote host name
.IP "PAM_RUSER" 25
The remote user name
.IP "PAM_CONV" 25
The pam_conv structure
.IP "PAM_USER_PROMPT" 25
The default prompt used by
.BR pam_get_user(\|)
.RE
.LP
The
.IR item_type
.SM PAM_AUTHTOK
and
.SM PAM_OLDAUTHTOK
are available only to the module providers for security reasons.
The authentication module, account module, and session management module
should treat
.SM PAM_AUTHTOK
as the current authentication token,
and should ignore
.SM PAM_OLDAUTHTOK.
The password management module should treat
.SM PAM_OLDAUTHTOK
as the current authentication token and
.SM PAM_AUTHTOK
as the new authentication token.
.LP
.B pam_set_item(\|)
is passed the authentication handle,
.IR pamh,
returned by
.BR pam_start(\|) ,
a pointer to the object,
.IR item,
and its type,
.IR item_type.
If successful,
.B pam_set_item(\|)
copies the item to an internal storage area allocated by the
authentication module and returns PAM_SUCCESS. An item that had
been previously set will be overwritten by the new value.
.LP
.B pam_get_item(\|)
is passed the authentication handle,
.IR pamh,
returned by
.BR pam_start(\|) ,
an
.IR item_type ,
and the address of the pointer,
.IR item ,
which is assigned the address of the requested object.
The object data is valid until modified by a subsequent call to
.B pam_set_item(\|)
for the same
.IR item_type ,
or unless it is modified by any of the underlying service modules.
If the item has not been previously set,
.B pam_get_item(\|)
returns a NULL pointer.
An
.IR item
retrieved by
.B pam_get_item(\|)
should not be modified or freed. The item will be released by
.BR pam_end(\|) .
.SH "RETURN VALUES"
.PP
Upon success
.B pam_get_item(\|)
returns PAM_SUCCESS; otherwise it returns an error code.
Refer to
.BR pam (3)
for information on error related return values.
.SH "SEE ALSO"
.BR pam_start (3),
.BR pam_authenticate (3),
.BR pam_acct_mgmt (3),
.BR pam_open_session (3),
.BR pam_setcred (3),
.BR pam_chauthtok (3),
.BR pam_get_user (3),
.BR pam (3)

View File

@@ -0,0 +1,86 @@
.\" $XConsortium: pam_setcred.3 /main/5 1996/10/29 15:19:22 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_setcred 3 "9 Jan 1996"
.SH NAME
pam_setcred \- modify\/delete user credentials for
an authentication service
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.\" .BI "int pam_setcred(pam_handle_t " "*pamh" ,
.\" .BI "int " flags");
\fBint pam_setcred(pam_handle_t \fI*pamh\fB, int \fIflags\fB);
.SH DESCRIPTION
.IX "pam_setcred" "" "\fLpam_setcred\fP \(em request setting credentials"
.B pam_setcred(\|)
is used to establish, modify, or delete user credentials.
.B pam_setcred(\|)
is typically called after the user has been authenticated
and after a session has been opened (refer to
.BR pam_authenticate (3),
.BR pam_acct_mgmt (3),
and
.BR pam_open_session (3)).
.LP
The user is specified by a prior call to
.B pam_start(\|)
or
.B pam_set_item(\|),
and is referenced by the authentication handle,
.IR pamh.
The following flags may be set in the
.IR flags
field. Note that the first four flags are mutually exclusive:
.RS
.IP "PAM_CRED_ESTABLISH" 26
Set user credentials for an authentication service
.IP "PAM_CRED_DELETE" 26
Delete user credentials associated with an authentication service
.IP "PAM_CRED_REINITIALIZE" 26
Reinitialize user credentials
.IP "PAM_CRED_REFRESH" 26
Extend lifetime of user credentials
.IP "PAM_SILENT" 26
Authentication service should not generate any messages
.RE
.LP
If none of the flags are set, PAM_CRED_ESTABLISH
is used as the default.
.SH "RETURN VALUES"
.PP
Upon success,
.B pam_setcred(\|)
returns PAM_SUCCESS.
In addition to the error return values described in
.BR pam (3),
the following values may be returned upon error:
.RS
.IP PAM_CRED_UNAVAIL 25
Underlying authentication service can not retrieve user credentials unavailable
.IP PAM_CRED_EXPIRED 25
User credentials expired
.IP PAM_USER_UNKNOWN 25
User unknown to underlying authentication service
.IP PAM_CRED_ERR 25
Failure setting user credentials
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_start (3),
.BR pam_authenticate (3),
.BR pam_acct_mgmt (3),
.BR pam_open_session (3)

View File

@@ -0,0 +1,295 @@
.\" $XConsortium: pam_sm.3 /main/4 1996/10/29 15:19:34 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_sm 3 "9 Jan 1996"
.SH NAME
PAM \- PAM Service Module APIs
.SH SYNOPSIS
.LP
.nf
.ft 3
#include <security/pam_appl.h>
#include <security/pam_modules.h>
.ft
.fi
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.SH DESCRIPTION
.IX "PAM" "" "\fLPAM\fP \(em Pluggable Authentication Module"
.PP
.SM PAM
gives system administrators the flexibility of choosing any authentication
service available on the system to perform authentication. The framework
also allows new authentication service modules to be plugged in and made
available without modifying the applications.
.LP
The
.SM PAM
framework,
.B libpam,
consists of an interface library and multiple authentication
service modules. The
.SM PAM
interface library is the layer implementing the
Application Programming Interface (API). The authentication service modules
are a set of dynamically loadable objects invoked by the
.SM PAM
API to provide a particular type of user authentication.
.PP
This manual page gives an overview of the PAM APIs for the service modules.
.SS Interface Overview
The
.SM PAM
service module interface
consists of functions which can be grouped into four categories. The
names for all the authentication library functions start with
.B pam_sm.
The only difference between the
.B pam_*(\|)
interfaces and their corresponding
.B pam_sm_*(\|)
interfaces is that all the
.B pam_sm_*(\|)
interfaces require extra parameters to pass service specific options
to the shared modules.
They are otherwise identical.
.PP
The first category contains functions to authenticate an individual user
(\f3pam_sm_authenticate\f1(3))
and to set the credentials of the user
.B (\f3pam_sm_setcred\f1(3)).
These back-end functions implement the functionality of
.BR pam_authenticate (3)
and
.BR pam_setcred (3)
respectively.
.PP
The second category contains functions to do account management
(\f3pam_sm_acct_mgmt\f1(3)).
This includes checking for password aging and access-hour restrictions.
This back-end function implements the functionality of
.BR pam_acct_mgmt (3).
.PP
The third category contains functions to perform session management
(\f3pam_sm_open_session\f1(3)
and
.BR pam_sm_close_session (3))
after access to the system has been granted.
These back-end functions implement the functionality of
.BR pam_open_session (3)
and
.BR pam_close_session (3),
respectively.
.PP
The fourth category consists a function to change authentication tokens
(\f3pam_sm_chauthtok\f1(3)).
This back-end function implements the functionality of
.BR pam_chauthtok (3).
.SS Stateful Interface
A sequence of calls sharing a common set of state information
is referred to as an authentication transaction. An authentication
transaction begins with a call to
.BR pam_start(\|) .
.B pam_start(\|)
allocates space, performs various initialization activities,
and assigns an authentication handle to be used for subsequent calls
to the library.
Note that the service modules do not get called or
initialized when
.B pam_start(\|)
is called.
The modules are loaded and the symbols resolved upon first use
of that function.
.LP
The PAM handle keeps certain information about the transaction
that can be accessed through the
.B pam_get_item(\|)
API.
Though the modules can also use
.B pam_set_item(\|)
to change any of the item information, it
is recommended that nothing be changed except PAM_AUTHTOK and
PAM_OLDAUTHTOK.
.LP
If the modules want to store any module specific state information
then they can use the
.BR pam_set_data (3)
function to store that
information with the PAM handle. The data should be stored with a
name which is unique across all modules and module types. For
example,
.SM SUNW_PAM_UNIX_AUTH_userid
can be used as a name by the UNIX
module to store information about the state of user's
authentication. Some modules use this technique to share data
across two different module types.
.LP
Also, during the call to
.BR pam_authenticate(\|) ,
the UNIX module may store the authentication status
(success or reason for failure)
in the handle, using a unique name such as
.SM SUNW_SECURE_RPC_DATA.
This information is intended for use by
.BR pam_setcred(\|) .
.LP
During the call to
.BR pam_acct_mgmt(\|) ,
the account modules may store data in the handle to indicate
which passwords have aged.
This information is intended for use by
.BR pam_chauthtok(\|) .
.LP
The module can also store a cleanup function associated with the
data. The PAM framework calls this cleanup function, when the
application calls
.BR pam_end(\|)
to close the transaction.
.SS Interaction with the User
.PP
The PAM service modules do not communicate directly with the user;
instead they rely on the application to perform all
such interactions. The application passes a pointer to the
function,
.BR conv(\|),
along with any associated application data
pointers, through the
.B pam_conv
structure when it initiates an
authentication transaction (via a call to
.BR pam_start(\|) ).
The service module will then use the function,
.BR conv(\|) ,
to prompt the user for data, output error messages,
and display text information.
Refer to
.BR pam_start (3)
for more information.
The modules are responsible for the localization of all
messages to the user.
.SH CONVENTIONS
.PP
By convention, applications that need to prompt for a user name should
call
.BR pam_set_item(\|)
and set the value of PAM_USER_PROMPT before calling
.BR pam_authenticate(\|) .
The service module's
.BR pam_sm_authenticate(\|)
function will then call
.BR pam_get_user(\|)
to prompt for the user name. Note that
certain PAM service modules (such as a smart card module) may override
the value of PAM_USER_PROMPT and pass in their own prompt.
.PP
Though the PAM framework enforces no rules about the module's names,
location, options and such, there are certain conventions that all
module providers are expected to follow.
.LP
By convention, the modules should be located in the
.B /usr/lib/security
directory. Additional modules may
be located in
.B /opt/<pkg>/lib.
.LP
By convention, the modules are named
.B pam_<service_name>_<module_type>.so.1.
If the given module implements
more than one module type (for example,
.B pam_unix.so.1
module), then
the module_type suffix should be dropped.
.LP
For every such module, there should be a corresponding manual page
in section 5 which should describe the
.I module_type
it supports,
the functionality of the module, along with the options it
supports. The dependencies should be clearly identified to the
system administrator. For example, it should be made clear
whether this module is a stand-alone module or depends upon the
presence of some other module. One should also specify whether
this module should come before or after some other module in the
stack.
.LP
By convention, the modules should support
the following options:
.RS
.IP debug 15
Syslog debugging information at LOG_DEBUG
level. Be careful as to not log any sensitive
information such as passwords.
.IP nowarn 15
Turn off warning messages such as "password is
about to expire"
.RE
.PP
In addition, it is recommended that the auth and the
password module support the following options:
.RS
.IP use_first_pass 15
Instead of prompting the user for the password,
use the user's initial password (entered when
the user was authenticated to the first authentication module
in the stack) for authentication.
If the passwords do not match, or if no
password has been entered, return failure and do not
prompt the user for a password. Support for
this scheme allows the user to type only one
password for multiple schemes.
.IP try_first_pass 15
Instead of prompting the user for the password,
use the user's initial password (entered when
the user was authenticated to the first authentication
module in the stack) for authentication.
If the passwords do not match, or if no password
has been entered, prompt the user for a password
after identifying which type of password (ie. UNIX,
etc.) is being requested.
Support for this scheme allows the user to try to
use only one password for multiple schemes, and type
multiple passwords only if necessary.
.RE
.PP
If an unsupported option is passed to the modules, it should
syslog the error at LOG_ERR level.
.PP
The permission bits on the service module should be set
such that it is not writable by either "group" or "other".
The PAM framework will not
load the module if the above permission rules are not followed.
.SH ERROR LOGGING
If there are any errors, the modules should log them using
.BR syslog (3)
at the LOG_ERR level.
.SH RETURN VALUES
The PAM service module functions may return any of the PAM
error numbers specified in the specific man pages. It can also
return a PAM_IGNORE error number to mean that the PAM framework
should ignore this module regardless of whether it is required, optional
or sufficient. This error number is normally returned when the
module does not want to deal with the given user at all.
.SH SEE ALSO
.BR pam (3),
.BR pam_start (3),
.BR pam_set_item (3),
.BR pam_get_user (3),
.BR pam_authenticate (3),
.BR pam_open_session (3),
.BR pam_setcred (3),
.BR pam_chauthtok (3),
.BR pam_strerror (3),
.BR pam_sm_authenticate (3),
.BR pam_sm_open_session (3),
.BR pam_sm_setcred (3),
.BR pam_sm_chauthtok (3),
.BR pam.conf (4)

View File

@@ -0,0 +1,113 @@
.\" $XConsortium: pam_sm_acct_mgmt.3 /main/5 1996/10/29 15:19:45 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.\" Don't forget to enter .IX index entries for each function.
.nr X
.TH pam_sm_acct_mgmt 3 "9 Jan 1996"
.SH NAME
pam_sm_acct_mgmt
\- Service provider implementation for pam_acct_mgmt
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
#include <security/pam_modules.h>
.ft
.fi
.LP
.BI "int pam_sm_acct_mgmt(pam_handle_t *" "pamh" ,
.BI "int " "flags" ,
.BI "int " "argc",
.BI "const char **" "argv" );
.SH DESCRIPTION
.IX "pam_sm_acct_mgmt" "" "\fLpam_sm_acct_mgmt\fP \(em account management"
In response to a call to
.BR pam_acct_mgmt (3),
the PAM framework calls
.B pam_sm_acct_mgmt(\|)
from the modules listed in the
.BR pam.conf (4)
file.
The account management provider supplies the back-end functionality for
this interface function.
The applications should not call this API directly.
.PP
The function,
.BR pam_sm_acct_mgmt(\|) ,
determines whether the current user's account and password are valid.
This includes checking for password
and account expiration, valid log-in times, etc.
The user in question is specified by a prior call to
.BR pam_start(\|) ,
and is referenced by the authentication handle,
.IR pamh,
which is passed as the first argument to
.B pam_sm_acct_mgmt(\|).
The following flags may be set in the
.IR flags
field:
.RS
.IP PAM_SILENT 30
The account management service should not generate any messages
.IP PAM_DISALLOW_NULL_AUTHTOK 30
The account management service should return PAM_AUTHTOKEN_REQD
if the user has a null authentication token
.RE
.PP
The
.I argc
argument
represents the number of module options passed in from the configuration file
.BR pam.conf (4).
.I argv
specifies the module options, which are interpreted and processed
by the account management service. Please refer to the specific
module man pages for the various available
.I options.
If an unknown option is passed to the module, an error should be
logged through
.BR syslog (3)
and the option ignored.
.PP
If an account management module determines that the user
password has aged or expired, it should save this information
as state in the authentication handle,
.I pamh,
using
.BR pam_set_data(\|) .
.B pam_chauthok(\|)
uses this information to determine which passwords have
expired.
.SH "RETURN VALUES"
.PP
If there are no restrictions to logging in, PAM_SUCCESS is returned.
The following error values may also be returned upon error:
.RS
.IP PAM_USER_UNKNOWN 30
User not known to underlying authentication module
.IP PAM_AUTHTOKEN_REQD 30
New authentication token required
.IP PAM_ACCT_EXPIRED 30
User account has expired
.IP PAM_PERM_DENIED 30
User denied access to account at this time
.IP PAM_IGNORE 30
Ignore underlying account module regardless of whether the control
flag is
.I required, optional
or
.I sufficient
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_acct_mgmt (3),
.BR syslog (3),
.BR pam.conf (4)

View File

@@ -0,0 +1,130 @@
.\" $XConsortium: pam_sm_authenticate.3 /main/5 1996/10/29 15:19:54 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.\" Don't forget to enter .IX index entries for each function.
.nr X
.TH pam_sm_authenticate 3 "9 Jan 1996"
.SH NAME
pam_sm_authenticate
\- Service provider implementation for pam_authenticate
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
#include <security/pam_modules.h>
.ft
.fi
.LP
.BI "int pam_sm_authenticate(pam_handle_t *" "pamh" ,
.BI "int " "flags" ,
.BI "int " "argc",
.BI "const char **" "argv");
.SH DESCRIPTION
.IX "pam_auth" "" "\fLpam_auth\fP \(em request authentication"
In response to a call to
.BR pam_authenticate (3),
the PAM framework calls
.B pam_sm_authenticate(\|)
from the modules listed in the
.BR pam.conf (4)
file.
The authentication provider supplies the back-end functionality for
this interface function.
.LP
The function,
.BR pam_sm_authenticate(\|) ,
is called to verify the identity of the current user.
The user is usually required to enter
a password or similar authentication token depending upon
the authentication scheme configured within the system.
The user in question is specified by a prior call to
.BR pam_start(\|) ,
and is referenced by the authentication handle,
.IR pamh.
.LP
If the user is unknown to the authentication service,
the service module should mask this error
and continue to prompt the user for a password.
It should then return the error,
PAM_USER_UNKNOWN.
.LP
The following flag may be passed in to
.B pam_sm_authenticate(\|):
.RS
.IP PAM_SILENT 35
The authentication service should not generate any messages
.IP PAM_DISALLOW_NULL_AUTHTOK 35
The authentication service should return PAM_AUTH_ERROR
if the user has a null authentication token
.RE
.PP
The
.I argc
argument
represents the number of module options passed in from the configuration file
.BR pam.conf (4).
.I argv
specifies the module options, which are interpreted and processed
by the authentication service.
Please refer to the specific module man pages
for the various available
.I options.
If any unknown option is passed in, the module should log the error and
ignore the option.
.LP
Before returning,
.B pam_sm_authenticate(\|)
should call
.B pam_get_item(\|)
and retrieve PAM_AUTHTOK.
If it has not been set before (ie. the value is NULL),
.B pam_sm_authenticate(\|)
should set it to the password entered by the user
using
.BR pam_set_item(\|) .
.PP
An authentication module may save the authentication status
(success or reason for failure)
as state in the authentication handle using
.BR pam_set_data (3).
This information is intended for use by
.BR pam_setcred(\|) .
.SH NOTES
Modules should not retry the authentication in the event of a failure.
Applications handle authentication retries and maintain the retry count.
To limit the number of retries, the module can return a
PAM_MAXTRIES error.
.SH "RETURN VALUES"
.PP
Upon successful completion, PAM_SUCCESS must be returned.
In addition, the following values may be returned:
.RS
.IP PAM_MAXTRIES 29
Maximum number of authentication attempts exceeded
.IP PAM_AUTH_ERR 29
Authentication failure
.IP PAM_CRED_INSUFFICIENT 29
Can not access authentication data due to insufficient credentials
.IP PAM_AUTHINFO_UNAVAIL 29
Underlying authentication service can not retrieve authentication information
.IP PAM_USER_UNKNOWN 29
User not known to underlying authentication module
.IP PAM_IGNORE 29
Ignore underlying authentication module regardless of whether the control
flag is
.I required, optional
or
.I sufficient
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_authenticate (3),
.BR pam.conf (4)

View File

@@ -0,0 +1,159 @@
.\" $XConsortium: pam_sm_chauthtok.3 /main/5 1996/10/29 15:20:04 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_sm_chauthtok 3 "9 Jan 1996"
.SH NAME
pam_sm_chauthtok
\- Service provider implementation for pam_chauthtok
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
#include <security/pam_modules.h>
.ft
.fi
.LP
.BI "int pam_sm_chauthtok(pam_handle_t " "*pamh" ,
.BI "const int " "flags");
.SH DESCRIPTION
.IX "pam_authtok" "" "\fLpam_authtok\fP \(em request changing authentication token"
In response to a call to
.BR pam_chauthtok (3)
the PAM framework calls
.BR pam_sm_chauthtok (3)
from the modules listed in the
.BR pam.conf (4)
file.
The password management provider
supplies the back-end functionality for
this interface function.
.PP
.B pam_sm_chauthtok(\|)
changes the authentication token associated with a
particular user referenced by the authentication handle,
.IR pamh.
.LP
The following flag may be passed in to
.BR pam_chauthtok(\|) :
.RS
.IP PAM_SILENT 30
The password service should not generate any messages
.IP PAM_CHANGE_EXPIRED_AUTHTOK 30
The password service should only update those passwords that have aged.
If this flag is not passed, the password service should update all passwords.
.IP PAM_PRELIM_CHECK 30
The password service should only perform preliminary checks.
No passwords should be updated.
.IP PAM_UPDATE_AUTHTOK 30
The password service should update passwords
.RE
.LP
Note that PAM_PRELIM_CHECK and PAM_UPDATE_AUTHTOK can not be
set at the same time.
.LP
Upon successful completion of the call, the authentication
token of the user will be ready for change or will be changed
(depending upon the flag)
in accordance with the authentication scheme
configured within the system.
.PP
The
.I argc
argument
represents the number of module options passed in from the configuration file
.BR pam.conf (4).
.I argv
specifies the module options, which are interpreted and processed
by the password management service. Please refer to the specific
module man pages for the various available
.I options.
.LP
It is the responsibility of
.B pam_sm_chauthtok(\|)
to determine if the new password meets certain strength requirements.
.B pam_sm_chauthtok(\|)
may continue to re-prompt the user (for a limited number of times)
for a new password until the password entered
meets the strength requirements.
.LP
Before returning,
.B pam_sm_chauthtok(\|)
should call
.B pam_get_item(\|)
and retrieve both PAM_AUTHTOK
and PAM_OLDAUTHTOK. If both are NULL,
.B pam_sm_chauthtok(\|)
should set them to the new and old passwords
as entered by the user.
.SH NOTES
The
.SM PAM
framework invokes the password services twice. The first time the modules
are invoked with the flag, PAM_PRELIM_CHECK.
During this stage, the password modules should only perform preliminary
checks (ping remote name services to see if they are
ready for updates, for example). If a password module
detects a transient error (remote name service temporarily down, for example)
it should return PAM_TRY_AGAIN to the
.SM PAM
framework, which
will immediately return the error back to the application.
If all password modules pass the preliminary check, the
.SM PAM
framework invokes the password services again with the flag,
PAM_UPDATE_AUTHTOK. During this stage, each password module should
proceed to update the appropriate password. Any error will again be
reported back to application.
.LP
If a service module receives the flag, PAM_CHANGE_EXPIRED_AUTHTOK,
it should check whether the password has aged or expired.
If the password has aged or expired,
then the service module should proceed to update the password.
If the status indicates that the
password has not yet aged/expired, then the password module
should return PAM_IGNORE.
.LP
If a user's password has aged or expired, a
.SM PAM
account module could save this information as state
in the authentication handle,
pamh, using
.BR pam_set_data(\|) .
The related password management module could retreive this information
using
.B pam_get_data(\|)
to determine whether or not it should prompt
the user to update the password for this particular module.
.SH "RETURN VALUES"
.PP
Upon successful completion, PAM_SUCCESS must be returned.
The following values may also be returned:
.RS
.IP PAM_PERM_DENIED 34
No permission
.IP PAM_AUTHTOK_ERR 34
Authentication token manipulation error
.IP PAM_AUTHTOK_RECOVERY_ERR 34
Old authentication token cannot be recovered
.IP PAM_AUTHTOK_LOCK_BUSY 34
Authentication token lock busy
.IP PAM_AUTHTOK_DISABLE_AGING 34
Authentication token aging disabled
.IP PAM_USER_UNKNOWN 34
User unknown to password service
.IP PAM_TRY_AGAIN 34
Preliminary check by password service failed
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_chauthtok (3),
.BR pam.conf (4)

View File

@@ -0,0 +1,92 @@
.\" $XConsortium: pam_sm_open_session.3 /main/5 1996/10/29 15:20:14 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_sm_open_session 3 "9 Jan 1996"
.SH NAME
pam_sm_open_session, pam_sm_close_session
\- Service provider implementation for pam_open_session and pam_close_session respectively
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
#include <security/pam_modules.h>
.ft
.fi
.LP
.BI "int pam_sm_open_session(pam_handle_t " "*pamh" ,
.BI "int " "flags" ,
.BI "int " "argc",
.BI "const char **" "argv" );
.LP
.BI "int pam_sm_close_session(pam_handle_t " "*pamh" ,
.BI "int " "flags" ,
.BI "int " "argc",
.BI "const char **" "argv" );
.SH DESCRIPTION
.IX "pam_sm_open_session" "" "\fLpam_open_session\fP \(em session management"
In response to a call to
.RB pam_open_session (3)
and
.BR pam_close_session (3),
the PAM framework calls
.B pam_sm_open_session(\|)
and
.BR pam_sm_close_session(\|) ,
respectively from the modules listed in the
.BR pam.conf (4)
file. The session management provider supplies the back-end functionality for
this interface function.
.PP
.B pam_sm_open_session(\|)
is called to initiate session management.
.B pam_sm_close_session(\|)
is invoked when a session has terminated.
The argument
.IR pamh
is an authentication handle.
The following flag may be set in the
.IR flags
field:
.RS
.IP PAM_SILENT 16
Session service should not generate any messages
.RE
The
.I argc
argument
represents the number of module options passed in from the configuration file
.BR pam.conf (4).
.I argv
specifies the module options, which are interpreted and processed
by the session management service. If an unknown option is passed in,
an error should be logged through
.BR syslog (3)
and the option ignored.
.SH "RETURN VALUES"
.PP
Upon successful completion, PAM_SUCCESS should be returned.
The following values may also be returned upon error:
.RS
.IP PAM_SESSION_ERR 22
Can not make/remove an entry for the specified session
.IP PAM_IGNORE 22
Ignore underlying session module regardless of whether the control
flag is
.I required, optional
or
.I sufficient
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_open_session (3),
.BR syslog (3),
.BR pam.conf (4)

View File

@@ -0,0 +1,114 @@
.\" $XConsortium: pam_sm_setcred.3 /main/5 1996/10/29 15:20:23 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_sm_setcred 3 "9 Jan 1996"
.SH NAME
pam_sm_setcred \- Service provider implementation for pam_setcred
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
#include <security/pam_modules.h>
.ft
.fi
.LP
.BI "int pam_sm_setcred(pam_handle_t " "*pamh" ,
.BI "int " "flags" ,
.BI "int " "argc",
.BI "const char **" "argv" );
.SH DESCRIPTION
.IX "pam_setcred" "" "\fLpam_setcred\fP \(em request setting credentials"
In response to a call to
.BR pam_set_cred (3),
the PAM framework calls
.B pam_sm_setcred(\|)
from the modules listed in the
.BR pam.conf (4)
file. The authentication provider supplies the back-end functionality for
this interface function.
.PP
.B pam_sm_setcred(\|)
is called to set the credentials of the current user
associated with the authentication handle,
.IR pamh.
The following flags may be set in the
.IR flags
field. Note that the first four flags are mutually exclusive:
.RS
.IP "PAM_CRED_ESTABLISH" 26
Set user credentials for the authentication service
.IP "PAM_CRED_DELETE" 26
Delete user credentials associated with the authentication service
.IP "PAM_CRED_REINITIALIZE" 26
Reinitialize user credentials
.IP "PAM_CRED_REFRESH" 26
Extend lifetime of user credentials
.IP "PAM_SILENT" 26
Authentication service should not generate messages
.RE
.PP
If none of these flags are set, PAM_CRED_ESTABLISH is used as
the default.
.PP
The
.I argc
argument
represents the number of module options passed in from the configuration file
.BR pam.conf (4).
.I argv
specifies the module options, which are interpreted and processed
by the authentication service. If an unknown option is passed to the
module, an error should be logged and the option ignored.
.LP
If the PAM_SILENT flag is not set, then
.B pam_sm_setcred(\|)
should print any failure status from the corresponding
.B pam_sm_authenticate(\|)
function using the conversation function.
.PP
The authentication status (success or reason for failure)
is saved as module-specific state in the authentication
handle by the authentication module.
The status should be retreived using
.BR pam_get_data(\|) ,
and used to determine if user credentials should be set.
.SH NOTES
.PP
.B pam_sm_setcred(\|)
is passed the same module options that are used by
.BR pam_sm_authenticate(\|) .
.SH "RETURN VALUES"
.PP
Upon successful completion, PAM_SUCCESS should be returned.
The following values may also be returned upon error:
.RS
.IP PAM_CRED_UNAVAIL 25
Underlying authentication service can not retrieve user credentials
.IP PAM_CRED_EXPIRED 25
User credentials have expired
.IP PAM_USER_UNKNOWN 25
User unknown to the authentication service
.IP PAM_CRED_ERR 25
Failure in setting user credentials
.IP PAM_IGNORE 25
Ignore underlying authentication module regardless of whether the
control flag is
.I required, optional
or
.I sufficient
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_authenticate (3),
.BR pam_setcred (3),
.BR pam_sm_authenticate (3),
.BR pam.conf (4)

View File

@@ -0,0 +1,223 @@
.\" $XConsortium: pam_start.3 /main/5 1996/10/29 15:20:32 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.\" Don't forget to enter .IX index entries for each function.
.nr X
.TH pam_start 3 "9 Jan 1996"
.SH NAME
pam_start, pam_end
\- authentication transaction routines for PAM
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.BI "int pam_start(const char *" "service" ,
.BI "const char *" "user" ,
.BI "const struct pam_conv *" "pam_conv" ,
.BI "pam_handle_t " "**pamh");
.LP
.BI "int pam_end(pam_handle_t *" "pamh" ,
.BI "int" " status" );
.SH DESCRIPTION
.IX "pam_start" "" "\fLpam_start\fP \(em initiate authentication transaction"
.B pam_start(\|)
is called to initiate an authentication transaction.
.B pam_start(\|)
takes as arguments the name of the current service,
.IR service,
the name of the user to be authenticated,
.IR user,
the address of the conversation structure,
.IR pam_conv,
and the address of a variable to be assigned the authentication handle,
.IR pamh.
Upon successful completion,
.IR pamh
will refer to a
.SM PAM
handle for use with subsequent calls to the authentication library.
.LP
The pam_conv structure,
.IR pam_conv,
contains the address of the conversation function provided by the
application. The underlying
.SM PAM
service module invokes this function
to output information to and retrieve input from the user.
The
.IR pam_conv
structure has the following entries:
.RS
.PP
.nf
.ft 3
struct pam_conv {
int (\(**conv)(); /* Conversation function */
void \(**appdata_ptr; /* Application data */
};
.ft 1
.fi
.RE
where
.RS
.PP
.nf
.ft 3
int conv(int num_msg,
const struct pam_message **msg, struct pam_response **resp,
void *appdata_ptr);
.ft 1
.fi
.RE
.LP
The function
.B conv(\|)
is called by a service module to hold a
.SM PAM
conversation with the application or user.
For window applications, the application can create a new
pop-up window to be used by the interaction.
.PP
The parameter
.IR num_msg
is the number of messages associated with the call.
The parameter
.IR msg
is a pointer to an array of length
.IR num_msg
of the
.IR pam_message
structure.
.PP
The structure
.IR pam_message
is used to pass prompt, error message, or any text
information from the authentication service to the application or user.
It is the responsibility of the
.SM PAM
service modules to localize the messages.
The memory used by
.IR pam_message
has to be allocated and freed by the PAM modules.
The
.IR pam_message
structure has the following entries:
.RS
.PP
.nf
.ft 3
struct pam_message{
int msg_style;
char \(**msg;
};
.ft 1
.fi
.RE
.PP
The message style,
.IR msg_style,
can be set to one of the following values:
.RS
.PP
.nf
.ft 1
.IP PAM_PROMPT_ECHO_OFF 26
prompt user, disabling echoing of response
.IP PAM_PROMPT_ECHO_ON 26
prompt user, enabling echoing of response
.IP PAM_ERROR_MSG 26
print error message
.IP PAM_TEXT_INFO 26
print general text information
.\"};
.ft 1
.fi
.RE
.PP
The maximum size of the message and the response string is
PAM_MAX_MSG_SIZE defined in
.BR <security/pam.appl.h> .
.PP
The structure
.I pam_response
is used by the authentication service to get the user's response back from
the application or user.
The storage used by
.I pam_response
has to be allocated by the application and freed by the PAM modules.
The
.I pam_response
structure has the following entries:
.RS
.PP
.nf
.ft 3
struct pam_response{
char \(**resp;
int resp_retcode; /* currently not used, should be set to 0 */
};
.ft 1
.fi
.RE
.LP
It is the responsibility of the conversation function
to strip off newline characters for
.SM PAM_PROMPT_ECHO_OFF
and
.SM PAM_PROMPT_ECHO_ON
message styles, and to add
newline characters (if appropriate) for
.SM PAM_ERROR_MSG
and
.SM PAM_TEXT_INFO
message styles.
.PP
.I appdata_ptr
is an application data pointer which is passed by the application
to the PAM service modules.
Since the PAM modules pass it back through the conversation function,
the applications can use this pointer to point to any application-specific
data.
.LP
.B pam_end(\|)
is called to terminate the authentication transaction identified
by
.I pamh
and to free any
storage area allocated by the authentication module.
The argument,
.IR status ,
is passed to the
.I cleanup(|\)
function stored within the pam handle, and is used to determine
what module specific state must be purged. A cleanup function
is attached to the handle by the underlying
.SM PAM
modules through a call to
.BR pam_set_item (3)
to free module specific data.
.SH "RETURN VALUES"
.PP
Refer to
.BR pam (3)
for information on error related return values.
.SH "SEE ALSO"
.BR pam_authenticate (3),
.BR pam_set_item (3),
.BR pam_acct_mgmt (3),
.BR pam_open_session (3),
.BR pam_setcred (3),
.BR pam_chauthtok (3),
.BR pam_strerror (3),
.BR pam (3)

View File

@@ -0,0 +1,60 @@
.\" $XConsortium: pam_strerror.3 /main/5 1996/10/29 15:20:47 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_strerror 3 "9 Jan 1996"
.SH NAME
pam_strerror \- get PAM error message string
.SH SYNOPSIS
.LP
.B cc
.RI "[ " "flag" " \|.\|.\|. ] " "file" " \|.\|.\|."
.B \-lpam
.RI "[ " "library" " \|.\|.\|. ]"
.LP
.nf
.ft 3
#include <security/pam_appl.h>
.ft
.fi
.LP
.BI "const char *pam_strerror(pam_handle_t" "*pamh" ,
.BI "int " "errnum" );
.SH DESCRIPTION
.IX "string operation" "get PAM error message string" "" "get PAM error message string \(em \fLpam_strerror\fP"
.IX "PAM error messages" "get string" "" "get string \(em \fLpam_strerror\fP"
.B pam_strerror(\|)
maps the
.SM PAM
error number in
.I errnum
to a
.SM PAM
error message string, and returns a pointer to that string.
The application should not free or modify the string returned.
.LP
The
.I pamh
arguement is the
.SM PAM
handle obtained by a prior call to
.BR pam_start(\|) .
If
.B pam_start(\|)
returns an error, a
.SB NULL
.SM PAM
handle should be passed.
.SH ERRORS
.LP
.B pam_strerror(\|)
returns
.SB NULL
if
.I errnum
is out-of-range.
.SH "SEE ALSO"
.BR pam (3),
.BR pam_start (3)

View File

@@ -0,0 +1,348 @@
.\" $XConsortium: pam.conf.4 /main/5 1996/10/29 15:41:38 drk $
.\" @(#)pam.conf.4 1.1 95/06/05 SMI; from SVr4
'\" macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.\"
.nr X
.TH pam.conf 4 "19 Jan 1996"
.SH NAME
pam.conf \- configuration file for pluggable authentication modules
.SH SYNOPSIS
.B /etc/pam.conf
.SH DESCRIPTION
.IX "pam.conf" "" "\fLpam.conf\fP \(em configuration file for pluggable authentication modules"
.PP
.B pam.conf
is the configuration file for the Pluggable Authentication Module architecture, or
.SM PAM.
A
.SM PAM
module provides functionality for one or more of four possible services:
authentication, account management, session management, and
password management.
An authentication service module provides
functionality to authenticate a user and
set up user credentials.
A account management module provides
functionality to determine if the current
user's account is valid.
This includes checking for password and account expiration,
as well as verifying access hour restrictions.
A session management module provides functionality
to set up and terminate login sessions.
A password management module provides functionality to change a user's
authentication token or password.
Each of the four service modules can be implemented as a shared library
object which can be referenced in the
.B pam.conf
configuration file.
.SH Simplified PAM.CONF configuration file
The
.B pam.conf
file contains a listing of services. Each service is paired with a
corresponding service module. When a service is requested, its
associated module is invoked. Each entry has the following format:
.IP
.I <service_name> <module_type> <control_flag> <module_path> <options>
.LP
Below is an example of the
.B pam.conf
configuration file with support for authentication, account management,
and session management modules.
.nf
.RS
.ta .7in +.8in +.8in +2.2in
login auth required /usr/lib/security/pam_unix.so.1 debug
login session required /usr/lib/security/pam_unix.so.1
login account required /usr/lib/security/pam_unix.so.1
telnet session required /usr/lib/security/pam_unix.so.1
other auth required /usr/lib/security/pam_unix.so.1
other passwd required /usr/lib/security/pam_unix.so.1
.RE
.fi
.ft 1
The
.I service_name
denotes the service (for example,
.BR login ,
.BR dtlogin ,
or
.BR rlogin ).
The keyword,
.IR other ,
indicates the module all other applications which have not
been specified should use. The
.I other
keyword can also be used if all services of the same
.I module_type
have the same requirements. In the example above, since all of the services use
the same session module, they could have been replace by
a single
.I other
line.
.LP
\fImodule_type\fP denotes the service module type:
authentication (\fIauth\fP),
account management (\fIaccount\fP),
session management (\fIsession\fP), or
password management (\fIpassword\fP).
.LP
The
\fIcontrol_flag\fP field determines the behavior of stacking, and will be
discussed in more detail below.
.LP
The
\fImodule_path\fP field specifies the pathname to a shared library object
which implements the service functionality.
If the pathname is not absolute, it is assumed to be relative
to
.B /usr/lib/security.
.LP
The \fIoptions\fP field is used by the
.SM PAM
framework layer to pass module specific options to the modules. It is
up to the module to parse and interpret the options. This field can
be used by the modules to turn on debugging or to pass any module
specific parameters such as a TIMEOUT value. It can also be used to
support unified login. The options supported by
the modules are documented in their respective manual pages. For example,
.BR pam_unix (5)
lists the options accepted by the UNIX module.
.LP
.SH Integrating Multiple Authentication Services With Stacking
When a service_name of the same
.I module_type
is defined more than once, the service is said to be
.I stacked.
Each module referenced in the
.I module_path
for that service is then processed in the order that it occurs
in the configuration file.
The
.I control_flag
field specifies the continuation and failure semantics of the modules,
and may be
.IR required ,
.IR optional ,
or
.IR sufficient .
.LP
The PAM framework processes each service module in the stack.
If all
.I required
modules in the stack succeed, then success is returned
.RI ( optional
and
.I sufficient
error values are ignored). If one or more
.I required
modules fail, then the error value from the first
.I required
module that failed is returned.
.LP
If none of the service modules in the stack are designated as
.I required,
then the PAM framework requires that at least one
.I optional
or
.I sufficient
module succeed. If all fail then the
error value from the first service module in the stack is returned.
.LP
The only exception to the above is caused by the
.I sufficient
flag. If a service module that is designated as
.I sufficient
succeeds, then the
.SM PAM
framework immediately returns success
to the application (all subsequent services modules,
even
.I required
ones, in the stack are
ignored), given that all prior
.I required
modules had also succeeded. If a prior
.I required
module failed, then the error value from that module is returned.
.LP
If a module does not exist or can not be opened,
then the
.B pam.conf
entry is ignored and an error will be logged through
.BR syslog (3)
at the LOG_CRIT level.
Below is a sample configuration file that stacks the
.B login,
.B dtlogin,
and
.B rlogin
services.
.nf
.RS
login auth required /usr/lib/security/pam_unix.so.1 debug
login auth optional /usr/lib/security/pam_inhouse.so.1
dtlogin auth required /usr/lib/security/pam_unix.so.1 debug
dtlogin auth optional /usr/lib/security/pam_inhouse.so.1
rlogin auth sufficient /usr/lib/security/pam_rhosts_auth.so.1
rlogin auth required /usr/lib/security/pam_unix.so.1
.RE
.fi
.ft 1
In the case of
.B login,
the user is authenticated by the UNIX and inhouse authentication modules. The
.I required
keyword for
.I control_flag
requires that the user be allowed to login only if the user is authenticated
by the UNIX service module.
Inhouse authentication is optional by
virtue of the
.I optional
keyword in the
.I control_flag
field. The user can still log in even if inhouse authentication fails.
In the case of
.BR rlogin ,
the
.I sufficient
keyword for
.I control_flag
specifies that if the
.I rhosts
authentication check succeeds, then PAM should return success to
.B rlogin
and
.B rlogin
should not prompt the user for a password.
The UNIX authentication module (the next module in the stack)
will only be invoked if the
.I rhosts
check fails. This gives the system administrator the flexibility to determine
if
.I rhosts
alone is sufficient enough to authenticate a remote user.
.LP
Some modules may return PAM_IGNORE in certain situations.
In these cases the
.SM PAM
framework ignores the entire entry in
.B pam.conf
regardless of whether or not it is
.IR required ,
.I optional
or
.IR sufficient .
.SH NOTES
If an error is found in an entry due to invalid
.IR service_name ,
.IR module_type ,
or
.IR control_flag ,
then the entry is ignored.
If there are no valid entries for the given
.I module_type,
the
.SM PAM
framework returns an error to the application.
.LP
.SH EXAMPLES
.PP
The following is a sample pam.conf configuration file. Lines that begin
with the
.I #
symbol are treated as comments, and therefore ignored.
.PP
.nf
#
# PAM configuration
#
# Authentication management for login service is stacked.
# Both UNIX and inhouse authentication functions are invoked.
login auth required /usr/lib/security/pam_unix.so.1
login auth required /usr/lib/security/pam_inhouse.so.1 try_first_pass
dtlogin auth required /usr/lib/security/pam_unix.so.1
dtlogin auth required /usr/lib/security/pam_inhouse.so.1 try_first_pass
#
# Authentication management for rlogin service is stacked.
# If the rhost check succeeds, do not continue
rlogin auth sufficient /usr/lib/security/pam_rhosts_auth.so.1
rlogin auth required /usr/lib/security/pam_unix.so.1
#
# Other services use UNIX authentication
other auth required /usr/lib/security/pam_unix.so.1
#
# Account management for login service is stacked.
# UNIX account management is required; inhouse account management is optional
login account required /usr/lib/security/pam_unix.so.1
login account optional /usr/lib/security/pam_inhouse.so.1
dtlogin account required /usr/lib/security/pam_unix.so.1
dtlogin account optional /usr/lib/security/pam_inhouse.so.1
other account required /usr/lib/security/pam_unix.so.1
#
# Session management
other session required /usr/lib/security/pam_unix.so.1
#
# Password management
other password required /usr/lib/security/pam_unix.so.1
.fi
.ft 1
.SH Utilities and files
A list of utilities that are known to use
.SM PAM
include:
.BR login ,
.BR passwd ,
.BR su ,
.BR dtlogin ,
.BR rlogind ,
.BR rshd ,
.BR telnetd ,
.BR ftpd ,
.BR rpc.rexd ,
.BR uucpd ,
.BR init ,
.BR sac ,
and
.BR ttymon .
.LP
The PAM configuration file does not dictate either the name or the
location of the service specific modules. The convention, however, is the
following:
.LP
.TP
.B /usr/lib/security/pam_<service_name>_<module_name>.so.x
implements various function of specific authentication services.
.LP
.TP
.PD 0
.B /etc/pam.conf
configuration file
.TP
.B /usr/lib/libpam.so.1
implements the PAM framework library
.sp 1n
.SH "SEE ALSO"
.BR dtlogin (1),
.BR init (1)
.BR in.ftpd (1M),
.BR in.rexd (1M),
.BR in.rshd (1M),
.BR in.rlogind (1M),
.BR in.telnetd (1M),
.BR in.uucpd (1),
.BR login (1),
.BR passwd (1),
.BR sac (1M),
.BR su (1M),
.BR ttymon (1M),
.BR pam (3)

View File

@@ -0,0 +1,146 @@
.\" $XConsortium: pam_dce.5 /main/5 1996/10/29 15:41:52 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_dce 5 "19 Jan 1996"
.SH NAME
pam_dce \- authentication, account, and password management PAM functions for DCE
.SH SYNOPSIS
.LP
.B /usr/lib/security/pam_dce.so.1
.P
.LP
.SH DESCRIPTION
.IX "pam_dce" "" "\fLpam_dce\fP \(em authentication, account, and password management for DCE"
.PP
The DCE PAM module allows for integration of DCE into the system entry services
(such as
.BR login )
through the
.BR pam.conf (4)
file.
The DCE service module for PAM consists of
three components:
authentication, account management, and password management.
All three components are supported through the same loadable library,
.BR /usr/lib/security/pam_dce.so.1 .
.SH DCE Authentication Module
The DCE authentication component
provides functions to verify the identity of a user
(\f3pam_sm_authenticate\f1(3)),
and to initialize DCE credentials
(\f3pam_sm_setcred\f1(3)).
The DCE implementation of the
.BR pam_sm_authenticate (3)
function compares the user entered password with the password from the DCE Security
Service (i.e., the DCE Registry). If the passwords match, the user is
authenticated and obtains DCE credentials.
The following options may be passed to the DCE Authentication module:
.RS
.IP debug 15
Syslog debugging information at the LOG_DEBUG level.
.IP nowarn 15
Turns off warning messages about not being able to acquire DCE credentials.
.IP use_first_pass 15
Use the user's initial password (entered when the user is authenticated to the
first authentication module in the stack) to authenticate with DCE.
If the passwords do not match, or if this is the first authentication module in the
stack, quit and do not prompt the user for a password. It is
recommended that this option only be used if the DCE authentication
module is designated as
.I optional
in the
.B pam.conf
configuration file.
.IP try_first_pass 15
Use the user's initial password (entered when the user is authenticated to the
first authentication module in the PAM stack) to authenticate with DCE. If the
passwords do not match, or if this is the first authentication module in the
stack, prompt the user for a password.
.IP use_mapped_pass 15
This option will attempt to retrieve the "onc_dce_passwd" attribute from
the user's XFN context and use the user's initial password to decrypt
the DCE password stored in this attribute. If the DCE password stored in
this attribute is incorrect, then quit and do not prompt the user for a
password. It is recommended that this option only be used if the DCE
authentication module is designated as
.I optional.
.IP try_mapped_pass 15
Similar to
.B use_mapped_pass
with two exceptions. If the DCE password is incorrect,
prompt for it. Once a valid DCE password is entered, encrypt it
using the initial (first) password and store the encrypted value in the
"onc_dce_passwd" attribute in the user's XFN context.
.PP
Note that both
.B use_mapped_pass
and
.B try_mapped_pass
require that the UNIX authentication module (see
.BR pam_unix (5))
occurs before the DCE
authentication module. This to ensure that the user's secure RPC credentials
(for XFN/NIS+) have already been acquired.
.RE
If the user's DCE account has expired then an
error will be returned from
.BR pam_sm_authenticate (3).
.PP
In order to authenticate the user to the DCE security service
.BR pam_sm_authenticate (3)
calls
.BR sec_login_setup_identity (3)
followed by
.BR sec_login_valid_and_cert_ident (3).
.PP
.BR pam_sm_setcred (3)
calls the function
.BR sec_login_set_context (3)
to set the DCE credentials after they have been validated by
.BR pam_sm_authenticate .
.SH DCE Account Management Module
The DCE account management component
provides a function to perform account management
(\f3pam_sm_acct_mgmt\f1(3)).
The DCE implementation of the
.BR pam_sm_acct_mgmt (3)
function retrieves the user's account and password expiration information from
the DCE Security Server and verifies that the user's account and password
have not expired.
The following options may be passed to the DCE account module:
.RS
.IP allow_expired_passwd 20
Allows a user with an expired password to login.
.IP debug 20
Syslog debugging information at the LOG_DEBUG level.
.IP nowarn 20
Turns off the warning messages displayed when a user's account and/or
password are going to expire.
.RE
.PP
.BR pam_sm_acct_mgmt (3)
calls the function
.BR sec_login_inquire_net_info (3)
to retrieve information about when a user's account and/or password is
going to expire.
.SH DCE Password Management Module
The DCE password management component
provides a function to change passwords
(\f3pam_sm_chauthtok\f1(3)).
The following option may be passwd to the DCE account module:
.RS
.IP debug 15
Syslog debugging information at the LOG_DEBUG level.
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR sec_login_setup_identity (3),
.BR sec_login_valid_and_cert_ident (3),
.BR sec_login_set_context (3),
.BR sec_login_inquire_net_info (3),
.BR pam.conf (4),
.BR pam_unix (5)

View File

@@ -0,0 +1,68 @@
.\" $XConsortium: pam_dial_auth.5 /main/4 1996/10/29 15:42:09 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_dial_auth 5 "19 Jan 1996"
.SH NAME
pam_dial_auth \- authentication management PAM module for dialups
.SH SYNOPSIS
.LP
.B /usr/lib/security/pam_dial_auth.so.1
.LP
.SH DESCRIPTION
.IX "pam_dial_auth" "" "\fLpam_dial_auth\fP \(em authentication management for dialups"
.PP
The dialup PAM module,
.BR /usr/lib/security/pam_dial_auth.so.1 ,
authenticates a user according to the
.B /etc/dialups
and
.B /etc/d_passwd
files.
Only
.B pam_sm_authenticate(\|)
is implemented within this module.
.B pam_sm_setcred(\|)
is a null function.
.B /usr/lib/security/pam_dial_auth.so.1
is designed to be stacked immediately below
the
.B /usr/lib/security/pam_unix.so.1
module
for the login service.
.PP
.B pam_sm_authenticate(\|)
performs authentication only if both the
.B /etc/dialups
and
.B /etc/d_passwd
files exist.
The user's terminal line is checked against
entries in the
.B /etc/dialups
file.
If there is a match, the user's
shell is compared against entries in the
.B /etc/d_passwd
file.
If there is a matching entry, the user is
prompted for a password which is validated against the entry
in the
.B /etc/d_passwd
file. If the passwords match, the
user is authenticated.
The following option may be passed in to this service module:
.RS
.IP debug 15
.BR syslog (3)
debugging information at LOG_DEBUG level
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_authenticate (3),
.BR d_passwd (4),
.BR dialups (4),
.BR pam.conf (4)

View File

@@ -0,0 +1,62 @@
.\" $XConsortium: pam_rhosts_auth.5 /main/4 1996/10/29 15:42:24 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_rhosts_auth 5 "19 Jan 1996"
.SH NAME
pam_rhosts_auth \- authentication management PAM modules using ruserok()
.SH SYNOPSIS
.LP
.B /usr/lib/security/pam_rhosts_auth.so.1
.LP
.SH DESCRIPTION
.IX "pam_rhosts_auth" "" "\fLpam_rhosts_auth\fP \(em authentication management using ruserok()"
.PP
The rhosts PAM module,
.BR /usr/lib/security/pam_rhosts_auth.so.1 ,
authenticates a user via the
.B rlogin
authentication protocol.
Only
.B pam_sm_authenticate(\|)
is implemented within this module.
.B pam_sm_authenticate(\|)
uses the
.BR ruserok (3)
library funtion to authenticate the
.B rlogin
or
.B rsh
user.
.B pam_sm_setcred(\|)
is a null function.
.PP
.B /usr/lib/security/pam_rhosts_auth.so.1
is designed to be stacked on top of
the
.B /usr/lib/security/pam_unix.so.1
module
for both the
.B rlogin
and
.B rsh
services.
This module is normally configured as
.I sufficient
so that subsequent
authentication is performed only on failure of
.BR pam_sm_authenticate(\|) .
The following option may be passed in to this service module:
.RS
.IP debug 15
.B syslog(3)
debugging information at LOG_DEBUG level
.RE
.SH "SEE ALSO"
.BR pam (3),
.BR pam_authenticate (3),
.BR ruserok (3),
.BR syslog (3),
.BR pam.conf (4)

View File

@@ -0,0 +1,206 @@
.\" $XConsortium: pam_unix.5 /main/5 1996/10/29 15:42:45 drk $
.\" Sccs id goes here
'\"macro stdmacro
.\" Copyright (c) 1995, Sun Microsystems, Inc.
.\" All Rights Reserved
.nr X
.TH pam_unix 5 "19 Jan 1996"
.SH NAME
pam_unix \- authentication, account, session, and password management PAM modules for UNIX
.SH SYNOPSIS
.LP
.B /usr/lib/security/pam_unix.so.1
.LP
.SH DESCRIPTION
.IX "pam_unix" "" "\fLpam_unix\fP \(em authentication, account, session and password management for UNIX"
.PP
The UNIX service module for PAM,
.BR /usr/lib/security/pam_unix.so.1 ,
provides functionality for all four
PAM modules: authentication, account management, session management
and password management.
The
.B pam_unix.so.1
module is a shared object
that can be dynamically loaded to provide
the necessary functionality upon demand.
Its path is specified in the
.SM PAM
configuration file.
.SH Unix Authentication Module
The UNIX authentication component
provides functions to verify the identity of a user,
(\f3pam_sm_authenticate(\|)\f1)
and to set user specific credentials
(\f3pam_sm_setcred(\|)\f1).
.B pam_sm_authenticate(\|)
compares the user entered password with the password from UNIX password
database. If the passwords match, the user is authenticated.
If the user also has secure
.SM RPC
credentials and the secure
.SM RPC
password is the same as the
.SM UNIX
password, then the secure
.SM RPC
credentials are also obtained.
.LP
The following options may be passed to the UNIX service module:
.RS
.IP debug 15
.BR syslog (3)
debugging information at LOG_DEBUG level
.IP nowarn 15
turn off warning messages
.IP use_first_pass 15
It compares the password in the password database with the user's initial
password (entered when the user authenticated to the first authentication
module in the stack). If the passwords do not match, or if no password
has been entered,
quit and do not prompt the user for a password. This option should
only be used if the authentication service is designated as
.I optional
in the
.B pam.conf
configuration file.
.IP try_first_pass 15
It compares the password in the password database with the user's initial
password (entered when the user authenticated to the first authentication
module in the stack). If the passwords do not match, or if no password
has been entered,
prompt the user for a password.
.RE
.LP
When prompting for the current password, the UNIX authentication
module will use the prompt, "password:" unless one of
the following scenarios occur:
.RS 6
.TP 5
1.
The option try_first_pass is specified and the password entered for the
first module in the stack fails for the
.SM UNIX
module.
.TP
2.
The option try_first_pass is not specified,
and the earlier authentication modules listed in the
.B pam.conf
file have prompted the user for the password.
.RE
.LP
In these two cases, the UNIX authentication module will use
the prompt "UNIX password:".
.LP
The
.B pam_sm_setcred(\|)
function sets user specific credentials.
If the user had secure
.SM RPC
credentials, but the secure
.SM RPC
password was not the same as the
.SM UNIX password,
then a warning message is printed.
If the user wants to get secure
.SM RPC
credentials, then
.BR keylogin (1)
needs to be run.
.SH Unix Account Management Module
The UNIX account management component
provides a function to perform account management
(\f3pam_sm_acct_mgmt\f1()).
The function
retrieves the user's password entry from the UNIX password database
and verifies that the user's account and password
have not expired.
The following options may be passed in to the UNIX service module:
.RS
.IP debug 15
.BR syslog (3)
debugging information at LOG_DEBUG level
.IP nowarn 15
turn off warning messages
.RE
.SH Unix Session Management Module
The UNIX session management component
provides functions to initiate
(\f3pam_sm_open_session(\|)\f1)
and terminate
(\f3pam_sm_close_session(\|)\f1)
UNIX sessions.
For UNIX ,
.B pam_open_session
updates the
.B /var/adm/lastlog
file.
The account management module reads this file to
determine the previous time the user logged in.
The following options may be passed in to the UNIX service module:
.RS
.IP debug 15
.BR syslog (3)
debugging information at LOG_DEBUG level
.IP nowarn 15
turn off warning messages
.RE
.LP
.B pam_close_session
is a NULL function.
.SH Unix Password Management Module
The UNIX password management component
provides a function to change passwords
(\f3pam_sm_chauthtok(\|)\f1)
in the UNIX password database.
This module must be
.I required
in
.B pam.conf.
It can not be
.I optional
or
.I sufficient.
The following options may be passed in to the UNIX service module:
.RS
.IP debug 15
.BR syslog (3)
debugging information at LOG_DEBUG level
.IP nowarn 15
turn off warning messages
.IP use_first_pass 15
It compares the password in the password database with the user's old
password (entered to the first password module in the stack).
If the passwords do not match, or if no password has been entered,
quit and do not prompt the user for the old password. It also attempts
to use the new password (entered to the first password module in the stack)
as the new password for this module. If the new password fails,
quit and do not prompt the user for a new password.
.IP try_first_pass 15
It compares the password in the password database with the user's old
password (entered to the first password module in the stack).
If the passwords do not match, or if no password has been entered,
prompt the user for the old password. It also attempts
to use the new password (entered to the first password module in the stack)
as the new password for this module. If the new password fails,
prompt the user for a new password.
.RE
.LP
If the user's password has expired, the UNIX account module saves
this information in the authentication handle using
.BR pam_set_data(\|) ,
with a unique name,
SUNW_UNIX_AUTHOK_DATA.
The UNIX password module retrieves this information
from the authentication handle using
.B pam_get_data(\|)
to determine whether or not to force the
user to update their password.
.SH "SEE ALSO"
.BR keylogin (1),
.BR pam (3),
.BR pam_authenticate (3),
.BR pam_setcred (3),
.BR syslog (3),
.BR pam.conf (4)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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