Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
21
cde/lib/pam/Imakefile
Normal file
21
cde/lib/pam/Imakefile
Normal 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
51052
cde/lib/pam/doc/pam.admin.mif
Normal file
File diff suppressed because it is too large
Load Diff
2363
cde/lib/pam/examples/login/login.c
Normal file
2363
cde/lib/pam/examples/login/login.c
Normal file
File diff suppressed because it is too large
Load Diff
56
cde/lib/pam/examples/login/login.dfl
Normal file
56
cde/lib/pam/examples/login/login.dfl
Normal 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=
|
||||
22
cde/lib/pam/examples/login/logindevperm
Normal file
22
cde/lib/pam/examples/login/logindevperm
Normal 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
|
||||
36
cde/lib/pam/libpam/Imakefile
Normal file
36
cde/lib/pam/libpam/Imakefile
Normal 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()
|
||||
35
cde/lib/pam/libpam/libpam.elist
Normal file
35
cde/lib/pam/libpam/libpam.elist
Normal 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
|
||||
148
cde/lib/pam/libpam/libpam.msg
Normal file
148
cde/lib/pam/libpam/libpam.msg
Normal 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:
|
||||
27
cde/lib/pam/libpam/pam.conf
Normal file
27
cde/lib/pam/libpam/pam.conf
Normal 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
|
||||
322
cde/lib/pam/libpam/pam_appl.h
Normal file
322
cde/lib/pam/libpam/pam_appl.h
Normal 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 */
|
||||
1797
cde/lib/pam/libpam/pam_framework.c
Normal file
1797
cde/lib/pam/libpam/pam_framework.c
Normal file
File diff suppressed because it is too large
Load Diff
866
cde/lib/pam/libpam/pam_framework_utils.c
Normal file
866
cde/lib/pam/libpam/pam_framework_utils.c
Normal 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
|
||||
191
cde/lib/pam/libpam/pam_impl.h
Normal file
191
cde/lib/pam/libpam/pam_impl.h
Normal 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 */
|
||||
30
cde/lib/pam/libpam/pam_loc.h
Normal file
30
cde/lib/pam/libpam/pam_loc.h
Normal 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 */
|
||||
80
cde/lib/pam/libpam/pam_modules.h
Normal file
80
cde/lib/pam/libpam/pam_modules.h
Normal 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
260
cde/lib/pam/man/man3/pam.3
Normal 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.
|
||||
74
cde/lib/pam/man/man3/pam_acct_mgmt.3
Normal file
74
cde/lib/pam/man/man3/pam_acct_mgmt.3
Normal 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)
|
||||
100
cde/lib/pam/man/man3/pam_authenticate.3
Normal file
100
cde/lib/pam/man/man3/pam_authenticate.3
Normal 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)
|
||||
100
cde/lib/pam/man/man3/pam_chauthtok.3
Normal file
100
cde/lib/pam/man/man3/pam_chauthtok.3
Normal 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)
|
||||
106
cde/lib/pam/man/man3/pam_open_session.3
Normal file
106
cde/lib/pam/man/man3/pam_open_session.3
Normal 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)
|
||||
108
cde/lib/pam/man/man3/pam_set_data.3
Normal file
108
cde/lib/pam/man/man3/pam_set_data.3
Normal 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)
|
||||
137
cde/lib/pam/man/man3/pam_set_item.3
Normal file
137
cde/lib/pam/man/man3/pam_set_item.3
Normal 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)
|
||||
86
cde/lib/pam/man/man3/pam_setcred.3
Normal file
86
cde/lib/pam/man/man3/pam_setcred.3
Normal 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)
|
||||
295
cde/lib/pam/man/man3/pam_sm.3
Normal file
295
cde/lib/pam/man/man3/pam_sm.3
Normal 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)
|
||||
113
cde/lib/pam/man/man3/pam_sm_acct_mgmt.3
Normal file
113
cde/lib/pam/man/man3/pam_sm_acct_mgmt.3
Normal 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)
|
||||
130
cde/lib/pam/man/man3/pam_sm_authenticate.3
Normal file
130
cde/lib/pam/man/man3/pam_sm_authenticate.3
Normal 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)
|
||||
159
cde/lib/pam/man/man3/pam_sm_chauthtok.3
Normal file
159
cde/lib/pam/man/man3/pam_sm_chauthtok.3
Normal 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)
|
||||
92
cde/lib/pam/man/man3/pam_sm_open_session.3
Normal file
92
cde/lib/pam/man/man3/pam_sm_open_session.3
Normal 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)
|
||||
114
cde/lib/pam/man/man3/pam_sm_setcred.3
Normal file
114
cde/lib/pam/man/man3/pam_sm_setcred.3
Normal 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)
|
||||
223
cde/lib/pam/man/man3/pam_start.3
Normal file
223
cde/lib/pam/man/man3/pam_start.3
Normal 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)
|
||||
60
cde/lib/pam/man/man3/pam_strerror.3
Normal file
60
cde/lib/pam/man/man3/pam_strerror.3
Normal 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)
|
||||
348
cde/lib/pam/man/man4/pam.conf.4
Normal file
348
cde/lib/pam/man/man4/pam.conf.4
Normal 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)
|
||||
146
cde/lib/pam/man/man5/pam_dce.5
Normal file
146
cde/lib/pam/man/man5/pam_dce.5
Normal 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)
|
||||
68
cde/lib/pam/man/man5/pam_dial_auth.5
Normal file
68
cde/lib/pam/man/man5/pam_dial_auth.5
Normal 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)
|
||||
|
||||
62
cde/lib/pam/man/man5/pam_rhosts_auth.5
Normal file
62
cde/lib/pam/man/man5/pam_rhosts_auth.5
Normal 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)
|
||||
206
cde/lib/pam/man/man5/pam_unix.5
Normal file
206
cde/lib/pam/man/man5/pam_unix.5
Normal 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)
|
||||
21
cde/lib/pam/pam_modules/Imakefile
Normal file
21
cde/lib/pam/pam_modules/Imakefile
Normal file
@@ -0,0 +1,21 @@
|
||||
/* $XConsortium: Imakefile /main/3 1996/04/21 19:13:01 drk $
|
||||
*
|
||||
* (c) Copyright 1996 Digital Equipment Corporation.
|
||||
* (c) Copyright 1996 Hewlett-Packard Company.
|
||||
* (c) Copyright 1996 International Business Machines Corp.
|
||||
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1996 Novell, Inc.
|
||||
* (c) Copyright 1996 FUJITSU LIMITED.
|
||||
* (c) Copyright 1996 Hitachi.
|
||||
*/
|
||||
|
||||
#define IHaveSubdirs
|
||||
#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
|
||||
|
||||
SUBDIRS = "unix" sample dial_auth rhosts_auth /*dce*/
|
||||
LINTSUBDIRS = "unix" sample dial_auth rhosts_auth /*dce*/
|
||||
|
||||
MakeSubdirs($(SUBDIRS))
|
||||
DependSubdirs($(SUBDIRS))
|
||||
MakeLintLibSubdirs($(LINTLIBSUBDIRS))
|
||||
LintSubdirs($(LINTSUBDIRS))
|
||||
48
cde/lib/pam/pam_modules/dce/Imakefile
Normal file
48
cde/lib/pam/pam_modules/dce/Imakefile
Normal file
@@ -0,0 +1,48 @@
|
||||
/* $XConsortium: Imakefile /main/4 1996/04/21 19:13:14 drk $
|
||||
*
|
||||
* (c) Copyright 1996 Digital Equipment Corporation.
|
||||
* (c) Copyright 1996 Hewlett-Packard Company.
|
||||
* (c) Copyright 1996 International Business Machines Corp.
|
||||
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1996 Novell, Inc.
|
||||
* (c) Copyright 1996 FUJITSU LIMITED.
|
||||
* (c) Copyright 1996 Hitachi.
|
||||
*/
|
||||
|
||||
#define DoNormalLib NormalLibPam
|
||||
#define DoSharedLib SharedLibPam
|
||||
#define DoDebugLib DebugLibPam
|
||||
#define DoProfileLib ProfileLibPam
|
||||
#define LibName pam_dce
|
||||
#define SoRev SOPAMREV
|
||||
#define LibHeaders NO
|
||||
|
||||
#include <Threads.tmpl>
|
||||
|
||||
SRCS = \
|
||||
dce_authenticate.c \
|
||||
dce_setcred.c \
|
||||
dce_acct_mgmt.c \
|
||||
dce_password.c \
|
||||
dce_session.c \
|
||||
utils.c \
|
||||
xfn_mapping.c
|
||||
|
||||
OBJS = \
|
||||
dce_authenticate.o \
|
||||
dce_setcred.o \
|
||||
dce_acct_mgmt.o \
|
||||
dce_password.o \
|
||||
dce_session.o \
|
||||
utils.o \
|
||||
xfn_mapping.o
|
||||
|
||||
#ifdef SharedPamDceAuthReqs
|
||||
REQUIREDLIBS = SharedPamDceAuthReqs
|
||||
#endif
|
||||
|
||||
INCLUDES = -I../../libpam
|
||||
|
||||
#include <Library.tmpl>
|
||||
|
||||
DependTarget()
|
||||
179
cde/lib/pam/pam_modules/dce/dce_acct_mgmt.c
Normal file
179
cde/lib/pam/pam_modules/dce/dce_acct_mgmt.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/* $XConsortium: dce_acct_mgmt.c /main/5 1996/05/09 04:26:10 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)dce_acct_mgmt.c 1.3 95/08/02 SMI"
|
||||
|
||||
#include <syslog.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <libintl.h>
|
||||
#include <dce/sec_login.h>
|
||||
#include <dce/dce_error.h>
|
||||
|
||||
#include "pam_impl.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* pam_sm_acct_mgmt main account managment routine.
|
||||
* XXX: The routine just prints out a warning message.
|
||||
* It may need to force the user to change his/her
|
||||
* passwd.
|
||||
*/
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
#define SECS_PER_HOUR (60*60)
|
||||
#define SECS_PER_DAY (SECS_PER_HOUR * 24)
|
||||
|
||||
static void
|
||||
do_warn(pam_handle_t *pamh, time_t cur, time_t t, char *desc);
|
||||
|
||||
static void
|
||||
do_warn_passwd(pam_handle_t *pamh);
|
||||
|
||||
int
|
||||
pam_sm_acct_mgmt(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
dce_module_data_t *dsd;
|
||||
sec_login_net_info_t net_info;
|
||||
error_status_t st;
|
||||
time_t curtime;
|
||||
int result = PAM_AUTH_ERR;
|
||||
int i, debug = 0;
|
||||
int warn = 1;
|
||||
int allow_expired_passwd = 0;
|
||||
int err;
|
||||
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcmp(argv[i], "allow_expired_passwd") == 0)
|
||||
allow_expired_passwd = 1;
|
||||
else if (strcmp(argv[i], "nowarn") == 0)
|
||||
warn = 0;
|
||||
else
|
||||
syslog(LOG_ERR,
|
||||
"illegal DCE acct_mgmt option %s", argv[i]);
|
||||
}
|
||||
|
||||
if (flags & PAM_SILENT) warn = 0;
|
||||
|
||||
if (debug) syslog(LOG_DEBUG, "DCE pam_sm_acct_mgmt");
|
||||
|
||||
if (pam_get_data(pamh, DCE_DATA, (void**)&dsd) != PAM_SUCCESS ||
|
||||
dsd == NULL) {
|
||||
return (PAM_AUTH_ERR);
|
||||
}
|
||||
|
||||
if (dsd->auth_status != PAM_SUCCESS)
|
||||
return (dsd->auth_status);
|
||||
|
||||
if (dsd->auth_src == sec_login_auth_src_local) {
|
||||
/* we can't call sec_login_inquire_net_info on locally */
|
||||
/* authenticated contexts. Might want an option to dis-allow */
|
||||
/* them. For now we just allow them. */
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
sec_login_inquire_net_info(dsd->login_context, &net_info, &st);
|
||||
|
||||
if (st != error_status_ok && st != sec_login_s_not_certified) {
|
||||
if (debug) {
|
||||
dce_error_string_t text;
|
||||
|
||||
syslog(LOG_DEBUG, "sec_login_inquire_net_info: %s",
|
||||
get_dce_error_message(st, text));
|
||||
}
|
||||
return (PAM_PERM_DENIED);
|
||||
}
|
||||
|
||||
time(&curtime);
|
||||
|
||||
if (warn) {
|
||||
if (dsd->reset_passwd) {
|
||||
do_warn_passwd(pamh);
|
||||
} else {
|
||||
do_warn(pamh, curtime,
|
||||
(time_t) net_info.passwd_expiration_date,
|
||||
"passwd");
|
||||
}
|
||||
}
|
||||
|
||||
if (warn) do_warn(pamh, curtime,
|
||||
(time_t) net_info.acct_expiration_date, "account");
|
||||
|
||||
result = PAM_SUCCESS;
|
||||
|
||||
if ((net_info.passwd_expiration_date &&
|
||||
net_info.passwd_expiration_date < curtime) ||
|
||||
dsd->reset_passwd) {
|
||||
|
||||
result = PAM_AUTHTOKEN_REQD;
|
||||
|
||||
dsd->passwd_expired = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* I assume an expired account is worse then an expired password,
|
||||
* so if both the password and account are expired we want to
|
||||
* return PAM_ACCT_EXPIRED.
|
||||
*/
|
||||
|
||||
if (net_info.acct_expiration_date &&
|
||||
net_info.acct_expiration_date < curtime) {
|
||||
result = PAM_ACCT_EXPIRED;
|
||||
}
|
||||
|
||||
sec_login_free_net_info(&net_info);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
do_warn(pam_handle_t *pamh, time_t cur, time_t t, char *desc)
|
||||
{
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
|
||||
if (t == 0)
|
||||
return; /* unlimited */
|
||||
|
||||
if (cur > t) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 1, "Warning: Your DCE %s has expired.\n"), desc);
|
||||
} else if ((cur + SECS_PER_DAY) > t) {
|
||||
int hours;
|
||||
|
||||
hours = (t - cur) / (SECS_PER_HOUR);
|
||||
hours = hours ? hours : 1;
|
||||
sprintf(messages[0], PAM_MSG(pamh, 2,
|
||||
"Warning: Your DCE %s will expire within %d hour%s.\n"),
|
||||
desc, hours, (hours == 1) ? "" : "s");
|
||||
} else if ((cur + (2*SECS_PER_DAY)) > t) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 3,
|
||||
"Warning: Your DCE %s will expire in 2 days.\n"), desc);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_warn_passwd(pam_handle_t *pamh)
|
||||
{
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 4, "Warning: Your DCE passwd has expired.\n"));
|
||||
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
|
||||
}
|
||||
434
cde/lib/pam/pam_modules/dce/dce_authenticate.c
Normal file
434
cde/lib/pam/pam_modules/dce/dce_authenticate.c
Normal file
@@ -0,0 +1,434 @@
|
||||
/* $XConsortium: dce_authenticate.c /main/5 1996/05/09 04:26:26 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)dce_authenticate.c 1.34 96/02/14 SMI"
|
||||
|
||||
#include <dce/nbase.h>
|
||||
#include <dce/sec_login.h>
|
||||
#include <dce/dce_error.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <rpc/des_crypt.h>
|
||||
#include <pwd.h>
|
||||
#include <syslog.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#include "pam_impl.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
#include "xfn_mapping.h"
|
||||
#endif /* XFN_MAPPING */
|
||||
|
||||
#define SLEEPTIME 4
|
||||
|
||||
/* maxmimum DCE_PASSWD_LENGTH. We need to pick something for
|
||||
* __pam_get_authtok to use.
|
||||
*/
|
||||
|
||||
#define DCE_PASSWD_LENGTH 256
|
||||
|
||||
static int
|
||||
attempt_dce_login(
|
||||
void *pamh,
|
||||
dce_module_data_t *dsd,
|
||||
error_status_t *st,
|
||||
char *user,
|
||||
char *dce_pass
|
||||
);
|
||||
|
||||
void
|
||||
dce_cleanup(
|
||||
pam_handle_t *pamh,
|
||||
void *data,
|
||||
int pam_status
|
||||
);
|
||||
|
||||
/*
|
||||
* pam_sm_authenticate - Authenticate user
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_authenticate(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
char *user;
|
||||
int err, result = PAM_AUTH_ERR;
|
||||
char messages[1][PAM_MAX_MSG_SIZE];
|
||||
error_status_t st;
|
||||
char *defpass;
|
||||
int num_msg = 0;
|
||||
int debug = 0;
|
||||
int warn = 1;
|
||||
int passwd_flag = 0;
|
||||
int try_first_pass = 0;
|
||||
int use_first_pass = 0;
|
||||
int ignore = 0;
|
||||
int invalid_user = 0;
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
int try_mapped_pass = 0;
|
||||
int use_mapped_pass = 0;
|
||||
#endif
|
||||
int i;
|
||||
char *firstpass = NULL, *password = NULL;
|
||||
uid_t pw_uid;
|
||||
dce_module_data_t *dsd = NULL;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcmp(argv[i], "try_first_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
try_first_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
} else if (strcmp(argv[i], "use_first_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
use_first_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
#ifdef XFN_MAPPING
|
||||
} else if (strcmp(argv[i], "try_mapped_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
try_mapped_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
} else if (strcmp(argv[i], "use_mapped_pass") == 0) {
|
||||
if (!passwd_flag) {
|
||||
use_mapped_pass = 1;
|
||||
passwd_flag = 1;
|
||||
}
|
||||
#endif
|
||||
} else if (strcmp(argv[i], "nowarn") == 0) {
|
||||
warn = 0;
|
||||
} else {
|
||||
syslog(LOG_ERR, "illegal module option %s", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & PAM_SILENT) warn = 0;
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE pam_sm_authenticate");
|
||||
|
||||
err = pam_get_user(pamh, &user, NULL);
|
||||
|
||||
if (err != PAM_SUCCESS)
|
||||
return (err);
|
||||
|
||||
if (user == NULL || !user[0])
|
||||
return (PAM_AUTH_ERR);
|
||||
|
||||
/* Don't bother to authenticate root in DCE */
|
||||
|
||||
if (strcmp(user, "root") == 0)
|
||||
ignore = 1;
|
||||
|
||||
/* make sure a password entry exists for this user */
|
||||
/* we also need the uid for XFN */
|
||||
|
||||
if (!get_pw_uid(user, &pw_uid)) {
|
||||
invalid_user = 1;
|
||||
}
|
||||
|
||||
if (pam_get_data(pamh, DCE_DATA, (void**)&dsd) != PAM_SUCCESS ||
|
||||
dsd == NULL) {
|
||||
|
||||
dsd = calloc(1, sizeof (dce_module_data_t));
|
||||
if (dsd == NULL) {
|
||||
result = PAM_BUF_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((err = pam_set_data(pamh, DCE_DATA, dsd, &dce_cleanup))
|
||||
!= PAM_SUCCESS) {
|
||||
free(dsd);
|
||||
result = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (dsd->login_context != sec_login_default_handle) {
|
||||
error_status_t st;
|
||||
sec_login_purge_context(&dsd->login_context, &st);
|
||||
}
|
||||
}
|
||||
|
||||
dsd->login_context = sec_login_default_handle;
|
||||
dsd->auth_status = PAM_AUTH_ERR;
|
||||
dsd->debug = debug;
|
||||
dsd->warn = warn;
|
||||
dsd->reset_passwd = 0;
|
||||
dsd->passwd_expired = 0;
|
||||
dsd->auth_src = sec_login_auth_src_network;
|
||||
|
||||
/* see if a legitimate DCE user */
|
||||
|
||||
if (!sec_login_setup_identity((unsigned char *)user,
|
||||
sec_login_no_flags, &dsd->login_context, &st)) {
|
||||
if (debug) {
|
||||
dce_error_string_t text;
|
||||
syslog(LOG_DEBUG,
|
||||
"PAM: DCE sec_login_setup_identity: %s",
|
||||
get_dce_error_message(st, text));
|
||||
}
|
||||
if (st == sec_rgy_object_not_found) {
|
||||
/* mask the unknown user case */
|
||||
invalid_user = 1;
|
||||
} else {
|
||||
result = PAM_AUTH_ERR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
err = pam_get_item(pamh, PAM_AUTHTOK, (void **) &firstpass);
|
||||
|
||||
if (err != PAM_SUCCESS && (use_first_pass || use_mapped_pass)) {
|
||||
result = PAM_AUTH_ERR;
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "PAM: DCE goto out!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (firstpass != NULL && (ignore || invalid_user))
|
||||
goto out;
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
|
||||
if (firstpass == NULL) {
|
||||
if (use_mapped_pass) goto out;
|
||||
} else if (try_mapped_pass || use_mapped_pass) {
|
||||
char dcepass[MAP_PASSLEN+1];
|
||||
uid_t saved_uid;
|
||||
int got_mapped_pass;
|
||||
|
||||
saved_uid = geteuid();
|
||||
|
||||
if (saved_uid != pw_uid && getuid() == 0 &&
|
||||
seteuid(pw_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd: seteuid: %m");
|
||||
/* continue since we might be able to get mapping */
|
||||
}
|
||||
|
||||
got_mapped_pass = xfn_get_mapped_password(
|
||||
debug ? XFN_MAP_DEBUG : 0, user, DCE_XFN_PASS_ATTR,
|
||||
firstpass, dcepass, sizeof (dcepass));
|
||||
|
||||
if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd seteuid restore: %m");
|
||||
/* XXX: what should we do here? */
|
||||
}
|
||||
|
||||
if (got_mapped_pass) {
|
||||
|
||||
result =
|
||||
attempt_dce_login(pamh, dsd, &st, user, dcepass);
|
||||
|
||||
memset(dcepass, 0, MAP_PASSLEN);
|
||||
|
||||
if (result == PAM_SUCCESS ||
|
||||
st == sec_login_s_acct_invalid) goto out;
|
||||
}
|
||||
if (use_mapped_pass) goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (firstpass == NULL) {
|
||||
if (use_first_pass) goto out;
|
||||
} else if (use_first_pass || try_first_pass) {
|
||||
|
||||
result = attempt_dce_login(pamh, dsd, &st,
|
||||
user, firstpass);
|
||||
|
||||
if (result == PAM_SUCCESS ||
|
||||
st == sec_login_s_acct_invalid ||
|
||||
use_first_pass) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the password from the user
|
||||
*/
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE pam_sm_auth prompting for password");
|
||||
|
||||
if (firstpass == NULL &&
|
||||
!(try_first_pass||try_mapped_pass||invalid_user))
|
||||
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 10,
|
||||
"Password: "));
|
||||
else
|
||||
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 11,
|
||||
"DCE Password: "));
|
||||
|
||||
num_msg = 1;
|
||||
|
||||
err = __pam_get_authtok(pamh, PAM_PROMPT, PAM_AUTHTOK,
|
||||
DCE_PASSWD_LENGTH,messages[0], &password);
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE __pam_get_authtok = %d", err);
|
||||
|
||||
if (err != PAM_SUCCESS) {
|
||||
result = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (password == NULL) {
|
||||
/* Need a password to proceed */
|
||||
result = PAM_AUTH_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (firstpass == NULL) {
|
||||
/* this is the first password, stash it away */
|
||||
pam_set_item(pamh, PAM_AUTHTOK, password);
|
||||
}
|
||||
|
||||
/* one last ditch attempt to login to DCE */
|
||||
|
||||
if (invalid_user || ignore)
|
||||
goto out;
|
||||
|
||||
result = attempt_dce_login(pamh, dsd, &st, user, password);
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
/* we had to prompt for DCE password, so attempt to */
|
||||
/* update mapping iff we got a good DCE password */
|
||||
|
||||
if (try_mapped_pass && result == PAM_SUCCESS && firstpass) {
|
||||
uid_t saved_uid;
|
||||
|
||||
saved_uid = geteuid();
|
||||
|
||||
if (saved_uid != pw_uid && seteuid(pw_uid) < 0) {
|
||||
syslog(LOG_ERR, "xfn_get_mapped_passwd: seteuid: %m");
|
||||
goto out;
|
||||
}
|
||||
|
||||
xfn_update_mapped_password(debug ? XFN_MAP_DEBUG : 0,
|
||||
user, DCE_XFN_PASS_ATTR, firstpass, password);
|
||||
|
||||
if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd seteuid restore: %m");
|
||||
/* XXX: what should we do here? */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
out:
|
||||
|
||||
if (ignore) {
|
||||
result = PAM_IGNORE;
|
||||
}
|
||||
|
||||
if (password != NULL)
|
||||
memset(password, 0, strlen(password));
|
||||
|
||||
if (invalid_user)
|
||||
result = PAM_USER_UNKNOWN;
|
||||
|
||||
if (dsd)
|
||||
dsd->auth_status = result;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
attempt_dce_login(
|
||||
void *pamh,
|
||||
dce_module_data_t *dsd,
|
||||
error_status_t *st,
|
||||
char *user,
|
||||
char *dce_pass)
|
||||
{
|
||||
sec_passwd_rec_t passwd_rec;
|
||||
boolean32 login_valid = 0;
|
||||
error_status_t set_st;
|
||||
|
||||
/* have to strdup password because the call clears it */
|
||||
passwd_rec.key.tagged_union.plain = (idl_char *) strdup(dce_pass);
|
||||
if (passwd_rec.key.tagged_union.plain == NULL) {
|
||||
return (PAM_BUF_ERR);
|
||||
}
|
||||
passwd_rec.key.key_type = sec_passwd_plain;
|
||||
passwd_rec.pepper = NULL;
|
||||
passwd_rec.version_number = sec_passwd_c_version_none;
|
||||
|
||||
login_valid = sec_login_valid_and_cert_ident(dsd->login_context,
|
||||
&passwd_rec, &dsd->reset_passwd, &dsd->auth_src, st);
|
||||
|
||||
if (dsd->debug) {
|
||||
dce_error_string_t text;
|
||||
|
||||
syslog(LOG_DEBUG, "sec_login_valid_and_cert_ident: %s",
|
||||
get_dce_error_message(*st, text));
|
||||
}
|
||||
|
||||
if (*st == sec_login_s_acct_invalid && dsd->warn) {
|
||||
char messages[1][PAM_MAX_MSG_SIZE];
|
||||
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 12, "Error: Your DCE Account has expired.\n"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
|
||||
}
|
||||
|
||||
/* the call to sec_login_valid_and_cert_ident already zeros */
|
||||
/* out the password, so we just free it */
|
||||
|
||||
free(passwd_rec.key.tagged_union.plain);
|
||||
|
||||
return (login_valid ? PAM_SUCCESS : PAM_AUTH_ERR);
|
||||
}
|
||||
|
||||
void
|
||||
dce_cleanup(
|
||||
pam_handle_t *pamh,
|
||||
void *data,
|
||||
int pam_status)
|
||||
{
|
||||
error_status_t st;
|
||||
dce_module_data_t *dsd = (dce_module_data_t *) data;
|
||||
int status;
|
||||
|
||||
if (dsd->debug) {
|
||||
syslog(LOG_DEBUG, "DCE dce_cleanup pam_sm_auth_status(%d)",
|
||||
dsd->auth_status);
|
||||
}
|
||||
|
||||
if (!dsd->login_context != sec_login_default_handle) {
|
||||
free(dsd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* if pam_end as PAM_SUCCESS, clean up based on value in */
|
||||
/* auth_status, otherwise just purge the context */
|
||||
|
||||
if (pam_status == PAM_SUCCESS) {
|
||||
pam_sec_login_free_context(dsd->auth_status,
|
||||
&dsd->login_context, &st);
|
||||
} else {
|
||||
sec_login_purge_context(&dsd->login_context, &st);
|
||||
if (dsd->debug) {
|
||||
dce_error_string_t text;
|
||||
syslog(LOG_DEBUG, "sec_login_purge_context: %s",
|
||||
get_dce_error_message(st, text));
|
||||
}
|
||||
}
|
||||
|
||||
free(dsd);
|
||||
}
|
||||
475
cde/lib/pam/pam_modules/dce/dce_password.c
Normal file
475
cde/lib/pam/pam_modules/dce/dce_password.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/* $XConsortium: dce_password.c /main/5 1996/05/09 04:26:43 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)dce_password.c 1.22 96/02/14 SMI"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <dce/acct.h>
|
||||
#include <dce/uuid.h>
|
||||
#include <dce/binding.h>
|
||||
#include <dce/sec_login.h>
|
||||
#include <dce/dce_error.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "pam_impl.h"
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
#include "xfn_mapping.h"
|
||||
#endif
|
||||
|
||||
static int
|
||||
dce_changepw(
|
||||
char *account_name,
|
||||
char *old_pass,
|
||||
char *new_pass);
|
||||
|
||||
static char *
|
||||
get_passwd(
|
||||
pam_handle_t *pamh,
|
||||
char *prompt);
|
||||
|
||||
/*
|
||||
* XXX: This module is NOT finished!
|
||||
*
|
||||
*/
|
||||
int
|
||||
pam_sm_chauthtok(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
char *user;
|
||||
int err, result = PAM_AUTH_ERR;
|
||||
char *newpass = NULL, *vnewpass = NULL;
|
||||
char *oldpass = NULL;
|
||||
int try_first_pass = 0;
|
||||
int use_first_pass = 0;
|
||||
char *firstpass = NULL;
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
int try_mapped_pass = 0;
|
||||
int use_mapped_pass = 0;
|
||||
uid_t saved_uid;
|
||||
#endif
|
||||
int i;
|
||||
int debug = 0;
|
||||
uid_t pw_uid;
|
||||
dce_module_data_t *dsd = NULL;
|
||||
error_status_t status;
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE Authentication\n");
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcmp(argv[i], "try_first_pass") == 0)
|
||||
try_first_pass = 1;
|
||||
else if (strcmp(argv[i], "use_first_pass") == 0)
|
||||
use_first_pass = 1;
|
||||
#ifdef XFN_MAPPING
|
||||
else if (strcmp(argv[i], "try_mapped_pass") == 0)
|
||||
try_mapped_pass = 1;
|
||||
else if (strcmp(argv[i], "use_mapped_pass") == 0)
|
||||
use_mapped_pass = 1;
|
||||
#endif
|
||||
else
|
||||
syslog(LOG_DEBUG, "illegal scheme option %s", argv[i]);
|
||||
}
|
||||
|
||||
|
||||
if (flags & PAM_PRELIM_CHECK) {
|
||||
|
||||
/* try and bind to registry master of local cell */
|
||||
|
||||
sec_rgy_handle_t rh = sec_rgy_default_handle;
|
||||
|
||||
sec_rgy_site_open_update(NULL, &rh, &status);
|
||||
if (status == error_status_ok) {
|
||||
sec_rgy_site_close(rh, &status);
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
/* make sure PAM framework is telling us to update passwords */
|
||||
if (!(flags & PAM_UPDATE_AUTHTOK)) {
|
||||
syslog(LOG_ERR, "dce pam_sm_chauthtok: bad flags: %d", flags);
|
||||
return (PAM_SYSTEM_ERR);
|
||||
}
|
||||
|
||||
|
||||
if (flags & PAM_CHANGE_EXPIRED_AUTHTOK) {
|
||||
if (pam_get_data(pamh, DCE_DATA, (void **)&dsd)
|
||||
== PAM_SUCCESS) {
|
||||
if (!dsd->passwd_expired)
|
||||
return (PAM_IGNORE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = pam_get_item(pamh, PAM_USER, (void **) &user)) < 0)
|
||||
return (err);
|
||||
|
||||
/* Don't bother to handle root in DCE */
|
||||
|
||||
if (strcmp(user, "root") == 0)
|
||||
return (PAM_IGNORE);
|
||||
|
||||
#ifdef XFN_MAPPING
|
||||
if (use_mapped_pass || try_mapped_pass) {
|
||||
int got_mapped = 0, updated_mapped = 0;
|
||||
char dcepass[MAP_PASSLEN+1];
|
||||
|
||||
if ((err = pam_get_item(pamh, PAM_AUTHTOK,
|
||||
(void **) &newpass)) < 0)
|
||||
return (err);
|
||||
if ((err = pam_get_item(pamh, PAM_OLDAUTHTOK,
|
||||
(void **) &oldpass)) < 0)
|
||||
return (err);
|
||||
|
||||
if (!get_pw_uid(user, &pw_uid)) {
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
/* XXX: need to seteuid */
|
||||
|
||||
saved_uid = geteuid();
|
||||
|
||||
if (saved_uid != pw_uid && getuid() == 0 &&
|
||||
seteuid(pw_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd: seteuid: %m");
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
got_mapped = xfn_get_mapped_password(0, user,
|
||||
DCE_XFN_PASS_ATTR, oldpass, dcepass, sizeof (dcepass));
|
||||
|
||||
if (got_mapped) {
|
||||
|
||||
updated_mapped = xfn_update_mapped_password(
|
||||
0, user, DCE_XFN_PASS_ATTR, newpass,
|
||||
dcepass);
|
||||
|
||||
memset(dcepass, 0, sizeof (dcepass));
|
||||
|
||||
} else {
|
||||
/* probably should prompt for DCE password */
|
||||
/* and attempt to update it */
|
||||
}
|
||||
|
||||
if (geteuid() != saved_uid && seteuid(saved_uid) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"xfn_get_mapped_passwd seteuid restore: %m");
|
||||
/* XXX: what should we do here? */
|
||||
}
|
||||
|
||||
if (use_mapped_pass) {
|
||||
if (updated_mapped)
|
||||
return (PAM_SUCCESS);
|
||||
else
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
#endif /* XFN_MAPPING */
|
||||
|
||||
if (try_first_pass || use_first_pass) {
|
||||
|
||||
if ((err = pam_get_item(pamh, PAM_AUTHTOK,
|
||||
(void **) &newpass)) < 0)
|
||||
return (err);
|
||||
if ((err = pam_get_item(pamh, PAM_OLDAUTHTOK,
|
||||
(void **) &oldpass)) < 0)
|
||||
return (err);
|
||||
|
||||
result = dce_changepw(user, oldpass, newpass);
|
||||
|
||||
if (result == PAM_SUCCESS) {
|
||||
/* might need to update PAM_OLDAUTHTOK and PAM_NEWAUTHTOK */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* assume we need to prompt for old DCE password? */
|
||||
|
||||
oldpass = get_passwd(pamh, PAM_MSG(pamh, 20,
|
||||
"Old DCE password: "));
|
||||
|
||||
if (oldpass == NULL || oldpass[0] == '\0') {
|
||||
/* Need a password to proceed */
|
||||
result = PAM_AUTHTOK_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = dce_changepw(user, oldpass, newpass);
|
||||
|
||||
if (result == PAM_SUCCESS) {
|
||||
/* might need to update PAM_OLDAUTHTOK and PAM_NEWAUTHTOK */
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
/* prompt for both old and new passwords */
|
||||
|
||||
if (firstpass == NULL && !(try_first_pass||try_mapped_pass))
|
||||
oldpass = get_passwd(pamh, PAM_MSG(pamh, 20,
|
||||
"Old DCE password: "));
|
||||
else
|
||||
oldpass = get_passwd(pamh, PAM_MSG(pamh, 20,
|
||||
"Old DCE password: "));
|
||||
|
||||
if (oldpass == NULL || oldpass[0] == '\0') {
|
||||
/* Need a password to proceed */
|
||||
result = PAM_AUTHTOK_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (firstpass == NULL && !(try_first_pass||try_mapped_pass))
|
||||
newpass = get_passwd(pamh, PAM_MSG(pamh, 21,
|
||||
"New DCE password: "));
|
||||
else
|
||||
newpass = get_passwd(pamh, PAM_MSG(pamh, 21,
|
||||
"New DCE password: "));
|
||||
|
||||
if (newpass == NULL || newpass[0] == '\0') {
|
||||
/* Need a password to proceed */
|
||||
result = PAM_AUTHTOK_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (firstpass == NULL && !(try_first_pass||try_mapped_pass))
|
||||
vnewpass = get_passwd(pamh,
|
||||
PAM_MSG(pamh, 22,
|
||||
"Re-enter new DCE password: "));
|
||||
else
|
||||
vnewpass = get_passwd(pamh,
|
||||
PAM_MSG(pamh, 22,
|
||||
"Re-enter new DCE password: "));
|
||||
|
||||
if (vnewpass == NULL || vnewpass[0] == '\0') {
|
||||
/* Need a password to proceed */
|
||||
result = PAM_AUTHTOK_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp(newpass, vnewpass)) {
|
||||
result = PAM_AUTHTOK_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = dce_changepw(user, oldpass, newpass);
|
||||
|
||||
if (result == PAM_SUCCESS) {
|
||||
/* might need to update PAM_OLDAUTHTOK and PAM_NEWAUTHTOK) */
|
||||
}
|
||||
out:
|
||||
|
||||
if (oldpass) {
|
||||
memset(oldpass, 0, strlen(oldpass));
|
||||
free(oldpass);
|
||||
}
|
||||
|
||||
if (newpass) {
|
||||
memset(newpass, 0, strlen(newpass));
|
||||
free(newpass);
|
||||
}
|
||||
|
||||
|
||||
if (vnewpass) {
|
||||
memset(vnewpass, 0, strlen(vnewpass));
|
||||
free(vnewpass);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
dce_changepw(
|
||||
char *account_name,
|
||||
char *old_pass,
|
||||
char *new_pass)
|
||||
{
|
||||
error_status_t status;
|
||||
sec_rgy_handle_t rgy_handle = sec_rgy_default_handle;
|
||||
sec_rgy_login_name_t name_key;
|
||||
sec_rgy_cursor_t account_cursor;
|
||||
sec_rgy_login_name_t name_result;
|
||||
sec_rgy_sid_t id_sid;
|
||||
sec_rgy_unix_sid_t unix_sid;
|
||||
sec_rgy_acct_key_t key_parts;
|
||||
sec_rgy_acct_user_t user_part;
|
||||
sec_rgy_acct_admin_t admin_part;
|
||||
sec_passwd_rec_t new_key, caller_key;
|
||||
sec_passwd_version_t new_key_version;
|
||||
sec_login_handle_t login_context = sec_login_default_handle;
|
||||
sec_passwd_rec_t passwd_rec;
|
||||
boolean32 reset_pass = 0, login_valid = 0;
|
||||
sec_login_auth_src_t auth_src;
|
||||
char *env;
|
||||
static char *krb5 = "KRB5CCNAME";
|
||||
char *krb5_value = NULL;
|
||||
|
||||
/* stash away the value of KRB5CCNAME, if there is one set */
|
||||
env = getenv(krb5);
|
||||
if (env) {
|
||||
krb5_value = malloc(strlen(krb5)+1+strlen(env)+1);
|
||||
if (krb5_value)
|
||||
sprintf(krb5_value, "%s=%s", krb5, env);
|
||||
else {
|
||||
status = sec_login_s_no_current_context;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* first we a get a login context. A future version should */
|
||||
/* check and see if there is a current context with the */
|
||||
/* same name as the user we are setting */
|
||||
|
||||
if (!sec_login_setup_identity((unsigned_char_p_t) account_name,
|
||||
sec_login_no_flags, &login_context, &status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* have to strdup password because the call clears it */
|
||||
passwd_rec.key.tagged_union.plain =
|
||||
(idl_char *) strdup(old_pass);
|
||||
if (passwd_rec.key.tagged_union.plain == NULL) {
|
||||
status = sec_login_s_no_current_context;
|
||||
goto out;
|
||||
}
|
||||
|
||||
passwd_rec.key.key_type = sec_passwd_plain;
|
||||
passwd_rec.pepper = NULL;
|
||||
passwd_rec.version_number = sec_passwd_c_version_none;
|
||||
|
||||
login_valid = sec_login_validate_identity(login_context,
|
||||
&passwd_rec, &reset_pass, &auth_src, &status);
|
||||
|
||||
free(passwd_rec.key.tagged_union.plain); /* already memset */
|
||||
|
||||
if (!login_valid)
|
||||
goto out;
|
||||
|
||||
sec_login_set_context(login_context, &status);
|
||||
|
||||
if (status != error_status_ok)
|
||||
goto out;
|
||||
|
||||
/* we now have a context with the same account as the one */
|
||||
/* we are trying to change the password on. Lets talk to the */
|
||||
/* registry... */
|
||||
|
||||
sec_rgy_site_open(NULL, &rgy_handle, &status);
|
||||
|
||||
if (status != error_status_ok) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
caller_key.key.key_type = sec_passwd_plain;
|
||||
caller_key.pepper = NULL;
|
||||
caller_key.version_number = sec_passwd_c_version_none;
|
||||
caller_key.key.tagged_union.plain = (idl_char *) old_pass;
|
||||
|
||||
sec_rgy_cursor_reset(&account_cursor);
|
||||
|
||||
strcpy((char *)name_key.pname, account_name);
|
||||
name_key.gname[0] = '\0';
|
||||
name_key.oname[0] = '\0';
|
||||
|
||||
/* need to do this in order to get the org and group for the */
|
||||
/* account. All we want is name_result... */
|
||||
|
||||
sec_rgy_acct_lookup(
|
||||
rgy_handle,
|
||||
&name_key,
|
||||
&account_cursor,
|
||||
&name_result,
|
||||
&id_sid,
|
||||
&unix_sid,
|
||||
&key_parts,
|
||||
&user_part,
|
||||
&admin_part,
|
||||
&status);
|
||||
|
||||
if (status != error_status_ok)
|
||||
goto out;
|
||||
|
||||
caller_key.key.key_type = sec_passwd_plain;
|
||||
caller_key.pepper = NULL;
|
||||
caller_key.version_number = sec_passwd_c_version_none;
|
||||
caller_key.key.tagged_union.plain = (idl_char *) old_pass;
|
||||
|
||||
new_key.key.key_type = sec_passwd_plain;
|
||||
new_key.pepper = NULL;
|
||||
new_key.version_number = sec_passwd_c_version_none;
|
||||
new_key.key.tagged_union.plain = (idl_char *) new_pass;
|
||||
|
||||
/* rock and roll. lets try to update the password... */
|
||||
|
||||
sec_rgy_acct_passwd(
|
||||
rgy_handle,
|
||||
&name_result,
|
||||
&caller_key,
|
||||
&new_key,
|
||||
sec_passwd_des,
|
||||
&new_key_version,
|
||||
&status);
|
||||
|
||||
out:
|
||||
/* restore the old KRB5CCNAME value */
|
||||
if (krb5_value) {
|
||||
putenv(krb5_value);
|
||||
}
|
||||
|
||||
if (rgy_handle != sec_rgy_default_handle) {
|
||||
error_status_t st; /* don't trash status */
|
||||
|
||||
sec_rgy_site_close(rgy_handle, &st);
|
||||
}
|
||||
|
||||
if (login_context != sec_login_default_handle) {
|
||||
error_status_t st; /* don't trash status */
|
||||
|
||||
sec_login_purge_context(&login_context, &st);
|
||||
}
|
||||
|
||||
if (status == error_status_ok) {
|
||||
return (PAM_SUCCESS);
|
||||
} else {
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char *
|
||||
get_passwd(
|
||||
pam_handle_t *pamh,
|
||||
char *prompt)
|
||||
{
|
||||
int err;
|
||||
char *p;
|
||||
|
||||
err = __pam_get_authtok(pamh, PAM_PROMPT, 0, 256, prompt, &p);
|
||||
|
||||
if (err != PAM_SUCCESS) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (p);
|
||||
}
|
||||
49
cde/lib/pam/pam_modules/dce/dce_session.c
Normal file
49
cde/lib/pam/pam_modules/dce/dce_session.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/* $XConsortium: dce_session.c /main/4 1996/05/09 04:27:00 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)dce_session.c 1.3 96/01/10 SMI"
|
||||
|
||||
#include <libintl.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <dce/sec_login.h>
|
||||
#include <dce/dce_error.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <syslog.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#include "pam_impl.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* pam_sm_open_session
|
||||
*/
|
||||
int
|
||||
pam_sm_open_session(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* pam_sm_close_session
|
||||
*/
|
||||
int
|
||||
pam_sm_close_session(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
125
cde/lib/pam/pam_modules/dce/dce_setcred.c
Normal file
125
cde/lib/pam/pam_modules/dce/dce_setcred.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/* $XConsortium: dce_setcred.c /main/5 1996/05/09 04:27:17 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)dce_setcred.c 1.21 96/01/11 SMI"
|
||||
|
||||
#include <libintl.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <dce/sec_login.h>
|
||||
#include <dce/dce_error.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <syslog.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#include "pam_impl.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void
|
||||
do_cred_warn(void *pamh)
|
||||
{
|
||||
char messages[1][PAM_MAX_MSG_SIZE];
|
||||
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 30, "warning: Unable to obtain DCE credentials.\n"));
|
||||
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* pam_sm_setcred
|
||||
*/
|
||||
int
|
||||
pam_sm_setcred(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
int debug = 0;
|
||||
int warn = 1;
|
||||
int i;
|
||||
dce_module_data_t *dsd;
|
||||
error_status_t st;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
if (strcmp(argv[i], "nowarn") == 0)
|
||||
warn = 0;
|
||||
}
|
||||
|
||||
if (flags & PAM_SILENT) warn = 0;
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "DCE pam_setcred");
|
||||
|
||||
if (pam_get_data(pamh, DCE_DATA, (void**)&dsd) != PAM_SUCCESS ||
|
||||
dsd == NULL) {
|
||||
if (flags & PAM_DELETE_CRED) {
|
||||
sec_login_handle_t context;
|
||||
|
||||
/* attempt to get current context and purge */
|
||||
sec_login_get_current_context(&context, &st);
|
||||
if (st == error_status_ok) {
|
||||
sec_login_purge_context(&context, &st);
|
||||
}
|
||||
return (st == error_status_ok ? PAM_SUCCESS :
|
||||
PAM_CRED_UNAVAIL);
|
||||
}
|
||||
|
||||
if (warn) do_cred_warn(pamh);
|
||||
return (PAM_IGNORE); /* since pam_auth was never called */
|
||||
}
|
||||
|
||||
if (dsd->auth_status != PAM_SUCCESS)
|
||||
return (dsd->auth_status);
|
||||
|
||||
if (flags & PAM_DELETE_CRED) {
|
||||
(void) sec_login_purge_context(dsd->login_context, &st);
|
||||
|
||||
if (debug) {
|
||||
dce_error_string_t text;
|
||||
|
||||
syslog(LOG_DEBUG,
|
||||
"PAM: DCE sec_login_purge_context: %s",
|
||||
get_dce_error_message(st, text));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (dsd->auth_src == sec_login_auth_src_local) {
|
||||
/* we can't set_context on locally authenticated */
|
||||
/* contexts */
|
||||
st = sec_login_s_auth_local;
|
||||
} else {
|
||||
(void) sec_login_set_context(dsd->login_context, &st);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
dce_error_string_t text;
|
||||
|
||||
syslog(LOG_DEBUG, "PAM: DCE sec_login_set_context: %s",
|
||||
get_dce_error_message(st, text));
|
||||
}
|
||||
}
|
||||
|
||||
/* might want an option to return success even if set_context failed */
|
||||
|
||||
if (st == error_status_ok) {
|
||||
return (PAM_SUCCESS);
|
||||
} else {
|
||||
if (warn) do_cred_warn(pamh);
|
||||
|
||||
if (debug) syslog(LOG_DEBUG,
|
||||
"Can't set user login context");
|
||||
return (PAM_CRED_ERR);
|
||||
}
|
||||
}
|
||||
22
cde/lib/pam/pam_modules/dce/libpam_cde.elist
Normal file
22
cde/lib/pam/pam_modules/dce/libpam_cde.elist
Normal file
@@ -0,0 +1,22 @@
|
||||
/****************************************************************************
|
||||
* Export list for libpam_dce.
|
||||
* This list *must* be updated whenever a change is made to the libpam_dce
|
||||
* API.
|
||||
*
|
||||
* The syntax for the symbol declarations in this list is as follows:
|
||||
* public sym => Public C symbol, i.e., publicised API
|
||||
* private sym => Private C symbol, i.e., unpublicised API
|
||||
* internal sym => Internal C symbol, i.e., not part of API
|
||||
* publicC++ sym => Public C++ symbol, i.e., publicised API
|
||||
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
|
||||
* internalC++ sym => Internal C++ symbol, i.e., not part of API
|
||||
*
|
||||
* $TOG: libpam_cde.elist /main/1 1999/09/08 15:58:14 mgreess $
|
||||
*****************************************************************************/
|
||||
|
||||
public pam_sm_authenticate
|
||||
public pam_sm_setcred
|
||||
public pam_sm_acct_mgmt
|
||||
public pam_sm_open_session
|
||||
public pam_sm_close_session
|
||||
public pam_sm_chauthtok
|
||||
71
cde/lib/pam/pam_modules/dce/pam_dce.msg
Normal file
71
cde/lib/pam/pam_modules/dce/pam_dce.msg
Normal file
@@ -0,0 +1,71 @@
|
||||
$ $XConsortium: pam_dce.msg /main/2 1996/07/24 19:04:00 drk $
|
||||
$ *************************************<+>*************************************
|
||||
$ *****************************************************************************
|
||||
$ **
|
||||
$ ** File: pam_dce.msg
|
||||
$ **
|
||||
$ ** Project: pam_dce
|
||||
$ **
|
||||
$ ** Description:
|
||||
$ ** -----------
|
||||
$ ** This file is the source for the message catalog for pam_unix module.
|
||||
$ **
|
||||
$ **
|
||||
$ *****************************************************************************
|
||||
$ **
|
||||
$ ** (c) Copyright 1996 Sun Microsystems, Inc.
|
||||
$ ** All Rights reserved
|
||||
$ **
|
||||
$ *****************************************************************************
|
||||
$ *************************************<+>*************************************
|
||||
|
||||
$ *****************************************************************************
|
||||
$
|
||||
$ ***** NOTE FOR MESSAGE CATALOG TRANSLATORS *****
|
||||
$
|
||||
$ There may be three types of messages in this file:
|
||||
$
|
||||
$ 1. Messages that appear in dialogs or are displayed to the user.
|
||||
$
|
||||
$ These messages are the default and they should ALL BE LOCALIZED.
|
||||
$ Note that these messages do NOT have any identification (see the
|
||||
$ comments for type 2 and 3 below).
|
||||
$
|
||||
$ 2. Messages that only appear in the error log file.
|
||||
$
|
||||
$ The localization of these messages is OPTIONAL. These messages are
|
||||
$ identified by the following:
|
||||
$
|
||||
$ MESSAGES xx-yy IN SET zz WILL ONLY APPEAR IN THE DT ERRORLOG FILE
|
||||
$
|
||||
$ 3. Messages that should not be localized.
|
||||
$
|
||||
$ These messages are identified by the following:
|
||||
$
|
||||
$ DO NOT TRANSLATE or CHANGE or LOCALIZE MESSAGES xx-yy from set zz
|
||||
$
|
||||
$ ***** END (NOTE FOR MESSAGE CATALOG TRANSLATORS) *****
|
||||
$
|
||||
$ ******************************************************************************
|
||||
|
||||
$set 1
|
||||
|
||||
$ dce_acct_mgmt.c
|
||||
1 Warning: Your DCE %s has expired.
|
||||
2 Warning: Your DCE %s will expire within %d hour%s.
|
||||
3 Warning: Your DCE %s will expire in 2 days.\n
|
||||
4 Warning: Your DCE passwd has expired.
|
||||
|
||||
$ dce_authenticate.c
|
||||
10 Password:
|
||||
11 DCE Password:
|
||||
12 Error: Your DCE Account has expired.\n
|
||||
|
||||
$ dce_password.c
|
||||
20 Old DCE password:
|
||||
21 New DCE password:
|
||||
22 Re-enter new DCE password:
|
||||
|
||||
$ dce_setcred.c
|
||||
30 warning: Unable to obtain DCE credentials.\n
|
||||
|
||||
96
cde/lib/pam/pam_modules/dce/utils.c
Normal file
96
cde/lib/pam/pam_modules/dce/utils.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/* $XConsortium: utils.c /main/4 1996/05/09 04:27:30 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)utils.c 1.13 95/09/19 SMI"
|
||||
|
||||
#include <dce/sec_login.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
/* ******************************************************************** */
|
||||
/* */
|
||||
/* Utilities Functions */
|
||||
/* */
|
||||
/* ******************************************************************** */
|
||||
|
||||
|
||||
/* return a string given an error status */
|
||||
|
||||
unsigned char *
|
||||
get_dce_error_message(
|
||||
error_status_t status,
|
||||
unsigned char *buffer
|
||||
)
|
||||
{
|
||||
int s;
|
||||
|
||||
dce_error_inq_text(status, buffer, &s);
|
||||
|
||||
if (s)
|
||||
sprintf((char *)buffer, "DCE error %u", status);
|
||||
|
||||
return (buffer);
|
||||
}
|
||||
|
||||
/* release login_context resources. if we are returning PAM_SUCCESS */
|
||||
/* we also have to save KRB5CCNAME and set it after calling release */
|
||||
/* because s_l_release_c unset's it even though we still need it */
|
||||
|
||||
void
|
||||
pam_sec_login_free_context(
|
||||
int pam_status,
|
||||
sec_login_handle_t *login_context,
|
||||
error_status_t *st)
|
||||
{
|
||||
if (pam_status == PAM_SUCCESS) {
|
||||
static char *krb5 = "KRB5CCNAME";
|
||||
char *krb5_value = NULL;
|
||||
char *env = getenv(krb5);
|
||||
|
||||
if (env) {
|
||||
/* we MUST malloc this for the putenv to work! */
|
||||
krb5_value = malloc(strlen(krb5)+1+strlen(env)+1);
|
||||
if (krb5_value)
|
||||
sprintf(krb5_value, "%s=%s", krb5, env);
|
||||
}
|
||||
|
||||
sec_login_release_context(login_context, st);
|
||||
|
||||
if (krb5_value)
|
||||
putenv(krb5_value);
|
||||
|
||||
} else { /* login failed. purge this context */
|
||||
|
||||
sec_login_purge_context(login_context, st);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_pw_uid():
|
||||
* To get the uid from the passwd entry for specified user
|
||||
* It returns 0 if the user can't be found, otherwise returns 1.
|
||||
*/
|
||||
|
||||
int
|
||||
get_pw_uid(char *user, uid_t *uid)
|
||||
{
|
||||
struct passwd sp;
|
||||
char buffer[1024];
|
||||
|
||||
if (getpwnam_r(user, &sp, buffer, sizeof (buffer)) == NULL) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
*uid = sp.pw_uid;
|
||||
|
||||
return (1);
|
||||
}
|
||||
58
cde/lib/pam/pam_modules/dce/utils.h
Normal file
58
cde/lib/pam/pam_modules/dce/utils.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* $XConsortium: utils.h /main/5 1996/05/09 04:27:45 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _UTILS_H
|
||||
#define _UTILS_H
|
||||
|
||||
#ident "@(#)utils.h 1.17 96/01/10 SMI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <dce/sec_login.h>
|
||||
|
||||
#define DCE_DATA "SUNW-DCE-AUTH-DATA"
|
||||
|
||||
/*
|
||||
* PAM_MSG macro for return of internationalized text
|
||||
*/
|
||||
|
||||
#define PAM_MSG(pamh, number, string)\
|
||||
(char *) __pam_get_i18n_msg(pamh, "pam_dce", 1, number, string)
|
||||
|
||||
typedef struct {
|
||||
sec_login_handle_t login_context;
|
||||
int debug;
|
||||
int warn;
|
||||
int auth_status;
|
||||
boolean32 reset_passwd;
|
||||
boolean32 passwd_expired;
|
||||
sec_login_auth_src_t auth_src;
|
||||
} dce_module_data_t;
|
||||
|
||||
void
|
||||
pam_sec_login_free_context(
|
||||
int pam_status,
|
||||
sec_login_handle_t *login_context,
|
||||
error_status_t *st);
|
||||
|
||||
unsigned char *
|
||||
get_dce_error_message(
|
||||
error_status_t status,
|
||||
unsigned char *buffer
|
||||
);
|
||||
|
||||
int
|
||||
get_pw_uid(char *user, uid_t *uid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DCE_UTILS_H */
|
||||
287
cde/lib/pam/pam_modules/dce/xfn_mapping.c
Normal file
287
cde/lib/pam/pam_modules/dce/xfn_mapping.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/* $XConsortium: xfn_mapping.c /main/4 1996/05/09 04:28:00 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)xfn_mapping.c 1.6 95/09/19 SMI"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <xfn/xfn.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "xfn_mapping.h"
|
||||
|
||||
static char hexval(char);
|
||||
static int hex2bin(int, char *, char *);
|
||||
static int bin2hex(int, unsigned char *, char *);
|
||||
|
||||
/*
|
||||
* attempt to get mapped password from XFN
|
||||
*/
|
||||
|
||||
int
|
||||
xfn_get_mapped_password(
|
||||
int flags,
|
||||
char *user, /* xfn user */
|
||||
char *xfn_attr, /* xfn attribute that holds the target pass */
|
||||
char *key, /* key (password) encrypting target password */
|
||||
char *out, /* un-encrypted target password */
|
||||
int out_max) /* buffer size of out */
|
||||
{
|
||||
|
||||
FN_status_t *status = NULL;
|
||||
FN_composite_name_t *compname = NULL;
|
||||
FN_ctx_t *ctx = NULL;
|
||||
FN_string_t *str = NULL;
|
||||
FN_attribute_t *attr = NULL;
|
||||
const FN_attrvalue_t *attr_val = NULL;
|
||||
FN_identifier_t attr_id; /* attr identifier */
|
||||
FN_identifier_t attr_syn; /* attr syntax */
|
||||
char hexpass[MAP_HEXLEN+1];
|
||||
char pass[MAP_PASSLEN+1];
|
||||
char composed_user[128]; /* XXX 128? */
|
||||
int result = 0;
|
||||
void *pos;
|
||||
|
||||
pass[0] = '\0';
|
||||
|
||||
status = fn_status_create(); /* free status */
|
||||
if (status == NULL)
|
||||
goto out;
|
||||
|
||||
ctx = fn_ctx_handle_from_initial(status); /* free ctx */
|
||||
if (ctx == NULL)
|
||||
goto out;
|
||||
|
||||
attr_id.format = FN_ID_STRING;
|
||||
attr_id.length = strlen(xfn_attr);
|
||||
attr_id.contents = xfn_attr;
|
||||
|
||||
if (strlen(user) > (sizeof (composed_user)-6))
|
||||
goto out;
|
||||
|
||||
sprintf(composed_user, "user/%s", user);
|
||||
|
||||
str = fn_string_from_str(
|
||||
(unsigned char *)composed_user); /* free str */
|
||||
if (str == NULL)
|
||||
goto out;
|
||||
|
||||
compname = fn_composite_name_from_string(str); /* free compname */
|
||||
if (compname == NULL)
|
||||
goto out;
|
||||
|
||||
attr = fn_attr_get(ctx, compname, &attr_id, status); /* free attr */
|
||||
if (attr == NULL)
|
||||
goto out;
|
||||
|
||||
attr_val = fn_attribute_first(attr, &pos); /* don't have to free */
|
||||
if (attr_val == NULL)
|
||||
goto out;
|
||||
|
||||
if (attr_val->length != MAP_HEXLEN)
|
||||
goto out;
|
||||
|
||||
memcpy(hexpass, attr_val->contents, attr_val->length);
|
||||
|
||||
if (xdecrypt(hexpass, key) == 0)
|
||||
goto out;
|
||||
|
||||
hexpass[MAP_HEXLEN] = '\0';
|
||||
|
||||
hex2bin(MAP_PASSLEN, hexpass, pass); /* we have the password!! */
|
||||
memset(hexpass, 0, MAP_HEXLEN);
|
||||
|
||||
if (strlen(pass)+1 > out_max)
|
||||
goto out; /* sigh... */
|
||||
|
||||
strcpy(out, pass);
|
||||
memset(pass, 0, strlen(pass));
|
||||
|
||||
result = 1;
|
||||
|
||||
out:
|
||||
if (pass[0])
|
||||
memset(pass, 0, MAP_PASSLEN);
|
||||
if (status)
|
||||
fn_status_destroy(status);
|
||||
if (ctx)
|
||||
fn_ctx_handle_destroy(ctx);
|
||||
if (str)
|
||||
fn_string_destroy(str);
|
||||
if (compname)
|
||||
fn_composite_name_destroy(compname);
|
||||
if (attr)
|
||||
fn_attribute_destroy(attr);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* attempt to update mapped password from XFN
|
||||
*/
|
||||
|
||||
int
|
||||
xfn_update_mapped_password(
|
||||
int flags, /* debug, etc */
|
||||
char *user, /* xfn user */
|
||||
char *xfn_attr, /* xfn attribute that holds the target pass */
|
||||
char *key, /* key (password) encrypting target password */
|
||||
char *password) /* un-encrypted target password */
|
||||
{
|
||||
|
||||
FN_status_t *status = NULL;
|
||||
FN_composite_name_t *compname = NULL;
|
||||
FN_ctx_t *ctx = NULL;
|
||||
FN_ref_t *ref = NULL;
|
||||
FN_string_t *str = NULL;
|
||||
FN_attribute_t *attr = NULL;
|
||||
FN_identifier_t attr_id; /* attr identifier */
|
||||
FN_identifier_t attr_syn; /* attr syntax */
|
||||
FN_attrvalue_t attr_val;
|
||||
char hexpass[MAP_HEXLEN+1];
|
||||
char pass[MAP_PASSLEN+1];
|
||||
char composed_user[128]; /* XXX 128? */
|
||||
int result;
|
||||
|
||||
result = 0; /* guilty until proven innocent */
|
||||
hexpass[0] = '\0';
|
||||
|
||||
if (strlen(pass) > MAP_PASSLEN)
|
||||
goto out;
|
||||
|
||||
status = fn_status_create(); /* free status */
|
||||
if (status == NULL)
|
||||
goto out;
|
||||
|
||||
ctx = fn_ctx_handle_from_initial(status); /* free ctx */
|
||||
if (ctx == NULL)
|
||||
goto out;
|
||||
|
||||
attr_id.format = FN_ID_STRING;
|
||||
attr_id.length = strlen(xfn_attr);
|
||||
attr_id.contents = xfn_attr;
|
||||
attr_syn.format = FN_ID_STRING;
|
||||
#define PASSWD_ATTR_SYNTAX "fn_attr_syntax_ascii"
|
||||
attr_syn.length = sizeof (PASSWD_ATTR_SYNTAX)-1; /* sizeof has null */
|
||||
attr_syn.contents = PASSWD_ATTR_SYNTAX;
|
||||
|
||||
attr = fn_attribute_create(&attr_id, &attr_syn); /* free attr */
|
||||
|
||||
if (strlen(user) > (sizeof (composed_user)-6))
|
||||
goto out;
|
||||
|
||||
sprintf(composed_user, "user/%s", user);
|
||||
str = fn_string_from_str(
|
||||
(unsigned char *)composed_user); /* free str */
|
||||
|
||||
if (str == NULL)
|
||||
goto out;
|
||||
|
||||
compname = fn_composite_name_from_string(str); /* free compname */
|
||||
if (compname == NULL)
|
||||
goto out;
|
||||
|
||||
ref = fn_ctx_lookup(ctx, compname, status);
|
||||
if (ref == NULL)
|
||||
goto out;
|
||||
|
||||
strcpy(pass, password);
|
||||
bin2hex(MAP_PASSLEN, (unsigned char *)pass, hexpass);
|
||||
hexpass[MAP_HEXLEN] = '\0';
|
||||
|
||||
memset(pass, 0, sizeof (pass));
|
||||
|
||||
if (xencrypt(hexpass, key) == 0)
|
||||
goto out;
|
||||
|
||||
attr_val.length = strlen(hexpass);
|
||||
attr_val.contents = hexpass;
|
||||
|
||||
if (fn_attribute_add(attr, &attr_val, 1) == 0)
|
||||
goto out;
|
||||
|
||||
if (fn_attr_modify(ctx, compname, FN_ATTR_OP_ADD, attr, status) == 0)
|
||||
goto out;
|
||||
|
||||
result = 1;
|
||||
|
||||
out:
|
||||
if (hexpass[0])
|
||||
memset(hexpass, 0, MAP_HEXLEN);
|
||||
if (status)
|
||||
fn_status_destroy(status);
|
||||
if (ctx)
|
||||
fn_ctx_handle_destroy(ctx);
|
||||
if (str)
|
||||
fn_string_destroy(str);
|
||||
if (compname)
|
||||
fn_composite_name_destroy(compname);
|
||||
if (attr)
|
||||
fn_attribute_destroy(attr);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hex to binary conversion
|
||||
*/
|
||||
static
|
||||
hex2bin(int len, char *hexnum, char *binnum)
|
||||
{
|
||||
int i;
|
||||
char v1;
|
||||
char v2;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
v1 = hexval(hexnum[2 * i]);
|
||||
if (v1 == -1)
|
||||
return (0);
|
||||
v2 = hexval(hexnum[2 * i + 1]);
|
||||
if (v2 == -1)
|
||||
return (0);
|
||||
*binnum++ = (v1 << 4) + v2;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Binary to hex conversion
|
||||
*/
|
||||
static
|
||||
bin2hex(int len, unsigned char *binnum, char *hexnum)
|
||||
{
|
||||
int i;
|
||||
unsigned val;
|
||||
static char hex[16] = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
};
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
val = binnum[i];
|
||||
hexnum[i*2] = hex[val >> 4];
|
||||
hexnum[i*2+1] = hex[val & 0xf];
|
||||
}
|
||||
hexnum[len*2] = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static char
|
||||
hexval(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') {
|
||||
return (c - '0');
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
return (c - 'a' + 10);
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
return (c - 'A' + 10);
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
46
cde/lib/pam/pam_modules/dce/xfn_mapping.h
Normal file
46
cde/lib/pam/pam_modules/dce/xfn_mapping.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* $XConsortium: xfn_mapping.h /main/4 1996/05/09 04:28:15 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _XFN_MAPPING_H
|
||||
#define _XFN_MAPPING_H
|
||||
|
||||
#ident "@(#)xfn_mapping.h 1.6 95/09/19 SMI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAP_PASSLEN 32 /* XXX max mapped passwd length */
|
||||
#define MAP_HEXLEN (2*MAP_PASSLEN) /* XXX max passwd length in hex */
|
||||
#define DCE_XFN_PASS_ATTR "onc_dce_passwd"
|
||||
|
||||
#define XFN_MAP_DEBUG 0x1 /* enable debugging */
|
||||
|
||||
int
|
||||
xfn_get_mapped_password(
|
||||
int flags, /* XFN_MAP_DEBUG, etc */
|
||||
char *user, /* xfn user */
|
||||
char *xfn_attr, /* xfn attribute that holds the target pass */
|
||||
char *key, /* key (password) encrypting target password */
|
||||
char *out, /* un-encrypted target password */
|
||||
int max_out_len /* buffer size of out */
|
||||
);
|
||||
|
||||
int
|
||||
xfn_update_mapped_password(
|
||||
int flags, /* XFN_MAP_DEBUG, etc */
|
||||
char *user, /* xfn user */
|
||||
char *xfn_attr, /* xfn attribute that holds the target pass */
|
||||
char *key, /* key (password) encrypting target password */
|
||||
char *password /* un-encrypted target password */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
32
cde/lib/pam/pam_modules/dial_auth/Imakefile
Normal file
32
cde/lib/pam/pam_modules/dial_auth/Imakefile
Normal file
@@ -0,0 +1,32 @@
|
||||
/* $XConsortium: Imakefile /main/4 1996/04/21 19:13:07 drk $
|
||||
*
|
||||
* (c) Copyright 1996 Digital Equipment Corporation.
|
||||
* (c) Copyright 1996 Hewlett-Packard Company.
|
||||
* (c) Copyright 1996 International Business Machines Corp.
|
||||
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1996 Novell, Inc.
|
||||
* (c) Copyright 1996 FUJITSU LIMITED.
|
||||
* (c) Copyright 1996 Hitachi.
|
||||
*/
|
||||
|
||||
#define DoNormalLib NormalLibPam
|
||||
#define DoSharedLib SharedLibPam
|
||||
#define DoDebugLib DebugLibPam
|
||||
#define DoProfileLib ProfileLibPam
|
||||
#define LibName pam_dial_auth
|
||||
#define SoRev SOPAMREV
|
||||
#define LibHeaders NO
|
||||
|
||||
#include <Threads.tmpl>
|
||||
|
||||
SRCS = dial_auth.c
|
||||
|
||||
OBJS = dial_auth.o
|
||||
|
||||
#ifdef SharedPamDialAuthReqs
|
||||
REQUIREDLIBS = SharedPamDialAuthReqs
|
||||
#endif
|
||||
|
||||
#include <Library.tmpl>
|
||||
|
||||
DependTarget()
|
||||
139
cde/lib/pam/pam_modules/dial_auth/dial_auth.c
Normal file
139
cde/lib/pam/pam_modules/dial_auth/dial_auth.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/* $XConsortium: dial_auth.c /main/5 1996/05/09 04:28:31 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)dial_auth.c 1.20 96/02/09 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
/*
|
||||
* pam_sm_auth_port - This is the top level function in the
|
||||
* module called by pam_auth_port in the framework
|
||||
* Returns: PAM_SERVICE_ERR on failure, 0 on success
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_authenticate(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
char *ttyn, *user;
|
||||
struct pam_conv *pam_convp;
|
||||
FILE *fp;
|
||||
char defpass[30];
|
||||
char line[80];
|
||||
char *p1, *p2;
|
||||
struct passwd pwd;
|
||||
char pwd_buffer[1024];
|
||||
char *password;
|
||||
static struct pam_response *ret_resp;
|
||||
int retcode;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
int num_msg;
|
||||
int i;
|
||||
int debug = 0;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else
|
||||
syslog(LOG_DEBUG, "illegal option %s", argv[i]);
|
||||
}
|
||||
|
||||
if ((retcode = pam_get_user(pamh, &user, NULL))
|
||||
!= PAM_SUCCESS ||
|
||||
(retcode = pam_get_item(pamh, PAM_TTY, (void **)&ttyn))
|
||||
!= PAM_SUCCESS ||
|
||||
(retcode = pam_get_item(pamh, PAM_CONV, (void **)&pam_convp))
|
||||
!= PAM_SUCCESS)
|
||||
return (retcode);
|
||||
|
||||
if (debug) {
|
||||
syslog(LOG_DEBUG,
|
||||
"Dialpass authenticate user = %s, ttyn = %s",
|
||||
user, ttyn);
|
||||
}
|
||||
|
||||
if (getpwnam_r(user, &pwd, pwd_buffer, sizeof (pwd_buffer)) == NULL)
|
||||
return (PAM_USER_UNKNOWN);
|
||||
|
||||
if ((fp = fopen(DIAL_FILE, "r")) == NULL) {
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
while ((p1 = fgets(line, sizeof (line), fp)) != NULL) {
|
||||
while (*p1 != '\n' && *p1 != ' ' && *p1 != '\t')
|
||||
p1++;
|
||||
*p1 = '\0';
|
||||
if (strcmp(line, ttyn) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
(void) fclose(fp);
|
||||
|
||||
if (p1 == NULL || (fp = fopen(DPASS_FILE, "r")) == NULL)
|
||||
return (PAM_SUCCESS);
|
||||
|
||||
defpass[0] = '\0';
|
||||
p2 = 0;
|
||||
|
||||
while ((p1 = fgets(line, sizeof (line)-1, fp)) != NULL) {
|
||||
while (*p1 && *p1 != ':')
|
||||
p1++;
|
||||
*p1++ = '\0';
|
||||
p2 = p1;
|
||||
while (*p1 && *p1 != ':')
|
||||
p1++;
|
||||
*p1 = '\0';
|
||||
if (pwd.pw_shell != NULL && strcmp(pwd.pw_shell, line) == 0)
|
||||
break;
|
||||
|
||||
if (strcmp(SHELL, line) == 0)
|
||||
SCPYN(defpass, p2);
|
||||
p2 = 0;
|
||||
}
|
||||
|
||||
(void) fclose(fp);
|
||||
|
||||
if (!p2)
|
||||
p2 = defpass;
|
||||
|
||||
if (*p2 != '\0') {
|
||||
strcpy(messages[0], PAM_MSG(pamh, 1, "Dialup Password: "));
|
||||
num_msg = 1;
|
||||
retcode = __pam_get_input(PAM_PROMPT_ECHO_OFF, pam_convp->conv,
|
||||
num_msg, messages, NULL, &ret_resp);
|
||||
if (retcode != PAM_SUCCESS)
|
||||
return (retcode);
|
||||
password = ret_resp->resp;
|
||||
|
||||
/* UNIX passwords can only be 8 characters long */
|
||||
password[8] = '\0';
|
||||
|
||||
if (strcmp(crypt(password, p2), p2)) {
|
||||
__pam_free_resp(num_msg, ret_resp);
|
||||
return (PAM_SERVICE_ERR);
|
||||
}
|
||||
__pam_free_resp(num_msg, ret_resp);
|
||||
}
|
||||
|
||||
return (PAM_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* dummy pam_sm_setcred - does nothing
|
||||
*/
|
||||
pam_sm_setcred(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
18
cde/lib/pam/pam_modules/dial_auth/libpam_dial_auth.elist
Normal file
18
cde/lib/pam/pam_modules/dial_auth/libpam_dial_auth.elist
Normal file
@@ -0,0 +1,18 @@
|
||||
/****************************************************************************
|
||||
* Export list for libpam_dial_auth.
|
||||
* This list *must* be updated whenever a change is made to the libpam_dial_auth
|
||||
* API.
|
||||
*
|
||||
* The syntax for the symbol declarations in this list is as follows:
|
||||
* public sym => Public C symbol, i.e., publicised API
|
||||
* private sym => Private C symbol, i.e., unpublicised API
|
||||
* internal sym => Internal C symbol, i.e., not part of API
|
||||
* publicC++ sym => Public C++ symbol, i.e., publicised API
|
||||
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
|
||||
* internalC++ sym => Internal C++ symbol, i.e., not part of API
|
||||
*
|
||||
* $TOG: libpam_dial_auth.elist /main/1 1999/09/08 15:58:41 mgreess $
|
||||
*****************************************************************************/
|
||||
|
||||
public pam_sm_authenticate
|
||||
public pam_sm_setcred
|
||||
92
cde/lib/pam/pam_modules/dial_auth/unix_headers.h
Normal file
92
cde/lib/pam/pam_modules/dial_auth/unix_headers.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* $XConsortium: unix_headers.h /main/4 1996/05/09 04:28:47 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _UNIX_HEADERS_H
|
||||
#define _UNIX_HEADERS_H
|
||||
|
||||
#pragma ident "@(#)unix_headers.h 1.6 96/02/02 SMI" /* PAM 2.6 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
|
||||
PROPRIETARY NOTICE(Combined)
|
||||
|
||||
This source code is unpublished proprietary information
|
||||
constituting, or derived under license from AT&T's UNIX(r) System V.
|
||||
In addition, portions of such source code were derived from Berkeley
|
||||
4.3 BSD under license from the Regents of the University of
|
||||
California.
|
||||
|
||||
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Notice of copyright on this source code product does not indicate
|
||||
publication.
|
||||
|
||||
(c) 1986, 1987, 1988, 1989, 1990, 1991, 1992 Sun Microsystems, Inc
|
||||
(c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T.
|
||||
All rights reserved.
|
||||
*******************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
******************************************************************** *
|
||||
* *
|
||||
* Unix Scheme Header Files *
|
||||
* *
|
||||
* ******************************************************************** */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <pwd.h>
|
||||
#include <shadow.h>
|
||||
#include <string.h>
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/auth.h>
|
||||
#include <locale.h>
|
||||
#include <crypt.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/*
|
||||
* Various useful files and string constants
|
||||
*/
|
||||
#define DIAL_FILE "/etc/dialups"
|
||||
#define DPASS_FILE "/etc/d_passwd"
|
||||
#define SHELL "/usr/bin/sh"
|
||||
|
||||
/*
|
||||
* PAM_MSG macro for return of internationalized text
|
||||
*/
|
||||
|
||||
#define PAM_MSG(pamh, number, string)\
|
||||
(char *) __pam_get_i18n_msg(pamh, "pam_unix", 2, number, string)
|
||||
|
||||
/*
|
||||
* Miscellaneous constants
|
||||
*/
|
||||
#define SLEEPTIME 4
|
||||
#define ERROR 1
|
||||
#define OK 0
|
||||
#define MAXTRYS 5
|
||||
#define ROOTUID 0
|
||||
|
||||
/*
|
||||
* String manipulation macros: SCPYN, EQN and ENVSTRNCAT
|
||||
*/
|
||||
#define SCPYN(a, b) (void) strncpy(a, b, sizeof (a))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UNIX_HEADERS_H */
|
||||
32
cde/lib/pam/pam_modules/rhosts_auth/Imakefile
Normal file
32
cde/lib/pam/pam_modules/rhosts_auth/Imakefile
Normal file
@@ -0,0 +1,32 @@
|
||||
/* $XConsortium: Imakefile /main/4 1996/04/21 19:13:11 drk $
|
||||
*
|
||||
* (c) Copyright 1996 Digital Equipment Corporation.
|
||||
* (c) Copyright 1996 Hewlett-Packard Company.
|
||||
* (c) Copyright 1996 International Business Machines Corp.
|
||||
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1996 Novell, Inc.
|
||||
* (c) Copyright 1996 FUJITSU LIMITED.
|
||||
* (c) Copyright 1996 Hitachi.
|
||||
*/
|
||||
|
||||
#define DoNormalLib NormalLibPam
|
||||
#define DoSharedLib SharedLibPam
|
||||
#define DoDebugLib DebugLibPam
|
||||
#define DoProfileLib ProfileLibPam
|
||||
#define LibName pam_rhosts_auth
|
||||
#define SoRev SOPAMREV
|
||||
#define LibHeaders NO
|
||||
|
||||
#include <Threads.tmpl>
|
||||
|
||||
SRCS = rhosts_auth.c
|
||||
|
||||
OBJS = rhosts_auth.o
|
||||
|
||||
#ifdef SharedPamRhostsAuthReqs
|
||||
REQUIREDLIBS = SharedPamRhostsAuthReqs
|
||||
#endif
|
||||
|
||||
#include <Library.tmpl>
|
||||
|
||||
DependTarget()
|
||||
18
cde/lib/pam/pam_modules/rhosts_auth/libpam_rhosts_auth.elist
Normal file
18
cde/lib/pam/pam_modules/rhosts_auth/libpam_rhosts_auth.elist
Normal file
@@ -0,0 +1,18 @@
|
||||
/****************************************************************************
|
||||
* Export list for libpam_rhosts_auth.
|
||||
* This list *must* be updated whenever a change is made to the
|
||||
* libpam_rhosts_auth API.
|
||||
*
|
||||
* The syntax for the symbol declarations in this list is as follows:
|
||||
* public sym => Public C symbol, i.e., publicised API
|
||||
* private sym => Private C symbol, i.e., unpublicised API
|
||||
* internal sym => Internal C symbol, i.e., not part of API
|
||||
* publicC++ sym => Public C++ symbol, i.e., publicised API
|
||||
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
|
||||
* internalC++ sym => Internal C++ symbol, i.e., not part of API
|
||||
*
|
||||
* $TOG: libpam_rhosts_auth.elist /main/1 1999/09/08 15:59:05 mgreess $
|
||||
*****************************************************************************/
|
||||
|
||||
public pam_sm_authenticate
|
||||
public pam_sm_setcred
|
||||
83
cde/lib/pam/pam_modules/rhosts_auth/rhosts_auth.c
Normal file
83
cde/lib/pam/pam_modules/rhosts_auth/rhosts_auth.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/* $XConsortium: rhosts_auth.c /main/5 1996/05/09 04:29:04 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)rhosts_auth.c 1.19 96/02/02 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
/*
|
||||
* pam_sm_auth_netuser - Checks if the user is allowed remote access
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_authenticate(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
char *host = NULL, *lusername = NULL;
|
||||
struct passwd pwd;
|
||||
char pwd_buffer[1024];
|
||||
int is_superuser;
|
||||
char *rusername;
|
||||
int err;
|
||||
int i;
|
||||
int debug = 0;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else
|
||||
syslog(LOG_DEBUG, "illegal option %s", argv[i]);
|
||||
}
|
||||
|
||||
if (pam_get_item(pamh, PAM_USER, (void **) &lusername) != PAM_SUCCESS)
|
||||
return (PAM_SERVICE_ERR);
|
||||
if (pam_get_item(pamh, PAM_RHOST, (void **) &host) != PAM_SUCCESS)
|
||||
return (PAM_SERVICE_ERR);
|
||||
if (pam_get_item(pamh, PAM_RUSER, (void **)&rusername) != PAM_SUCCESS)
|
||||
return (PAM_SERVICE_ERR);
|
||||
|
||||
if (debug) {
|
||||
syslog(LOG_DEBUG,
|
||||
"rhosts authenticate: user = %s, host = %s",
|
||||
lusername, host);
|
||||
}
|
||||
|
||||
if (getpwnam_r(lusername, &pwd, pwd_buffer, sizeof (pwd_buffer))
|
||||
== NULL)
|
||||
return (PAM_USER_UNKNOWN);
|
||||
|
||||
/*
|
||||
* RHOST may not be set due to unknown USER or reset by previous
|
||||
* authentication failure.
|
||||
*/
|
||||
if ((rusername == NULL) || (rusername[0] == '\0'))
|
||||
return (PAM_AUTH_ERR);
|
||||
|
||||
if (pwd.pw_uid == 0)
|
||||
is_superuser = 1;
|
||||
else
|
||||
is_superuser = 0;
|
||||
|
||||
return (ruserok(host, is_superuser, rusername, lusername)
|
||||
== -1 ? PAM_AUTH_ERR : PAM_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* dummy pam_sm_setcred - does nothing
|
||||
*/
|
||||
pam_sm_setcred(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
69
cde/lib/pam/pam_modules/rhosts_auth/unix_headers.h
Normal file
69
cde/lib/pam/pam_modules/rhosts_auth/unix_headers.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* $XConsortium: unix_headers.h /main/4 1996/05/09 04:29:21 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _UNIX_HEADERS_H
|
||||
#define _UNIX_HEADERS_H
|
||||
|
||||
#pragma ident "@(#)unix_headers.h 1.6 96/02/02 SMI" /* PAM 2.6 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
******************************************************************
|
||||
|
||||
PROPRIETARY NOTICE(Combined)
|
||||
|
||||
This source code is unpublished proprietary information
|
||||
constituting, or derived under license from AT&T's UNIX(r) System V.
|
||||
In addition, portions of such source code were derived from Berkeley
|
||||
4.3 BSD under license from the Regents of the University of
|
||||
California.
|
||||
|
||||
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Notice of copyright on this source code product does not indicate
|
||||
publication.
|
||||
|
||||
(c) 1986, 1987, 1988, 1989, 1990, 1991, 1992 Sun Microsystems, Inc
|
||||
(c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T.
|
||||
All rights reserved.
|
||||
*******************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
******************************************************************** *
|
||||
* *
|
||||
* Unix Scheme Header Files *
|
||||
* *
|
||||
* ******************************************************************** */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <pwd.h>
|
||||
#include <shadow.h>
|
||||
#include <string.h>
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/auth.h>
|
||||
#include <locale.h>
|
||||
#include <crypt.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/*
|
||||
* Miscellaneous constants
|
||||
*/
|
||||
#define ROOTUID 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UNIX_HEADERS_H */
|
||||
46
cde/lib/pam/pam_modules/sample/Imakefile
Normal file
46
cde/lib/pam/pam_modules/sample/Imakefile
Normal file
@@ -0,0 +1,46 @@
|
||||
/* $XConsortium: Imakefile /main/2 1996/04/21 19:14:34 drk $
|
||||
*
|
||||
* (c) Copyright 1996 Digital Equipment Corporation.
|
||||
* (c) Copyright 1996 Hewlett-Packard Company.
|
||||
* (c) Copyright 1996 International Business Machines Corp.
|
||||
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1996 Novell, Inc.
|
||||
* (c) Copyright 1996 FUJITSU LIMITED.
|
||||
* (c) Copyright 1996 Hitachi.
|
||||
*/
|
||||
|
||||
#define DoNormalLib NormalLibPam
|
||||
#define DoSharedLib SharedLibPam
|
||||
#define DoDebugLib DebugLibPam
|
||||
#define DoProfileLib ProfileLibPam
|
||||
#define LibName pam_sample
|
||||
#define SoRev SOPAMREV
|
||||
#define LibHeaders NO
|
||||
|
||||
#include <Threads.tmpl>
|
||||
|
||||
SRCS = \
|
||||
sample_acct_mgmt.c \
|
||||
sample_authenticate.c \
|
||||
sample_close_session.c \
|
||||
sample_open_session.c \
|
||||
sample_password.c \
|
||||
sample_setcred.c \
|
||||
sample_utils.c
|
||||
|
||||
OBJS = \
|
||||
sample_acct_mgmt.o \
|
||||
sample_authenticate.o \
|
||||
sample_close_session.o \
|
||||
sample_open_session.o \
|
||||
sample_password.o \
|
||||
sample_setcred.o \
|
||||
sample_utils.o
|
||||
|
||||
#ifdef SharedPamSampleReqs
|
||||
REQUIREDLIBS = SharedPamSampleReqs
|
||||
#endif
|
||||
|
||||
#include <Library.tmpl>
|
||||
|
||||
DependTarget()
|
||||
28
cde/lib/pam/pam_modules/sample/libpam_sample.elist
Normal file
28
cde/lib/pam/pam_modules/sample/libpam_sample.elist
Normal file
@@ -0,0 +1,28 @@
|
||||
/****************************************************************************
|
||||
* Export list for libpam_sample.
|
||||
* This list *must* be updated whenever a change is made to the libpam_sample
|
||||
* API.
|
||||
*
|
||||
* The syntax for the symbol declarations in this list is as follows:
|
||||
* public sym => Public C symbol, i.e., publicised API
|
||||
* private sym => Private C symbol, i.e., unpublicised API
|
||||
* internal sym => Internal C symbol, i.e., not part of API
|
||||
* publicC++ sym => Public C++ symbol, i.e., publicised API
|
||||
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
|
||||
* internalC++ sym => Internal C++ symbol, i.e., not part of API
|
||||
*
|
||||
* $TOG: libpam_sample.elist /main/1 1999/09/08 15:59:30 mgreess $
|
||||
*****************************************************************************/
|
||||
|
||||
public pam_sm_authenticate
|
||||
public pam_sm_setcred
|
||||
public pam_sm_acct_mgmt
|
||||
public pam_sm_open_session
|
||||
public pam_sm_close_session
|
||||
public pam_sm_chauthtok
|
||||
|
||||
internal display_errmsg
|
||||
internal get_authtok
|
||||
internal free_msg
|
||||
internal free_resp
|
||||
|
||||
127
cde/lib/pam/pam_modules/sample/sample_acct_mgmt.c
Normal file
127
cde/lib/pam/pam_modules/sample/sample_acct_mgmt.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/* $XConsortium: sample_acct_mgmt.c /main/2 1996/05/09 04:29:37 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)sample_acct_mgmt.c 1.12 96/02/02 SMI"
|
||||
|
||||
#include <syslog.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <libintl.h>
|
||||
|
||||
static parse_allow_name(char *, char *);
|
||||
|
||||
/*
|
||||
* pam_sm_acct_mgmt main account managment routine.
|
||||
* It only checks the flag passed from pam_sm_auth_user().
|
||||
* XXX: The routine just prints out a warning message.
|
||||
* It may need to force the user to change his/her
|
||||
* passwd.
|
||||
*/
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#define PAMTXD "SUNW_OST_SYSOSPAM"
|
||||
|
||||
int
|
||||
pam_sm_acct_mgmt(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
char *user;
|
||||
char *pg;
|
||||
int i;
|
||||
int debug = 0;
|
||||
int nowarn = 0;
|
||||
int error = 0;
|
||||
|
||||
if (argc == 0)
|
||||
return (PAM_SUCCESS);
|
||||
|
||||
if (pam_get_item(pamh, PAM_USER, (void **)&user) != PAM_SUCCESS)
|
||||
return (PAM_SERVICE_ERR);
|
||||
|
||||
if (pam_get_item(pamh, PAM_SERVICE, (void **)&pg) != PAM_SUCCESS)
|
||||
return (PAM_SERVICE_ERR);
|
||||
|
||||
/*
|
||||
* kludge alert. su needs to be handled specially for allow policy.
|
||||
* we want to use the policy of the current user not the "destination"
|
||||
* user. This will enable us to prevent su to root but not to rlogin,
|
||||
* telnet, rsh, ftp to root.
|
||||
*
|
||||
* description of problem: user name is the "destination" name. not
|
||||
* the current name. The allow policy needs to be applied to the
|
||||
* current name in the case of su. user is "root" in this case and
|
||||
* we will be getting the root policy instead of the user policy.
|
||||
*/
|
||||
if (strcmp(pg, "su") == 0) {
|
||||
struct passwd *pw;
|
||||
uid_t uid;
|
||||
uid = getuid();
|
||||
pw = getpwuid(uid);
|
||||
if (pw == NULL)
|
||||
return (PAM_SYSTEM_ERR);
|
||||
user = pw->pw_name;
|
||||
}
|
||||
|
||||
if (user == 0 || *user == '\0' || (strcmp(user, "root") == 0))
|
||||
return (PAM_SUCCESS);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcasecmp(argv[i], "nowarn") == 0) {
|
||||
nowarn = 1;
|
||||
flags = flags | PAM_SILENT;
|
||||
} else if (strncmp(argv[i], "allow=", 6) == 0)
|
||||
error |= parse_allow_name(user, (char *)(argv[i]+6));
|
||||
else
|
||||
syslog(LOG_DEBUG, "illegal option %s", argv[i]);
|
||||
}
|
||||
return (error?PAM_SUCCESS:PAM_AUTH_ERR);
|
||||
}
|
||||
|
||||
static
|
||||
parse_allow_name(char *who, char *cp)
|
||||
{
|
||||
char name[256];
|
||||
static char *getname();
|
||||
|
||||
/* catch "allow=" */
|
||||
if (*cp == '\0')
|
||||
return (0);
|
||||
while (cp) {
|
||||
cp = getname(cp, name);
|
||||
/* catch things such as =, and ,, */
|
||||
if (*name == '\0')
|
||||
continue;
|
||||
if (strcmp(who, name) == 0)
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static char *
|
||||
getname(char *cp, char *name)
|
||||
{
|
||||
/* force name to be initially null string */
|
||||
*name = '\0';
|
||||
|
||||
/* end of string? */
|
||||
if (*cp == '\0')
|
||||
return ((char *)0);
|
||||
while (*cp) {
|
||||
/* end of name? */
|
||||
if (*cp == ',' || *cp == '\0')
|
||||
break;
|
||||
*name++ = *cp++;
|
||||
}
|
||||
/* make name into string */
|
||||
*name++ = '\0';
|
||||
return ((*cp == '\0')? (char *)0 : ++cp);
|
||||
}
|
||||
168
cde/lib/pam/pam_modules/sample/sample_authenticate.c
Normal file
168
cde/lib/pam/pam_modules/sample/sample_authenticate.c
Normal file
@@ -0,0 +1,168 @@
|
||||
/* $XConsortium: sample_authenticate.c /main/2 1996/05/09 04:29:50 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)sample_authenticate.c 1.14 96/01/15 SMI"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <syslog.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#include "sample_utils.h"
|
||||
|
||||
#define SLEEPTIME 4
|
||||
|
||||
/*
|
||||
*
|
||||
* Sample module for pam_sm_authenticate.
|
||||
*
|
||||
* options -
|
||||
*
|
||||
* debug
|
||||
* use_first_pass
|
||||
* try_first_pass
|
||||
* first_pass_good (first password is always good when used with use/try)
|
||||
* first_pass_bad (first password is always bad when used with use/try)
|
||||
* pass=foobar (set good password to "foobar". default good password
|
||||
* is test)
|
||||
* always_fail always return PAM_AUTH_ERR
|
||||
* always_succeed always return PAM_SUCCESS
|
||||
* always_ignore
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* pam_sm_authenticate - Authenticate user
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_authenticate(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
char *user;
|
||||
struct pam_conv *pam_convp;
|
||||
int err, result = PAM_AUTH_ERR;
|
||||
struct pam_response *ret_resp = (struct pam_response *)0;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
int debug = 0;
|
||||
int try_first_pass = 0;
|
||||
int use_first_pass = 0;
|
||||
int first_pass_good = 0;
|
||||
int first_pass_bad = 0;
|
||||
int i, num_msg;
|
||||
char *firstpass, *password;
|
||||
char the_password[64];
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "Sample Authentication\n");
|
||||
|
||||
strcpy(the_password, "test");
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcmp(argv[i], "try_first_pass") == 0)
|
||||
try_first_pass = 1;
|
||||
else if (strcmp(argv[i], "first_pass_good") == 0)
|
||||
first_pass_good = 1;
|
||||
else if (strcmp(argv[i], "first_pass_bad") == 0)
|
||||
first_pass_bad = 1;
|
||||
else if (strcmp(argv[i], "use_first_pass") == 0)
|
||||
use_first_pass = 1;
|
||||
else if (strcmp(argv[i], "always_fail") == 0)
|
||||
return (PAM_AUTH_ERR);
|
||||
else if (strcmp(argv[i], "always_succeed") == 0)
|
||||
return (PAM_SUCCESS);
|
||||
else if (strcmp(argv[i], "always_ignore") == 0)
|
||||
return (PAM_IGNORE);
|
||||
else if (sscanf(argv[i], "pass=%s", the_password) == 1) {
|
||||
/* nothing */;
|
||||
}
|
||||
else
|
||||
syslog(LOG_DEBUG, "illegal scheme option %s", argv[i]);
|
||||
}
|
||||
|
||||
err = pam_get_item(pamh, PAM_USER, (void**) &user);
|
||||
if (err != PAM_SUCCESS)
|
||||
return (err);
|
||||
|
||||
err = pam_get_item(pamh, PAM_CONV, (void**) &pam_convp);
|
||||
if (err != PAM_SUCCESS)
|
||||
return (err);
|
||||
|
||||
(void) pam_get_item(pamh, PAM_AUTHTOK, (void **) &firstpass);
|
||||
|
||||
if (firstpass && (use_first_pass || try_first_pass)) {
|
||||
|
||||
if ((first_pass_good ||
|
||||
strcmp(firstpass, the_password) == 0) &&
|
||||
!first_pass_bad) {
|
||||
result = PAM_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
if (use_first_pass) goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the password from the user
|
||||
*/
|
||||
if (firstpass) {
|
||||
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 1,
|
||||
"TEST Password: "));
|
||||
} else {
|
||||
(void) sprintf(messages[0], (const char *) PAM_MSG(pamh, 2,
|
||||
"Password: "));
|
||||
}
|
||||
num_msg = 1;
|
||||
err = get_authtok(pam_convp->conv,
|
||||
num_msg, messages, NULL, &ret_resp);
|
||||
|
||||
if (err != PAM_SUCCESS) {
|
||||
result = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
password = ret_resp->resp;
|
||||
|
||||
if (password == NULL) {
|
||||
result = PAM_AUTH_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* one last ditch attempt to "login" to TEST */
|
||||
|
||||
if (strcmp(password, the_password) == 0) {
|
||||
result = PAM_SUCCESS;
|
||||
if (firstpass == NULL) {
|
||||
/* this is the first password, stash it away */
|
||||
pam_set_item(pamh, PAM_AUTHTOK, password);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (num_msg > 0) {
|
||||
if (ret_resp != 0) {
|
||||
if (ret_resp->resp != 0) {
|
||||
/* avoid leaving password cleartext around */
|
||||
memset(ret_resp->resp, 0,
|
||||
strlen(ret_resp->resp));
|
||||
}
|
||||
free_resp(num_msg, ret_resp);
|
||||
ret_resp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
21
cde/lib/pam/pam_modules/sample/sample_close_session.c
Normal file
21
cde/lib/pam/pam_modules/sample/sample_close_session.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/* $XConsortium: sample_close_session.c /main/2 1996/05/09 04:30:08 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)sample_close_session.c 1.8 96/01/12 SMI"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <syslog.h>
|
||||
|
||||
int
|
||||
pam_sm_close_session(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
21
cde/lib/pam/pam_modules/sample/sample_open_session.c
Normal file
21
cde/lib/pam/pam_modules/sample/sample_open_session.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/* $XConsortium: sample_open_session.c /main/2 1996/05/09 04:30:22 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)sample_open_session.c 1.8 96/01/12 SMI"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <syslog.h>
|
||||
|
||||
int
|
||||
pam_sm_open_session(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
27
cde/lib/pam/pam_modules/sample/sample_password.c
Normal file
27
cde/lib/pam/pam_modules/sample/sample_password.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* $XConsortium: sample_password.c /main/2 1996/05/09 04:30:43 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)sample_password.c 1.10 96/01/15 SMI"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
|
||||
int
|
||||
pam_sm_chauthtok(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
|
||||
{
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
32
cde/lib/pam/pam_modules/sample/sample_setcred.c
Normal file
32
cde/lib/pam/pam_modules/sample/sample_setcred.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/* $XConsortium: sample_setcred.c /main/2 1996/05/09 04:31:02 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)sample_setcred.c 1.9 96/01/12 SMI"
|
||||
|
||||
#include <libintl.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
|
||||
#define PAMTXD "SUNW_OST_SYSOSPAM"
|
||||
|
||||
/*
|
||||
* pam_sm_setcred
|
||||
*/
|
||||
int
|
||||
pam_sm_setcred(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
|
||||
/*
|
||||
* Set the credentials
|
||||
*/
|
||||
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
174
cde/lib/pam/pam_modules/sample/sample_utils.c
Normal file
174
cde/lib/pam/pam_modules/sample/sample_utils.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/* $XConsortium: sample_utils.c /main/2 1996/05/09 04:31:21 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)sample_utils.c 1.8 96/01/12 SMI"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "sample_utils.h"
|
||||
|
||||
/* ******************************************************************** */
|
||||
/* */
|
||||
/* Utilities Functions */
|
||||
/* */
|
||||
/* ******************************************************************** */
|
||||
|
||||
/*
|
||||
* free_msg():
|
||||
* free storage for messages used in the call back "pam_conv" functions
|
||||
*/
|
||||
|
||||
void
|
||||
free_msg(num_msg, msg)
|
||||
int num_msg;
|
||||
struct pam_message *msg;
|
||||
{
|
||||
int i;
|
||||
struct pam_message *m;
|
||||
|
||||
if (msg) {
|
||||
m = msg;
|
||||
for (i = 0; i < num_msg; i++, m++) {
|
||||
if (m->msg)
|
||||
free(m->msg);
|
||||
}
|
||||
free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* free_resp():
|
||||
* free storage for responses used in the call back "pam_conv" functions
|
||||
*/
|
||||
|
||||
void
|
||||
free_resp(num_msg, resp)
|
||||
int num_msg;
|
||||
struct pam_response *resp;
|
||||
{
|
||||
int i;
|
||||
struct pam_response *r;
|
||||
|
||||
if (resp) {
|
||||
r = resp;
|
||||
for (i = 0; i < num_msg; i++, r++) {
|
||||
if (r->resp)
|
||||
free(r->resp);
|
||||
}
|
||||
free(resp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* display_errmsg():
|
||||
* display error message by calling the call back functions
|
||||
* provided by the application through "pam_conv" structure
|
||||
*/
|
||||
|
||||
int
|
||||
display_errmsg(conv_funp, num_msg, messages, conv_apdp)
|
||||
int (*conv_funp)();
|
||||
int num_msg;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
void *conv_apdp;
|
||||
{
|
||||
struct pam_message *msg;
|
||||
struct pam_message *m;
|
||||
struct pam_response *resp;
|
||||
int i;
|
||||
int k;
|
||||
int retcode;
|
||||
|
||||
msg = (struct pam_message *)calloc(num_msg,
|
||||
sizeof (struct pam_message));
|
||||
if (msg == NULL) {
|
||||
return (PAM_CONV_ERR);
|
||||
}
|
||||
m = msg;
|
||||
|
||||
i = 0;
|
||||
k = num_msg;
|
||||
resp = NULL;
|
||||
while (k--) {
|
||||
/*
|
||||
* fill out the pam_message structure to display error message
|
||||
*/
|
||||
m->msg_style = PAM_ERROR_MSG;
|
||||
m->msg = (char *)malloc(PAM_MAX_MSG_SIZE);
|
||||
if (m->msg != NULL)
|
||||
(void) strcpy(m->msg, (const char *)messages[i]);
|
||||
else
|
||||
continue;
|
||||
m++;
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call conv function to display the message,
|
||||
* ignoring return value for now
|
||||
*/
|
||||
retcode = conv_funp(num_msg, &msg, &resp, conv_apdp);
|
||||
free_msg(num_msg, msg);
|
||||
free_resp(num_msg, resp);
|
||||
return (retcode);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_authtok():
|
||||
* get authentication token by calling the call back functions
|
||||
* provided by the application through "pam_conv" structure
|
||||
*/
|
||||
|
||||
int
|
||||
get_authtok(conv_funp, num_msg, messages, conv_apdp, ret_respp)
|
||||
int (*conv_funp)();
|
||||
int num_msg;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
void *conv_apdp;
|
||||
struct pam_response **ret_respp;
|
||||
{
|
||||
struct pam_message *msg;
|
||||
struct pam_message *m;
|
||||
int i;
|
||||
int k;
|
||||
int retcode;
|
||||
|
||||
i = 0;
|
||||
k = num_msg;
|
||||
|
||||
msg = (struct pam_message *)calloc(num_msg,
|
||||
sizeof (struct pam_message));
|
||||
if (msg == NULL) {
|
||||
return (PAM_CONV_ERR);
|
||||
}
|
||||
m = msg;
|
||||
|
||||
while (k--) {
|
||||
/*
|
||||
* fill out the message structure to display error message
|
||||
*/
|
||||
m->msg_style = PAM_PROMPT_ECHO_OFF;
|
||||
m->msg = (char *)malloc(PAM_MAX_MSG_SIZE);
|
||||
if (m->msg != NULL)
|
||||
(void) strcpy(m->msg, (char *)messages[i]);
|
||||
else
|
||||
continue;
|
||||
m++;
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call conv function to display the prompt,
|
||||
* ignoring return value for now
|
||||
*/
|
||||
retcode = conv_funp(num_msg, &msg, ret_respp, conv_apdp);
|
||||
free_msg(num_msg, msg);
|
||||
return (retcode);
|
||||
}
|
||||
51
cde/lib/pam/pam_modules/sample/sample_utils.h
Normal file
51
cde/lib/pam/pam_modules/sample/sample_utils.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* $XConsortium: sample_utils.h /main/2 1996/05/09 04:31:40 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _TEST_UTILS_H
|
||||
#define _TEST_UTILS_H
|
||||
|
||||
#pragma ident "@(#)sample_utils.h 1.7 96/02/02 SMI" /* PAM 2.6 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
free_msg(int num_msg, struct pam_message *msg);
|
||||
|
||||
void
|
||||
free_resp(int num_msg, struct pam_response *resp);
|
||||
|
||||
int
|
||||
display_errmsg(
|
||||
int (*conv_funp)(),
|
||||
int num_msg,
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE],
|
||||
void *conv_apdp
|
||||
);
|
||||
|
||||
int
|
||||
get_authtok(
|
||||
int (*conv_funp)(),
|
||||
int num_msg,
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE],
|
||||
void *conv_apdp,
|
||||
struct pam_response **ret_respp
|
||||
);
|
||||
|
||||
/*
|
||||
* PAM_MSG macro for return of internationalized text
|
||||
*/
|
||||
|
||||
#define PAM_MSG(pamh, number, string)\
|
||||
(char *) __pam_get_i18n_msg(pamh, "pam_unix", 3, number, string)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TEST_UTILS_H */
|
||||
66
cde/lib/pam/pam_modules/unix/Imakefile
Normal file
66
cde/lib/pam/pam_modules/unix/Imakefile
Normal file
@@ -0,0 +1,66 @@
|
||||
/* $XConsortium: Imakefile /main/4 1996/04/21 19:13:04 drk $
|
||||
*
|
||||
* (c) Copyright 1996 Digital Equipment Corporation.
|
||||
* (c) Copyright 1996 Hewlett-Packard Company.
|
||||
* (c) Copyright 1996 International Business Machines Corp.
|
||||
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1996 Novell, Inc.
|
||||
* (c) Copyright 1996 FUJITSU LIMITED.
|
||||
* (c) Copyright 1996 Hitachi.
|
||||
*/
|
||||
|
||||
#define DoNormalLib NormalLibPam
|
||||
#define DoSharedLib SharedLibPam
|
||||
#define DoDebugLib DebugLibPam
|
||||
#define DoProfileLib ProfileLibPam
|
||||
#define LibName pam_unix
|
||||
#define SoRev SOPAMREV
|
||||
#define LibHeaders NO
|
||||
|
||||
#include <Threads.tmpl>
|
||||
|
||||
SRCS = unix_acct_mgmt.c \
|
||||
unix_authenticate.c \
|
||||
unix_chauthtok.c \
|
||||
unix_close_session.c \
|
||||
unix_get_authtokattr.c \
|
||||
unix_open_session.c \
|
||||
unix_set_authtokattr.c \
|
||||
npd_clnt.c \
|
||||
unix_setcred.c \
|
||||
unix_update_authtok.c \
|
||||
unix_update_authtok_file.c \
|
||||
unix_update_authtok_nis.c \
|
||||
unix_update_authtok_nisplus.c \
|
||||
switch_utils.c \
|
||||
unix_utils.c \
|
||||
yppasswdxdr.c
|
||||
|
||||
OBJS = unix_acct_mgmt.o \
|
||||
unix_authenticate.o \
|
||||
unix_chauthtok.o \
|
||||
unix_close_session.o \
|
||||
unix_get_authtokattr.o \
|
||||
unix_open_session.o \
|
||||
unix_set_authtokattr.o \
|
||||
npd_clnt.o \
|
||||
unix_setcred.o \
|
||||
unix_update_authtok.o \
|
||||
unix_update_authtok_file.o \
|
||||
unix_update_authtok_nis.o \
|
||||
unix_update_authtok_nisplus.o \
|
||||
switch_utils.o \
|
||||
unix_utils.o \
|
||||
yppasswdxdr.o
|
||||
|
||||
#ifdef SharedPamUnixReqs
|
||||
REQUIREDLIBS = SharedPamUnixReqs
|
||||
#endif
|
||||
|
||||
#ifdef PamUnixDefines
|
||||
DEFINES = PamUnixDefines
|
||||
#endif
|
||||
|
||||
#include <Library.tmpl>
|
||||
|
||||
DependTarget()
|
||||
48
cde/lib/pam/pam_modules/unix/libpam_unix.elist
Normal file
48
cde/lib/pam/pam_modules/unix/libpam_unix.elist
Normal file
@@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
* Export list for libpam_unix.
|
||||
* This list *must* be updated whenever a change is made to the libpam_unix API.
|
||||
*
|
||||
* The syntax for the symbol declarations in this list is as follows:
|
||||
* public sym => Public C symbol, i.e., publicised API
|
||||
* private sym => Private C symbol, i.e., unpublicised API
|
||||
* internal sym => Internal C symbol, i.e., not part of API
|
||||
* publicC++ sym => Public C++ symbol, i.e., publicised API
|
||||
* privateC++ sym => Private C++ symbol, i.e., unpublicised API
|
||||
* internalC++ sym => Internal C++ symbol, i.e., not part of API
|
||||
*
|
||||
* $TOG: libpam_unix.elist /main/1 1999/09/08 15:59:55 mgreess $
|
||||
*****************************************************************************/
|
||||
|
||||
public pam_sm_authenticate
|
||||
public pam_sm_setcred
|
||||
public pam_sm_acct_mgmt
|
||||
public pam_sm_open_session
|
||||
public pam_sm_close_session
|
||||
public pam_sm_chauthtok
|
||||
|
||||
internal get_ns
|
||||
internal __set_authtoken_attr
|
||||
internal defcntl
|
||||
internal defopen
|
||||
internal ck_perm
|
||||
internal gethomedir
|
||||
internal str2spwd
|
||||
internal xdr_yppasswd
|
||||
internal getspnam_from
|
||||
internal update_authtok_file
|
||||
internal setup_attr
|
||||
internal getfingerinfo
|
||||
internal free_setattr
|
||||
internal defread
|
||||
internal repository_to_string
|
||||
internal _priv_lock
|
||||
internal getpwnam_from
|
||||
internal update_authtok_nis
|
||||
internal attr_find
|
||||
internal getloginshell
|
||||
internal xdr_passwd
|
||||
internal attr_match
|
||||
internal __update_authtok
|
||||
internal free_passwd_structs
|
||||
internal __get_authtoken_attr
|
||||
|
||||
414
cde/lib/pam/pam_modules/unix/npd_clnt.c
Normal file
414
cde/lib/pam/pam_modules/unix/npd_clnt.c
Normal file
@@ -0,0 +1,414 @@
|
||||
/* $TOG: npd_clnt.c /main/5 1999/10/15 17:23:53 mgreess $ */
|
||||
/*
|
||||
* npd_clnt.c
|
||||
* Contains all the client-side routines to communicate
|
||||
* with the NIS+ passwd update deamon.
|
||||
*
|
||||
* Copyright (c) 1992-5 Sun Microsystems Inc
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)npd_clnt.c 1.11 95/09/19 SMI"
|
||||
|
||||
#ifdef PAM_NISPLUS
|
||||
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <shadow.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <rpc/des_crypt.h>
|
||||
#include <mp.h>
|
||||
#include <rpc/key_prot.h>
|
||||
#include <rpcsvc/nis.h>
|
||||
#include <rpcsvc/nispasswd.h>
|
||||
#include <memory.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define _NPD_PASSMAXLEN 16
|
||||
|
||||
extern int pow(); /* from libmp.so (undocumented) */
|
||||
extern int _mp_move(); /* from libmp.so (undocumented) */
|
||||
extern int sdiv(); /* from libmp.so (undocumented) */
|
||||
extern bool_t __npd_ecb_crypt();
|
||||
extern bool_t __npd_cbc_crypt();
|
||||
extern void *calloc();
|
||||
extern void free();
|
||||
|
||||
/*
|
||||
* given the domain return the client handle to the rpc.nispasswdd
|
||||
* that I need to contact and the master_servers' publickey.
|
||||
* returns TRUE on success and FALSE on failure.
|
||||
*/
|
||||
bool_t
|
||||
npd_makeclnthandle(domain, clnt, srv_pubkey, keysize)
|
||||
char *domain;
|
||||
CLIENT **clnt; /* returned */
|
||||
char *srv_pubkey; /* buf to hold the pubkey; returned */
|
||||
int keysize; /* size of buffer */
|
||||
{
|
||||
nis_server **srvs; /* servers that serve 'domain' */
|
||||
nis_server *master_srv;
|
||||
char buf[NIS_MAXNAMELEN];
|
||||
CLIENT *tmpclnt = NULL;
|
||||
|
||||
if (domain == NULL || *domain == '\0')
|
||||
domain = nis_local_directory();
|
||||
|
||||
/* strlen("org_dir.") + null + "." = 10 */
|
||||
if ((strlen(domain) + 10) > (size_t) NIS_MAXNAMELEN)
|
||||
return (FALSE);
|
||||
(void) sprintf(buf, "org_dir.%s", domain);
|
||||
if (buf[strlen(buf) - 1] != '.')
|
||||
(void) strcat(buf, ".");
|
||||
|
||||
srvs = nis_getservlist(buf);
|
||||
if (srvs == NULL) {
|
||||
/* can't find any of the servers that serve this domain */
|
||||
/* something is very wrong ! */
|
||||
syslog(LOG_ERR,
|
||||
"can't get a list of servers for %s domain",
|
||||
domain);
|
||||
return (FALSE);
|
||||
}
|
||||
master_srv = srvs[0]; /* the first one is always the master */
|
||||
|
||||
/*
|
||||
* copy the publickey -- should be safe to assume there is one,
|
||||
* BUT just in case lets check first !
|
||||
*/
|
||||
switch (master_srv->key_type) {
|
||||
case NIS_PK_DH:
|
||||
if (keysize < master_srv->pkey.n_len) {
|
||||
syslog(LOG_ERR,
|
||||
"buf is %d bytes only, need %d bytes for the key",
|
||||
keysize, master_srv->pkey.n_len);
|
||||
|
||||
(void) nis_freeservlist(srvs);
|
||||
return (FALSE);
|
||||
}
|
||||
(void) strcpy(srv_pubkey, master_srv->pkey.n_bytes);
|
||||
break;
|
||||
case NIS_PK_NONE:
|
||||
default:
|
||||
/* server does not have a D-H key-pair */
|
||||
syslog(LOG_ERR, "no publickey for %s", master_srv->name);
|
||||
(void) nis_freeservlist(srvs);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* now that we have the universal addr for the master server,
|
||||
* lets create the client handle to rpc.nispasswdd.
|
||||
* always use VC and attempt to create an authenticated handle.
|
||||
* nis_make_rpchandle() will attempt to use auth_des first,
|
||||
* if user does not have D-H keys, then it will try auth_sys.
|
||||
* sendsz and recvsz are 0 ==> choose defaults.
|
||||
*/
|
||||
tmpclnt = nis_make_rpchandle(master_srv, 0, NISPASSWD_PROG,
|
||||
NISPASSWD_VERS, ZMH_VC+ZMH_AUTH, 0, 0);
|
||||
|
||||
/* done with server list */
|
||||
(void) nis_freeservlist(srvs);
|
||||
if (tmpclnt == NULL) {
|
||||
/*
|
||||
* error syslog'd by nis_make_rpchandle()
|
||||
*/
|
||||
return (FALSE);
|
||||
}
|
||||
*clnt = tmpclnt;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* generate a common DES key with the publickey I give and
|
||||
* my secret key -- used by the client-side because the secret
|
||||
* key is not cached with keyserv.
|
||||
* returns TRUE on success and FALSE on failure.
|
||||
*/
|
||||
bool_t
|
||||
__get_cmnkey(public, secret, deskey)
|
||||
char *public;
|
||||
char *secret;
|
||||
des_block *deskey;
|
||||
{
|
||||
MINT *pub;
|
||||
MINT *sec;
|
||||
MINT *cmn;
|
||||
MINT *tmp;
|
||||
short reg;
|
||||
short base = (1 << 8);
|
||||
int i;
|
||||
char *k;
|
||||
|
||||
pub = xtom(public);
|
||||
sec = xtom(secret);
|
||||
|
||||
if ((pub == NULL) || (sec == NULL))
|
||||
return (FALSE);
|
||||
|
||||
cmn = itom(0);
|
||||
(void) pow(pub, sec, xtom(HEXMODULUS), cmn);
|
||||
|
||||
/*
|
||||
* Choose middle 64 bits of the common key to use as our des
|
||||
* key, possibly overwriting the lower order bits by setting
|
||||
* parity.
|
||||
*/
|
||||
|
||||
tmp = itom(0);
|
||||
(void) _mp_move(cmn, tmp);
|
||||
for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
|
||||
(void) sdiv(tmp, base, tmp, ®);
|
||||
}
|
||||
k = deskey->c;
|
||||
for (i = 0; i < 8; i++) {
|
||||
(void) sdiv(tmp, base, tmp, ®);
|
||||
*k++ = reg;
|
||||
}
|
||||
des_setparity((char *)deskey);
|
||||
|
||||
mfree(tmp);
|
||||
mfree(sec);
|
||||
mfree(pub);
|
||||
mfree(cmn);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* Default timeout can be changed using clnt_control() */
|
||||
static struct timeval TIMEOUT = { 55, 0 };
|
||||
|
||||
/*
|
||||
* initiate the passwd update request session by sending
|
||||
* username, domainname, the generated public key and
|
||||
* the callers' old passwd encrypted with the common DES key.
|
||||
* if it succeeds, decrypt the identifier and randval sent in
|
||||
* the response; otherwise return an appropriate error code.
|
||||
*/
|
||||
nispasswd_status
|
||||
nispasswd_auth(user, domain, oldpass, u_pubkey, deskey, clnt,
|
||||
ident, randval, err)
|
||||
char *user; /* user name */
|
||||
char *domain; /* domain */
|
||||
char *oldpass; /* clear old password */
|
||||
unsigned char *u_pubkey; /* users' public key */
|
||||
des_block *deskey; /* the common DES key */
|
||||
CLIENT *clnt; /* client handle to rpc.nispasswdd */
|
||||
unsigned long *ident; /* ID, returned on first attempt */
|
||||
unsigned long *randval; /* R, returned on first attempt */
|
||||
int *err; /* error code, returned */
|
||||
{
|
||||
npd_request req_arg;
|
||||
nispasswd_authresult res;
|
||||
des_block ivec;
|
||||
unsigned char xpass[_NPD_PASSMAXLEN];
|
||||
des_block cryptbuf;
|
||||
int cryptstat;
|
||||
int i;
|
||||
char *keystr = "DES";
|
||||
|
||||
if ((user == NULL || *user == '\0') ||
|
||||
(domain == NULL || *domain == '\0') ||
|
||||
(oldpass == NULL || *oldpass == '\0') ||
|
||||
(u_pubkey == NULL || *u_pubkey == '\0') ||
|
||||
(deskey == (des_block *) NULL) ||
|
||||
(clnt == (CLIENT *) NULL)) {
|
||||
*err = NPD_INVALIDARGS;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
(void) memset((char *)&req_arg, 0, sizeof (req_arg));
|
||||
(void) memset((char *)&res, 0, sizeof (res));
|
||||
|
||||
/* encrypt the passwd with the common des key */
|
||||
if (strlen(oldpass) > (size_t) _NPD_PASSMAXLEN) {
|
||||
*err = NPD_BUFTOOSMALL;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
(void) strcpy((char *)xpass, oldpass);
|
||||
for (i = strlen(oldpass); i < _NPD_PASSMAXLEN; i++)
|
||||
xpass[i] = '\0';
|
||||
|
||||
ivec.key.high = ivec.key.low = 0;
|
||||
cryptstat = cbc_crypt((char *) deskey, (char *) xpass,
|
||||
_NPD_PASSMAXLEN, DES_ENCRYPT | DES_HW,
|
||||
(char *) &ivec);
|
||||
|
||||
if (DES_FAILED(cryptstat)) {
|
||||
*err = NPD_ENCRYPTFAIL;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
|
||||
req_arg.username = user;
|
||||
req_arg.domain = domain;
|
||||
req_arg.key_type = keystr;
|
||||
req_arg.user_pub_key.user_pub_key_len =
|
||||
strlen((char *)u_pubkey) + 1;
|
||||
req_arg.user_pub_key.user_pub_key_val = u_pubkey;
|
||||
req_arg.npd_authpass.npd_authpass_len = _NPD_PASSMAXLEN;
|
||||
req_arg.npd_authpass.npd_authpass_val = xpass;
|
||||
req_arg.ident = *ident; /* on re-tries ident is non-zero */
|
||||
|
||||
if (clnt_call(clnt, NISPASSWD_AUTHENTICATE,
|
||||
(xdrproc_t) xdr_npd_request, (caddr_t) &req_arg,
|
||||
(xdrproc_t) xdr_nispasswd_authresult, (caddr_t) &res,
|
||||
TIMEOUT) != RPC_SUCCESS) {
|
||||
|
||||
/* following msg is printed on stderr */
|
||||
(void) clnt_perror(clnt, "call to rpc.nispasswdd failed");
|
||||
*err = NPD_SRVNOTRESP;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
|
||||
switch (res.status) {
|
||||
case NPD_SUCCESS:
|
||||
case NPD_TRYAGAIN:
|
||||
/*
|
||||
* decrypt the ident & randval
|
||||
*/
|
||||
cryptbuf.key.high =
|
||||
ntohl(res.nispasswd_authresult_u.npd_verf.npd_xid);
|
||||
cryptbuf.key.low =
|
||||
ntohl(res.nispasswd_authresult_u.npd_verf.npd_xrandval);
|
||||
|
||||
if (! __npd_ecb_crypt(ident, randval, &cryptbuf,
|
||||
sizeof (des_block), DES_DECRYPT, deskey)) {
|
||||
*err = NPD_DECRYPTFAIL;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
return (res.status);
|
||||
|
||||
case NPD_FAILED:
|
||||
*err = res.nispasswd_authresult_u.npd_err;
|
||||
return (NPD_FAILED);
|
||||
default:
|
||||
/*
|
||||
* should never reach this case !
|
||||
*/
|
||||
*err = NPD_SYSTEMERR;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* authenticated the caller, now send the identifier; and the
|
||||
* new password and the random value encrypted with the common
|
||||
* DES key. Send any other changed password information in the
|
||||
* clear.
|
||||
*/
|
||||
int
|
||||
nispasswd_pass(clnt, ident, randval, deskey, newpass, gecos, shell, err, errlst)
|
||||
CLIENT *clnt; /* client handle to rpc.nispasswdd */
|
||||
unsigned long ident; /* ID */
|
||||
unsigned long randval; /* R */
|
||||
des_block *deskey; /* common DES key */
|
||||
char *newpass; /* clear new password */
|
||||
char *gecos; /* gecos */
|
||||
char *shell; /* shell */
|
||||
int *err; /* error code, returned */
|
||||
nispasswd_error **errlst; /* error list on partial success, returned */
|
||||
{
|
||||
npd_update send_arg;
|
||||
nispasswd_updresult result;
|
||||
npd_newpass cryptbuf;
|
||||
unsigned long tmp_xrval;
|
||||
nispasswd_error *errl = NULL, *p;
|
||||
|
||||
if ((clnt == (CLIENT *) NULL) ||
|
||||
(deskey == (des_block *) NULL) ||
|
||||
(newpass == NULL || *newpass == '\0')) {
|
||||
*err = NPD_INVALIDARGS;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
(void) memset((char *)&send_arg, 0, sizeof (send_arg));
|
||||
(void) memset((char *)&result, 0, sizeof (result));
|
||||
|
||||
send_arg.ident = ident;
|
||||
|
||||
if (! __npd_cbc_crypt(&randval, newpass, strlen(newpass),
|
||||
&cryptbuf, _NPD_PASSMAXLEN, DES_ENCRYPT, deskey)) {
|
||||
|
||||
*err = NPD_ENCRYPTFAIL;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
tmp_xrval = cryptbuf.npd_xrandval;
|
||||
cryptbuf.npd_xrandval = htonl(tmp_xrval);
|
||||
send_arg.xnewpass = cryptbuf;
|
||||
|
||||
/* gecos */
|
||||
send_arg.pass_info.pw_gecos = gecos;
|
||||
|
||||
/* shell */
|
||||
send_arg.pass_info.pw_shell = shell;
|
||||
|
||||
if (clnt_call(clnt, NISPASSWD_UPDATE,
|
||||
(xdrproc_t) xdr_npd_update, (caddr_t) &send_arg,
|
||||
(xdrproc_t) xdr_nispasswd_updresult, (caddr_t) &result,
|
||||
TIMEOUT) != RPC_SUCCESS) {
|
||||
|
||||
/* printed to stderr */
|
||||
(void) clnt_perror(clnt, "call to rpc.nispasswdd failed");
|
||||
*err = NPD_SRVNOTRESP;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
switch (result.status) {
|
||||
case NPD_SUCCESS:
|
||||
return (NPD_SUCCESS);
|
||||
case NPD_PARTIALSUCCESS:
|
||||
/* need to assign field/err code */
|
||||
errl = &result.nispasswd_updresult_u.reason;
|
||||
if (errl == (struct nispasswd_error *) NULL) {
|
||||
*err = NPD_SYSTEMERR;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
*errlst = (nispasswd_error *)
|
||||
calloc(1, sizeof (nispasswd_error));
|
||||
if (*errlst == (struct nispasswd_error *) NULL) {
|
||||
*err = NPD_SYSTEMERR;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
|
||||
for (p = *errlst; errl != NULL; errl = errl->next) {
|
||||
p->npd_field = errl->npd_field;
|
||||
p->npd_code = errl->npd_code;
|
||||
if (errl->next != NULL) {
|
||||
p->next = (nispasswd_error *)
|
||||
calloc(1, sizeof (nispasswd_error));
|
||||
p = p->next;
|
||||
} else
|
||||
p->next = (nispasswd_error *) NULL;
|
||||
}
|
||||
return (NPD_PARTIALSUCCESS);
|
||||
case NPD_FAILED:
|
||||
*err = result.nispasswd_updresult_u.npd_err;
|
||||
return (NPD_FAILED);
|
||||
default:
|
||||
/*
|
||||
* should never reach this case !
|
||||
*/
|
||||
*err = NPD_SYSTEMERR;
|
||||
return (NPD_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__npd_free_errlist(list)
|
||||
nispasswd_error *list;
|
||||
{
|
||||
nispasswd_error *p;
|
||||
|
||||
if (list == NULL)
|
||||
return;
|
||||
for (; list != NULL; list = p) {
|
||||
p = list->next;
|
||||
free(list);
|
||||
}
|
||||
list = NULL;
|
||||
}
|
||||
#else
|
||||
#if defined(sun)
|
||||
/* Quiet warnings */
|
||||
static int dummy;
|
||||
#endif /* sun */
|
||||
#endif /* PAM_NISPLUS */
|
||||
213
cde/lib/pam/pam_modules/unix/pam_unix.msg
Normal file
213
cde/lib/pam/pam_modules/unix/pam_unix.msg
Normal file
@@ -0,0 +1,213 @@
|
||||
$ $XConsortium: pam_unix.msg /main/2 1996/07/24 19:04:15 drk $
|
||||
$ *************************************<+>*************************************
|
||||
$ *****************************************************************************
|
||||
$ **
|
||||
$ ** File: pam_unix.msg
|
||||
$ **
|
||||
$ ** Project: pam
|
||||
$ **
|
||||
$ ** Description:
|
||||
$ ** -----------
|
||||
$ ** This file is the source for the pam_unix message catalog.
|
||||
$ **
|
||||
$ ** It contains messages for the pam_unix service module (set 1).
|
||||
$ **
|
||||
$ ** Also contains messages for pam_dial (set 2) and pam_test (set 3) modules.
|
||||
$ **
|
||||
$ *****************************************************************************
|
||||
$ **
|
||||
$ ** (c) Copyright 1996 Sun Microsystems, Inc.
|
||||
$ ** All Rights reserved
|
||||
$ **
|
||||
$ *****************************************************************************
|
||||
$ *************************************<+>*************************************
|
||||
|
||||
$ *****************************************************************************
|
||||
$
|
||||
$ ***** NOTE FOR MESSAGE CATALOG TRANSLATORS *****
|
||||
$
|
||||
$ There may be three types of messages in this file:
|
||||
$
|
||||
$ 1. Messages that appear in dialogs or are displayed to the user.
|
||||
$
|
||||
$ These messages are the default and they should ALL BE LOCALIZED.
|
||||
$ Note that these messages do NOT have any identification (see the
|
||||
$ comments for type 2 and 3 below).
|
||||
$
|
||||
$ 2. Messages that only appear in the error log file.
|
||||
$
|
||||
$ The localization of these messages is OPTIONAL. These messages are
|
||||
$ identified by the following:
|
||||
$
|
||||
$ MESSAGES xx-yy IN SET zz WILL ONLY APPEAR IN THE DT ERRORLOG FILE
|
||||
$
|
||||
$ 3. Messages that should not be localized.
|
||||
$
|
||||
$ These messages are identified by the following:
|
||||
$
|
||||
$ DO NOT TRANSLATE or CHANGE or LOCALIZE MESSAGES xx-yy from set zz
|
||||
$
|
||||
$ ***** END (NOTE FOR MESSAGE CATALOG TRANSLATORS) *****
|
||||
$
|
||||
$ ******************************************************************************
|
||||
|
||||
$ unix module messages
|
||||
$set 1
|
||||
|
||||
$ switch_utils.c
|
||||
$ Msg 1 thru 8 print on consecutive lines.
|
||||
$ Keep intentation for "passwd:" in messages 2 thru 7
|
||||
|
||||
1 Supported configurations for passwd management are as follows:
|
||||
2 passwd: files
|
||||
3 passwd: files nis
|
||||
4 passwd: files nisplus
|
||||
5 passwd: compat
|
||||
6 passwd: compat AND
|
||||
7 passwd_compat: nisplus
|
||||
8 Please check your /etc/nsswitch.conf file
|
||||
|
||||
9 Can't find name service for passwd
|
||||
10 You may not use nisplus repository
|
||||
11 Your specified repository is not defined in the nsswitch file!
|
||||
|
||||
$ unix_acct_mgmt.c
|
||||
20 Your password has been expired for too long.
|
||||
21 Please contact the system administrator
|
||||
22 Your password will expire within 24 hours.
|
||||
23 Your password will expire in %d day.
|
||||
24 Your password will expire in %d days.
|
||||
|
||||
$ unix_authenticate.c
|
||||
30 UNIX Password:
|
||||
31 Password:
|
||||
|
||||
$ unix_get_authtokattr.c
|
||||
40 You must specify repository when displaying passwd attributes
|
||||
|
||||
$ leave "%s" unchanged
|
||||
41 %s: System error: repository out of range
|
||||
42 Unable to retrieve username.
|
||||
|
||||
$ leave "%s" unchanged
|
||||
43 %s: Unexpected failure. Password database unchanged.
|
||||
|
||||
$ unix_setcred.c
|
||||
$ translate 50-51 as a single sentence
|
||||
50 Removing root credentials would break the rpc services that
|
||||
51 use secure rpc on this host!
|
||||
|
||||
52 Root may use keylogout -f to do this (at your own risk)!
|
||||
53 Could not unset your secret key.
|
||||
54 Maybe the keyserver is down?
|
||||
55 Warning: NFS credentials not destroyed
|
||||
56 Password does not decrypt secret key for %s.
|
||||
57 Could not set secret key for %s. The key server may be down.
|
||||
|
||||
$ unix_update_authtok.c
|
||||
60 %s%s: %s does not exist
|
||||
61 %s%s: user must have NIS+ credential
|
||||
62 Enter login(NIS) password:
|
||||
63 Enter login(NIS+) password:
|
||||
64 Enter login password:
|
||||
65 %s%s: Sorry.
|
||||
66 %s%s: Sorry, wrong passwd
|
||||
67 This password differs from your secure RPC password.
|
||||
68 Please enter your old Secure RPC password:
|
||||
69 This password does not decrypt your secure RPC credentials. Try again:
|
||||
70 Please enter your old Secure RPC password:
|
||||
71 %s%s: Sorry: less than %ld days since the last change.
|
||||
72 %s%s: You may not change this password.
|
||||
73 %s%s: can't create process
|
||||
74 New password:
|
||||
75 Re-enter new password:
|
||||
76 %s%s: Too many tries; try again later
|
||||
77 %s%s: They don't match; try again.
|
||||
78 %s%s: Too many failures - try later.
|
||||
79 %s%s: Password too short - must be at least 6 characters.
|
||||
80 %s%s: Password cannot be circular shift of logonid.
|
||||
81 %s%s: The first %d characters of the password
|
||||
82 must contain at least two alphabetic characters and at least
|
||||
83 one numeric or special character.
|
||||
84 %s%s: Passwords must differ by at least 3 positions
|
||||
85 nispasswd: user must have LOCAL credential
|
||||
86 %s: invalid LOCAL credential
|
||||
|
||||
$ unix_update_authtok_file.c
|
||||
90 %s%s: Password database busy. Try again later.
|
||||
91 %s%s: Unexpected failure. Password database unchanged.
|
||||
92 %s%s: Unexpected failure. Password database missing.
|
||||
93 %s%s: passwd successfully changed for %s
|
||||
94 %s: No local passwd record
|
||||
|
||||
$ unix_update_authtok_nis.c
|
||||
100 %s%s: couldn't change passwd/attributes
|
||||
101 %s%s: Couldn't change passwd/attributes for %s
|
||||
102 NIS(YP) passwd/attributes changed on %s
|
||||
103 System error: no NIS passwd record for %s
|
||||
104 %s: System error%s: shell is set illegally
|
||||
105 System error%s: homedir is set illegally.
|
||||
106 System error: gecos is set illegally.
|
||||
107 %s: secret key reencrypted for %s on %s
|
||||
|
||||
$ unix_update_authtok_nisplus.c
|
||||
108 NIS+ password information changed for %s
|
||||
109 NIS+ credential information changed for %s
|
||||
110 Unable to reencrypt NIS+ credentials for %s;
|
||||
111 %s%s: Password information update failed
|
||||
112 NIS+ password information changed for %s
|
||||
113 The NIS+ credential information for %s will not be changed.
|
||||
114 User %s must do the following to update his/her
|
||||
115 credential information:
|
||||
116 Use NEW passwd for login and OLD passwd for keylogin.
|
||||
|
||||
$ translate 117-118 as a single sentance.
|
||||
117 Use \"chkey -p\" to reencrypt the credentials with the
|
||||
118 new login passwd.
|
||||
|
||||
119 The user must keylogin explicitly after their next login.
|
||||
120 WARNING: Could not reencrypt NIS+ credentials for %s;
|
||||
121 login and keylogin passwords differ.
|
||||
122 Use NEW passwd for login and OLD passwd for keylogin.
|
||||
123 You must keylogin explicitly after your next login.
|
||||
124 %s%s: couldn't change password for %s.
|
||||
125 Reason: failed to update the cred table with reencrypted credentials.
|
||||
126 Please notify your System Administrator.
|
||||
127 NIS+ Password incorrect: try again
|
||||
128 NIS+ password information update failed while talking to NIS+ passwd daemon
|
||||
129 GECOS information was not updated: check NIS+ permissions.
|
||||
130 SHELL information was not updated: check NIS+ permissions.
|
||||
131 NIS+ Credential information was not updated.
|
||||
132 No NIS+ record
|
||||
133 NIS+ password information update failed (update_attr)
|
||||
|
||||
$ unix_utils.c
|
||||
140 %s%s: Permission denied
|
||||
141 %s%s: Can't change local passwd file\n
|
||||
142 %s%s: System error: repository out of range
|
||||
143 Cannot change from restricted shell %s
|
||||
144 Old shell: %s
|
||||
145 New shell:
|
||||
146 Login shell unchanged.
|
||||
147 %s is unacceptable as a new shell
|
||||
148 warning: %s is unavailable on this machine
|
||||
149 Default values are printed inside of '[]'.
|
||||
150 To accept the default, type <return>.
|
||||
151 To have a blank entry, type the word 'none'.
|
||||
152 Name [%s]:
|
||||
153 Finger information unchanged.
|
||||
154 Home Directory [%s]:
|
||||
155 Homedir information unchanged.
|
||||
156 ':' is not allowed.
|
||||
157 Maximum number of characters allowed is %d.
|
||||
158 Control characters are not allowed.
|
||||
|
||||
$ dialup password module messages
|
||||
$set 2
|
||||
|
||||
1 Dialup Password:
|
||||
|
||||
$ dialup password module messages
|
||||
$set 3
|
||||
1 TEST Password:
|
||||
2 Password:
|
||||
684
cde/lib/pam/pam_modules/unix/switch_utils.c
Normal file
684
cde/lib/pam/pam_modules/unix/switch_utils.c
Normal file
@@ -0,0 +1,684 @@
|
||||
/* $XConsortium: switch_utils.c /main/5 1996/05/09 04:32:20 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)switch_utils.c 1.31 96/02/02 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* This file relies on the fact that you are using NSS_SWITCH.
|
||||
* If PAM_NIS or PAM_NISPLUS is defined, then the
|
||||
* include files for nss_switch are included.
|
||||
* Otherwise, the repository is assumed to be FILES,
|
||||
* and NSS_SWITCH is not used.
|
||||
*/
|
||||
|
||||
static void pr_config();
|
||||
|
||||
/*
|
||||
* The following is similar to getpwnam() except that it specifies
|
||||
* where to get the information. This is modeled after getpwnam_r().
|
||||
*/
|
||||
#ifdef PAM_NIS
|
||||
static void
|
||||
nss_nis_passwd(p)
|
||||
nss_db_params_t *p;
|
||||
{
|
||||
p->name = NSS_DBNAM_PASSWD;
|
||||
p->flags |= NSS_USE_DEFAULT_CONFIG;
|
||||
p->default_config = "nis";
|
||||
}
|
||||
|
||||
static void
|
||||
nss_nis_shadow(p)
|
||||
nss_db_params_t *p;
|
||||
{
|
||||
p->name = NSS_DBNAM_SHADOW;
|
||||
p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */
|
||||
p->flags |= NSS_USE_DEFAULT_CONFIG;
|
||||
p->default_config = "nis";
|
||||
}
|
||||
#endif /* PAM_NIS */
|
||||
|
||||
#ifdef PAM_NISPLUS
|
||||
static void
|
||||
nss_nisplus_passwd(p)
|
||||
nss_db_params_t *p;
|
||||
{
|
||||
p->name = NSS_DBNAM_PASSWD;
|
||||
p->flags |= NSS_USE_DEFAULT_CONFIG;
|
||||
p->default_config = "nisplus";
|
||||
}
|
||||
|
||||
static void
|
||||
nss_nisplus_shadow(p)
|
||||
nss_db_params_t *p;
|
||||
{
|
||||
p->name = NSS_DBNAM_SHADOW;
|
||||
p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */
|
||||
p->flags |= NSS_USE_DEFAULT_CONFIG;
|
||||
p->default_config = "nisplus";
|
||||
}
|
||||
#endif /* PAM_NISPLUS */
|
||||
|
||||
static char *
|
||||
gettok(nextpp)
|
||||
char **nextpp;
|
||||
{
|
||||
char *p = *nextpp;
|
||||
char *q = p;
|
||||
char c;
|
||||
|
||||
if (p == 0) {
|
||||
return (0);
|
||||
}
|
||||
while ((c = *q) != '\0' && c != ':') {
|
||||
q++;
|
||||
}
|
||||
if (c == '\0') {
|
||||
*nextpp = 0;
|
||||
} else {
|
||||
*q++ = '\0';
|
||||
*nextpp = q;
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
#if (PAM_NIS || PAM_NISPLUS)
|
||||
|
||||
/*
|
||||
* Return values: 0 = success, 1 = parse error, 2 = erange ...
|
||||
* The structure pointer passed in is a structure in the caller's space
|
||||
* wherein the field pointers would be set to areas in the buffer if
|
||||
* need be. instring and buffer should be separate areas.
|
||||
*/
|
||||
static int
|
||||
str2passwd(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
|
||||
{
|
||||
struct passwd *passwd = (struct passwd *)ent;
|
||||
char *p, *next;
|
||||
int black_magic; /* "+" or "-" entry */
|
||||
|
||||
if (lenstr + 1 > buflen) {
|
||||
return (NSS_STR_PARSE_ERANGE);
|
||||
}
|
||||
/*
|
||||
* We copy the input string into the output buffer and
|
||||
* operate on it in place.
|
||||
*/
|
||||
(void) memcpy(buffer, instr, lenstr);
|
||||
buffer[lenstr] = '\0';
|
||||
|
||||
next = buffer;
|
||||
|
||||
passwd->pw_name = p = gettok(&next); /* username */
|
||||
if (*p == '\0') {
|
||||
/* Empty username; not allowed */
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
black_magic = (*p == '+' || *p == '-');
|
||||
if (black_magic) {
|
||||
passwd->pw_uid = UID_NOBODY;
|
||||
passwd->pw_gid = GID_NOBODY;
|
||||
/*
|
||||
* pwconv tests pw_passwd and pw_age == NULL
|
||||
*/
|
||||
passwd->pw_passwd = "";
|
||||
passwd->pw_age = "";
|
||||
/*
|
||||
* the rest of the passwd entry is "optional"
|
||||
*/
|
||||
passwd->pw_comment = "";
|
||||
passwd->pw_gecos = "";
|
||||
passwd->pw_dir = "";
|
||||
passwd->pw_shell = "";
|
||||
}
|
||||
|
||||
passwd->pw_passwd = p = gettok(&next); /* password */
|
||||
if (p == 0) {
|
||||
if (black_magic)
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
for (; *p != '\0'; p++) { /* age */
|
||||
if (*p == ',') {
|
||||
*p++ = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
passwd->pw_age = p;
|
||||
|
||||
p = next; /* uid */
|
||||
if (p == 0 || *p == '\0') {
|
||||
if (black_magic)
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
if (!black_magic) {
|
||||
passwd->pw_uid = strtol(p, &next, 10);
|
||||
if (next == p) {
|
||||
/* uid field should be nonempty */
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
/*
|
||||
* The old code (in 2.0 thru 2.5) would check
|
||||
* for the uid being negative, or being greater
|
||||
* than 60001 (the rfs limit). If it met either of
|
||||
* these conditions, the uid was translated to 60001.
|
||||
*
|
||||
* Now we just check for negative uids; anything else
|
||||
* is administrative policy
|
||||
*/
|
||||
if (passwd->pw_uid < 0)
|
||||
passwd->pw_uid = UID_NOBODY;
|
||||
}
|
||||
if (*next++ != ':') {
|
||||
if (black_magic)
|
||||
p = gettok(&next);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
p = next; /* gid */
|
||||
if (p == 0 || *p == '\0') {
|
||||
if (black_magic)
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
if (!black_magic) {
|
||||
passwd->pw_gid = strtol(p, &next, 10);
|
||||
if (next == p) {
|
||||
/* gid field should be nonempty */
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
/*
|
||||
* gid should be non-negative; anything else
|
||||
* is administrative policy.
|
||||
*/
|
||||
if (passwd->pw_gid < 0)
|
||||
passwd->pw_gid = GID_NOBODY;
|
||||
}
|
||||
if (*next++ != ':') {
|
||||
if (black_magic)
|
||||
p = gettok(&next);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
|
||||
passwd->pw_gecos = passwd->pw_comment = p = gettok(&next);
|
||||
if (p == 0) {
|
||||
if (black_magic)
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
|
||||
passwd->pw_dir = p = gettok(&next);
|
||||
if (p == 0) {
|
||||
if (black_magic)
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
|
||||
passwd->pw_shell = p = gettok(&next);
|
||||
if (p == 0) {
|
||||
if (black_magic)
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
|
||||
/* Better not be any more fields... */
|
||||
if (next == 0) {
|
||||
/* Successfully parsed and stored */
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
}
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
|
||||
typedef const char *constp;
|
||||
|
||||
static bool_t /* 1 means success and more input, 0 means error or no more */
|
||||
getfield(nextp, limit, uns, valp)
|
||||
constp *nextp;
|
||||
constp limit;
|
||||
int uns;
|
||||
void *valp;
|
||||
{
|
||||
constp p = *nextp;
|
||||
char *endfield;
|
||||
char numbuf[12]; /* Holds -2^31 and trailing \0 */
|
||||
int len;
|
||||
|
||||
if (p == 0 || p >= limit) {
|
||||
return (0);
|
||||
}
|
||||
if (*p == ':') {
|
||||
p++;
|
||||
*nextp = p;
|
||||
return (p < limit);
|
||||
}
|
||||
if ((len = limit - p) > sizeof (numbuf) - 1) {
|
||||
len = sizeof (numbuf) - 1;
|
||||
}
|
||||
/*
|
||||
* We want to use strtol() and we have a readonly non-zero-terminated
|
||||
* string, so first we copy and terminate the interesting bit.
|
||||
* Ugh. (It's convenient to terminate with a colon rather than \0).
|
||||
*/
|
||||
if ((endfield = memccpy(numbuf, p, ':', len)) == 0) {
|
||||
if (len != limit - p) {
|
||||
/* Error -- field is too big to be a legit number */
|
||||
return (0);
|
||||
}
|
||||
numbuf[len] = ':';
|
||||
p = limit;
|
||||
} else {
|
||||
p += (endfield - numbuf);
|
||||
}
|
||||
if (uns) {
|
||||
*((unsigned long *)valp) = strtoul(numbuf, &endfield, 10);
|
||||
} else {
|
||||
*((long *)valp) = strtol(numbuf, &endfield, 10);
|
||||
}
|
||||
if (*endfield != ':') {
|
||||
/* Error -- expected <integer><colon>, got something else */
|
||||
return (0);
|
||||
}
|
||||
*nextp = p;
|
||||
return (p < limit);
|
||||
}
|
||||
|
||||
/*
|
||||
* str2spwd() -- convert a string to a shadow passwd entry. The parser is
|
||||
* more liberal than the passwd or group parsers; since it's legitimate
|
||||
* for almost all the fields here to be blank, the parser lets one omit
|
||||
* any number of blank fields at the end of the entry. The acceptable
|
||||
* forms for '+' and '-' entries are the same as those for normal entries.
|
||||
* === Is this likely to do more harm than good?
|
||||
*
|
||||
* Return values: 0 = success, 1 = parse error, 2 = erange ...
|
||||
* The structure pointer passed in is a structure in the caller's space
|
||||
* wherein the field pointers would be set to areas in the buffer if
|
||||
* need be. instring and buffer should be separate areas.
|
||||
*/
|
||||
int
|
||||
str2spwd(instr, lenstr, ent, buffer, buflen)
|
||||
const char *instr;
|
||||
int lenstr;
|
||||
void *ent; /* really (struct spwd *) */
|
||||
char *buffer;
|
||||
int buflen;
|
||||
{
|
||||
struct spwd *shadow = (struct spwd *)ent;
|
||||
const char *p = instr, *limit;
|
||||
char *bufp;
|
||||
int lencopy, black_magic;
|
||||
|
||||
limit = p + lenstr;
|
||||
if ((p = memchr(instr, ':', lenstr)) == 0 ||
|
||||
++p >= limit ||
|
||||
(p = memchr(p, ':', limit - p)) == 0) {
|
||||
lencopy = lenstr;
|
||||
p = 0;
|
||||
} else {
|
||||
lencopy = p - instr;
|
||||
p++;
|
||||
}
|
||||
if (lencopy + 1 > buflen) {
|
||||
return (NSS_STR_PARSE_ERANGE);
|
||||
}
|
||||
(void) memcpy(buffer, instr, lencopy);
|
||||
buffer[lencopy] = 0;
|
||||
|
||||
black_magic = (*instr == '+' || *instr == '-');
|
||||
shadow->sp_namp = bufp = buffer;
|
||||
shadow->sp_pwdp = 0;
|
||||
shadow->sp_lstchg = -1;
|
||||
shadow->sp_min = -1;
|
||||
shadow->sp_max = -1;
|
||||
shadow->sp_warn = -1;
|
||||
shadow->sp_inact = -1;
|
||||
shadow->sp_expire = -1;
|
||||
shadow->sp_flag = 0;
|
||||
|
||||
if ((bufp = strchr(bufp, ':')) == 0) {
|
||||
if (black_magic)
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
*bufp++ = '\0';
|
||||
|
||||
shadow->sp_pwdp = bufp;
|
||||
if (instr == 0) {
|
||||
if ((bufp = strchr(bufp, ':')) == 0) {
|
||||
if (black_magic)
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
else
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
*bufp++ = '\0';
|
||||
p = bufp;
|
||||
} /* else p was set when we copied name and passwd into the buffer */
|
||||
|
||||
if (!getfield(&p, limit, 0, &shadow->sp_lstchg))
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
if (!getfield(&p, limit, 0, &shadow->sp_min))
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
if (!getfield(&p, limit, 0, &shadow->sp_max))
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
if (!getfield(&p, limit, 0, &shadow->sp_warn))
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
if (!getfield(&p, limit, 0, &shadow->sp_inact))
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
if (!getfield(&p, limit, 0, &shadow->sp_expire))
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
if (!getfield(&p, limit, 1, &shadow->sp_flag))
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
if (p != limit) {
|
||||
/* Syntax error -- garbage at end of line */
|
||||
return (NSS_STR_PARSE_PARSE);
|
||||
}
|
||||
return (NSS_STR_PARSE_SUCCESS);
|
||||
}
|
||||
|
||||
static nss_XbyY_buf_t *buffer;
|
||||
static DEFINE_NSS_DB_ROOT(db_root);
|
||||
|
||||
#define GETBUF() \
|
||||
NSS_XbyY_ALLOC(&buffer, sizeof (struct passwd), NSS_BUFLEN_PASSWD)
|
||||
|
||||
struct passwd *
|
||||
getpwnam_from(name, rep)
|
||||
const char *name;
|
||||
int rep;
|
||||
{
|
||||
nss_XbyY_buf_t *b = GETBUF();
|
||||
nss_XbyY_args_t arg;
|
||||
|
||||
if (b == 0)
|
||||
return (0);
|
||||
|
||||
NSS_XbyY_INIT(&arg, b->result, b->buffer, b->buflen, str2passwd);
|
||||
arg.key.name = name;
|
||||
|
||||
switch (rep) {
|
||||
#ifdef PAM_NISPLUS
|
||||
case PAM_REP_NISPLUS:
|
||||
nss_search(&db_root, nss_nisplus_passwd, NSS_DBOP_PASSWD_BYNAME,
|
||||
&arg);
|
||||
break;
|
||||
#endif
|
||||
#ifdef PAM_NIS
|
||||
case PAM_REP_NIS:
|
||||
nss_search(&db_root, nss_nis_passwd, NSS_DBOP_PASSWD_BYNAME,
|
||||
&arg);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (struct passwd *) NSS_XbyY_FINI(&arg);
|
||||
}
|
||||
|
||||
static nss_XbyY_buf_t *spbuf;
|
||||
static DEFINE_NSS_DB_ROOT(spdb_root);
|
||||
|
||||
#define GETSPBUF() \
|
||||
NSS_XbyY_ALLOC(&spbuf, sizeof (struct spwd), NSS_BUFLEN_SHADOW)
|
||||
|
||||
struct spwd *
|
||||
getspnam_from(name, rep)
|
||||
const char *name;
|
||||
int rep;
|
||||
{
|
||||
nss_XbyY_buf_t *b = GETSPBUF();
|
||||
nss_XbyY_args_t arg;
|
||||
|
||||
if (b == 0)
|
||||
return (0);
|
||||
|
||||
NSS_XbyY_INIT(&arg, b->result, b->buffer, b->buflen, str2spwd);
|
||||
arg.key.name = name;
|
||||
switch (rep) {
|
||||
#ifdef PAM_NISPLUS
|
||||
case PAM_REP_NISPLUS:
|
||||
nss_search(&spdb_root, nss_nisplus_shadow,
|
||||
NSS_DBOP_SHADOW_BYNAME, &arg);
|
||||
break;
|
||||
#endif
|
||||
#ifdef PAM_NIS
|
||||
case PAM_REP_NIS:
|
||||
nss_search(&spdb_root, nss_nis_shadow,
|
||||
NSS_DBOP_SHADOW_BYNAME, &arg);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
return (struct spwd *) NSS_XbyY_FINI(&arg);
|
||||
}
|
||||
#endif /* (PAM_NIS || PAM_NISPLUS) */
|
||||
|
||||
static void
|
||||
pr_config(pamh)
|
||||
pam_handle_t *pamh;
|
||||
{
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
|
||||
sprintf(messages[0], PAM_MSG(pamh, 1,
|
||||
"Supported configurations for passwd management are as follows:"));
|
||||
sprintf(messages[1], PAM_MSG(pamh, 2, " passwd: files"));
|
||||
sprintf(messages[2], PAM_MSG(pamh, 3, " passwd: files nis"));
|
||||
sprintf(messages[3], PAM_MSG(pamh, 4, " passwd: files nisplus"));
|
||||
sprintf(messages[4], PAM_MSG(pamh, 5, " passwd: compat"));
|
||||
sprintf(messages[5], PAM_MSG(pamh, 6, " passwd: compat AND"));
|
||||
sprintf(messages[6], PAM_MSG(pamh, 7, " passwd_compat: nisplus"));
|
||||
sprintf(messages[7],
|
||||
PAM_MSG(pamh, 8, "Please check your /etc/nsswitch.conf file"));
|
||||
|
||||
/* display the above 8 messages */
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG, 8, messages, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* get name services (or repositories) of passwd.
|
||||
* o_rep: the specified respository in command line. If no repository is
|
||||
* specified in the command line, o_rep is equal to PAM_REP_DEFAULT.
|
||||
* return value: new repositories
|
||||
* 1. In the case of PAM_REP_DEFAULT, new repositories are from nsswitch
|
||||
* file (as long as it represents a valid and supported configuration).
|
||||
* 2. In the case of specified repository, it should be present as one
|
||||
* of the valid services (or repositories) in nsswitch file.
|
||||
* A warning is printed if this happens. Operation is continued.
|
||||
*/
|
||||
int
|
||||
get_ns(pamh, o_rep, debug, nowarn)
|
||||
pam_handle_t *pamh;
|
||||
int o_rep;
|
||||
int debug;
|
||||
int nowarn;
|
||||
{
|
||||
#if (PAM_NIS || PAM_NISPLUS)
|
||||
struct __nsw_switchconfig *conf = NULL;
|
||||
struct __nsw_switchconfig *confcomp = NULL;
|
||||
enum __nsw_parse_err pserr;
|
||||
struct __nsw_lookup *lkp;
|
||||
struct __nsw_lookup *lkp2;
|
||||
int rep = 0;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
|
||||
/* yppasswd/nispasswd doesn't care about nsswitch file */
|
||||
if (IS_OPWCMD(o_rep))
|
||||
return (o_rep);
|
||||
|
||||
conf = __nsw_getconfig("passwd", &pserr);
|
||||
if (conf == NULL) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 9,
|
||||
"Can't find name service for passwd"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
|
||||
if (IS_NISPLUS(o_rep)) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 10,
|
||||
"You may not use nisplus repository"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (-1);
|
||||
} else if (o_rep != PAM_REP_DEFAULT) {
|
||||
/*
|
||||
* The user specified a repository:
|
||||
* Allow the user to try to change the passwd
|
||||
* even though the specified repository is
|
||||
* not listed in nsswitch.conf
|
||||
*/
|
||||
return (o_rep);
|
||||
} else {
|
||||
/*
|
||||
* The user did not specify a repository:
|
||||
* Allow the user to try to change the passwd
|
||||
* in the default repositories (files and nis)
|
||||
* even though we can not find the name service
|
||||
* switch entry.
|
||||
*/
|
||||
rep = PAM_REP_FILES | PAM_REP_NIS;
|
||||
return (rep); /* default */
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "number of services is %d",
|
||||
conf->num_lookups);
|
||||
lkp = conf->lookups;
|
||||
|
||||
/*
|
||||
* XXX: Currently we do now support more than 2 services
|
||||
*/
|
||||
if (conf->num_lookups > 2) {
|
||||
pr_config(pamh);
|
||||
return (-1);
|
||||
} else if (conf->num_lookups == 1) {
|
||||
/* files or compat */
|
||||
if (strcmp(lkp->service_name, "files") == 0) {
|
||||
rep |= PAM_REP_FILES;
|
||||
if (o_rep == PAM_REP_NIS || o_rep == PAM_REP_NISPLUS) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 11,
|
||||
"Your specified repository is not defined in the nsswitch file!"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (o_rep);
|
||||
}
|
||||
return (rep);
|
||||
} else if (strcmp(lkp->service_name, "compat") == 0) {
|
||||
/* get passwd_compat */
|
||||
confcomp = __nsw_getconfig("passwd_compat", &pserr);
|
||||
if (confcomp == NULL) {
|
||||
rep = PAM_REP_FILES | PAM_REP_NIS;
|
||||
if (o_rep == PAM_REP_NISPLUS) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 11,
|
||||
"Your specified repository is not defined in the nsswitch file!"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (o_rep);
|
||||
} else if (o_rep != PAM_REP_DEFAULT)
|
||||
return (o_rep);
|
||||
else
|
||||
return (rep);
|
||||
} else {
|
||||
/* check the service: nisplus? */
|
||||
if (strcmp(confcomp->lookups->service_name,
|
||||
"nisplus") == 0) {
|
||||
rep = PAM_REP_FILES | PAM_REP_NISPLUS;
|
||||
if (o_rep == PAM_REP_NIS) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 11,
|
||||
"Your specified repository is not defined in the nsswitch file!"));
|
||||
__pam_display_msg(pamh,
|
||||
PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (o_rep);
|
||||
} else if (o_rep != PAM_REP_DEFAULT)
|
||||
return (o_rep);
|
||||
else
|
||||
return (rep);
|
||||
} else {
|
||||
/* passwd_compat must be nisplus?? */
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pr_config(pamh);
|
||||
return (-1);
|
||||
}
|
||||
} else { /* two services */
|
||||
lkp = conf->lookups;
|
||||
lkp2 = lkp->next;
|
||||
if (strcmp(lkp->service_name, "files") == 0) {
|
||||
/* files nis, or files nisplus */
|
||||
rep |= PAM_REP_FILES;
|
||||
/* continue */
|
||||
} else {
|
||||
pr_config(pamh);
|
||||
return (-1);
|
||||
}
|
||||
if (strcmp(lkp2->service_name, "nis") == 0) {
|
||||
rep |= PAM_REP_NIS;
|
||||
if (o_rep == PAM_REP_NISPLUS) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 11,
|
||||
"Your specified repository is not defined in the nsswitch file!"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (o_rep);
|
||||
} else if (o_rep != PAM_REP_DEFAULT)
|
||||
return (o_rep);
|
||||
else
|
||||
return (rep);
|
||||
} else if (strcmp(lkp2->service_name, "nisplus") == 0) {
|
||||
rep |= PAM_REP_NISPLUS;
|
||||
if (o_rep == PAM_REP_NIS) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 11,
|
||||
"Your specified repository is not defined in the nsswitch file!"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (o_rep);
|
||||
} else if (o_rep != PAM_REP_DEFAULT)
|
||||
return (o_rep);
|
||||
else
|
||||
return (rep);
|
||||
} else {
|
||||
pr_config(pamh);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
return (PAM_REP_FILES);
|
||||
#endif /* (PAM_NIS || PAM_NISPLUS) */
|
||||
}
|
||||
313
cde/lib/pam/pam_modules/unix/unix_acct_mgmt.c
Normal file
313
cde/lib/pam/pam_modules/unix/unix_acct_mgmt.c
Normal file
@@ -0,0 +1,313 @@
|
||||
/* $XConsortium: unix_acct_mgmt.c /main/5 1996/05/09 04:32:39 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_acct_mgmt.c 1.35 95/12/08 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
static void
|
||||
unix_cleanup(
|
||||
pam_handle_t *pamh,
|
||||
void *data,
|
||||
int pam_status)
|
||||
{
|
||||
free((unix_authtok_data *)data);
|
||||
}
|
||||
|
||||
/*
|
||||
* check_for_login_inactivity - Check for login inactivity
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
check_for_login_inactivity(
|
||||
struct passwd pwd,
|
||||
struct spwd shpwd)
|
||||
{
|
||||
int fdl;
|
||||
struct lastlog ll;
|
||||
int retval;
|
||||
long long offset;
|
||||
|
||||
offset = (long long) pwd.pw_uid * (long long) sizeof (struct lastlog);
|
||||
|
||||
if ((fdl = open(LASTLOG, O_RDWR|O_CREAT, 0444)) >= 0) {
|
||||
/*
|
||||
* Read the last login (ll) time
|
||||
*/
|
||||
if (llseek(fdl, offset, SEEK_SET) != offset) {
|
||||
/*
|
||||
* XXX uid too large for database
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
retval = read(fdl, (char *)&ll, sizeof (ll));
|
||||
|
||||
/* Check for login inactivity */
|
||||
|
||||
if ((shpwd.sp_inact > 0) && (retval == sizeof (ll)) &&
|
||||
ll.ll_time) {
|
||||
if (((ll.ll_time / DAY) + shpwd.sp_inact) < DAY_NOW) {
|
||||
/*
|
||||
* Account inactive for too long
|
||||
*/
|
||||
(void) close(fdl);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
(void) close(fdl);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* new_password_check()
|
||||
*
|
||||
* check to see if the user needs to change their password
|
||||
*/
|
||||
|
||||
static int
|
||||
new_password_check(pwd, shpwd, flags)
|
||||
struct passwd *pwd;
|
||||
struct spwd *shpwd;
|
||||
int flags;
|
||||
{
|
||||
int now = DAY_NOW;
|
||||
|
||||
/*
|
||||
* We want to make sure that we change the password only if
|
||||
* passwords are required for the system, the user does not
|
||||
* have a password, AND the user's NULL password can be changed
|
||||
* according to its password aging information
|
||||
*/
|
||||
|
||||
if ((flags & PAM_DISALLOW_NULL_AUTHTOK) != 0) {
|
||||
if (shpwd->sp_pwdp[0] == '\0') {
|
||||
if ((pwd->pw_uid != 0) &&
|
||||
((shpwd->sp_max == -1) ||
|
||||
(shpwd->sp_lstchg > now) ||
|
||||
((now >= shpwd->sp_lstchg + shpwd->sp_min) &&
|
||||
(shpwd->sp_max >= shpwd->sp_min)))) {
|
||||
return (PAM_NEW_AUTHTOK_REQD);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* perform_passwd_aging_check
|
||||
* - Check for password exipration.
|
||||
*/
|
||||
|
||||
static int
|
||||
perform_passwd_aging_check(
|
||||
pam_handle_t *pamh,
|
||||
struct spwd shpwd,
|
||||
int flags)
|
||||
{
|
||||
int now = DAY_NOW;
|
||||
int Idleweeks = -1;
|
||||
char *ptr;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
|
||||
|
||||
if (defopen(LOGINADMIN) == 0) {
|
||||
if ((ptr = defread("IDLEWEEKS=")) != NULL)
|
||||
Idleweeks = atoi(ptr);
|
||||
(void) defopen(NULL);
|
||||
}
|
||||
|
||||
if ((shpwd.sp_lstchg == 0) ||
|
||||
((shpwd.sp_max >= 0) &&
|
||||
(now > (shpwd.sp_lstchg + shpwd.sp_max)) &&
|
||||
(shpwd.sp_max >= shpwd.sp_min))) {
|
||||
if ((Idleweeks == 0) ||
|
||||
((Idleweeks > 0) &&
|
||||
(now > (shpwd.sp_lstchg + (7 * Idleweeks))))) {
|
||||
if (!(flags & PAM_SILENT)) {
|
||||
strcpy(messages[0], PAM_MSG(pamh, 20,
|
||||
"Your password has been expired for too long."));
|
||||
strcpy(messages[1], PAM_MSG(pamh, 21,
|
||||
"Please contact the system administrator"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
2, messages, NULL);
|
||||
}
|
||||
return (PAM_AUTHTOK_EXPIRED);
|
||||
} else {
|
||||
return (PAM_NEW_AUTHTOK_REQD);
|
||||
}
|
||||
}
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* warn_user_passwd_will_expire - warn the user when the password will
|
||||
* expire.
|
||||
*/
|
||||
|
||||
static void
|
||||
warn_user_passwd_will_expire(
|
||||
pam_handle_t *pamh,
|
||||
struct spwd shpwd)
|
||||
{
|
||||
int now = DAY_NOW;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
int days;
|
||||
|
||||
if ((shpwd.sp_warn > 0) && (shpwd.sp_max > 0) &&
|
||||
(now + shpwd.sp_warn) >= (shpwd.sp_lstchg + shpwd.sp_max)) {
|
||||
days = (shpwd.sp_lstchg + shpwd.sp_max) - now;
|
||||
if (days <= 0)
|
||||
sprintf(messages[0], PAM_MSG(pamh, 22,
|
||||
"Your password will expire within 24 hours."));
|
||||
else if (days == 1)
|
||||
sprintf(messages[0], PAM_MSG(pamh, 23,
|
||||
"Your password will expire in %d day."), days);
|
||||
else
|
||||
sprintf(messages[0], PAM_MSG(pamh, 24,
|
||||
"Your password will expire in %d days."), days);
|
||||
__pam_display_msg(pamh, PAM_TEXT_INFO, 1, messages, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pam_sm_acct_mgmt - main account managment routine.
|
||||
* Returns: module error or specific error on failure
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_acct_mgmt(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
struct spwd shpwd;
|
||||
struct passwd pwd;
|
||||
char pwd_buf[1024];
|
||||
char shpwd_buf[1024];
|
||||
int error = PAM_ACCT_EXPIRED;
|
||||
char *user;
|
||||
int i;
|
||||
int debug = 0;
|
||||
int nowarn = 0;
|
||||
uid_t orig_uid;
|
||||
unix_authtok_data *status;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcasecmp(argv[i], "nowarn") == 0) {
|
||||
nowarn = 1;
|
||||
flags = flags | PAM_SILENT;
|
||||
} else {
|
||||
syslog(LOG_ERR,
|
||||
"UNIX pam_sm_acct_mgmt: illegal option %s",
|
||||
argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = pam_get_item(pamh, PAM_USER, (void **)&user))
|
||||
!= PAM_SUCCESS)
|
||||
goto out;
|
||||
|
||||
if (user == NULL) {
|
||||
error = PAM_USER_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the password and shadow password entries
|
||||
*/
|
||||
if (getpwnam_r(user, &pwd, pwd_buf, sizeof (pwd_buf)) == NULL ||
|
||||
getspnam_r(user, &shpwd, shpwd_buf, sizeof (shpwd_buf)) == NULL) {
|
||||
error = PAM_USER_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (shpwd.sp_pwdp != NULL && strcmp(shpwd.sp_pwdp, "*NP*") == 0) {
|
||||
orig_uid = geteuid();
|
||||
seteuid(pwd.pw_uid);
|
||||
memset(pwd_buf, 0, sizeof (pwd_buf));
|
||||
memset(shpwd_buf, 0, sizeof (shpwd_buf));
|
||||
if (getpwnam_r(user, &pwd, pwd_buf, sizeof (pwd_buf)) == NULL ||
|
||||
getspnam_r(user, &shpwd, shpwd_buf, sizeof (shpwd_buf))
|
||||
== NULL) {
|
||||
error = PAM_USER_UNKNOWN;
|
||||
seteuid(orig_uid);
|
||||
goto out;
|
||||
}
|
||||
seteuid(orig_uid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for account expiration
|
||||
*/
|
||||
if (shpwd.sp_expire > 0 &&
|
||||
shpwd.sp_expire < DAY_NOW) {
|
||||
error = PAM_ACCT_EXPIRED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for excessive login account inactivity
|
||||
*/
|
||||
if (check_for_login_inactivity(pwd, shpwd)) {
|
||||
error = PAM_PERM_DENIED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the user needs to change their password
|
||||
*/
|
||||
if (error = new_password_check(&pwd, &shpwd, flags)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to make sure password aging information is okay
|
||||
*/
|
||||
if ((error = perform_passwd_aging_check(pamh, shpwd, flags))
|
||||
!= PAM_SUCCESS) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, warn the user if their password is about to expire.
|
||||
*/
|
||||
if (!(flags & PAM_SILENT)) {
|
||||
warn_user_passwd_will_expire(pamh, shpwd);
|
||||
}
|
||||
|
||||
/*
|
||||
* All done, return Success
|
||||
*/
|
||||
error = PAM_SUCCESS;
|
||||
|
||||
out:
|
||||
|
||||
memset(shpwd_buf, 0, sizeof (shpwd_buf));
|
||||
/* store the password aging status in the pam handle */
|
||||
if (pam_get_data(pamh, UNIX_AUTHTOK_DATA, (void **)&status)
|
||||
!= PAM_SUCCESS) {
|
||||
if ((status = (unix_authtok_data *)calloc
|
||||
(1, sizeof (unix_authtok_data))) == NULL) {
|
||||
return (PAM_BUF_ERR);
|
||||
}
|
||||
}
|
||||
status->age_status = error;
|
||||
if (pam_set_data(pamh, UNIX_AUTHTOK_DATA, status, unix_cleanup)
|
||||
!= PAM_SUCCESS) {
|
||||
free(status);
|
||||
return (PAM_SERVICE_ERR);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
355
cde/lib/pam/pam_modules/unix/unix_authenticate.c
Normal file
355
cde/lib/pam/pam_modules/unix/unix_authenticate.c
Normal file
@@ -0,0 +1,355 @@
|
||||
/* $XConsortium: unix_authenticate.c /main/5 1996/05/09 04:32:58 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_authenticate.c 1.58 96/02/09 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
#ifdef PAM_SECURE_RPC
|
||||
static void
|
||||
unix_cleanup(
|
||||
pam_handle_t *pamh,
|
||||
void *data,
|
||||
int pam_status)
|
||||
{
|
||||
free((unix_auth_data *)data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int attempt_authentication(char *, char *, char *, uid_t, int, int);
|
||||
|
||||
/*
|
||||
* pam_sm_authenticate - Authenticate user
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_authenticate(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
struct spwd shpwd; /* Shadow password structure */
|
||||
struct passwd pwd; /* password structure */
|
||||
char shpwd_buf[1024];
|
||||
char pwd_buf[1024];
|
||||
char *password = NULL;
|
||||
char *dummy_passwd = "no:password";
|
||||
int err = PAM_SUCCESS;
|
||||
int retcode;
|
||||
int debug = 0;
|
||||
int try_first_pass = 0;
|
||||
int use_first_pass = 0;
|
||||
int i;
|
||||
uid_t uid;
|
||||
char *service, *user;
|
||||
#ifdef PAM_SECURE_RPC
|
||||
unix_auth_data *status;
|
||||
char netname[MAXNETNAMELEN+1];
|
||||
int estkey_stat;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcasecmp(argv[i], "nowarn") == 0)
|
||||
flags = flags | PAM_SILENT;
|
||||
else if (strcmp(argv[i], "try_first_pass") == 0)
|
||||
try_first_pass = 1;
|
||||
else if (strcmp(argv[i], "use_first_pass") == 0)
|
||||
use_first_pass = 1;
|
||||
else {
|
||||
syslog(LOG_ERR, "illegal option %s", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = pam_get_item(pamh, PAM_SERVICE, (void **)&service))
|
||||
!= PAM_SUCCESS ||
|
||||
(err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
|
||||
return (err);
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"unix pam_sm_authenticate(%s %s), flags = %x ",
|
||||
service, (user)?user:"no-user", flags);
|
||||
|
||||
if (!user) {
|
||||
return (PAM_USER_UNKNOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the password and shadow password entry
|
||||
*/
|
||||
memset(pwd_buf, 0, sizeof (pwd_buf));
|
||||
memset(shpwd_buf, 0, sizeof (shpwd_buf));
|
||||
if (getpwnam_r(user, &pwd, pwd_buf, sizeof (pwd_buf)) == NULL ||
|
||||
getspnam_r(user, &shpwd, shpwd_buf, sizeof (shpwd_buf)) == NULL) {
|
||||
err = PAM_USER_UNKNOWN;
|
||||
/*
|
||||
* Mask unknown users.
|
||||
* Set up a dummy password.
|
||||
*/
|
||||
shpwd.sp_pwdp = dummy_passwd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is a password check required?
|
||||
*/
|
||||
/* Is there anything there to check? */
|
||||
if ((shpwd.sp_pwdp == 0) || (*shpwd.sp_pwdp == '\0')) {
|
||||
/*
|
||||
* The /etc/default/login file will specify if passwords
|
||||
* are required. If not, then simply return SUCCESS.
|
||||
* Otherwise, flag the error, but still prompt the user
|
||||
* for a password to mask the failure.
|
||||
*/
|
||||
if ((flags & PAM_DISALLOW_NULL_AUTHTOK) == 0)
|
||||
goto out;
|
||||
err = PAM_SERVICE_ERR;
|
||||
goto prompt;
|
||||
}
|
||||
|
||||
if ((err = __pam_get_authtok(pamh, PAM_HANDLE, PAM_AUTHTOK,
|
||||
PASSWORD_LEN, NULL, &password)) != PAM_SUCCESS)
|
||||
goto out;
|
||||
|
||||
if (try_first_pass) {
|
||||
/*
|
||||
* Try to login using the password from the first
|
||||
* scheme, e.g. DCE password. If anything goes wrong,
|
||||
* then simply prompt users for password.
|
||||
*/
|
||||
|
||||
retcode = attempt_authentication(user, password,
|
||||
shpwd.sp_pwdp, pwd.pw_uid,
|
||||
flags, debug);
|
||||
if (err != PAM_USER_UNKNOWN)
|
||||
err = retcode;
|
||||
|
||||
if (err == PAM_SUCCESS)
|
||||
goto post_prompt;
|
||||
else
|
||||
goto prompt;
|
||||
} else if (use_first_pass) {
|
||||
/*
|
||||
* Try to login using the password from the first
|
||||
* scheme, e.g. DCE password. If anything goes wrong,
|
||||
* quit, and return the error;
|
||||
*/
|
||||
retcode = attempt_authentication(user, password,
|
||||
shpwd.sp_pwdp, pwd.pw_uid,
|
||||
flags, debug);
|
||||
if (err != PAM_USER_UNKNOWN)
|
||||
err = retcode;
|
||||
|
||||
if (err == PAM_SUCCESS)
|
||||
goto post_prompt;
|
||||
else
|
||||
goto out;
|
||||
}
|
||||
|
||||
prompt:
|
||||
/*
|
||||
* Get the password from the user
|
||||
*/
|
||||
if ((password != NULL && password[0] != '\0') || try_first_pass) {
|
||||
if (password) {
|
||||
memset(password, 0, strlen(password));
|
||||
free(password);
|
||||
password = NULL;
|
||||
}
|
||||
if ((retcode = __pam_get_authtok(pamh, PAM_PROMPT,
|
||||
PAM_AUTHTOK, PASSWORD_LEN,
|
||||
PAM_MSG(pamh, 30, "UNIX Password: "),
|
||||
&password)) != PAM_SUCCESS) {
|
||||
if (err != PAM_USER_UNKNOWN)
|
||||
err = retcode;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (password) {
|
||||
memset(password, 0, strlen(password));
|
||||
free(password);
|
||||
password = NULL;
|
||||
}
|
||||
if ((retcode = __pam_get_authtok(pamh, PAM_PROMPT,
|
||||
PAM_AUTHTOK, PASSWORD_LEN,
|
||||
PAM_MSG(pamh, 31, "Password: "),
|
||||
&password)) != PAM_SUCCESS) {
|
||||
if (err != PAM_USER_UNKNOWN)
|
||||
err = retcode;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
retcode = attempt_authentication(user, password,
|
||||
shpwd.sp_pwdp, pwd.pw_uid, flags, debug);
|
||||
if (err != PAM_USER_UNKNOWN)
|
||||
err = retcode;
|
||||
|
||||
if (err != PAM_SUCCESS)
|
||||
goto out;
|
||||
|
||||
post_prompt:
|
||||
|
||||
#ifdef PAM_SECURE_RPC
|
||||
/*
|
||||
* Do a keylogin if the password is
|
||||
* not null and its not a root login.
|
||||
* This code used to be in pam_setcred().
|
||||
*/
|
||||
uid = pwd.pw_uid;
|
||||
if (password != NULL &&
|
||||
password[0] != '\0' &&
|
||||
uid != 0) {
|
||||
/*
|
||||
* we always ask to reestablish the private key with
|
||||
* keyserv to solve the problem that the keys may have
|
||||
* changed and a re-keylogin not done
|
||||
*/
|
||||
estkey_stat = establish_key(uid, password, 1, netname);
|
||||
|
||||
/*
|
||||
* Store the return value as module specific data
|
||||
* to be printed out later in pam_setcred().
|
||||
*/
|
||||
if (pam_get_data(pamh, UNIX_AUTH_DATA, (void**)&status)
|
||||
!= PAM_SUCCESS) {
|
||||
if ((status = (unix_auth_data *)calloc
|
||||
(1, sizeof (unix_auth_data)))
|
||||
== NULL) {
|
||||
err = PAM_BUF_ERR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
status->key_status = estkey_stat;
|
||||
strcpy(status->netname, netname);
|
||||
if (pam_set_data(pamh, UNIX_AUTH_DATA, status, unix_cleanup)
|
||||
!= PAM_SUCCESS) {
|
||||
err = PAM_SERVICE_ERR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif /* PAM_SECURE_RPC */
|
||||
|
||||
out:
|
||||
if (password) {
|
||||
memset(password, 0, strlen(password));
|
||||
free(password);
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
attempt_authentication(char *user, char *password, char *enc_passwd,
|
||||
uid_t uid, int flags, int debug)
|
||||
{
|
||||
struct passwd pwd;
|
||||
struct spwd shpwd;
|
||||
char shpwd_buf[1024];
|
||||
char pwd_buf[1024];
|
||||
int estkey_stat;
|
||||
uid_t orig_uid;
|
||||
int err = 0;
|
||||
|
||||
if (password == NULL || password[0] == '\0') {
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"unix_auth: NULL passwd in attempt_authenticate()");
|
||||
return (PAM_AUTH_ERR);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Yes, there is some string in the sp_pwdp field.
|
||||
* We have one of the following two situations:
|
||||
* 1) the sp_pwdp string is actually the encrypted
|
||||
* user's password,
|
||||
* or 2) the sp_pwdp string is "*NP*", which means we
|
||||
* didn't actually have permission to read the
|
||||
* password field in the name service.
|
||||
*
|
||||
* In either case, we must obtain the password from the
|
||||
* user. In situation 2, we can't actually tell yet
|
||||
* whether the unix password is present or not. We must
|
||||
* get the password from the user, just to establish
|
||||
* the user's secure RPC credentials. Then, having
|
||||
* established the user's Secure RPC credentials, we
|
||||
* need to re-obtain the shpwd structure. At that point,
|
||||
* if the unix password is present there, we check it
|
||||
* against that too.
|
||||
*/
|
||||
|
||||
if (strcmp(enc_passwd, "*NP*") == 0) {
|
||||
#ifdef PAM_SECURE_RPC
|
||||
estkey_stat = establish_key(uid,
|
||||
password, 1, NULL);
|
||||
if (estkey_stat != ESTKEY_SUCCESS) {
|
||||
/* Failed to establish secret key. */
|
||||
switch (estkey_stat) {
|
||||
case ESTKEY_BADPASSWD:
|
||||
err = PAM_AUTH_ERR;
|
||||
break;
|
||||
case ESTKEY_NOCREDENTIALS:
|
||||
/*
|
||||
* user requires credentials to
|
||||
* read passwd field but doesn't
|
||||
* have any should syslog() a
|
||||
* message for admin
|
||||
*/
|
||||
syslog(LOG_ALERT,
|
||||
"User %s needs Secure RPC \
|
||||
credentials to login.", user);
|
||||
err = PAM_SERVICE_ERR;
|
||||
break;
|
||||
default:
|
||||
err = PAM_SERVICE_ERR;
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
orig_uid = geteuid();
|
||||
seteuid(uid);
|
||||
memset(pwd_buf, 0, sizeof (pwd_buf));
|
||||
memset(shpwd_buf, 0, sizeof (shpwd_buf));
|
||||
if (getpwnam_r(user, &pwd, pwd_buf,
|
||||
sizeof (pwd_buf)) == NULL ||
|
||||
getspnam_r(user, &shpwd, shpwd_buf,
|
||||
sizeof (shpwd_buf)) == NULL) {
|
||||
seteuid(orig_uid);
|
||||
return (PAM_USER_UNKNOWN);
|
||||
}
|
||||
seteuid(orig_uid);
|
||||
|
||||
if ((shpwd.sp_pwdp != 0) &&
|
||||
(strcmp(shpwd.sp_pwdp, "*NP*") == 0)) {
|
||||
syslog(LOG_ALERT,
|
||||
"Permissions on the password database may be too restrictive");
|
||||
return (PAM_AUTH_ERR);
|
||||
}
|
||||
enc_passwd = shpwd.sp_pwdp;
|
||||
#else
|
||||
return (PAM_AUTH_ERR);
|
||||
#endif /* PAM_SECURE_RPC */
|
||||
}
|
||||
|
||||
if ((enc_passwd == 0) ||
|
||||
(*enc_passwd == '\0')) {
|
||||
if (flags & PAM_DISALLOW_NULL_AUTHTOK)
|
||||
return (PAM_AUTH_ERR);
|
||||
/* return success if passwords are not required */
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
if (strcmp(crypt(password, enc_passwd),
|
||||
enc_passwd) != 0) {
|
||||
return (PAM_AUTH_ERR);
|
||||
}
|
||||
/* success! */
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
}
|
||||
89
cde/lib/pam/pam_modules/unix/unix_chauthtok.c
Normal file
89
cde/lib/pam/pam_modules/unix/unix_chauthtok.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/* $XConsortium: unix_chauthtok.c /main/5 1996/05/09 04:33:18 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_chauthtok.c 1.83 95/12/12 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
/*
|
||||
* pam_sm_chauthtok():
|
||||
* To change authentication token.
|
||||
*
|
||||
* This function handles all requests from the "passwd" command
|
||||
* to change a user's password in all repositories specified
|
||||
* in nsswitch.conf.
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_chauthtok(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
int i;
|
||||
int debug = 0; /* debug option from pam.conf */
|
||||
int authtok_aged = 0; /* flag to check if password expired */
|
||||
unix_authtok_data *status; /* status in pam handle stating if */
|
||||
/* password aged */
|
||||
|
||||
/*
|
||||
* Only check for debug here - parse remaining options
|
||||
* in __update_authtok();
|
||||
*/
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
}
|
||||
|
||||
if (flags & PAM_PRELIM_CHECK) {
|
||||
/* do not do any prelim check at this time */
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"unix pam_sm_chauthtok(): prelim check");
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
/* make sure PAM framework is telling us to update passwords */
|
||||
if (!(flags & PAM_UPDATE_AUTHTOK)) {
|
||||
syslog(LOG_ERR, "unix pam_sm_chauthtok: bad flags: %d", flags);
|
||||
return (PAM_SYSTEM_ERR);
|
||||
}
|
||||
|
||||
if (flags & PAM_CHANGE_EXPIRED_AUTHTOK) {
|
||||
if (pam_get_data(pamh, UNIX_AUTHTOK_DATA, (void **)&status)
|
||||
== PAM_SUCCESS) {
|
||||
switch (status->age_status) {
|
||||
case PAM_NEW_AUTHTOK_REQD:
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"pam_sm_chauthtok: UNIX password aged");
|
||||
authtok_aged = 1;
|
||||
break;
|
||||
default:
|
||||
/* UNIX authtok did not expire */
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"pam_sm_chauthtok: UNIX password young");
|
||||
authtok_aged = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!authtok_aged)
|
||||
return (PAM_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function calls __update_authtok() to change passwords.
|
||||
* By passing PAM_REP_DEFAULT, the repository will be determined
|
||||
* by looking in nsswitch.conf.
|
||||
*
|
||||
* To obtain the domain name (passed as NULL), __update_authtok()
|
||||
* will call: nis_local_directory();
|
||||
*/
|
||||
return (__update_authtok(pamh, flags, PAM_REP_DEFAULT, NULL,
|
||||
argc, argv));
|
||||
}
|
||||
34
cde/lib/pam/pam_modules/unix/unix_close_session.c
Normal file
34
cde/lib/pam/pam_modules/unix/unix_close_session.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/* $XConsortium: unix_close_session.c /main/5 1996/05/09 04:33:38 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_close_session.c 1.26 95/12/12 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
/*
|
||||
* pam_sm_close_session - Terminate a PAM authenticated session
|
||||
*/
|
||||
|
||||
int
|
||||
pam_sm_close_session(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
int i;
|
||||
int debug = 0;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else
|
||||
syslog(LOG_ERR, "illegal option %s", argv[i]);
|
||||
}
|
||||
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
352
cde/lib/pam/pam_modules/unix/unix_get_authtokattr.c
Normal file
352
cde/lib/pam/pam_modules/unix/unix_get_authtokattr.c
Normal file
@@ -0,0 +1,352 @@
|
||||
/* $XConsortium: unix_get_authtokattr.c /main/8 1996/11/21 20:00:50 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_get_authtokattr.c 1.59 96/01/07 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
#define XOS_USE_NO_LOCKING
|
||||
#define X_INCLUDE_TIME_H
|
||||
#include <X11/Xos_r.h>
|
||||
|
||||
#ifdef PAM_NISPLUS
|
||||
static void _np_nss_initf_shadow(nss_db_params_t *);
|
||||
static void _np_setspent();
|
||||
static void _np_endspent();
|
||||
static struct spwd * _np_getspent_r(struct spwd *, char *, int);
|
||||
static struct spwd * _np_getspent();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __get_authtoken_attr():
|
||||
* To get authentication token attribute values.
|
||||
*
|
||||
* This function calls ck_perm() first to check the caller's
|
||||
* permission. If the check succeeds, it will read the
|
||||
* attribute/value pairs from the shadow password entry of
|
||||
* the user specified by the authentication handle "pamh"
|
||||
* and store them into a character array and return.
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX: We use our own version of the shadow passwd getent routine.
|
||||
* See below for details. Compatible with version 2 of the name service
|
||||
* switch. In the future, the name service switch implementation may
|
||||
* change and these functions and the Makefile may have to
|
||||
* be modified.
|
||||
*/
|
||||
|
||||
int
|
||||
__get_authtoken_attr(
|
||||
pam_handle_t *pamh,
|
||||
char ***ga_getattr,
|
||||
int repository,
|
||||
const char *domain,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
register int k;
|
||||
char value[PAM_MAX_ATTR_SIZE];
|
||||
int retcode;
|
||||
long lstchg;
|
||||
char *usrname;
|
||||
char *prognamep;
|
||||
char **get_attributes;
|
||||
struct passwd *pwd;
|
||||
struct spwd *shpwd;
|
||||
int found = 0;
|
||||
struct spwd *psp;
|
||||
struct tm *tmp;
|
||||
int privileged = 0;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
int debug = 0;
|
||||
int nowarn = 0;
|
||||
int i;
|
||||
void *passwd_res;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcmp(argv[i], "nowarn") == 0)
|
||||
nowarn = 1;
|
||||
else
|
||||
syslog(LOG_ERR, "illegal UNIX module option %s",
|
||||
argv[i]);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"__get_authtoken_attr(): repository=%s",
|
||||
repository_to_string(repository));
|
||||
|
||||
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
|
||||
!= PAM_SUCCESS ||
|
||||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
|
||||
!= PAM_SUCCESS)
|
||||
return (retcode);
|
||||
|
||||
if ((get_attributes = (char **)
|
||||
calloc(PAM_MAX_NUM_ATTR, sizeof (char *))) == NULL)
|
||||
return (PAM_BUF_ERR);
|
||||
|
||||
/* repository must be specified in the command line. */
|
||||
if (repository == PAM_REP_DEFAULT) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 40,
|
||||
"You must specify repository when displaying passwd attributes"));
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
if (!IS_FILES(repository) && !IS_NIS(repository) &&
|
||||
!IS_NISPLUS(repository)) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 41,
|
||||
"%s: System error: repository out of range"), prognamep);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1,
|
||||
messages, NULL);
|
||||
return (PAM_SYSTEM_ERR);
|
||||
}
|
||||
|
||||
#ifdef PAM_NISPLUS
|
||||
if (usrname == NULL || *usrname == NULL) {
|
||||
/* print nis+ table */
|
||||
/*
|
||||
* Cat the table using our private _np_getspent()
|
||||
*/
|
||||
if (!IS_NISPLUS(repository)) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 42,
|
||||
"Unable to retrieve username."));
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
return (PAM_AUTHTOK_RECOVERY_ERR);
|
||||
}
|
||||
|
||||
(void) _np_setspent();
|
||||
while ((psp = _np_getspent()) != NULL) {
|
||||
found++;
|
||||
sprintf(value, "%s ", psp->sp_namp);
|
||||
|
||||
if (psp->sp_pwdp == NULL) {
|
||||
sprintf(messages[0],
|
||||
"%s NP ", value);
|
||||
} else if ((int)strlen(psp->sp_pwdp) < NUMCP) {
|
||||
sprintf(messages[0],
|
||||
"%s LK ", value);
|
||||
} else {
|
||||
sprintf(messages[0],
|
||||
"%s PS ", value);
|
||||
}
|
||||
|
||||
if (psp->sp_max != -1) {
|
||||
_Xgtimeparams gmtime_buf;
|
||||
strcpy(value, messages[0]);
|
||||
if (psp->sp_lstchg) {
|
||||
lstchg = psp->sp_lstchg * DAY;
|
||||
tmp = _XGmtime(&lstchg, gmtime_buf);
|
||||
sprintf(messages[0],
|
||||
"%s %.2d/%.2d/%.2d ",
|
||||
value,
|
||||
(tmp->tm_mon + 1),
|
||||
tmp->tm_mday, tmp->tm_year);
|
||||
} else
|
||||
sprintf(messages[0],
|
||||
"%s 00/00/00 ",
|
||||
value);
|
||||
|
||||
strcpy(value, messages[0]);
|
||||
if ((psp->sp_min >= 0) && (psp->sp_warn > 0)) {
|
||||
sprintf(messages[0],
|
||||
"%s %d %d %d ",
|
||||
value,
|
||||
psp->sp_min, psp->sp_max,
|
||||
psp->sp_warn);
|
||||
} else if (psp->sp_min >= 0) {
|
||||
sprintf(messages[0],
|
||||
"%s %d %d ", value,
|
||||
psp->sp_min, psp->sp_max);
|
||||
} else if (psp->sp_warn > 0) {
|
||||
sprintf(messages[0],
|
||||
"%s %d %d ", value,
|
||||
psp->sp_max, psp->sp_warn);
|
||||
} else {
|
||||
sprintf(messages[0],
|
||||
"%s %d ",
|
||||
value, psp->sp_max);
|
||||
}
|
||||
}
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
|
||||
1, messages, NULL);
|
||||
}
|
||||
(void) _np_endspent();
|
||||
|
||||
/*
|
||||
* If password table does not have any entries or is missing,
|
||||
* return fatal error.
|
||||
*/
|
||||
if (found == 0) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 43,
|
||||
"%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
return (PAM_SYSTEM_ERR);
|
||||
}
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
#endif /* PAM_NISPLUS */
|
||||
|
||||
retcode = ck_perm(pamh, repository,
|
||||
(char *)domain, &pwd, &shpwd, &privileged,
|
||||
(void **)&passwd_res, getuid(), debug, nowarn);
|
||||
if (retcode != 0) {
|
||||
return (retcode);
|
||||
}
|
||||
|
||||
k = 0;
|
||||
|
||||
/* get attribute "AUTHTOK_STATUS" */
|
||||
if (shpwd->sp_pwdp == NULL)
|
||||
(void) strcpy(value, "NP ");
|
||||
else if ((int)strlen(shpwd->sp_pwdp) < NUMCP)
|
||||
(void) strcpy(value, "LK ");
|
||||
else
|
||||
(void) strcpy(value, "PS ");
|
||||
setup_attr(get_attributes, k++, "AUTHTOK_STATUS=", value);
|
||||
|
||||
|
||||
if (shpwd->sp_max != -1) {
|
||||
/* get attribute "AUTHTOK_LASTCHANGE" */
|
||||
if (shpwd->sp_lstchg) {
|
||||
lstchg = shpwd->sp_lstchg * DAY;
|
||||
sprintf(value, "%d", lstchg);
|
||||
} else {
|
||||
sprintf(value, "%d", shpwd->sp_lstchg);
|
||||
}
|
||||
setup_attr(get_attributes, k++,
|
||||
"AUTHTOK_LASTCHANGE=", value);
|
||||
|
||||
/* get attribute "AUTHTOK_MINAGE" */
|
||||
/* "AUTHTOK_MAXAGE", and "AUTHTOK_WARNDATE" */
|
||||
if ((shpwd->sp_min >= 0) && (shpwd->sp_warn > 0)) {
|
||||
sprintf(value, "%d", shpwd->sp_min);
|
||||
setup_attr(get_attributes, k++,
|
||||
"AUTHTOK_MINAGE=", value);
|
||||
sprintf(value, "%d", shpwd->sp_max);
|
||||
setup_attr(get_attributes, k++,
|
||||
"AUTHTOK_MAXAGE=", value);
|
||||
sprintf(value, "%d", shpwd->sp_warn);
|
||||
setup_attr(get_attributes, k++,
|
||||
"AUTHTOK_WARNDATE=", value);
|
||||
} else {
|
||||
if (shpwd->sp_min >= 0) {
|
||||
sprintf(value, "%d", shpwd->sp_min);
|
||||
setup_attr(get_attributes, k++,
|
||||
"AUTHTOK_MINAGE=", value);
|
||||
sprintf(value, "%d", shpwd->sp_max);
|
||||
setup_attr(get_attributes, k++,
|
||||
"AUTHTOK_MAXAGE=", value);
|
||||
} else {
|
||||
if (shpwd->sp_warn > 0) {
|
||||
sprintf(value, "%d", shpwd->sp_max);
|
||||
setup_attr(get_attributes, k++,
|
||||
"AUTHTOK_MAXAGE=", value);
|
||||
sprintf(value, "%d", shpwd->sp_warn);
|
||||
setup_attr(get_attributes, k++,
|
||||
"AUTHTOK_WARNDATE=", value);
|
||||
} else {
|
||||
sprintf(value, "%d", shpwd->sp_max);
|
||||
setup_attr(get_attributes, k++,
|
||||
"AUTHTOK_MAXAGE=", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* terminate with NULL */
|
||||
setup_attr(get_attributes, k, NULL, NULL);
|
||||
|
||||
*ga_getattr = &get_attributes[0];
|
||||
|
||||
free_passwd_structs(pwd, shpwd);
|
||||
return (PAM_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef PAM_NISPLUS
|
||||
|
||||
/*
|
||||
* XXX Our private version of the switch frontend for getspent. We want to
|
||||
* search just the nisplus sp file, so we want to bypass normal nsswitch.conf
|
||||
* based processing. This implementation compatible with version 2 of the
|
||||
* name service switch.
|
||||
*/
|
||||
|
||||
#define NSS_NISPLUS_ONLY "nisplus"
|
||||
|
||||
int str2spwd(const char *, int, void *, char *, int);
|
||||
|
||||
static DEFINE_NSS_DB_ROOT(db_root);
|
||||
static DEFINE_NSS_GETENT(context);
|
||||
|
||||
static void
|
||||
_np_nss_initf_shadow(p)
|
||||
nss_db_params_t *p;
|
||||
{
|
||||
p->name = NSS_DBNAM_SHADOW;
|
||||
p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */
|
||||
p->default_config = NSS_NISPLUS_ONLY; /* Use nisplus only */
|
||||
p->flags = NSS_USE_DEFAULT_CONFIG;
|
||||
}
|
||||
|
||||
static void
|
||||
_np_setspent()
|
||||
{
|
||||
nss_setent(&db_root, _np_nss_initf_shadow, &context);
|
||||
}
|
||||
|
||||
static void
|
||||
_np_endspent()
|
||||
{
|
||||
nss_endent(&db_root, _np_nss_initf_shadow, &context);
|
||||
nss_delete(&db_root);
|
||||
}
|
||||
|
||||
static struct spwd *
|
||||
_np_getspent_r(result, buffer, buflen)
|
||||
struct spwd *result;
|
||||
char *buffer;
|
||||
int buflen;
|
||||
{
|
||||
nss_XbyY_args_t arg;
|
||||
char *nam;
|
||||
|
||||
/* In getXXent_r(), protect the unsuspecting caller from +/- entries */
|
||||
|
||||
do {
|
||||
NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
|
||||
/* No key to fill in */
|
||||
nss_getent(&db_root, _np_nss_initf_shadow, &context, &arg);
|
||||
} while (arg.returnval != 0 &&
|
||||
(nam = ((struct spwd *)arg.returnval)->sp_namp) != 0 &&
|
||||
(*nam == '+' || *nam == '-'));
|
||||
|
||||
return (struct spwd *) NSS_XbyY_FINI(&arg);
|
||||
}
|
||||
|
||||
static nss_XbyY_buf_t *buffer;
|
||||
|
||||
static struct spwd *
|
||||
_np_getspent()
|
||||
{
|
||||
nss_XbyY_buf_t *b;
|
||||
|
||||
b = NSS_XbyY_ALLOC(&buffer, sizeof (struct spwd), NSS_BUFLEN_SHADOW);
|
||||
|
||||
return (b == 0 ? 0 : _np_getspent_r(b->result, b->buffer, b->buflen));
|
||||
}
|
||||
|
||||
#endif /* PAM_NISPLUS */
|
||||
206
cde/lib/pam/pam_modules/unix/unix_headers.h
Normal file
206
cde/lib/pam/pam_modules/unix/unix_headers.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/* $XConsortium: unix_headers.h /main/5 1996/05/09 04:34:13 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _UNIX_HEADERS_H
|
||||
#define _UNIX_HEADERS_H
|
||||
|
||||
#pragma ident "@(#)unix_headers.h 1.61 96/02/02 SMI" /* PAM 2.6 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*******************************************************************
|
||||
*
|
||||
* PROPRIETARY NOTICE(Combined)
|
||||
*
|
||||
* This source code is unpublished proprietary information
|
||||
* constituting, or derived under license from AT&T's UNIX(r) System V.
|
||||
* In addition, portions of such source code were derived from Berkeley
|
||||
* 4.3 BSD under license from the Regents of the University of
|
||||
* California.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Copyright Notice
|
||||
*
|
||||
* Notice of copyright on this source code product does not indicate
|
||||
* publication.
|
||||
*
|
||||
* (c) 1986, 1987, 1988, 1989, 1990, 1991, 1992 Sun Microsystems, Inc
|
||||
* (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T.
|
||||
* All rights reserved.
|
||||
*******************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
********************************************************************** *
|
||||
* *
|
||||
* Unix Scheme Header Files *
|
||||
* *
|
||||
********************************************************************** */
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_modules.h>
|
||||
#include "../../libpam/pam_impl.h"
|
||||
#include <syslog.h>
|
||||
#include <pwd.h>
|
||||
#include <shadow.h>
|
||||
#include <lastlog.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <libintl.h>
|
||||
#include <thread.h>
|
||||
#include <synch.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <string.h>
|
||||
#include <crypt.h>
|
||||
|
||||
#ifdef PAM_NISPLUS
|
||||
#include <rpcsvc/nis.h>
|
||||
#include <rpcsvc/nispasswd.h>
|
||||
#endif
|
||||
|
||||
#if (PAM_NIS || PAM_NISPLUS)
|
||||
#include <rpcsvc/yppasswd.h>
|
||||
#include <rpcsvc/ypclnt.h>
|
||||
#include <nss_dbdefs.h>
|
||||
#include <nsswitch.h>
|
||||
#include <rpc/key_prot.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfssys.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Various useful files and string constants
|
||||
*/
|
||||
#define SHELL "/usr/bin/sh"
|
||||
#define DEFSHELL "/bin/sh"
|
||||
#define LASTLOG "/var/adm/lastlog"
|
||||
#define PWADMIN "/etc/default/passwd"
|
||||
#define LOGINADMIN "/etc/default/login"
|
||||
#define PASSWD "/etc/passwd"
|
||||
#define SHADOW "/etc/shadow"
|
||||
#define UNIX_AUTH_DATA "SUNW-UNIX-AUTH-DATA"
|
||||
#define UNIX_AUTHTOK_DATA "SUNW-UNIX-AUTHTOK-DATA"
|
||||
#define UNIX_MSG "(Unix)"
|
||||
#define NIS_MSG "(NIS)"
|
||||
#define NISPLUS_MSG "(NIS+)"
|
||||
#define PASSWORD_LEN 8
|
||||
#define PAM_NISPLUS_PARTIAL_SUCCESS -1
|
||||
|
||||
/*
|
||||
* PAM_MSG macro for return of internationalized text
|
||||
*/
|
||||
|
||||
#define PAM_MSG(pamh, number, string)\
|
||||
(char *) __pam_get_i18n_msg(pamh, "pam_unix", 1, number, string)
|
||||
|
||||
/*
|
||||
* Returned status codes for establish_key () utility function
|
||||
*/
|
||||
|
||||
#define ESTKEY_SUCCESS 0
|
||||
#define ESTKEY_NOCREDENTIALS 1
|
||||
#define ESTKEY_BADPASSWD 2
|
||||
#define ESTKEY_CANTSETKEY 3
|
||||
#define ESTKEY_ALREADY 4
|
||||
|
||||
|
||||
/*
|
||||
* Miscellaneous constants
|
||||
*/
|
||||
#define ROOTUID 0
|
||||
#define MINWEEKS -1 /* minimum weeks before next password change */
|
||||
#define MAXWEEKS -1 /* maximum weeks before password change */
|
||||
#define WARNWEEKS -1 /* number weeks before password expires */
|
||||
/* to warn the user */
|
||||
#define MINLENGTH 6 /* minimum length for passwords */
|
||||
#define MAXLENGTH 8 /* maximum length for passwords */
|
||||
#define NUMCP 13 /* number of characters for valid password */
|
||||
#define MAX_CHANCES 3 /* 3 chances to enter new passwd */
|
||||
|
||||
/*
|
||||
* variables declarations
|
||||
*/
|
||||
mutex_t _priv_lock;
|
||||
|
||||
/*
|
||||
* nis+ definition
|
||||
*/
|
||||
#define PKTABLE "cred.org_dir"
|
||||
#define PKTABLELEN 12
|
||||
#define PASSTABLE "passwd.org_dir"
|
||||
#define PASSTABLELEN 14
|
||||
#define PKMAP "publickey.byname"
|
||||
|
||||
/* define error messages */
|
||||
#define NULLSTRING ""
|
||||
|
||||
/*
|
||||
* Function Declarations
|
||||
*/
|
||||
extern int defopen();
|
||||
extern char *defread();
|
||||
extern int key_setnet();
|
||||
|
||||
/* from unix_utils.c */
|
||||
extern int ck_perm(pam_handle_t *, int,
|
||||
char *, struct passwd **, struct spwd **,
|
||||
int *, void **, uid_t, int, int);
|
||||
extern char *attr_match(register char *, register char *);
|
||||
extern char *getloginshell(pam_handle_t *, char *, int, int);
|
||||
extern char *gethomedir(pam_handle_t *, char *, int);
|
||||
extern char *getfingerinfo(pam_handle_t *, char *, int);
|
||||
extern char *repository_to_string(int);
|
||||
extern void free_passwd_structs(struct passwd *, struct spwd *);
|
||||
|
||||
/* from switch_utils.c */
|
||||
extern int str2spwd(const char *, int, void *, char *, int);
|
||||
extern struct passwd *getpwnam_from(const char *, int);
|
||||
extern struct spwd *getspnam_from(const char *, int);
|
||||
extern int get_ns(pam_handle_t *, int, int, int);
|
||||
|
||||
/* from update_authtok_<repository> */
|
||||
extern int update_authtok_file(pam_handle_t *, char *, char **,
|
||||
struct passwd *, int, int);
|
||||
#ifdef PAM_NIS
|
||||
extern int update_authtok_nis(pam_handle_t *, char *, char **,
|
||||
char *, char *,
|
||||
struct passwd *, int, int);
|
||||
#endif
|
||||
#ifdef PAM_NISPLUS
|
||||
extern int update_authtok_nisplus(pam_handle_t *, char *, char *,
|
||||
char **, char *, char *,
|
||||
char *, int, struct passwd *, char *,
|
||||
int, nis_result *, nis_result *, int, int);
|
||||
#endif
|
||||
|
||||
#ifdef PAM_SECURE_RPC
|
||||
extern int establish_key(uid_t, char *, int, char *);
|
||||
|
||||
typedef struct _unix_auth_data_ {
|
||||
int key_status;
|
||||
char netname[MAXNETNAMELEN+1];
|
||||
}unix_auth_data;
|
||||
#endif
|
||||
|
||||
typedef struct _unix_authtok_data_ {
|
||||
int age_status;
|
||||
}unix_authtok_data;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UNIX_HEADERS_H */
|
||||
82
cde/lib/pam/pam_modules/unix/unix_open_session.c
Normal file
82
cde/lib/pam/pam_modules/unix/unix_open_session.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/* $XConsortium: unix_open_session.c /main/5 1996/05/09 04:34:32 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_open_session.c 1.32 95/12/08 SMI"
|
||||
|
||||
/*
|
||||
* pam_sm_open_session - session management for individual users
|
||||
*/
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
|
||||
int
|
||||
pam_sm_open_session(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
int error;
|
||||
char *ttyn, *rhost, *user;
|
||||
int fdl;
|
||||
struct lastlog newll;
|
||||
struct passwd pwd;
|
||||
char buffer[2048];
|
||||
int i;
|
||||
int debug = 0;
|
||||
long long offset;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else
|
||||
syslog(LOG_ERR, "illegal option %s", argv[i]);
|
||||
}
|
||||
|
||||
if ((error = pam_get_item(pamh, PAM_TTY, (void **)&ttyn))
|
||||
!= PAM_SUCCESS ||
|
||||
(error = pam_get_item(pamh, PAM_USER, (void **)&user))
|
||||
!= PAM_SUCCESS ||
|
||||
(error = pam_get_item(pamh, PAM_RHOST, (void **)&rhost))
|
||||
!= PAM_SUCCESS) {
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (getpwnam_r(user, &pwd, buffer, sizeof (buffer)) == NULL) {
|
||||
return (PAM_USER_UNKNOWN);
|
||||
}
|
||||
|
||||
if ((fdl = open(LASTLOG, O_RDWR|O_CREAT, 0444)) >= 0) {
|
||||
|
||||
/*
|
||||
* The value of lastlog is read by the UNIX
|
||||
* account management module
|
||||
*/
|
||||
|
||||
offset = (long long) pwd.pw_uid *
|
||||
(long long) sizeof (struct lastlog);
|
||||
|
||||
if (llseek(fdl, offset, SEEK_SET) != offset) {
|
||||
/*
|
||||
* XXX uid too large for database
|
||||
*/
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
(void) time(&newll.ll_time);
|
||||
strncpy(newll.ll_line,
|
||||
(ttyn + sizeof ("/dev/")-1),
|
||||
sizeof (newll.ll_line));
|
||||
strncpy(newll.ll_host, rhost, sizeof (newll.ll_host));
|
||||
|
||||
(void) write(fdl, (char *)&newll, sizeof (newll));
|
||||
(void) close(fdl);
|
||||
}
|
||||
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
112
cde/lib/pam/pam_modules/unix/unix_set_authtokattr.c
Normal file
112
cde/lib/pam/pam_modules/unix/unix_set_authtokattr.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/* $XConsortium: unix_set_authtokattr.c /main/5 1996/05/09 04:34:50 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)__set_authtoken_attr.c 1.33 95/09/11 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
/*
|
||||
* __set_authtoken_attr():
|
||||
* To set authentication token attribute values.
|
||||
*
|
||||
* This function calls ck_perm() to check the caller's
|
||||
* permission. If the check succeeds, It will
|
||||
* call update_authentok_file() and passes attributes/value
|
||||
* pairs pointed by "sa_setattr" to set the authentication
|
||||
* token attribute values of the user specified by the
|
||||
* authentication handle "pamh".
|
||||
*/
|
||||
|
||||
int
|
||||
__set_authtoken_attr(
|
||||
pam_handle_t *pamh,
|
||||
const char **sa_setattr,
|
||||
int repository,
|
||||
const char *domain,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
register int i;
|
||||
int retcode;
|
||||
char *usrname;
|
||||
char *prognamep;
|
||||
struct passwd *pwd = NULL;
|
||||
struct spwd *shpwd = NULL;
|
||||
int privileged = 0;
|
||||
int debug = 0;
|
||||
int nowarn = 0;
|
||||
void *passwd_res;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcmp(argv[i], "nowarn") == 0)
|
||||
nowarn = 1;
|
||||
else
|
||||
syslog(LOG_ERR, "illegal UNIX module option %s",
|
||||
argv[i]);
|
||||
}
|
||||
|
||||
|
||||
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
|
||||
!= PAM_SUCCESS ||
|
||||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
|
||||
!= PAM_SUCCESS)
|
||||
return (retcode);
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"__set_authtoken_attr(): repository %x, usrname %s",
|
||||
repository, usrname);
|
||||
|
||||
retcode = ck_perm(pamh, repository,
|
||||
(char *)domain, &pwd, &shpwd, &privileged,
|
||||
(void **)&passwd_res, getuid(), debug, nowarn);
|
||||
if (retcode != 0) {
|
||||
return (retcode);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: why do this???
|
||||
* ignore all the signals
|
||||
*/
|
||||
for (i = 1; i < NSIG; i++)
|
||||
(void) sigset(i, SIG_IGN);
|
||||
|
||||
/* update authentication token file */
|
||||
/* make sure the user exists before we update the repository */
|
||||
#ifdef PAM_NIS
|
||||
if (IS_NIS(repository) && (pwd != NULL)) {
|
||||
retcode = update_authtok_nis(pamh, "attr",
|
||||
(char **)sa_setattr, NULL, NULL, pwd,
|
||||
privileged, nowarn);
|
||||
free_passwd_structs(pwd, shpwd);
|
||||
return (retcode);
|
||||
} else
|
||||
#endif
|
||||
#ifdef PAM_NISPLUS
|
||||
if (IS_NISPLUS(repository) && (pwd != NULL)) {
|
||||
/* nis+ needs clear versions of old and new passwds */
|
||||
retcode = update_authtok_nisplus(pamh,
|
||||
(char *)domain, "attr", (char **)sa_setattr,
|
||||
NULL, NULL, NULL, IS_OPWCMD(repository) ? 1 : 0, pwd,
|
||||
NULL, privileged, (nis_result *)passwd_res, NULL,
|
||||
debug, nowarn);
|
||||
free_passwd_structs(pwd, shpwd);
|
||||
return (retcode);
|
||||
} else
|
||||
#endif
|
||||
if (IS_FILES(repository) && (pwd != NULL)) {
|
||||
retcode = update_authtok_file(pamh, "attr",
|
||||
(char **)sa_setattr, pwd,
|
||||
privileged, nowarn);
|
||||
free_passwd_structs(pwd, shpwd);
|
||||
return (retcode);
|
||||
}
|
||||
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
172
cde/lib/pam/pam_modules/unix/unix_setcred.c
Normal file
172
cde/lib/pam/pam_modules/unix/unix_setcred.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/* $XConsortium: unix_setcred.c /main/5 1996/05/09 04:35:09 drk $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_setcred.c 1.51 95/12/12 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
|
||||
/*
|
||||
* pam_sm_setcred - Set the process credentials
|
||||
*
|
||||
* XXX: If this module succeeds when invoked with PAM_ESTABLISH_CREd,
|
||||
* and a subsequent module in the stack fails, then there is no way
|
||||
* to delete the user's Secure RPC credentials (keylogout). Currently
|
||||
* there is no way for PAM to correct this problem.
|
||||
*/
|
||||
int
|
||||
pam_sm_setcred(
|
||||
pam_handle_t *pamh,
|
||||
int flags,
|
||||
int argc,
|
||||
const char **argv)
|
||||
{
|
||||
int i;
|
||||
int debug = 0;
|
||||
int err = 0;
|
||||
struct pam_conv *pam_convp;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
#ifdef PAM_SECURE_RPC
|
||||
unix_auth_data *status;
|
||||
char secret[HEXKEYBYTES + 1];
|
||||
struct nfs_revauth_args nra; /* revoking kernel NFS creds */
|
||||
#endif
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "debug") == 0)
|
||||
debug = 1;
|
||||
else if (strcasecmp(argv[i], "nowarn") == 0)
|
||||
flags = flags | PAM_SILENT;
|
||||
}
|
||||
|
||||
/* make sure flags are valid */
|
||||
if (flags &&
|
||||
!(flags & PAM_ESTABLISH_CRED) &&
|
||||
!(flags & PAM_REINITIALIZE_CRED) &&
|
||||
!(flags & PAM_REFRESH_CRED) &&
|
||||
!(flags & PAM_DELETE_CRED) &&
|
||||
!(flags & PAM_SILENT)) {
|
||||
syslog(LOG_ERR, "unix setcred: illegal flag %d", flags);
|
||||
err = PAM_SYSTEM_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pam_get_item(pamh, PAM_CONV, (void **) &pam_convp) !=
|
||||
PAM_SUCCESS) {
|
||||
if (debug) {
|
||||
syslog(LOG_DEBUG,
|
||||
"pam_sm_setcred(): unable to get conv structure");
|
||||
}
|
||||
err = PAM_SERVICE_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((flags & PAM_REINITIALIZE_CRED) ||
|
||||
(flags & PAM_REFRESH_CRED)) {
|
||||
/* For unix, these flags are not applicable */
|
||||
err = PAM_SUCCESS;
|
||||
} else if (flags & PAM_DELETE_CRED) {
|
||||
#ifdef PAM_SECURE_RPC
|
||||
/* do a keylogout */
|
||||
memset(secret, 0, sizeof (secret));
|
||||
if (geteuid() == 0) {
|
||||
if (!(flags & PAM_SILENT)) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 50,
|
||||
"removing root credentials would break the rpc services that"));
|
||||
sprintf(messages[1], PAM_MSG(pamh, 51,
|
||||
"use secure rpc on this host!"));
|
||||
sprintf(messages[2], PAM_MSG(pamh, 52,
|
||||
"root may use keylogout -f to do this (at your own risk)!"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
3, messages, NULL);
|
||||
}
|
||||
err = PAM_PERM_DENIED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (key_setsecret(secret) < 0) {
|
||||
if (!(flags & PAM_SILENT)) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 53,
|
||||
"Could not unset your secret key."));
|
||||
sprintf(messages[1], PAM_MSG(pamh, 54,
|
||||
"Maybe the keyserver is down?"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
2, messages, NULL);
|
||||
}
|
||||
err = PAM_AUTH_ERR;
|
||||
goto out;
|
||||
}
|
||||
nra.authtype = AUTH_DES; /* only revoke DES creds */
|
||||
nra.uid = getuid(); /* use the real uid */
|
||||
if (_nfssys(NFS_REVAUTH, &nra) < 0) {
|
||||
if (!(flags & PAM_SILENT)) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 55,
|
||||
"Warning: NFS credentials not destroyed"));
|
||||
__pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
err = PAM_AUTH_ERR;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
err = PAM_SUCCESS;
|
||||
} else {
|
||||
#ifdef PAM_SECURE_RPC
|
||||
/*
|
||||
* Default case: PAM_ESTABLISH_CRED
|
||||
* For unix, the keylogin was already done in
|
||||
* unix_authenticate.c. Only print out the
|
||||
* keylogin status here.
|
||||
*/
|
||||
if (!(flags & PAM_SILENT)) {
|
||||
if (pam_get_data(pamh, UNIX_AUTH_DATA,
|
||||
(void**)&status) == PAM_SUCCESS) {
|
||||
switch (status->key_status) {
|
||||
case ESTKEY_SUCCESS:
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"unix setcred successful");
|
||||
case ESTKEY_ALREADY:
|
||||
case ESTKEY_NOCREDENTIALS:
|
||||
break;
|
||||
case ESTKEY_BADPASSWD:
|
||||
if (!(flags & PAM_SILENT)) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 56,
|
||||
"Password does not decrypt secret key for %s."),
|
||||
status->netname);
|
||||
__pam_display_msg(
|
||||
pamh,
|
||||
PAM_ERROR_MSG, 1,
|
||||
messages, NULL);
|
||||
}
|
||||
break;
|
||||
case ESTKEY_CANTSETKEY:
|
||||
if (!(flags & PAM_SILENT)) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 57,
|
||||
"Could not set secret key for %s. The key server may be down."),
|
||||
status->netname);
|
||||
__pam_display_msg(
|
||||
pamh,
|
||||
PAM_ERROR_MSG, 1,
|
||||
messages, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"pam_sm_setcred(): no module data");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
err = PAM_SUCCESS;
|
||||
}
|
||||
out:
|
||||
return (err);
|
||||
}
|
||||
1519
cde/lib/pam/pam_modules/unix/unix_update_authtok.c
Normal file
1519
cde/lib/pam/pam_modules/unix/unix_update_authtok.c
Normal file
File diff suppressed because it is too large
Load Diff
637
cde/lib/pam/pam_modules/unix/unix_update_authtok_file.c
Normal file
637
cde/lib/pam/pam_modules/unix/unix_update_authtok_file.c
Normal file
@@ -0,0 +1,637 @@
|
||||
/* $XConsortium: unix_update_authtok_file.c /main/5 1996/05/09 04:35:55 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_update_authtok_file.c 1.26 95/09/11 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
static int update_spent(pam_handle_t *, char *, char **,
|
||||
struct passwd *, struct spwd *, int *, int, int);
|
||||
static int process_passwd(pam_handle_t *, char *, char *,
|
||||
struct passwd *, int);
|
||||
|
||||
/*
|
||||
* update_authtok_file():
|
||||
* To update the authentication token file.
|
||||
*
|
||||
* This function is called by either __set_authtoken_attr() to
|
||||
* update the token attributes or pam_chauthtok() to update the
|
||||
* authentication token. The parameter "field" has to be specified
|
||||
* as "attr" if the caller wants to update token attributes, and
|
||||
* the attribute-value pairs to be set needs to be passed in by parameter
|
||||
* "data". If the function is called to update authentication
|
||||
* token itself, then "field" needs to be specified as "passwd"
|
||||
* and the new authentication token has to be passed in by "data".
|
||||
*/
|
||||
|
||||
int
|
||||
update_authtok_file(pamh, field, data, unix_pwd, privileged, nowarn)
|
||||
pam_handle_t *pamh;
|
||||
char *field;
|
||||
char *data[];
|
||||
struct passwd *unix_pwd;
|
||||
int privileged;
|
||||
int nowarn;
|
||||
{
|
||||
char *prognamep;
|
||||
char *usrname;
|
||||
struct stat buf;
|
||||
register int found = 0;
|
||||
FILE *tsfp, *spfp;
|
||||
struct spwd unix_sp;
|
||||
char spbuf[1024];
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
int passwd_flag = 0; /* attrs in shadow or passwd file */
|
||||
int retcode;
|
||||
|
||||
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
|
||||
!= PAM_SUCCESS ||
|
||||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
|
||||
!= PAM_SUCCESS)
|
||||
return (retcode);
|
||||
|
||||
/*
|
||||
* XXX:
|
||||
* Assume effective UID already set to 0
|
||||
* so we can update the passwd file.
|
||||
*
|
||||
* This will be the last update (after nis/nis+)
|
||||
*/
|
||||
|
||||
errno = 0;
|
||||
|
||||
/* lock the password file */
|
||||
if (lckpwdf() != 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 90,
|
||||
"%s%s: Password database busy. Try again later."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (PAM_AUTHTOK_LOCK_BUSY);
|
||||
}
|
||||
|
||||
/* Mode of the shadow file should be 400 or 000 */
|
||||
if (stat(SHADOW, &buf) < 0) {
|
||||
syslog(LOG_ERR, "%s: stat of shadow file failed",
|
||||
prognamep);
|
||||
(void) ulckpwdf();
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
(void) umask(S_IAMB & ~(buf.st_mode & S_IRUSR));
|
||||
if ((tsfp = fopen(SHADTEMP, "w")) == NULL) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
(void) ulckpwdf();
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* copy passwd files to temps, replacing matching lines
|
||||
* with new password attributes.
|
||||
*/
|
||||
if ((spfp = fopen(SHADOW, "r")) == NULL) {
|
||||
fclose(tsfp);
|
||||
goto err;
|
||||
}
|
||||
while (fgetspent_r(spfp, &unix_sp, spbuf, sizeof (spbuf)) != NULL) {
|
||||
if (strcmp(unix_sp.sp_namp, usrname) == 0) {
|
||||
found = 1;
|
||||
retcode = update_spent(pamh, field, data,
|
||||
unix_pwd, &unix_sp, &passwd_flag,
|
||||
privileged, nowarn);
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fclose(tsfp);
|
||||
fclose(spfp);
|
||||
goto err;
|
||||
}
|
||||
if (passwd_flag) {
|
||||
/* The attributes are in passwd file */
|
||||
if ((retcode = process_passwd(pamh,
|
||||
prognamep, usrname, unix_pwd,
|
||||
nowarn)) != PAM_SUCCESS) {
|
||||
fclose(tsfp);
|
||||
fclose(spfp);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (putspent(&unix_sp, tsfp) != 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
fclose(tsfp);
|
||||
fclose(spfp);
|
||||
goto err;
|
||||
}
|
||||
memset(spbuf, 0, sizeof (spbuf));
|
||||
} /* end of while */
|
||||
|
||||
if ((fclose(tsfp)) || (fclose(spfp))) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check if user name exists */
|
||||
if (found == 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename temp file back to appropriate passwd file.
|
||||
*/
|
||||
|
||||
/* remove old shadow file */
|
||||
if (unlink(OSHADOW) && access(OSHADOW, 0) == 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* rename shadow file to old shadow file */
|
||||
if (rename(SHADOW, OSHADOW) == -1) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* rename temparory shadow file to shadow file */
|
||||
if (rename(SHADTEMP, SHADOW) == -1) {
|
||||
(void) unlink(SHADOW);
|
||||
if (link(OSHADOW, SHADOW)) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 92,
|
||||
"%s%s: Unexpected failure. Password database missing."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
(void) ulckpwdf();
|
||||
memset(spbuf, 0, sizeof (spbuf));
|
||||
if (strcmp(field, "passwd") == 0) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 93,
|
||||
"%s%s: passwd successfully changed for %s"),
|
||||
prognamep, UNIX_MSG, usrname);
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (PAM_SUCCESS);
|
||||
err:
|
||||
unlink(SHADTEMP);
|
||||
(void) ulckpwdf();
|
||||
memset(spbuf, 0, sizeof (spbuf));
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* update_spent():
|
||||
* To update a shadow password file entry in the Unix
|
||||
* authentication token file.
|
||||
* This function is called by update_authtok_file() to
|
||||
* update the token to token attributes.
|
||||
* The parameter "field" indicates whenther token attributes or
|
||||
* token itself will be changes, and the parameter "data" has
|
||||
* the new values for the attributes or token.
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
update_spent(pamh, field, data, unix_pwd, unix_sp,
|
||||
passwd_flag, privileged, nowarn)
|
||||
pam_handle_t *pamh;
|
||||
char *field;
|
||||
char **data;
|
||||
struct passwd *unix_pwd;
|
||||
struct spwd *unix_sp;
|
||||
int *passwd_flag;
|
||||
int privileged;
|
||||
int nowarn;
|
||||
{
|
||||
char *value;
|
||||
char *char_p;
|
||||
char *tmp_pwd_entry;
|
||||
char **data_p = data;
|
||||
int mindate;
|
||||
int maxdate;
|
||||
int warndate;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
static char *lkstring = "*LK*"; /* lock string to lock */
|
||||
/* user's password */
|
||||
|
||||
if (strcmp(field, "attr") == 0) {
|
||||
while (*data != NULL) {
|
||||
/* check attribute: AUTHTOK_DEL */
|
||||
if ((value =
|
||||
attr_match("AUTHTOK_DEL", *data))
|
||||
!= NULL) {
|
||||
if (strcmp(value, "1") == 0) {
|
||||
|
||||
/* delete password */
|
||||
if (unix_sp->sp_pwdp)
|
||||
memset(unix_sp->sp_pwdp, 0,
|
||||
strlen(unix_sp->sp_pwdp));
|
||||
|
||||
/*
|
||||
* set "AUTHTOK_EXT" will clear
|
||||
* the sp_lstchg field. We do not
|
||||
* want sp_lstchg field to be set
|
||||
* if one execute passwd -d -f
|
||||
* name or passwd -l -f name.
|
||||
*/
|
||||
if (attr_find("AUTHTOK_EXP",
|
||||
data_p) == 0)
|
||||
unix_sp->sp_lstchg = DAY_NOW;
|
||||
}
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check attribute: AUTHTOK_LK */
|
||||
if ((value = attr_match("AUTHTOK_LK", *data))
|
||||
!= NULL) {
|
||||
if (strcmp(value, "1") == 0) {
|
||||
memset(unix_sp->sp_pwdp, 0,
|
||||
strlen(unix_sp->sp_pwdp));
|
||||
/* lock password */
|
||||
unix_sp->sp_pwdp = lkstring;
|
||||
if (attr_find("AUTHTOK_EXP",
|
||||
data_p) == 0)
|
||||
unix_sp->sp_lstchg = DAY_NOW;
|
||||
}
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check attribute: AUTHTOK_EXP */
|
||||
if ((value = attr_match("AUTHTOK_EXP", *data))
|
||||
!= NULL) {
|
||||
if (strcmp(value, "1") == 0) {
|
||||
/* expire password */
|
||||
unix_sp->sp_lstchg = (long) 0;
|
||||
}
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check attribute: AUTHTOK_MAXAGE */
|
||||
if ((value = attr_match("AUTHTOK_MAXAGE", *data))
|
||||
!= NULL) {
|
||||
/* set max field */
|
||||
maxdate = (int)strtol(value, &char_p, 10);
|
||||
if ((attr_find("AUTHTOK_MINAGE", data_p) ==
|
||||
0) && unix_sp->sp_min == -1)
|
||||
unix_sp->sp_min = 0;
|
||||
if (maxdate == -1) { /* turn off aging */
|
||||
unix_sp->sp_min = -1;
|
||||
unix_sp->sp_warn = -1;
|
||||
} else if (unix_sp->sp_max == -1)
|
||||
/*
|
||||
* It was set to 0 before. That
|
||||
* will force passwd change at the
|
||||
* next login. There are several
|
||||
* ways to force passwd change. I don't
|
||||
* think turning on aging should imply
|
||||
* that.
|
||||
*/
|
||||
unix_sp->sp_lstchg = DAY_NOW;
|
||||
|
||||
unix_sp->sp_max = maxdate;
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check attribute: AUTHTOK_MINAGE */
|
||||
if ((value = attr_match("AUTHTOK_MINAGE", *data))
|
||||
!= NULL) {
|
||||
/* set min field */
|
||||
mindate = (int)strtol(value, &char_p, 10);
|
||||
if ((attr_find("AUTHTOK_MAXAGE", data_p) ==
|
||||
0) &&
|
||||
unix_sp->sp_max == -1 && mindate != -1) {
|
||||
return (PAM_AUTHTOK_DISABLE_AGING);
|
||||
}
|
||||
unix_sp->sp_min = mindate;
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check attribute: AUTHTOK_WARNDATE */
|
||||
if ((value =
|
||||
attr_match
|
||||
("AUTHTOK_WARNDATE", *data)) != NULL) {
|
||||
/* set warn field */
|
||||
warndate = (int)strtol(value, &char_p, 10);
|
||||
if (unix_sp->sp_max == -1 && warndate != -1) {
|
||||
return (PAM_AUTHTOK_DISABLE_AGING);
|
||||
}
|
||||
unix_sp->sp_warn = warndate;
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* new shell */
|
||||
if ((value = attr_match("AUTHTOK_SHELL", *data))
|
||||
!= NULL) {
|
||||
if (unix_pwd == NULL) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 94,
|
||||
"%s: No local passwd record"),
|
||||
UNIX_MSG);
|
||||
(void) __pam_display_msg(
|
||||
pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (PAM_AUTHTOK_RECOVERY_ERR);
|
||||
}
|
||||
tmp_pwd_entry = unix_pwd->pw_shell;
|
||||
unix_pwd->pw_shell =
|
||||
getloginshell(pamh, unix_pwd->pw_shell,
|
||||
privileged, nowarn);
|
||||
if (tmp_pwd_entry)
|
||||
free(tmp_pwd_entry);
|
||||
/* if NULL, shell unchanged */
|
||||
if (unix_pwd->pw_shell == NULL)
|
||||
return (PAM_SUCCESS);
|
||||
*passwd_flag = 1;
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* new homedir */
|
||||
if ((value = attr_match("AUTHTOK_HOMEDIR", *data))
|
||||
!= NULL) {
|
||||
if (unix_pwd == NULL) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 94,
|
||||
"%s: No local passwd record"),
|
||||
UNIX_MSG);
|
||||
(void) __pam_display_msg(
|
||||
pamh, PAM_ERROR_MSG, 1,
|
||||
messages, NULL);
|
||||
}
|
||||
return (PAM_AUTHTOK_RECOVERY_ERR);
|
||||
}
|
||||
tmp_pwd_entry = unix_pwd->pw_dir;
|
||||
unix_pwd->pw_dir =
|
||||
gethomedir(pamh, unix_pwd->pw_dir,
|
||||
nowarn);
|
||||
if (tmp_pwd_entry)
|
||||
free(tmp_pwd_entry);
|
||||
/* if NULL, homedir unchanged */
|
||||
if (unix_pwd->pw_dir == NULL)
|
||||
return (PAM_SUCCESS);
|
||||
*passwd_flag = 1;
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* new gecos */
|
||||
if ((value = attr_match("AUTHTOK_GECOS", *data))
|
||||
!= NULL) {
|
||||
if (unix_pwd == NULL) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 94,
|
||||
"%s: No local passwd record"),
|
||||
UNIX_MSG);
|
||||
(void) __pam_display_msg(
|
||||
pamh, PAM_ERROR_MSG, 1,
|
||||
messages, NULL);
|
||||
}
|
||||
return (PAM_AUTHTOK_RECOVERY_ERR);
|
||||
}
|
||||
tmp_pwd_entry = unix_pwd->pw_gecos;
|
||||
unix_pwd->pw_gecos =
|
||||
getfingerinfo(pamh, unix_pwd->pw_gecos,
|
||||
nowarn);
|
||||
if (tmp_pwd_entry)
|
||||
free(tmp_pwd_entry);
|
||||
/* if NULL, gecos unchanged */
|
||||
if (unix_pwd->pw_gecos == NULL)
|
||||
return (PAM_SUCCESS);
|
||||
*passwd_flag = 1;
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (strcmp(field, "passwd") == 0) { /* change password */
|
||||
unix_sp->sp_pwdp = *data_p;
|
||||
|
||||
/* update the last change field */
|
||||
unix_sp->sp_lstchg = DAY_NOW;
|
||||
if (unix_sp->sp_max == 0) { /* turn off aging */
|
||||
unix_sp->sp_max = -1;
|
||||
unix_sp->sp_min = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* shell, homedir and gecos are in passwd file. The update is modeled
|
||||
* after shadow file.
|
||||
*/
|
||||
static int
|
||||
process_passwd(pamh, prognamep, usrname, unix_pwd, nowarn)
|
||||
pam_handle_t *pamh;
|
||||
char *prognamep;
|
||||
char *usrname;
|
||||
struct passwd *unix_pwd;
|
||||
int nowarn;
|
||||
{
|
||||
FILE *tpfp; /* tmp passwd file pointer */
|
||||
FILE *pwfp; /* passwd file pointer */
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
struct passwd *unix_p;
|
||||
struct passwd unix_tmp;
|
||||
int found;
|
||||
char buf[4 * BUFSIZ];
|
||||
struct stat stat_buf;
|
||||
|
||||
if (stat(PASSWD, &stat_buf) < 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
(void) umask(S_IAMB & ~(stat_buf.st_mode & S_IRUSR));
|
||||
if ((tpfp = fopen(PASSTEMP, "w")) == NULL) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
|
||||
if ((pwfp = fopen(PASSWD, "r")) == NULL) {
|
||||
fclose(tpfp);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
while ((unix_p = fgetpwent_r(pwfp, &unix_tmp, buf, 4*BUFSIZ)) != NULL) {
|
||||
if (strcmp(unix_p->pw_name, usrname) == 0) {
|
||||
found = 1;
|
||||
unix_p->pw_gecos = unix_pwd->pw_gecos;
|
||||
unix_p->pw_dir = unix_pwd->pw_dir;
|
||||
unix_p->pw_shell = unix_pwd->pw_shell;
|
||||
}
|
||||
if (putpwent(unix_p, tpfp) != 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
fclose(tpfp);
|
||||
fclose(pwfp);
|
||||
goto err;
|
||||
}
|
||||
memset(buf, 0, 4 * BUFSIZ);
|
||||
|
||||
} /* end of while */
|
||||
|
||||
if ((fclose(tpfp)) || (fclose(pwfp))) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check if user name exists */
|
||||
if (found == 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename temp file back to appropriate passwd file.
|
||||
*/
|
||||
|
||||
/* remove old passwd file */
|
||||
if (unlink(OPASSWD) && access(OPASSWD, 0) == 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: %s"),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* rename password file to old password file */
|
||||
if (rename(PASSWD, OPASSWD) == -1) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* rename temporary password file to password file */
|
||||
if (rename(PASSTEMP, PASSWD) == -1) {
|
||||
(void) unlink(PASSWD);
|
||||
if (link(OPASSWD, PASSWD)) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 91,
|
||||
"%s%s: Unexpected failure. Password database unchanged."),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
(void) chmod(PASSWD, 0644);
|
||||
return (PAM_SUCCESS);
|
||||
|
||||
err:
|
||||
(void) unlink(PASSTEMP);
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
}
|
||||
326
cde/lib/pam/pam_modules/unix/unix_update_authtok_nis.c
Normal file
326
cde/lib/pam/pam_modules/unix/unix_update_authtok_nis.c
Normal file
@@ -0,0 +1,326 @@
|
||||
/* $XConsortium: unix_update_authtok_nis.c /main/5 1996/05/09 04:36:14 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1992-1996, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_update_authtok_nis.c 1.43 96/02/02 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
#ifdef PAM_NIS
|
||||
|
||||
static void reencrypt_secret(pam_handle_t *, char *, char *, char *,
|
||||
int);
|
||||
static int update_nisattr(pam_handle_t *, char *, char **,
|
||||
struct passwd *, int, int);
|
||||
|
||||
int
|
||||
update_authtok_nis(
|
||||
pam_handle_t *pamh,
|
||||
char *field,
|
||||
char *data[], /* encrypted new passwd */
|
||||
/* or new attribute info */
|
||||
char *old, /* old passwd: clear */
|
||||
char *new, /* new passwd: clear */
|
||||
struct passwd *nis_pwd, /* password structure */
|
||||
int privileged,
|
||||
int nowarn) /* no compat mode: npd and yp server */
|
||||
/* take the same protocol */
|
||||
{
|
||||
int ok;
|
||||
enum clnt_stat ans;
|
||||
char *domain;
|
||||
char *master;
|
||||
CLIENT *client;
|
||||
struct timeval timeout;
|
||||
char *prognamep;
|
||||
char *usrname;
|
||||
int retcode = PAM_SYSTEM_ERR;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
struct yppasswd yppasswd;
|
||||
|
||||
/* initialize this */
|
||||
yppasswd.oldpass = NULL;
|
||||
|
||||
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
|
||||
!= PAM_SUCCESS ||
|
||||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
|
||||
!= PAM_SUCCESS)
|
||||
goto out;
|
||||
|
||||
if (strcmp(field, "passwd") == 0) {
|
||||
/*
|
||||
* ck_passwd() already checked the old passwd. It won't get here
|
||||
* if the old passwd is not matched.
|
||||
* We are just preparing the passwd update packet here.
|
||||
*/
|
||||
|
||||
if ((yppasswd.oldpass = strdup(old)) == NULL) {
|
||||
retcode = PAM_BUF_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nis_pwd->pw_passwd) {
|
||||
memset(nis_pwd->pw_passwd, 0,
|
||||
strlen(nis_pwd->pw_passwd));
|
||||
free(nis_pwd->pw_passwd);
|
||||
}
|
||||
nis_pwd->pw_passwd = *data; /* encrypted new passwd */
|
||||
} else {
|
||||
/*
|
||||
* prompt for passwd: required for the options
|
||||
* nis_pwd struct will be modified by update_nisattr().
|
||||
* The encrypted passwd remains the same because we are not
|
||||
* changing passwd here.
|
||||
*/
|
||||
|
||||
retcode = __pam_get_authtok(pamh, PAM_PROMPT, 0, PASSWORD_LEN,
|
||||
PAM_MSG(pamh, 62, "Enter login(NIS) password: "),
|
||||
&(yppasswd.oldpass));
|
||||
if (retcode != PAM_SUCCESS)
|
||||
goto out;
|
||||
|
||||
if ((retcode = update_nisattr(pamh, field, data,
|
||||
nis_pwd, privileged, nowarn)) != PAM_SUCCESS) {
|
||||
|
||||
if (retcode == -1) {
|
||||
/* finger, shell, or gecos info unchanged */
|
||||
retcode = PAM_SUCCESS;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
yppasswd.newpw = *nis_pwd;
|
||||
if (yp_get_default_domain(&domain) != 0) {
|
||||
syslog(LOG_ERR, "%s%s: can't get domain",
|
||||
prognamep, NIS_MSG);
|
||||
retcode = PAM_SYSTEM_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (yp_master(domain, "passwd.byname", &master) != 0) {
|
||||
syslog(LOG_ERR, "%s%s: can't get master for passwd map",
|
||||
prognamep, NIS_MSG);
|
||||
retcode = PAM_SYSTEM_ERR;
|
||||
goto out;
|
||||
}
|
||||
client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
|
||||
if (client == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"%s%s: couldn't create client to YP master",
|
||||
prognamep, NIS_MSG);
|
||||
retcode = PAM_SYSTEM_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 55; /* npd uses 55 seconds */
|
||||
|
||||
ans = CLNT_CALL(client, YPPASSWDPROC_UPDATE, xdr_yppasswd,
|
||||
(char *)&yppasswd, xdr_int, (char *)&ok, timeout);
|
||||
(void) clnt_destroy(client);
|
||||
if (ans != RPC_SUCCESS) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 100,
|
||||
"%s%s: couldn't change passwd/attributes"),
|
||||
prognamep, NIS_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
|
||||
retcode = PAM_PERM_DENIED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ok != 0) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 101,
|
||||
"%s%s: Couldn't change passwd/attributes for %s"),
|
||||
prognamep, NIS_MSG, usrname);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
|
||||
retcode = PAM_PERM_DENIED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sprintf(messages[0], PAM_MSG(pamh, 102,
|
||||
"NIS(YP) passwd/attributes changed on %s"),
|
||||
master);
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
|
||||
1, messages, NULL);
|
||||
|
||||
reencrypt_secret(pamh, domain, old, new, nowarn);
|
||||
|
||||
retcode = PAM_SUCCESS;
|
||||
out:
|
||||
if (yppasswd.oldpass) {
|
||||
memset(yppasswd.oldpass, 0, strlen(yppasswd.oldpass));
|
||||
free(yppasswd.oldpass);
|
||||
}
|
||||
return (retcode);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
update_nisattr(pam_handle_t *pamh, char *field, char **data,
|
||||
struct passwd *nis_pwd, int privileged, int nowarn)
|
||||
{
|
||||
char *username;
|
||||
char *value;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
|
||||
if (nis_pwd == NULL) {
|
||||
if (!nowarn) {
|
||||
pam_get_item(pamh, PAM_USER, (void **)&username);
|
||||
sprintf(messages[0], PAM_MSG(pamh, 103,
|
||||
"System error: no NIS passwd record for %s"),
|
||||
username);
|
||||
(void) __pam_display_msg(pamh,
|
||||
PAM_ERROR_MSG, 1, messages, NULL);
|
||||
}
|
||||
return (PAM_USER_UNKNOWN);
|
||||
}
|
||||
|
||||
if (strcmp(field, "attr") == 0) {
|
||||
|
||||
while (*data != NULL) {
|
||||
/* AUTHTOK_DEL: not applicable */
|
||||
|
||||
if ((value = attr_match("AUTHTOK_SHELL", *data))
|
||||
!= NULL) {
|
||||
if (strcmp(value, "1") != 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 104,
|
||||
"%s: System error%s: shell is set illegally"),
|
||||
value, NIS_MSG);
|
||||
(void) __pam_display_msg(pamh,
|
||||
PAM_ERROR_MSG, 1,
|
||||
messages, NULL);
|
||||
}
|
||||
return (PAM_SYSTEM_ERR);
|
||||
}
|
||||
nis_pwd->pw_shell =
|
||||
getloginshell(pamh, nis_pwd->pw_shell,
|
||||
privileged, nowarn);
|
||||
/* if NULL, shell unchanged */
|
||||
if (nis_pwd->pw_shell == NULL)
|
||||
return (-1);
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((value = attr_match("AUTHTOK_HOMEDIR", *data))
|
||||
!= NULL) {
|
||||
/* home directory */
|
||||
if (strcmp(value, "1") != 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 105,
|
||||
"System error%s: homedir is set illegally."),
|
||||
NIS_MSG);
|
||||
(void) __pam_display_msg(
|
||||
pamh,
|
||||
PAM_ERROR_MSG, 1,
|
||||
messages, NULL);
|
||||
}
|
||||
return (PAM_SYSTEM_ERR);
|
||||
}
|
||||
nis_pwd->pw_dir =
|
||||
gethomedir(pamh, nis_pwd->pw_dir, nowarn);
|
||||
/* if NULL, homedir unchanged */
|
||||
if (nis_pwd->pw_dir == NULL)
|
||||
return (-1);
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((value = attr_match("AUTHTOK_GECOS", *data))
|
||||
!= NULL) {
|
||||
/* finger information */
|
||||
if (strcmp(value, "1") != 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 106,
|
||||
"System error: gecos is set illegally."));
|
||||
(void) __pam_display_msg(
|
||||
pamh,
|
||||
PAM_ERROR_MSG, 1,
|
||||
messages, NULL);
|
||||
}
|
||||
return (PAM_SYSTEM_ERR);
|
||||
}
|
||||
nis_pwd->pw_gecos =
|
||||
getfingerinfo(pamh, nis_pwd->pw_gecos,
|
||||
nowarn);
|
||||
/* if NULL, gecos unchanged */
|
||||
if (nis_pwd->pw_gecos == NULL)
|
||||
return (-1);
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
} /* while */
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
return (PAM_AUTHTOK_ERR);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* If the user has a secret key, reencrypt it.
|
||||
* Otherwise, be quiet.
|
||||
*/
|
||||
static void
|
||||
reencrypt_secret(pam_handle_t *pamh, char *domain, char *oldpass,
|
||||
char *newpass, int nowarn)
|
||||
{
|
||||
#ifdef PAM_SECURE_RPC
|
||||
char who[MAXNETNAMELEN+1];
|
||||
char secret[HEXKEYBYTES+1];
|
||||
char public[HEXKEYBYTES+1];
|
||||
char crypt[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
|
||||
char pkent[sizeof (crypt) + sizeof (public) + 1];
|
||||
char *master;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
|
||||
getnetname(who);
|
||||
if (!getsecretkey(who, secret, oldpass)) {
|
||||
/*
|
||||
* Quiet: net is not running secure RPC
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if (secret[0] == 0) {
|
||||
/*
|
||||
* Quiet: user has no secret key
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if (getpublickey(who, public) == FALSE) {
|
||||
return;
|
||||
}
|
||||
(void) memcpy(crypt, secret, HEXKEYBYTES);
|
||||
(void) memcpy(crypt + HEXKEYBYTES, secret, KEYCHECKSUMSIZE);
|
||||
crypt[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
|
||||
(void) xencrypt(crypt, newpass);
|
||||
(void) sprintf(pkent, "%s:%s", public, crypt);
|
||||
if (yp_update(domain, PKMAP, YPOP_STORE,
|
||||
who, strlen(who), pkent, strlen(pkent)) != 0) {
|
||||
|
||||
return;
|
||||
}
|
||||
if (yp_master(domain, PKMAP, &master) != 0) {
|
||||
master = "yp master"; /* should never happen */
|
||||
}
|
||||
|
||||
sprintf(messages[0], PAM_MSG(pamh, 107,
|
||||
"%s: secret key reencrypted for %s on %s"),
|
||||
NIS_MSG, who, master);
|
||||
__pam_display_msg(pamh, PAM_TEXT_INFO, 1, messages, NULL);
|
||||
#else
|
||||
return;
|
||||
#endif /* PAM_SECURE_RPC */
|
||||
|
||||
}
|
||||
|
||||
#endif /* PAM_NIS */
|
||||
1049
cde/lib/pam/pam_modules/unix/unix_update_authtok_nisplus.c
Normal file
1049
cde/lib/pam/pam_modules/unix/unix_update_authtok_nisplus.c
Normal file
File diff suppressed because it is too large
Load Diff
974
cde/lib/pam/pam_modules/unix/unix_utils.c
Normal file
974
cde/lib/pam/pam_modules/unix/unix_utils.c
Normal file
@@ -0,0 +1,974 @@
|
||||
/* $XConsortium: unix_utils.c /main/5 1996/05/09 04:36:55 drk $ */
|
||||
/*
|
||||
* Copyright (c) 1992-1995, by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ident "@(#)unix_utils.c 1.53 95/09/11 SMI"
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
static char *spskip();
|
||||
static int special_case();
|
||||
static int illegal_input();
|
||||
static int copy_passwd_structs(struct passwd **, struct passwd *,
|
||||
struct spwd **, struct spwd *);
|
||||
|
||||
void free_passwd_structs(struct passwd *, struct spwd *);
|
||||
|
||||
/* ******************************************************************** */
|
||||
/* */
|
||||
/* Utilities Functions */
|
||||
/* */
|
||||
/* ******************************************************************** */
|
||||
|
||||
#ifdef PAM_SECURE_RPC
|
||||
|
||||
/*
|
||||
* Establish the Secure RPC secret key for the given uid using
|
||||
* the given password to decrypt the secret key, and store it with
|
||||
* the key service.
|
||||
*
|
||||
* If called with a nonzero 'reestablish' parameter, the key
|
||||
* is obtained from the name service, decrypted, and stored
|
||||
* even if the keyserver already has a key stored for the uid.
|
||||
* If the 'reestablish' parameter is zero, the function will not
|
||||
* try to reset the key. It will return immediately with
|
||||
* ESTKEY_ALREADY.
|
||||
*
|
||||
* Returns one of the following codes:
|
||||
* ESTKEY_ALREADY - reestablish flag was zero, and key was already set.
|
||||
* ESTKEY_SUCCESS - successfully obtained, decrypted, and set the key
|
||||
* ESTKEY_NOCREDENTIALS - the user has no credentials.
|
||||
* ESTKEY_BADPASSWD - the password supplied didn't decrypt the key
|
||||
* ESTKEY_CANTSETKEY - decrypted the key, but couldn't store key with
|
||||
* the key service.
|
||||
*
|
||||
* If netnamebuf is a non-NULL pointer, the netname will be returned in
|
||||
* netnamebuf, provided that the return status is not
|
||||
* ESTKEY_NOCREDENTIALS or ESTKEY_ALREADY. If non-NULL, the
|
||||
* netnamebuf pointer must point to a buffer of length at least
|
||||
* MAXNETNAMELEN+1 characters.
|
||||
*/
|
||||
|
||||
int
|
||||
establish_key(uid, password, reestablish, netnamebuf)
|
||||
uid_t uid;
|
||||
char *password;
|
||||
int reestablish;
|
||||
char *netnamebuf;
|
||||
{
|
||||
char netname[MAXNETNAMELEN+1];
|
||||
struct key_netstarg netst;
|
||||
uid_t orig_uid;
|
||||
|
||||
orig_uid = geteuid();
|
||||
if (seteuid(uid) == -1)
|
||||
/* can't set uid */
|
||||
return (ESTKEY_NOCREDENTIALS);
|
||||
|
||||
|
||||
if (!reestablish && key_secretkey_is_set()) {
|
||||
/* key is already established and we are not to reestablish */
|
||||
(void) seteuid(orig_uid);
|
||||
return (ESTKEY_ALREADY);
|
||||
}
|
||||
|
||||
|
||||
if (!getnetname(netname)) {
|
||||
/* can't construct netname */
|
||||
(void) seteuid(orig_uid);
|
||||
return (ESTKEY_NOCREDENTIALS);
|
||||
}
|
||||
|
||||
if (!getsecretkey(netname, (char *) &(netst.st_priv_key), password)) {
|
||||
/* no secret key */
|
||||
(void) seteuid(orig_uid);
|
||||
return (ESTKEY_NOCREDENTIALS);
|
||||
}
|
||||
|
||||
if (netnamebuf) {
|
||||
/* return copy of netname in caller's buffer */
|
||||
(void) strcpy(netnamebuf, netname);
|
||||
}
|
||||
|
||||
if (netst.st_priv_key[0] == 0) {
|
||||
/* password does not decrypt secret key */
|
||||
(void) seteuid(orig_uid);
|
||||
return (ESTKEY_BADPASSWD);
|
||||
}
|
||||
|
||||
|
||||
/* secret key successfully decrypted at this point */
|
||||
|
||||
/* store with key service */
|
||||
|
||||
if ((netst.st_netname = strdup(netname)) == NULL) {
|
||||
(void) seteuid(orig_uid);
|
||||
return (PAM_BUF_ERR);
|
||||
}
|
||||
(void) memset(netst.st_pub_key, 0, HEXKEYBYTES);
|
||||
|
||||
if (key_setnet(&netst) < 0) {
|
||||
free(netst.st_netname);
|
||||
(void) seteuid(orig_uid);
|
||||
return (ESTKEY_CANTSETKEY);
|
||||
}
|
||||
|
||||
free(netst.st_netname);
|
||||
(void) seteuid(orig_uid);
|
||||
return (ESTKEY_SUCCESS);
|
||||
}
|
||||
|
||||
#endif /* PAM_SECURE_RPC */
|
||||
|
||||
/* ******************************************************************** */
|
||||
/* */
|
||||
/* Utilities Functions */
|
||||
/* */
|
||||
/* ******************************************************************** */
|
||||
|
||||
/*
|
||||
* ck_perm():
|
||||
* Check the permission of the user specified by "usrname".
|
||||
*
|
||||
* It returns PAM_PERM_DENIED if (1) the user has a NULL pasword or
|
||||
* shadow password file entry, or (2) the caller is not root and
|
||||
* its uid is not equivalent to the uid specified by the user's
|
||||
* password file entry.
|
||||
*/
|
||||
|
||||
int
|
||||
ck_perm(pamh, repository, domain, pwd, shpwd, privileged, passwd_res, uid,
|
||||
debug, nowarn)
|
||||
pam_handle_t *pamh;
|
||||
int repository;
|
||||
char *domain;
|
||||
struct passwd **pwd;
|
||||
struct spwd **shpwd;
|
||||
int *privileged;
|
||||
void **passwd_res;
|
||||
uid_t uid;
|
||||
int debug;
|
||||
int nowarn;
|
||||
{
|
||||
FILE *pwfp, *spfp;
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
struct passwd local_pwd, *local_pwdp;
|
||||
struct spwd local_shpwd, *local_shpwdp;
|
||||
char pwdbuf[1024], shpwdbuf[1024];
|
||||
char *prognamep;
|
||||
char *usrname;
|
||||
int retcode = 0;
|
||||
#ifdef PAM_NISPLUS
|
||||
char buf[NIS_MAXNAMELEN+1];
|
||||
nis_name local_principal;
|
||||
nis_name pwd_domain;
|
||||
#endif
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"ck_perm() called: repository=%s",
|
||||
repository_to_string(repository));
|
||||
|
||||
if ((retcode = pam_get_item(pamh, PAM_SERVICE, (void **)&prognamep))
|
||||
!= PAM_SUCCESS ||
|
||||
(retcode = pam_get_item(pamh, PAM_USER, (void **)&usrname))
|
||||
!= PAM_SUCCESS) {
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
return (retcode);
|
||||
}
|
||||
|
||||
if (repository == PAM_REP_FILES) {
|
||||
if (((pwfp = fopen(PASSWD, "r")) == NULL) ||
|
||||
((spfp = fopen(SHADOW, "r")) == NULL)) {
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
syslog(LOG_ERR,
|
||||
"ck_perm: can not open passwd/shadow file");
|
||||
return (PAM_PERM_DENIED);
|
||||
}
|
||||
while ((local_pwdp = fgetpwent_r(pwfp, &local_pwd, pwdbuf,
|
||||
sizeof (pwdbuf))) != NULL)
|
||||
if (strcmp(local_pwd.pw_name, usrname) == 0)
|
||||
break;
|
||||
while ((local_shpwdp = fgetspent_r(spfp, &local_shpwd,
|
||||
shpwdbuf, sizeof (shpwdbuf))) != NULL)
|
||||
if (strcmp(local_shpwd.sp_namp, usrname) == 0)
|
||||
break;
|
||||
(void) fclose(pwfp);
|
||||
(void) fclose(spfp);
|
||||
if (local_pwdp == NULL || local_shpwdp == NULL) {
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
return (PAM_USER_UNKNOWN);
|
||||
}
|
||||
|
||||
if (uid != 0 && uid != local_pwd.pw_uid) {
|
||||
/*
|
||||
* Change passwd for another person:
|
||||
* Even if you are nis+ admin, you can't do anything
|
||||
* locally. Don't bother to continue.
|
||||
*/
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 140,
|
||||
"%s%s: Permission denied"), prognamep,
|
||||
UNIX_MSG);
|
||||
sprintf(messages[1], PAM_MSG(pamh, 141,
|
||||
"%s%s: Can't change local passwd file\n"),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(
|
||||
pamh, PAM_ERROR_MSG, 2,
|
||||
messages, NULL);
|
||||
}
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
return (PAM_PERM_DENIED);
|
||||
}
|
||||
return (copy_passwd_structs(pwd, local_pwdp,
|
||||
shpwd, local_shpwdp));
|
||||
}
|
||||
|
||||
#ifdef PAM_NIS
|
||||
if (repository == PAM_REP_NIS) {
|
||||
/*
|
||||
* Special case root: don't bother to get root from nis(yp).
|
||||
*/
|
||||
if (strcmp(usrname, "root") == 0) {
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
return (PAM_USER_UNKNOWN);
|
||||
}
|
||||
|
||||
/* get pwd struct from yp */
|
||||
|
||||
local_pwdp = getpwnam_from(usrname, PAM_REP_NIS);
|
||||
local_shpwdp = getspnam_from(usrname, PAM_REP_NIS);
|
||||
|
||||
if (local_pwdp == NULL || local_shpwdp == NULL)
|
||||
return (PAM_USER_UNKNOWN);
|
||||
|
||||
if (uid != local_pwdp->pw_uid) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 140,
|
||||
"%s%s: Permission denied"), prognamep,
|
||||
NIS_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
return (PAM_PERM_DENIED);
|
||||
}
|
||||
return (copy_passwd_structs(pwd, local_pwdp,
|
||||
shpwd, local_shpwdp));
|
||||
}
|
||||
#endif /* PAM_NIS */
|
||||
|
||||
#ifdef PAM_NISPLUS
|
||||
if (repository == PAM_REP_NISPLUS) {
|
||||
/*
|
||||
* Special case root: don't bother to get root from nis+.
|
||||
*/
|
||||
if (strcmp(usrname, "root") == 0) {
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
return (PAM_USER_UNKNOWN);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "ck_perm(): NIS+ domain=%s", domain);
|
||||
|
||||
/*
|
||||
* We need to use user id to
|
||||
* make any nis+ request. But don't give up the super
|
||||
* user power yet. It may be needed elsewhere.
|
||||
*/
|
||||
(void) setuid(0); /* keep real user id as root */
|
||||
(void) seteuid(uid);
|
||||
|
||||
local_shpwdp = getspnam_from(usrname, PAM_REP_NISPLUS);
|
||||
local_pwdp = getpwnam_from(usrname, PAM_REP_NISPLUS);
|
||||
|
||||
if (local_pwdp == NULL || local_shpwdp == NULL)
|
||||
return (PAM_USER_UNKNOWN);
|
||||
|
||||
/*
|
||||
* local_principal is internal, it is not meant to be free()ed
|
||||
*/
|
||||
local_principal = nis_local_principal();
|
||||
|
||||
if ((9 + strlen(usrname) + strlen(domain) + PASSTABLELEN) >
|
||||
(size_t) NIS_MAXNAMELEN) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 140,
|
||||
"%s%s: Permission denied"), prognamep, NISPLUS_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
return (PAM_PERM_DENIED);
|
||||
}
|
||||
|
||||
sprintf(buf, "[name=%s],%s.%s", usrname, PASSTABLE, domain);
|
||||
if (buf[strlen(buf) - 1] != '.')
|
||||
(void) strcat(buf, ".");
|
||||
|
||||
/*
|
||||
* We must use an authenticated handle to get the cred
|
||||
* table information for the user we want to modify the
|
||||
* cred info for. If we can't even read that info, we
|
||||
* definitely wouldn't have modify permission. Well..
|
||||
*/
|
||||
*passwd_res = (void *) nis_list(buf,
|
||||
USE_DGRAM+FOLLOW_LINKS+FOLLOW_PATH+MASTER_ONLY,
|
||||
NULL, NULL);
|
||||
if (((nis_result *)(*passwd_res))->status != NIS_SUCCESS) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 140,
|
||||
"%s%s: Permission denied"), prognamep, NISPLUS_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
return (PAM_PERM_DENIED);
|
||||
}
|
||||
|
||||
pwd_domain =
|
||||
NIS_RES_OBJECT((nis_result *)(*passwd_res))->zo_domain;
|
||||
if (strcmp(nis_leaf_of(pwd_domain), "org_dir") == 0) {
|
||||
pwd_domain = nis_domain_of(
|
||||
NIS_RES_OBJECT((nis_result *)(*passwd_res))->zo_domain);
|
||||
|
||||
}
|
||||
*privileged = __nis_isadmin(local_principal, "passwd",
|
||||
pwd_domain);
|
||||
|
||||
return (copy_passwd_structs(pwd, local_pwdp,
|
||||
shpwd, local_shpwdp));
|
||||
}
|
||||
#endif /* PAM_NISPLUS */
|
||||
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 142,
|
||||
"%s%s: System error: repository out of range"),
|
||||
prognamep, UNIX_MSG);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1,
|
||||
messages, NULL);
|
||||
}
|
||||
*pwd = NULL; *shpwd = NULL;
|
||||
return (PAM_PERM_DENIED);
|
||||
}
|
||||
|
||||
/*
|
||||
* attr_match():
|
||||
*
|
||||
* Check if the attribute name in string s1 is equivalent to
|
||||
* that in string s2.
|
||||
* s1 is either name, or name=value
|
||||
* s2 is name=value
|
||||
* if names match, return value of s2, else NULL
|
||||
*/
|
||||
|
||||
char *
|
||||
attr_match(s1, s2)
|
||||
register char *s1, *s2;
|
||||
{
|
||||
while (*s1 == *s2++)
|
||||
if (*s1++ == '=')
|
||||
return (s2);
|
||||
if (*s1 == '\0' && *(s2-1) == '=')
|
||||
return (s2);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* attr_find():
|
||||
*
|
||||
* Check if the attribute name in string s1 is present in the
|
||||
* attribute=value pairs array pointed by s2.
|
||||
* s1 is name
|
||||
* s2 is an array of name=value pairs
|
||||
* if s1 match the name of any one of the name in the name=value pairs
|
||||
* pointed by s2, then 1 is returned; else 0 is returned
|
||||
*/
|
||||
|
||||
int
|
||||
attr_find(s1, s2)
|
||||
register char *s1, *s2[];
|
||||
{
|
||||
int i;
|
||||
char *sa, *sb;
|
||||
|
||||
i = 0;
|
||||
while (s2[i] != NULL) {
|
||||
sa = s1;
|
||||
sb = s2[i];
|
||||
while (*sa++ == *sb++) {
|
||||
if ((*sa == '\0') && (*sb == '='))
|
||||
return (1); /* find */
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return (0); /* not find */
|
||||
}
|
||||
|
||||
/*
|
||||
* free_setattr():
|
||||
* free storage pointed by "setattr"
|
||||
*/
|
||||
|
||||
void
|
||||
free_setattr(setattr)
|
||||
char * setattr[];
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; setattr[i] != NULL; i++)
|
||||
free(setattr[i]);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* setup_attr():
|
||||
* allocate memory and copy in attribute=value pair
|
||||
* into the array of attribute=value pairs pointed to
|
||||
* by "dest_attr"
|
||||
*/
|
||||
|
||||
void
|
||||
setup_attr(dest_attr, k, attr, value)
|
||||
char *dest_attr[];
|
||||
int k;
|
||||
char attr[];
|
||||
char value[];
|
||||
{
|
||||
if (attr != NULL) {
|
||||
dest_attr[k] = (char *)calloc(PAM_MAX_ATTR_SIZE, sizeof (char));
|
||||
(void) strncpy(dest_attr[k], attr, PAM_MAX_ATTR_SIZE);
|
||||
(void) strncat(dest_attr[k], value, PAM_MAX_ATTR_SIZE);
|
||||
} else
|
||||
dest_attr[k] = NULL;
|
||||
}
|
||||
|
||||
#ifdef PAM_NISPLUS
|
||||
static char *
|
||||
spskip(p)
|
||||
register char *p;
|
||||
{
|
||||
while (*p && *p != ':' && *p != '\n')
|
||||
++p;
|
||||
if (*p == '\n')
|
||||
*p = '\0';
|
||||
else if (*p)
|
||||
*p++ = '\0';
|
||||
return (p);
|
||||
}
|
||||
|
||||
void
|
||||
nisplus_populate_age(enobj, sp)
|
||||
struct nis_object *enobj;
|
||||
struct spwd *sp;
|
||||
{
|
||||
char *oldage, *p, *end;
|
||||
long x;
|
||||
|
||||
/*
|
||||
* shadow (col 7)
|
||||
*/
|
||||
|
||||
sp->sp_lstchg = -1;
|
||||
sp->sp_min = -1;
|
||||
sp->sp_max = -1;
|
||||
sp->sp_warn = -1;
|
||||
sp->sp_inact = -1;
|
||||
sp->sp_expire = -1;
|
||||
sp->sp_flag = 0;
|
||||
|
||||
if ((p = ENTRY_VAL(enobj, 7)) == NULL)
|
||||
return;
|
||||
oldage = strdup(p);
|
||||
|
||||
p = oldage;
|
||||
|
||||
x = strtol(p, &end, 10);
|
||||
if (end != memchr(p, ':', strlen(p)))
|
||||
return;
|
||||
if (end != p)
|
||||
sp->sp_lstchg = x;
|
||||
|
||||
p = spskip(p);
|
||||
x = strtol(p, &end, 10);
|
||||
if (end != memchr(p, ':', strlen(p)))
|
||||
return;
|
||||
if (end != p)
|
||||
sp->sp_min = x;
|
||||
|
||||
p = spskip(p);
|
||||
x = strtol(p, &end, 10);
|
||||
if (end != memchr(p, ':', strlen(p)))
|
||||
return;
|
||||
if (end != p)
|
||||
sp->sp_max = x;
|
||||
|
||||
p = spskip(p);
|
||||
x = strtol(p, &end, 10);
|
||||
if (end != memchr(p, ':', strlen(p)))
|
||||
return;
|
||||
if (end != p)
|
||||
sp->sp_warn = x;
|
||||
|
||||
p = spskip(p);
|
||||
x = strtol(p, &end, 10);
|
||||
if (end != memchr(p, ':', strlen(p)))
|
||||
return;
|
||||
if (end != p)
|
||||
sp->sp_inact = x;
|
||||
|
||||
p = spskip(p);
|
||||
x = strtol(p, &end, 10);
|
||||
if (end != memchr(p, ':', strlen(p)))
|
||||
return;
|
||||
if (end != p)
|
||||
sp->sp_expire = x;
|
||||
|
||||
p = spskip(p);
|
||||
x = strtol(p, &end, 10);
|
||||
if ((end != memchr(p, ':', strlen(p))) &&
|
||||
(end != memchr(p, '\n', strlen(p))))
|
||||
return;
|
||||
if (end != p)
|
||||
sp->sp_flag = x;
|
||||
|
||||
free(oldage);
|
||||
}
|
||||
#endif /* PAM_NISPLUS */
|
||||
|
||||
/*
|
||||
* getloginshell() displays old login shell and asks for new login shell.
|
||||
* The new login shell is then returned to calling function.
|
||||
*/
|
||||
char *
|
||||
getloginshell(pamh, oldshell, privileged, nowarn)
|
||||
pam_handle_t *pamh;
|
||||
char *oldshell;
|
||||
int privileged;
|
||||
int nowarn;
|
||||
{
|
||||
char newshell[PAM_MAX_MSG_SIZE];
|
||||
char *cp, *valid, *getusershell();
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
struct pam_response *ret_resp = (struct pam_response *)0;
|
||||
|
||||
if (oldshell == 0 || *oldshell == '\0')
|
||||
oldshell = DEFSHELL;
|
||||
|
||||
if (privileged == 0) {
|
||||
mutex_lock(&_priv_lock);
|
||||
setusershell();
|
||||
for (valid = getusershell(); valid; valid = getusershell())
|
||||
if (strcmp(oldshell, valid) == 0)
|
||||
break;
|
||||
mutex_unlock(&_priv_lock);
|
||||
if (valid == NULL) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 143,
|
||||
"Cannot change from restricted shell %s"),
|
||||
oldshell);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 144, "Old shell: %s"), oldshell);
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO, 1, messages, NULL);
|
||||
sprintf(messages[0],
|
||||
PAM_MSG(pamh, 145, "New shell: "));
|
||||
(void) __pam_get_input(pamh, PAM_PROMPT_ECHO_ON,
|
||||
1, messages, NULL, &ret_resp);
|
||||
strncpy(newshell, ret_resp->resp, PAM_MAX_MSG_SIZE);
|
||||
newshell[PAM_MAX_RESP_SIZE-1] = '\0';
|
||||
__pam_free_resp(1, ret_resp);
|
||||
|
||||
cp = strchr(newshell, '\n');
|
||||
if (cp)
|
||||
*cp = '\0';
|
||||
if (newshell[0] == '\0' || (strcmp(newshell, oldshell) == 0)) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 146,
|
||||
"Login shell unchanged."));
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* XXX:
|
||||
* Keep in mind that, for whatever this validation is worth,
|
||||
* a root on a machine can edit /etc/shells and get any shell
|
||||
* accepted as a valid shell in the NIS+ table.
|
||||
*/
|
||||
mutex_lock(&_priv_lock);
|
||||
setusershell();
|
||||
if (!privileged) {
|
||||
for (valid = getusershell(); valid; valid = getusershell()) {
|
||||
/*
|
||||
* Allow user to give shell w/o preceding pathname.
|
||||
*/
|
||||
if (newshell[0] == '/') {
|
||||
cp = valid;
|
||||
} else {
|
||||
cp = strrchr(valid, '/');
|
||||
if (cp == 0)
|
||||
cp = valid;
|
||||
else
|
||||
cp++;
|
||||
}
|
||||
if (strcmp(newshell, cp) == 0) {
|
||||
strncpy(newshell, valid, strlen(valid));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex_unlock(&_priv_lock);
|
||||
|
||||
if (newshell == 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 147,
|
||||
"%s is unacceptable as a new shell"),
|
||||
newshell);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
__pam_free_resp(1, ret_resp);
|
||||
return (NULL);
|
||||
}
|
||||
if (access(newshell, X_OK) < 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 148,
|
||||
"warning: %s is unavailable on this machine"),
|
||||
newshell);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
}
|
||||
return (strdup(newshell));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get name.
|
||||
*/
|
||||
char *
|
||||
getfingerinfo(pamh, old_gecos, nowarn)
|
||||
pam_handle_t *pamh;
|
||||
char *old_gecos;
|
||||
int nowarn;
|
||||
{
|
||||
char new_gecos[PAM_MAX_MSG_SIZE];
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
struct pam_response *ret_resp = (struct pam_response *)0;
|
||||
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 149,
|
||||
"Default values are printed inside of '[]'."));
|
||||
sprintf(messages[1], PAM_MSG(pamh, 150,
|
||||
"To accept the default, type <return>."));
|
||||
sprintf(messages[2], PAM_MSG(pamh, 151,
|
||||
"To have a blank entry, type the word 'none'."));
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
|
||||
3, messages, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get name.
|
||||
*/
|
||||
do {
|
||||
sprintf(messages[0], " ");
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO, 1,
|
||||
messages, NULL);
|
||||
sprintf(messages[0], PAM_MSG(pamh, 152,
|
||||
"Name [%s]: "), old_gecos);
|
||||
(void) __pam_get_input(pamh, PAM_PROMPT_ECHO_ON,
|
||||
1, messages, NULL, &ret_resp);
|
||||
strncpy(new_gecos, ret_resp->resp, PAM_MAX_MSG_SIZE);
|
||||
new_gecos[PAM_MAX_MSG_SIZE-1] = '\0';
|
||||
__pam_free_resp(1, ret_resp);
|
||||
if (special_case(new_gecos, old_gecos))
|
||||
break;
|
||||
} while (illegal_input(pamh, new_gecos, nowarn));
|
||||
if (strcmp(new_gecos, old_gecos) == 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 153,
|
||||
"Finger information unchanged."));
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
return (strdup(new_gecos));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get Home Dir.
|
||||
*/
|
||||
char *
|
||||
gethomedir(pamh, olddir, nowarn)
|
||||
pam_handle_t *pamh;
|
||||
char *olddir;
|
||||
int nowarn;
|
||||
{
|
||||
char newdir[PAM_MAX_MSG_SIZE];
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
struct pam_response *ret_resp = (struct pam_response *)0;
|
||||
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 149,
|
||||
"Default values are printed inside of '[]'."));
|
||||
sprintf(messages[1], PAM_MSG(pamh, 150,
|
||||
"To accept the default, type <return>."));
|
||||
sprintf(messages[2], PAM_MSG(pamh, 151,
|
||||
"To have a blank entry, type the word 'none'."));
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
|
||||
3, messages, NULL);
|
||||
}
|
||||
do {
|
||||
sprintf(messages[0], " ");
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
|
||||
1, messages, NULL);
|
||||
sprintf(messages[0], PAM_MSG(pamh, 154,
|
||||
"Home Directory [%s]: "), olddir);
|
||||
(void) __pam_get_input(pamh, PAM_PROMPT_ECHO_ON,
|
||||
1, messages, NULL, &ret_resp);
|
||||
strncpy(newdir, ret_resp->resp, PAM_MAX_MSG_SIZE);
|
||||
newdir[PAM_MAX_MSG_SIZE-1] = '\0';
|
||||
__pam_free_resp(1, ret_resp);
|
||||
if (special_case(newdir, olddir))
|
||||
break;
|
||||
} while (illegal_input(pamh, newdir, nowarn));
|
||||
if (strcmp(newdir, olddir) == 0) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 155,
|
||||
"Homedir information unchanged."));
|
||||
(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
|
||||
1, messages, NULL);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
return (strdup(newdir));
|
||||
}
|
||||
|
||||
char *
|
||||
repository_to_string(int repository)
|
||||
{
|
||||
/* if NISPLUS and FILES */
|
||||
switch (repository) {
|
||||
case (PAM_REP_FILES | PAM_REP_NISPLUS):
|
||||
return ("files and nisplus");
|
||||
case (PAM_REP_FILES | PAM_REP_NIS):
|
||||
return ("files and nis");
|
||||
case PAM_REP_NISPLUS:
|
||||
return ("nisplus");
|
||||
case PAM_REP_NIS:
|
||||
return ("nis");
|
||||
case PAM_REP_FILES:
|
||||
return ("files");
|
||||
case PAM_REP_DEFAULT:
|
||||
return ("default");
|
||||
default:
|
||||
return ("bad repository");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints an error message if a ':' or a newline is found in the string.
|
||||
* A message is also printed if the input string is too long.
|
||||
* The password sources use :'s as seperators, and are not allowed in the "gcos"
|
||||
* field. Newlines serve as delimiters between users in the password source,
|
||||
* and so, those too, are checked for. (I don't think that it is possible to
|
||||
* type them in, but better safe than sorry)
|
||||
*
|
||||
* Returns '1' if a colon or newline is found or the input line is too long.
|
||||
*/
|
||||
static int
|
||||
illegal_input(pamh, input_str, nowarn)
|
||||
pam_handle_t *pamh;
|
||||
char *input_str;
|
||||
int nowarn;
|
||||
{
|
||||
char *ptr;
|
||||
int error_flag = 0;
|
||||
int length = (int)strlen(input_str);
|
||||
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
|
||||
|
||||
if (strchr(input_str, ':')) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 156,
|
||||
"':' is not allowed."));
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
error_flag = 1;
|
||||
}
|
||||
if (input_str[length-1] != '\n') {
|
||||
/* the newline and the '\0' eat up two characters */
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 157,
|
||||
"Maximum number of characters allowed is %d."),
|
||||
PAM_MAX_MSG_SIZE-2);
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
error_flag = 1;
|
||||
}
|
||||
/*
|
||||
* Delete newline by shortening string by 1.
|
||||
*/
|
||||
input_str[length-1] = '\0';
|
||||
/*
|
||||
* Don't allow control characters, etc in input string.
|
||||
*/
|
||||
for (ptr = input_str; *ptr != '\0'; ptr++) {
|
||||
/* 040 is ascii char "space" */
|
||||
if ((int) *ptr < 040) {
|
||||
if (!nowarn) {
|
||||
sprintf(messages[0], PAM_MSG(pamh, 158,
|
||||
"Control characters are not allowed."));
|
||||
(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
|
||||
1, messages, NULL);
|
||||
}
|
||||
error_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (error_flag);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* special_case returns true when either the default is accepted
|
||||
* (str = '\n'), or when 'none' is typed. 'none' is accepted in
|
||||
* either upper or lower case (or any combination). 'str' is modified
|
||||
* in these two cases.
|
||||
*/
|
||||
static int
|
||||
special_case(str, default_str)
|
||||
char *str, *default_str;
|
||||
{
|
||||
static char word[] = "none\n";
|
||||
char *ptr, *wordptr;
|
||||
|
||||
/*
|
||||
* If the default is accepted, then change the old string do the
|
||||
* default string.
|
||||
*/
|
||||
if (*str == '\n') {
|
||||
(void) strcpy(str, default_str);
|
||||
return (1);
|
||||
}
|
||||
/*
|
||||
* Check to see if str is 'none'. (It is questionable if case
|
||||
* insensitivity is worth the hair).
|
||||
*/
|
||||
wordptr = word - 1;
|
||||
for (ptr = str; *ptr != '\0'; ++ptr) {
|
||||
++wordptr;
|
||||
if (*wordptr == '\0') /* then words are different sizes */
|
||||
return (0);
|
||||
if (*ptr == *wordptr)
|
||||
continue;
|
||||
if (isupper(*ptr) && (tolower(*ptr) == *wordptr))
|
||||
continue;
|
||||
/*
|
||||
* At this point we have a mismatch, so we return
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* Make sure that words are the same length.
|
||||
*/
|
||||
if (*(wordptr+1) != '\0')
|
||||
return (0);
|
||||
/*
|
||||
* Change 'str' to be the null string
|
||||
*/
|
||||
*str = '\0';
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
copy_passwd_structs(struct passwd **pwd, struct passwd *local_pwd,
|
||||
struct spwd **shpwd, struct spwd *local_shpwd)
|
||||
{
|
||||
|
||||
/* copy the passwd information */
|
||||
if ((*pwd = (struct passwd *)
|
||||
calloc(1, sizeof (struct passwd))) == NULL)
|
||||
return (PAM_BUF_ERR);
|
||||
if (local_pwd->pw_name) {
|
||||
if (((*pwd)->pw_name = strdup(local_pwd->pw_name)) == NULL)
|
||||
goto out;
|
||||
}
|
||||
if (local_pwd->pw_passwd) {
|
||||
if (((*pwd)->pw_passwd = strdup(local_pwd->pw_passwd)) == NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
(*pwd)->pw_uid = local_pwd->pw_uid;
|
||||
(*pwd)->pw_gid = local_pwd->pw_gid;
|
||||
|
||||
if (local_pwd->pw_gecos) {
|
||||
if (((*pwd)->pw_gecos = strdup(local_pwd->pw_gecos)) == NULL)
|
||||
goto out;
|
||||
}
|
||||
if (local_pwd->pw_dir) {
|
||||
if (((*pwd)->pw_dir = strdup(local_pwd->pw_dir)) == NULL)
|
||||
goto out;
|
||||
}
|
||||
if (local_pwd->pw_shell) {
|
||||
if (((*pwd)->pw_shell = strdup(local_pwd->pw_shell)) == NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* copy the shadow passwd information */
|
||||
if ((*shpwd = (struct spwd *)
|
||||
calloc(1, sizeof (struct spwd))) == NULL)
|
||||
goto out;
|
||||
**shpwd = *local_shpwd;
|
||||
if (local_shpwd->sp_namp) {
|
||||
if (((*shpwd)->sp_namp = strdup(local_shpwd->sp_namp)) == NULL)
|
||||
goto out;
|
||||
}
|
||||
if (local_shpwd->sp_pwdp) {
|
||||
if (((*shpwd)->sp_pwdp = strdup(local_shpwd->sp_pwdp)) == NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
return (PAM_SUCCESS);
|
||||
out:
|
||||
free_passwd_structs(*pwd, *shpwd);
|
||||
return (PAM_BUF_ERR);
|
||||
}
|
||||
|
||||
void
|
||||
free_passwd_structs(struct passwd *pwd, struct spwd *shpwd)
|
||||
{
|
||||
if (pwd) {
|
||||
if (pwd->pw_name)
|
||||
free(pwd->pw_name);
|
||||
if (pwd->pw_passwd) {
|
||||
memset(pwd->pw_passwd, 0, strlen(pwd->pw_passwd));
|
||||
free(pwd->pw_passwd);
|
||||
}
|
||||
if (pwd->pw_gecos)
|
||||
free(pwd->pw_gecos);
|
||||
if (pwd->pw_dir)
|
||||
free(pwd->pw_dir);
|
||||
if (pwd->pw_shell)
|
||||
free(pwd->pw_shell);
|
||||
free(pwd);
|
||||
}
|
||||
|
||||
if (shpwd) {
|
||||
if (shpwd->sp_namp)
|
||||
free(shpwd->sp_namp);
|
||||
if (shpwd->sp_pwdp) {
|
||||
memset(shpwd->sp_pwdp, 0, strlen(shpwd->sp_pwdp));
|
||||
free(shpwd->sp_pwdp);
|
||||
}
|
||||
free(shpwd);
|
||||
}
|
||||
}
|
||||
68
cde/lib/pam/pam_modules/unix/yppasswdxdr.c
Normal file
68
cde/lib/pam/pam_modules/unix/yppasswdxdr.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/* $XConsortium: yppasswdxdr.c /main/2 1996/05/08 13:46:51 drk $
|
||||
*
|
||||
* (c) Copyright 1996 Digital Equipment Corporation.
|
||||
* (c) Copyright 1996 Hewlett-Packard Company.
|
||||
* (c) Copyright 1996 International Business Machines Corp.
|
||||
* (c) Copyright 1995,1996 Sun Microsystems, Inc.
|
||||
* (c) Copyright 1996 Novell, Inc.
|
||||
* (c) Copyright 1996 FUJITSU LIMITED.
|
||||
* (c) Copyright 1996 Hitachi.
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
** yppasswd utilies
|
||||
*******************************************************************************/
|
||||
|
||||
#if (PAM_NIS || PAM_NISPLUS)
|
||||
|
||||
#include "unix_headers.h"
|
||||
|
||||
bool_t
|
||||
xdr_passwd(xdrs, pw)
|
||||
XDR *xdrs;
|
||||
struct passwd *pw;
|
||||
{
|
||||
if (!xdr_wrapstring(xdrs, &pw->pw_name)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_wrapstring(xdrs, &pw->pw_passwd)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_uid_t(xdrs, &pw->pw_uid)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_gid_t(xdrs, (&pw->pw_gid))){
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_wrapstring(xdrs, &pw->pw_gecos)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_wrapstring(xdrs, &pw->pw_dir)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_wrapstring(xdrs, &pw->pw_shell)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_yppasswd(xdrs, yppw)
|
||||
XDR *xdrs;
|
||||
struct yppasswd *yppw;
|
||||
{
|
||||
if (!xdr_wrapstring(xdrs, &yppw->oldpass)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_passwd(xdrs, &yppw->newpw)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Some compilers complain about empty compilation modules. */
|
||||
static int dummy;
|
||||
|
||||
#endif /* PAM_NIS or PAM_NISPLUS */
|
||||
Reference in New Issue
Block a user