unix_acct.c revision 36e852a172cba914383d7341c988128b2c667fbd
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <fcntl.h>
#include <stdlib.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <security/pam_impl.h>
#include <syslog.h>
#include <pwd.h>
#include <shadow.h>
#include <lastlog.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <libintl.h>
#include <signal.h>
#include <thread.h>
#include <synch.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <crypt.h>
#include <assert.h>
#include <deflt.h>
#include <libintl.h>
#include <passwdutil.h>
#define LOGINADMIN "/etc/default/login"
#define UNIX_AUTH_DATA "SUNW-UNIX-AUTH-DATA"
#define UNIX_AUTHTOK_DATA "SUNW-UNIX-AUTHTOK-DATA"
/*
* Function Declarations
*/
extern void setusershell();
extern int _nfssys(int, void *);
typedef struct _unix_authtok_data_ {
int age_status;
/*ARGSUSED*/
static void
void *data,
int pam_status)
{
}
/*
* check_for_login_inactivity - Check for login inactivity
*
*/
static int
{
int fdl;
int retval;
/*
* Read the last login (ll) time
*/
"pam_unix_acct: pam_sm_acct_mgmt: "
"can't obtain last login info on uid %d "
"(uid too large)", pw_uid);
return (0);
}
/* Check for login inactivity */
/*
* account inactive too long.
* and no update password set
* and no last pwd change date in shadow file
* and last pwd change more than inactive time
* then account inactive too long and no access.
*/
< DAY_NOW) &&
/*
* Account inactive for too long
*/
return (1);
}
}
}
return (0);
}
/*
* new_password_check()
*
* check to see if the user needs to change their password
*/
static int
int flags;
{
/*
* 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) {
return (PAM_NEW_AUTHTOK_REQD);
}
}
}
return (PAM_SUCCESS);
}
/*
* perform_passwd_aging_check
* - Check for password exipration.
*/
static int
int flags)
{
int idledays = -1;
char *ptr;
void *defp;
}
/*
* if (sp_lstchg == 0), the administrator has forced the
*/
return (PAM_NEW_AUTHTOK_REQD);
/* If password aging is disabled (or min>max), all is well */
return (PAM_SUCCESS);
/* Password aging is enabled. See if the password has aged */
return (PAM_SUCCESS);
/* Password has aged. Has it aged more than idledays ? */
if (idledays < 0) /* IDLEWEEKS not configured */
return (PAM_NEW_AUTHTOK_REQD);
/* idledays is configured */
return (PAM_NEW_AUTHTOK_REQD);
/* password has aged more that allowed for by IDLEWEEKS */
if (!(flags & PAM_SILENT)) {
"Your password has been expired for too long."),
sizeof (messages[0]));
"Please contact the system administrator."),
sizeof (messages[0]));
NULL);
}
return (PAM_AUTHTOK_EXPIRED);
}
/*
* warn_user_passwd_will_expire - warn the user when the password will
* expire.
*/
static void
{
if (days <= 0)
sizeof (messages[0]),
"Your password will expire within 24 hours."));
else if (days == 1)
sizeof (messages[0]),
"Your password will expire in 1 day."));
else
sizeof (messages[0]),
"Your password will expire in %d days."),
(int)days);
NULL);
}
}
/*
* pam_sm_acct_mgmt - main account managment routine.
* Returns: module error or specific error on failure
*/
int
{
char *repository_name = NULL;
char *user;
int error = PAM_ACCT_EXPIRED;
int result;
int i;
int debug = 0;
int server_policy = 0;
-1, -1, -1, -1, -1, -1, 0};
for (i = 0; i < argc; i++) {
debug = 1;
server_policy = 1;
} else {
"ACCOUNT:pam_sm_acct_mgmt: illegal option %s",
argv[i]);
}
}
if (debug)
"pam_unix_account: entering pam_sm_acct_mgmt()");
!= PAM_SUCCESS)
goto out;
goto out;
} else
!= PAM_SUCCESS)
goto out;
} else {
error = PAM_BUF_ERR;
goto out;
}
}
/*
* First get the password information
*/
if (result == PWU_NOT_FOUND) {
goto out;
} else if (result == PWU_DENIED) {
goto out;
error = PAM_BUF_ERR;
goto out;
} else if (result != PWU_SUCCESS) {
goto out;
} else {
}
/*
* if repository is not files|nis, and user wants server_policy,
* we don't care about aging and hence return PAM_IGNORE
*/
if (server_policy &&
error = PAM_IGNORE;
goto out;
}
/*
* Now get the aging information
*/
if (result == PWU_SUCCESS) {
}
if (debug) {
char *pw = "Unix PW";
pw = "NULL";
sizeof (LOCKSTRING) - 1) == 0)
pw = LOCKSTRING;
if (result == PWU_DENIED) {
"pam_unix_account: %s: permission denied "
"to access password aging information. "
"Using defaults.", user);
}
"%s Policy:Unix, pw=%s, lstchg=%d, min=%d, max=%d, "
"warn=%d, inact=%d, expire=%d",
}
if (pwu_rep != PWU_DEFAULT_REP) {
}
if (result == PWU_NOT_FOUND) {
goto out;
error = PAM_BUF_ERR;
goto out;
goto out;
}
/*
* Check for locked account
*/
char *service;
"pam_unix_account: %s attempting to validate locked "
"account %s from %s",
goto out;
}
/*
* Check for NULL password and, if so, see if such is allowed
*/
(flags & PAM_DISALLOW_NULL_AUTHTOK) != 0) {
char *service;
"pam_unix_account: %s: empty password not allowed for "
goto out;
}
/*
* Check for account expiration
*/
goto out;
}
/*
* Check for excessive login account inactivity
*/
goto out;
}
/*
* Check to see if the user needs to change their password
*/
goto out;
}
/*
* Check to make sure password aging information is okay
*/
!= PAM_SUCCESS) {
goto out;
}
/*
* Finally, warn the user if their password is about to expire.
*/
if (!(flags & PAM_SILENT)) {
}
/*
* All done, return Success
*/
error = PAM_SUCCESS;
out:
{
int pam_res;
if (debug) {
"pam_unix_account: %s: %s",
}
if (repository_name)
if (pwu_rep != PWU_DEFAULT_REP)
}
/* store the password aging status in the pam handle */
(const void **)&authtok_data);
sizeof (unix_authtok_data))) == NULL) {
return (PAM_BUF_ERR);
}
if (pam_res == PAM_SUCCESS)
sizeof (unix_authtok_data));
!= PAM_SUCCESS) {
return (PAM_SERVICE_ERR);
}
}
return (error);
}