freebsd-dev/contrib/libpam/modules/pam_pwdb/pam_unix_acct.-c

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.
*/