832 lines
20 KiB
C
832 lines
20 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $XConsortium: validate.c /main/4 1995/10/27 16:19:47 rswiston $ */
|
|
/************************************<+>*************************************
|
|
****************************************************************************
|
|
**
|
|
** File: validate.c
|
|
**
|
|
** Project: HP Visual User Environment (DT)
|
|
**
|
|
** Description: Dtgreet BLS user authentication routines
|
|
**
|
|
** These routines validate the user; checking name, password,
|
|
** number of users on the system, password aging, etc.
|
|
**
|
|
**
|
|
** (c) Copyright 1987, 1988, 1989 by Hewlett-Packard Company
|
|
**
|
|
**
|
|
** Conditional compiles:
|
|
**
|
|
** OSMAJORVERSION < 8
|
|
** HP-UX 7.0/7.03 restricted license counting algorithms
|
|
** are used. Otherwise HP-UX 8.0 and beyond is used
|
|
**
|
|
** BLS HP BLS B1 simple authentication.
|
|
**
|
|
** __hpux HP-UX OS only
|
|
**
|
|
****************************************************************************
|
|
************************************<+>*************************************/
|
|
|
|
#ifdef BLS
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Includes & Defines
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <pwd.h>
|
|
|
|
#include "../vg.h"
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* HP-UX BLS authentication routines
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include <sys/param.h> /* for MAXUID macro */
|
|
#include <sys/types.h>
|
|
#include <sys/utsname.h>
|
|
#include <string.h>
|
|
#include <utmp.h>
|
|
#include <time.h>
|
|
#include <grp.h>
|
|
|
|
|
|
/* BLS only headers */
|
|
# include <sys/security.h>
|
|
# include <prot.h>
|
|
# include "bls.h"
|
|
|
|
|
|
#define how_to_count ut_exit.e_exit
|
|
|
|
#ifdef __hp9000s300
|
|
static int num_users[] = { 2, 32767 };
|
|
# define MIN_VERSION 'A'
|
|
# define UNLIMITED 'B'
|
|
#else
|
|
static int num_users[] = { 2, 16, 32, 64 , 8 };
|
|
# define MIN_VERSION 'A'
|
|
# define UNLIMITED 'U'
|
|
#endif
|
|
|
|
/* Maximum number of users allowed with restricted license */
|
|
#if OSMAJORVERSION < 8
|
|
# define MAX_STRICT_USERS 2
|
|
#else
|
|
# define MAX_STRICT_USERS 8
|
|
#endif
|
|
|
|
#define NUM_VERSIONS (sizeof(num_users)/sizeof(num_users[0])) - 1
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* External declarations
|
|
*
|
|
***************************************************************************/
|
|
|
|
extern Widget focusWidget; /* login or password text field */
|
|
|
|
extern long groups[NGROUPS];
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Procedure declarations
|
|
*
|
|
***************************************************************************/
|
|
|
|
static int CheckPassword( char *name, char *passwd );
|
|
static int CountUsers( int added_users) ;
|
|
static int CountUsersStrict( char *new_user) ;
|
|
static void WriteBtmp( char *name) ;
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Global variables
|
|
*
|
|
***************************************************************************/
|
|
|
|
/* BLS only data */
|
|
struct pr_passwd *b1_pwd;
|
|
struct verify_info verify_data;
|
|
struct verify_info *verify = &verify_data;
|
|
struct greet_info greet_data;
|
|
struct greet_info *greet = &greet_data;
|
|
static int UserHasPassword = 1;
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* CountUsers
|
|
*
|
|
* see if new user has exceeded the maximum.
|
|
***************************************************************************/
|
|
|
|
#define NCOUNT 16
|
|
|
|
static int
|
|
CountUsers( int added_users )
|
|
{
|
|
int count[NCOUNT], nusers, i;
|
|
struct utmp *entry;
|
|
|
|
for (i=0; i<NCOUNT; i++)
|
|
count[i] = 0;
|
|
|
|
count[added_users]++;
|
|
|
|
while ( (entry = getutent()) != NULL) {
|
|
if (entry->ut_type == USER_PROCESS) {
|
|
i = entry->how_to_count;
|
|
if (i < 0 || i >= NCOUNT)
|
|
i = 1; /* if out of range, then count */
|
|
/* as ordinary user */
|
|
count[i]++;
|
|
}
|
|
}
|
|
endutent();
|
|
|
|
/*
|
|
* KEY:
|
|
* [0] does not count at all
|
|
* [1] counts as real user
|
|
* [2] logins via a pty which have not gone trough login. These
|
|
* collectively count as 1 user IF count[3] is 0, otherwise,
|
|
* they are not counted. Starting with HP-UX 8.0 they are
|
|
* no longer counted at all.
|
|
* [3] logins via a pty which have been logged through login (i.e.
|
|
* rlogin and telnet). these count as 1 "real" user per
|
|
* unique user name.
|
|
* [4-15] may be used for groups of users which collectively
|
|
* count as 1
|
|
*/
|
|
nusers = count[1];
|
|
|
|
#if OSMAJORVERSION < 8
|
|
for (i=2; i<NCOUNT; i++)
|
|
#else
|
|
for (i=3; i<NCOUNT; i++)
|
|
#endif
|
|
if (count[i] > 0)
|
|
nusers++;
|
|
|
|
return(nusers);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* CountUsersStrict
|
|
*
|
|
* see if new user has exceeded the maximum.
|
|
***************************************************************************/
|
|
|
|
static int
|
|
CountUsersStrict( char *new_user )
|
|
{
|
|
char pty_users[MAX_STRICT_USERS][8];
|
|
int count[NCOUNT], nusers, i, cnt, pty_off = -1, uname_off;
|
|
struct utmp *entry;
|
|
|
|
/*
|
|
* Initialize count array...
|
|
*/
|
|
for (i = 0; i < NCOUNT; i++)
|
|
count[i] = 0;
|
|
|
|
/*
|
|
* Add in the new user (we know it's not a pty)...
|
|
*/
|
|
count[1]++;
|
|
|
|
while ( (entry = getutent()) != NULL ) {
|
|
if (entry->ut_type == USER_PROCESS) {
|
|
i = entry->how_to_count;
|
|
|
|
/* if out of range, then count as ordinary user logged in
|
|
via a tty */
|
|
if (i == 1 || (i < 0 || i >= NCOUNT))
|
|
count[1]++;
|
|
/* See if it is a pty login granted by login program */
|
|
else if (i == 3) {
|
|
count[3]++;
|
|
/* See if user is already logged in via login pty */
|
|
uname_off = -1;
|
|
for (cnt = 0; cnt <= pty_off; cnt++)
|
|
if (strncmp(pty_users[cnt], entry->ut_user, 8) == 0)
|
|
uname_off = cnt;
|
|
|
|
if (uname_off == -1) { /* user is not logged in via pty yet */
|
|
|
|
if (pty_off >= MAX_STRICT_USERS) /* cannot add any
|
|
more users */
|
|
return(MAX_STRICT_USERS + 1);
|
|
/* add the user name to the array of pty users */
|
|
else
|
|
strncpy(pty_users[++pty_off], entry->ut_user, 8);
|
|
}
|
|
} /* end if (i == 3) */
|
|
else
|
|
count[i]++;
|
|
} /* end if entry->ut_type == USER_PROCESS */
|
|
} /* end while (entry = getutent()) */
|
|
|
|
endutent();
|
|
/*
|
|
* KEY:
|
|
* [0] does not count at all
|
|
* [1] counts as "real" user
|
|
* [2] logins via a pty which have not gone trough login. These
|
|
* collectively count as 1 user IF count[3] is 0, otherwise,
|
|
* they are not counted. Starting with HP-UX 8.0 they are
|
|
* no longer counted at all.
|
|
* [3] logins via a pty which have been logged through login (i.e.
|
|
* rlogin and telnet). these count as 1 "real" user per
|
|
* unique user name.
|
|
* [4-15] may be used for groups of users which collectively count
|
|
* as 1
|
|
*/
|
|
|
|
nusers = pty_off + 1 + count[1]; /* Current number of users is sum of
|
|
users logged in via tty + the
|
|
number of unique users logged in
|
|
via pty which have gone through
|
|
login */
|
|
|
|
#if OSMAJORVERSION < 8
|
|
if ((count[3] == 0) && (count[2] != 0))
|
|
nusers++; /* Add 1 user for all pty logins IF
|
|
none of pty logins have been
|
|
granted by the login program */
|
|
#else
|
|
/*
|
|
* Don't count any hpterm logins (exit status of 2). We already
|
|
* counted all pty logins granted by the login program.
|
|
*/
|
|
#endif
|
|
|
|
for (i = 4; i < NCOUNT; i++)
|
|
if (count[i] > 0)
|
|
nusers++;
|
|
return(nusers);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* CheckPassword
|
|
*
|
|
* Check validity of user password.
|
|
*
|
|
***************************************************************************/
|
|
|
|
static int
|
|
CheckPassword( char *name, char *passwd )
|
|
{
|
|
|
|
char *crypt();
|
|
struct passwd *p;
|
|
char *reason;
|
|
|
|
/*
|
|
* HP BLS B1 password authentication...
|
|
*/
|
|
|
|
if ( ISSECURE ) {
|
|
b1_pwd = getprpwnam(name);
|
|
|
|
if ( b1_pwd == NULL || strlen(name) == 0 ) {
|
|
Debug("unknown user '%s'\n", name);
|
|
audit_login((struct pr_passwd *)0, (struct passwd *)0,
|
|
dpyinfo.name, "No entry in protected password db",
|
|
ES_LOGIN_FAILED);
|
|
return(FALSE);
|
|
}
|
|
|
|
/*
|
|
* look up user's regular account information...
|
|
*/
|
|
|
|
p = getpwnam(name);
|
|
|
|
if ( p == NULL || strlen(name) == 0 ) {
|
|
Debug("unknown user '%s'\n", name);
|
|
audit_login((struct pr_passwd *)0, (struct passwd *)0,
|
|
dpyinfo.name, "No entry in password file",
|
|
ES_LOGIN_FAILED);
|
|
return(FALSE);
|
|
}
|
|
|
|
/* verify_info has become a catchall for info needed later */
|
|
verify->user_name = name;
|
|
verify->prpwd = b1_pwd;
|
|
verify->pwd = p;
|
|
strncpy(verify->terminal, dpyinfo.name, 15);
|
|
verify->terminal[15]='\0';
|
|
|
|
}
|
|
|
|
Debug("Verify %s \n",name);
|
|
|
|
/* if the password doesn't exists, we can't check it, but
|
|
* the user will be forced to change it later */
|
|
if ( (UserHasPassword = password_exists(verify)) != 0 )
|
|
if ( strcmp(bigcrypt(passwd,b1_pwd->ufld.fd_encrypt),
|
|
b1_pwd->ufld.fd_encrypt) ) {
|
|
Debug("verify failed\n");
|
|
audit_login( b1_pwd, p ,dpyinfo.name,
|
|
"Password incorrect",
|
|
ES_LOGIN_FAILED);
|
|
return(FALSE);
|
|
} else {
|
|
Debug ("username/password verify succeeded\n");
|
|
return(TRUE);
|
|
}
|
|
/*
|
|
* all password checks failed...
|
|
*/
|
|
|
|
return (FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* BLS_Verify
|
|
*
|
|
* verify the user
|
|
*
|
|
* return codes indicate authentication results.
|
|
***************************************************************************/
|
|
|
|
#define MAXATTEMPTS 3
|
|
|
|
static struct passwd nouser = {"", "nope"}; /* invalid user password struct */
|
|
|
|
int
|
|
BLS_Verify( char *name, char *passwd )
|
|
{
|
|
|
|
static int login_attempts = 0; /* # failed authentications */
|
|
|
|
struct passwd *p; /* password structure */
|
|
struct pr_passwd *prpwd;
|
|
|
|
struct utsname utsnam;
|
|
int n;
|
|
int uid;
|
|
|
|
/*
|
|
* Desparate maneuvre to give dtgreet the privledges it needs
|
|
*/
|
|
if ( login_attempts == 0 ) {
|
|
Debug("Setting luid for dtgreet\n");
|
|
if ( getluid() == -1 )
|
|
setluid(getuid());
|
|
}
|
|
|
|
/*
|
|
* validate password...
|
|
*/
|
|
|
|
if ( CheckPassword(name, passwd) == FALSE) {
|
|
p = verify->pwd;
|
|
if ( focusWidget == passwd_text ) {
|
|
|
|
WriteBtmp(name);
|
|
|
|
if ((++login_attempts % MAXATTEMPTS) == 0 ) {
|
|
|
|
if (p->pw_name == NULL )
|
|
p = &nouser;
|
|
|
|
audit_login( b1_pwd, p ,dpyinfo.name,
|
|
"Failed login(bailout)",
|
|
ES_LOGIN_FAILED);
|
|
}
|
|
|
|
} else if ( !UserHasPassword ) {
|
|
/*
|
|
* The user has not password -- this must be the initial login for this
|
|
* user. Treat it like an expired password. This should invoke the
|
|
* password program on behalf of the user.
|
|
*/
|
|
UserHasPassword = 1;
|
|
return VF_PASSWD_AGED;
|
|
}
|
|
|
|
return(VF_INVALID);
|
|
}
|
|
prpwd = verify->prpwd;
|
|
p = verify->pwd;
|
|
|
|
/* check that the uid of both passwd and pr_passwd struct's agree */
|
|
uid = p->pw_uid;
|
|
if (uid != prpwd->ufld.fd_uid) {
|
|
audit_login(prpwd, p, verify->terminal,
|
|
"User id's inconsistent across password database\n",
|
|
ES_LOGIN_FAILED);
|
|
Debug("login failed - uid's do not match\n");
|
|
return VF_BAD_UID;
|
|
}
|
|
verify->uid = uid;
|
|
|
|
/* check if user's account is locked
|
|
* This can be by dead password (lifetime exceeded),
|
|
* fd_lock is set, or fd_max_tries is exceeded.
|
|
* locked_out is from libsec, but is poorly documented.
|
|
*/
|
|
if (locked_out(prpwd)) {
|
|
Debug("Account locked\n");
|
|
audit_login(prpwd, p, verify->terminal,
|
|
"Account locked", ES_LOGIN_FAILED);
|
|
return VF_INVALID;
|
|
}
|
|
/* can user log in at this time?
|
|
* time_lock is in libsec, but poorly documented
|
|
*/
|
|
if (time_lock(prpwd)) {
|
|
Debug("Account time-locked\n");
|
|
audit_login(prpwd, p, verify->terminal,
|
|
"Account time-locked", ES_LOGIN_FAILED);
|
|
return VF_INVALID;
|
|
}
|
|
|
|
/****************************************************
|
|
xdm checks the security level here using
|
|
verify_sec_user
|
|
We do it later from the dtgreet callback rountine
|
|
VerifySensitivityLevel()
|
|
****************************************************/
|
|
|
|
#if 0
|
|
/*
|
|
* check restricted license...
|
|
*
|
|
* Note: This only applies to local displays. Foreign displays
|
|
* (i.e. X-terminals) apparently do not count.
|
|
*/
|
|
|
|
/* Get the version info via uname. If it doesn't look right,
|
|
* assume the smallest user configuration
|
|
*/
|
|
|
|
if (getenv(LOCATION) != NULL) {
|
|
if (uname(&utsnam) < 0)
|
|
utsnam.version[0] = MIN_VERSION;
|
|
|
|
/*
|
|
* Mappings:
|
|
* 834 -> 834
|
|
* 844 -> 844
|
|
* 836 -> 635
|
|
* 846 -> 645
|
|
* 843 -> 642
|
|
* 853 -> 652
|
|
*/
|
|
|
|
if ((!strncmp(utsnam.machine, "9000/834", UTSLEN)) ||
|
|
(!strncmp(utsnam.machine, "9000/844", UTSLEN)) ||
|
|
(!strncmp(utsnam.machine, "9000/836", UTSLEN)) ||
|
|
(!strncmp(utsnam.machine, "9000/846", UTSLEN)) ||
|
|
(!strncmp(utsnam.machine, "9000/843", UTSLEN)) ||
|
|
(!strncmp(utsnam.machine, "9000/853", UTSLEN))) {
|
|
|
|
/* strict_count = 1;*/
|
|
if (CountUsersStrict(name) > MAX_STRICT_USERS) {
|
|
audit_login( b1_pwd, p ,dpyinfo.name,
|
|
"Attempted to login - too many users on the system",
|
|
ES_LOGIN_FAILED);
|
|
return(VF_MAX_USERS);
|
|
}
|
|
}
|
|
else {
|
|
if (utsnam.version[0] != UNLIMITED) {
|
|
if ((utsnam.version[0]-'A' < 0) ||
|
|
(utsnam.version[0]-'A' > NUM_VERSIONS))
|
|
utsnam.version[0] = MIN_VERSION;
|
|
|
|
n = (int) utsnam.version[0] - 'A';
|
|
if (CountUsers(1) > num_users[n]) {
|
|
audit_login( b1_pwd, p ,dpyinfo.name,
|
|
"Attempted to login - too many users on the system",
|
|
ES_LOGIN_FAILED);
|
|
return(VF_MAX_USERS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* 0 */
|
|
|
|
/*
|
|
* check password aging...
|
|
*/
|
|
|
|
if ( passwordExpired(verify)) {
|
|
audit_login( b1_pwd, p ,dpyinfo.name,
|
|
"Password expired",
|
|
ES_LOGIN_FAILED);
|
|
return(VF_PASSWD_AGED);
|
|
}
|
|
|
|
|
|
/*
|
|
* verify home directory exists...
|
|
*/
|
|
|
|
if(chdir(p->pw_dir) < 0) {
|
|
Debug("Attempted to login -- no home directory\n");
|
|
audit_login( b1_pwd, p ,dpyinfo.name,
|
|
" Attempted to login - no home directory",
|
|
ES_LOGIN_FAILED);
|
|
return(VF_HOME);
|
|
}
|
|
|
|
/*
|
|
* validate uid and gid...
|
|
*/
|
|
#ifdef NGROUPS
|
|
getGroups(greet->name, verify, p->pw_gid);
|
|
#else
|
|
verify->gid = pwd->pw_gid;
|
|
|
|
if ((p->pw_gid < 0) ||
|
|
(p->pw_gid > MAXUID) ||
|
|
(setgid(p->pw_gid) == -1)) {
|
|
|
|
Debug("Attempted to login -- bad group id");
|
|
audit_login( b1_pwd, p ,dpyinfo.name,
|
|
"Attempted to login - bad group id",
|
|
ES_LOGIN_FAILED);
|
|
return(VF_BAD_GID);
|
|
}
|
|
#endif /* NGROUPS */
|
|
|
|
if ((p->pw_uid < 0) ||
|
|
(p->pw_uid > MAXUID) ||
|
|
(setresuid(p->pw_uid, p->pw_uid, 0) == -1)) {
|
|
|
|
Debug("Attempted to login -- bad user id\n");
|
|
audit_login( b1_pwd, p ,dpyinfo.name,
|
|
"Attempted to login - bad user id",
|
|
ES_LOGIN_FAILED);
|
|
return(VF_BAD_UID);
|
|
}
|
|
|
|
|
|
/*
|
|
* verify ok...
|
|
*/
|
|
|
|
Debug ("Successful login\n");
|
|
audit_login( b1_pwd, p ,dpyinfo.name,
|
|
"Successful login",
|
|
ES_LOGIN_REMOTE);
|
|
return(VF_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* WriteBtmp
|
|
*
|
|
* log bad login attempts
|
|
*
|
|
***************************************************************************/
|
|
|
|
static void
|
|
WriteBtmp( char *name )
|
|
{
|
|
int fd;
|
|
struct utmp utmp, *u;
|
|
|
|
Boolean found=FALSE;
|
|
|
|
bzero(&utmp, sizeof(struct utmp));
|
|
|
|
utmp.ut_pid = getppid();
|
|
while ((u = getutent()) != NULL) {
|
|
if ( (u->ut_type == INIT_PROCESS ||
|
|
u->ut_type == LOGIN_PROCESS ||
|
|
u->ut_type == USER_PROCESS) &&
|
|
u->ut_pid == utmp.ut_pid ) {
|
|
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* if no utmp entry, this may be an X-terminal. Construct a utmp
|
|
* entry for it...
|
|
*/
|
|
|
|
if ( ! found ) {
|
|
strncpy(utmp.ut_id, "??", sizeof(utmp.ut_id));
|
|
strncpy(utmp.ut_line, dpyinfo.name, sizeof(utmp.ut_line));
|
|
utmp.ut_type = LOGIN_PROCESS;
|
|
strncpy(utmp.ut_host, dpyinfo.name, sizeof(utmp.ut_host));
|
|
u = &utmp;
|
|
}
|
|
|
|
|
|
/*
|
|
* If btmp exists, then record the bad attempt
|
|
*/
|
|
if ( (fd = open(BTMP_FILE,O_WRONLY|O_APPEND)) >= 0) {
|
|
strncpy(u->ut_user, name, sizeof(u->ut_user));
|
|
(void) time(&u->ut_time);
|
|
write(fd, (char *)u, sizeof(utmp));
|
|
(void) close(fd);
|
|
}
|
|
|
|
endutent(); /* Close utmp file */
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* VerifySensitivityLevel
|
|
*
|
|
* verify B1 Sensitivity Level
|
|
**************************************************************************/
|
|
extern char *sensitivityLevel;
|
|
|
|
int
|
|
VerifySensitivityLevel( void)
|
|
{
|
|
|
|
int i;
|
|
|
|
greet->b1security = sensitivityLevel =
|
|
(char *) XmTextFieldGetString(passwd_text);
|
|
|
|
/* new functions: (side effects: auditing, change verify) */
|
|
if (verify_user_seclevel(verify, sensitivityLevel)
|
|
&& verify_sec_xterm(verify, sensitivityLevel)) {
|
|
|
|
Debug("verify_user_seclevel succeeded.\n");
|
|
return VF_OK;
|
|
}
|
|
|
|
Debug("verify_user_seclevel failed\n");
|
|
return (VF_BAD_SEN_LEVEL);
|
|
}
|
|
|
|
|
|
#ifdef NGROUPS
|
|
groupMember ( char *name, char **members )
|
|
{
|
|
while (*members) {
|
|
if (!strcmp (name, *members))
|
|
return 1;
|
|
++members;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
getGroups ( char *name, struct verify_info *verify, int gid)
|
|
{
|
|
int ngroups;
|
|
struct group *g;
|
|
int i;
|
|
|
|
ngroups = 0;
|
|
verify->groups[ngroups++] = gid;
|
|
setgrent ();
|
|
while (g = getgrent()) {
|
|
/*
|
|
* make the list unique
|
|
*/
|
|
for (i = 0; i < ngroups; i++)
|
|
if (verify->groups[i] == g->gr_gid)
|
|
break;
|
|
if (i != ngroups)
|
|
continue;
|
|
if (groupMember (name, g->gr_mem)) {
|
|
if (ngroups >= NGROUPS)
|
|
LogError ("%s belongs to more than %d groups, %s ignored\n",
|
|
name, NGROUPS, g->gr_name);
|
|
else
|
|
verify->groups[ngroups++] = g->gr_gid;
|
|
}
|
|
}
|
|
verify->ngroups = ngroups;
|
|
endgrent ();
|
|
}
|
|
#endif
|
|
|
|
/* check whether the password has expired or not.
|
|
* return 1 means that the password has expired.
|
|
*/
|
|
int
|
|
passwordExpired( struct verify_info *verify)
|
|
{
|
|
struct pr_passwd *pr;
|
|
time_t expiration;
|
|
time_t last_change;
|
|
time_t expiration_time;
|
|
time_t now;
|
|
int passwd_status;
|
|
struct pr_passwd save_data;
|
|
struct pr_default *df;
|
|
char *ttime;
|
|
char ptime[64];
|
|
|
|
pr = verify->prpwd;
|
|
|
|
/*
|
|
* If null password, do not check expiration.
|
|
*/
|
|
|
|
if (!pr->uflg.fg_encrypt || (pr->ufld.fd_encrypt[0] == '\0'))
|
|
return 0;
|
|
|
|
now = time((long *) 0);
|
|
|
|
if (pr->uflg.fg_schange)
|
|
last_change = pr->ufld.fd_schange;
|
|
else
|
|
last_change = (time_t) 0;
|
|
|
|
if (pr->uflg.fg_expire)
|
|
expiration = pr->ufld.fd_expire;
|
|
else if (pr->sflg.fg_expire)
|
|
expiration = pr->sfld.fd_expire;
|
|
else
|
|
expiration = (time_t) 0;
|
|
|
|
df = getprdfnam(AUTH_DEFAULT);
|
|
|
|
/*
|
|
* A 0 or missing expiration field means there is no
|
|
* expiration.
|
|
*/
|
|
expiration_time = expiration ? last_change + expiration : 0;
|
|
|
|
if (expiration_time && now > expiration_time ) {
|
|
/*
|
|
* The password has expired
|
|
*/
|
|
Debug("The password is expired\n");
|
|
return 1;
|
|
}
|
|
|
|
Debug("The password is not expired\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* end HP-UX authentication routines
|
|
*
|
|
***************************************************************************/
|
|
#endif /* BLS */
|