diff options
Diffstat (limited to 'modules/pam_pwdb/pam_unix_acct.-c')
-rw-r--r-- | modules/pam_pwdb/pam_unix_acct.-c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/modules/pam_pwdb/pam_unix_acct.-c b/modules/pam_pwdb/pam_unix_acct.-c new file mode 100644 index 00000000..16869054 --- /dev/null +++ b/modules/pam_pwdb/pam_unix_acct.-c @@ -0,0 +1,298 @@ +/* + * $Id$ + * + * $Log$ + * Revision 1.1 2000/06/20 22:11:49 agmorgan + * Initial revision + * + * Revision 1.1.1.1 1998/07/12 05:17:17 morgan + * Linux PAM sources pre-0.66 + * + * 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$\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. + */ |