293 lines
8.3 KiB
Plaintext
293 lines
8.3 KiB
Plaintext
|
/*
|
||
|
* $Id: pam_unix_acct.-c,v 1.6 1997/01/04 20:37:15 morgan Exp morgan $
|
||
|
*
|
||
|
* $Log: pam_unix_acct.-c,v $
|
||
|
* Revision 1.6 1997/01/04 20:37:15 morgan
|
||
|
* extra debugging
|
||
|
*
|
||
|
* Revision 1.5 1996/12/01 03:05:54 morgan
|
||
|
* debugging with _pam_macros.h
|
||
|
*
|
||
|
* Revision 1.4 1996/11/10 21:03:57 morgan
|
||
|
* pwdb conversion
|
||
|
*
|
||
|
* Revision 1.3 1996/09/05 06:45:45 morgan
|
||
|
* tidied shadow acct management
|
||
|
*
|
||
|
* Revision 1.2 1996/09/01 01:13:14 morgan
|
||
|
* Cristian Gafton's patches
|
||
|
*
|
||
|
* Revision 1.1 1996/08/29 13:27:51 morgan
|
||
|
* Initial revision
|
||
|
*
|
||
|
*
|
||
|
* See end of file for copyright information
|
||
|
*/
|
||
|
|
||
|
static const char rcsid_acct[] =
|
||
|
"$Id: pam_unix_acct.-c,v 1.6 1997/01/04 20:37:15 morgan Exp morgan $\n"
|
||
|
" - PAM_PWDB account management <gafton@redhat.com>";
|
||
|
|
||
|
/* the shadow suite has accout managment.. */
|
||
|
|
||
|
static int _shadow_acct_mgmt_exp(pam_handle_t *pamh, unsigned int ctrl,
|
||
|
const struct pwdb *pw, const char *uname)
|
||
|
{
|
||
|
const struct pwdb_entry *pwe = NULL;
|
||
|
time_t curdays;
|
||
|
int last_change, max_change;
|
||
|
int retval;
|
||
|
|
||
|
D(("called."));
|
||
|
|
||
|
/* Now start the checks */
|
||
|
|
||
|
curdays = time(NULL)/(60*60*24); /* today */
|
||
|
|
||
|
/* First: has account expired ? (CG)
|
||
|
* - expire < curdays
|
||
|
* - or (last_change + max_change + defer_change) < curdays
|
||
|
* - in both cases, deny access
|
||
|
*/
|
||
|
|
||
|
D(("pwdb_get_entry"));
|
||
|
retval = pwdb_get_entry(pw, "expire", &pwe);
|
||
|
if (retval == PWDB_SUCCESS) {
|
||
|
int expire;
|
||
|
|
||
|
expire = *( (const int *) pwe->value );
|
||
|
(void) pwdb_entry_delete(&pwe); /* no longer needed */
|
||
|
|
||
|
if ((curdays > expire) && (expire > 0)) {
|
||
|
|
||
|
_log_err(LOG_NOTICE
|
||
|
, "acct: account %s has expired (account expired)"
|
||
|
, uname);
|
||
|
make_remark(pamh, ctrl, PAM_ERROR_MSG
|
||
|
, "Your account has expired; "
|
||
|
"please contact your system administrator");
|
||
|
|
||
|
D(("account expired"));
|
||
|
return PAM_ACCT_EXPIRED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
D(("pwdb_get_entry"));
|
||
|
retval = pwdb_get_entry(pw, "last_change", &pwe);
|
||
|
if ( retval == PWDB_SUCCESS ) {
|
||
|
last_change = *( (const int *) pwe->value );
|
||
|
} else {
|
||
|
last_change = curdays;
|
||
|
}
|
||
|
(void) pwdb_entry_delete(&pwe);
|
||
|
|
||
|
D(("pwdb_get_entry"));
|
||
|
retval = pwdb_get_entry(pw, "max_change", &pwe);
|
||
|
if ( retval == PWDB_SUCCESS ) {
|
||
|
max_change = *( (const int *) pwe->value );
|
||
|
} else {
|
||
|
max_change = -1;
|
||
|
}
|
||
|
(void) pwdb_entry_delete(&pwe);
|
||
|
|
||
|
D(("pwdb_get_entry"));
|
||
|
retval = pwdb_get_entry(pw, "defer_change", &pwe);
|
||
|
if (retval == PWDB_SUCCESS) {
|
||
|
int defer_change;
|
||
|
|
||
|
defer_change = *( (const int *) pwe->value );
|
||
|
(void) pwdb_entry_delete(&pwe);
|
||
|
|
||
|
if ((curdays > (last_change + max_change + defer_change))
|
||
|
&& (max_change != -1) && (defer_change != -1)
|
||
|
&& (last_change > 0)) {
|
||
|
|
||
|
if ( on(UNIX_DEBUG, ctrl) ) {
|
||
|
_log_err(LOG_NOTICE, "acct: account %s has expired "
|
||
|
"(failed to change password)", uname);
|
||
|
}
|
||
|
make_remark(pamh, ctrl, PAM_ERROR_MSG
|
||
|
, "Your password has expired; "
|
||
|
"please see your system administrator");
|
||
|
|
||
|
D(("account expired2"));
|
||
|
return PAM_ACCT_EXPIRED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Now test if the password is expired, but the user still can
|
||
|
* change their password. (CG)
|
||
|
* - last_change = 0
|
||
|
* - last_change + max_change < curdays
|
||
|
*/
|
||
|
|
||
|
D(("when was the last change"));
|
||
|
if (last_change == 0) {
|
||
|
|
||
|
if ( on(UNIX_DEBUG, ctrl) ) {
|
||
|
_log_err(LOG_NOTICE
|
||
|
, "acct: expired password for user %s (root enforced)"
|
||
|
, uname);
|
||
|
}
|
||
|
make_remark(pamh, ctrl, PAM_ERROR_MSG
|
||
|
, "You are required to change your password immediately"
|
||
|
);
|
||
|
|
||
|
D(("need a new password"));
|
||
|
return PAM_NEW_AUTHTOK_REQD;
|
||
|
}
|
||
|
|
||
|
if (((last_change + max_change) < curdays) &&
|
||
|
(max_change < 99999) && (max_change > 0)) {
|
||
|
|
||
|
if ( on(UNIX_DEBUG, ctrl) ) {
|
||
|
_log_err(LOG_DEBUG
|
||
|
, "acct: expired password for user %s (password aged)"
|
||
|
, uname);
|
||
|
}
|
||
|
make_remark(pamh, ctrl, PAM_ERROR_MSG
|
||
|
, "Your password has expired; please change it!");
|
||
|
|
||
|
D(("need a new password 2"));
|
||
|
return PAM_NEW_AUTHTOK_REQD;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Now test if the password is about to expire (CG)
|
||
|
* - last_change + max_change - curdays <= warn_change
|
||
|
*/
|
||
|
|
||
|
retval = pwdb_get_entry(pw, "warn_change", &pwe);
|
||
|
if ( retval == PWDB_SUCCESS ) {
|
||
|
int warn_days, daysleft;
|
||
|
|
||
|
daysleft = last_change + max_change - curdays;
|
||
|
warn_days = *((const int *) pwe->value);
|
||
|
(void) pwdb_entry_delete(&pwe);
|
||
|
|
||
|
if ((daysleft <= warn_days) && (warn_days > 0)) {
|
||
|
char *s;
|
||
|
|
||
|
if ( on(UNIX_DEBUG, ctrl) ) {
|
||
|
_log_err(LOG_DEBUG
|
||
|
, "acct: password for user %s will expire in %d days"
|
||
|
, uname, daysleft);
|
||
|
}
|
||
|
|
||
|
#define LocalComment "Warning: your password will expire in %d day%s"
|
||
|
if ((s = (char *) malloc(30+sizeof(LocalComment))) == NULL) {
|
||
|
_log_err(LOG_CRIT, "malloc failure in " __FILE__);
|
||
|
retval = PAM_BUF_ERR;
|
||
|
} else {
|
||
|
|
||
|
sprintf(s, LocalComment, daysleft, daysleft == 1 ? "":"s");
|
||
|
|
||
|
make_remark(pamh, ctrl, PAM_TEXT_INFO, s);
|
||
|
free(s);
|
||
|
}
|
||
|
#undef LocalComment
|
||
|
}
|
||
|
} else {
|
||
|
retval = PAM_SUCCESS;
|
||
|
}
|
||
|
|
||
|
D(("all done"));
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* this function checks for the account details. The user may not be
|
||
|
* permitted to log in at this time etc.. Within the context of
|
||
|
* vanilla Unix, this function simply does nothing. The shadow suite
|
||
|
* added password/account expiry, but PWDB takes care of this
|
||
|
* transparently.
|
||
|
*/
|
||
|
|
||
|
static int _unix_acct_mgmt(pam_handle_t *pamh, unsigned int ctrl)
|
||
|
{
|
||
|
const struct pwdb *pw = NULL;
|
||
|
|
||
|
char *uname=NULL;
|
||
|
int retval;
|
||
|
|
||
|
D(("called."));
|
||
|
|
||
|
/* identify user */
|
||
|
|
||
|
retval = pam_get_item(pamh,PAM_USER,(const void **)&uname);
|
||
|
D(("user = `%s'", uname));
|
||
|
if (retval != PAM_SUCCESS || uname == NULL) {
|
||
|
_log_err(LOG_ALERT
|
||
|
, "acct; could not identify user (from uid=%d)"
|
||
|
, getuid());
|
||
|
return PAM_USER_UNKNOWN;
|
||
|
}
|
||
|
|
||
|
/* get database information for user */
|
||
|
|
||
|
retval = pwdb_locate("user", PWDB_DEFAULT, uname, PWDB_ID_UNKNOWN, &pw);
|
||
|
if (retval != PWDB_SUCCESS || pw == NULL) {
|
||
|
|
||
|
_log_err(LOG_ALERT, "acct; %s (%s from uid=%d)"
|
||
|
, pwdb_strerror(retval), uname, getuid());
|
||
|
if ( pw ) {
|
||
|
(void) pwdb_delete(&pw);
|
||
|
}
|
||
|
return PAM_USER_UNKNOWN;
|
||
|
}
|
||
|
|
||
|
/* now check the user's times etc.. */
|
||
|
|
||
|
retval = _shadow_acct_mgmt_exp(pamh, ctrl, pw, uname);
|
||
|
if (retval != PAM_SUCCESS) {
|
||
|
_log_err(LOG_NOTICE, "expiry check failed for '%s'", uname);
|
||
|
}
|
||
|
|
||
|
/* Done with pw */
|
||
|
|
||
|
(void) pwdb_delete(&pw);
|
||
|
|
||
|
/* all done */
|
||
|
|
||
|
D(("done."));
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Copyright (c) Elliot Lee, 1996.
|
||
|
* Copyright (c) Andrew Morgan <morgan@parc.power.net> 1996.
|
||
|
* Copyright (c) Cristian Gafton <gafton@redhat.com> 1996.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, and the entire permission notice in its entirety,
|
||
|
* including the disclaimer of warranties.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
* 3. The name of the author may not be used to endorse or promote
|
||
|
* products derived from this software without specific prior
|
||
|
* written permission.
|
||
|
*
|
||
|
* ALTERNATIVELY, this product may be distributed under the terms of
|
||
|
* the GNU Public License, in which case the provisions of the GPL are
|
||
|
* required INSTEAD OF the above restrictions. (This clause is
|
||
|
* necessary due to a potential bad interaction between the GPL and
|
||
|
* the restrictions contained in a BSD-style copyright.)
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|