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