2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: sysauth.c /main/7 1996/10/30 11:12:45 drk $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
30 /************************************<+>*************************************
31 ****************************************************************************
37 ** Description: Dtgreet user authentication routines
39 ** These routines validate the user; checking name, password,
40 ** number of users on the system, password aging, etc.
43 ** (c) Copyright 1987, 1988, 1989 by Hewlett-Packard Company
46 ** Conditional compiles for HPUX:
49 ** HP-UX 7.0/7.03 restricted license counting algorithms
50 ** are used. Otherwise HP-UX 8.0 and beyond is used
52 ** AUDIT HP C2 security enhancements; checks for existence of
53 ** SECUREPASSWD file and authenticates user against
54 ** password contained in that file. Also performs
55 ** self-auditing of login actions. Incompatible with
58 ** BLS HP BLS B1 simple authentication.
60 ** __AFS AFS 3 authentication mechanism
61 ** __KERBEROS Kerberos authentication mechanism
62 ** __PASSWD_ETC Domain/OS Registry from HP-UX authentication mechanism
64 ** Platform identification:
66 ** __hpux HP-UX OS only
70 ** _POWER AIX version 4 only
72 ****************************************************************************
73 ************************************<+>*************************************/
76 /***************************************************************************
80 ***************************************************************************/
88 #include <security/pam_appl.h>
94 #include <sys/access.h>
98 #include <sys/audit.h>
101 /* necessary for bzero */
103 #include <X11/Xfuncs.h>
115 * Define as generic those without platform specific code.
117 #if !(defined(__hpux) || defined(_AIX) || defined(sun))
121 #if defined(__linux__)
126 /***************************************************************************
128 * Start authentication routines (HPUX)
130 ***************************************************************************/
132 #include <sys/param.h> /* for MAXUID macro */
133 #include <sys/types.h>
134 #include <sys/utsname.h>
141 # include <sys/audit.h>
142 # include <sys/errno.h>
143 # include <sys/stat.h>
144 # define SECUREPASS "/.secure/etc/passwd"
148 # include <sys/security.h>
153 #include <afs/kautils.h>
158 # define KRBLIFE 255 /* max lifetime */
159 #endif /* __KERBEROS */
162 # include "rgy_base.h"
167 #define how_to_count ut_exit.e_exit
170 int num_users[] = { 2, 32767 };
171 # define MIN_VERSION 'A'
172 # define UNLIMITED 'B'
174 int num_users[] = { 2, 16, 32, 64 , 8 };
175 # define MIN_VERSION 'A'
176 # define UNLIMITED 'U'
179 /* Maximum number of users allowed with restricted license */
180 #if OSMAJORVERSION < 8
181 # define MAX_STRICT_USERS 2
183 # define MAX_STRICT_USERS 8
186 #define NUM_VERSIONS (sizeof(num_users)/sizeof(num_users[0])) - 1
188 extern char *globalDisplayName;
190 /***************************************************************************
192 * External declarations (HPUX)
194 ***************************************************************************/
196 extern long groups[NGROUPS];
200 extern boolean rgy_$using_local_registry();
201 extern struct passwd * getpwnam_full();
202 extern boolean is_acct_expired();
203 extern boolean is_passwd_expired();
204 extern boolean is_passwd_invalid();
205 extern boolean rgy_$is_des();
210 /***************************************************************************
212 * Procedure declarations (HPUX)
214 ***************************************************************************/
216 static void Audit( struct passwd *p, char *msg, int errnum) ;
217 static int CheckPassword( char *name, char *passwd, struct passwd **ppwd );
218 static int CountUsers( int added_users) ;
219 static int CountUsersStrict( char *new_user) ;
220 static int PasswordAged( struct passwd *pw) ;
221 static void WriteBtmp( char *name) ;
226 /***************************************************************************
228 * Global variables (HPUX)
230 ***************************************************************************/
233 struct s_passwd *s_pwd;
235 int secure; /* flag to denote existence of secure passwd file */
240 struct pr_passwd *b1_pwd;
244 rgy_$acct_admin_t admin_part;
245 rgy_$policy_t policy;
246 rgy_$acct_user_t user_part;
251 /***************************************************************************
255 * Construct self audit record for event and write to the audit trail.
256 * This routine assumes that the effective uid is currently 0. If auditing
257 * is not defined, this routine does nothing.
258 ***************************************************************************/
261 Audit( struct passwd *p, char *msg, int errnum )
267 struct self_audit_rec audrec;
272 * make sure program is back to super-user...
280 txtptr = (char *)audrec.aud_body.text;
281 sprintf(txtptr, "User= %s uid=%ld audid=%ld%s", p->pw_name,
282 (long)p->pw_uid, (long)p->pw_audid, msg);
283 audrec.aud_head.ah_pid = getpid();
284 audrec.aud_head.ah_error = errnum;
285 audrec.aud_head.ah_event = EN_LOGINS;
286 audrec.aud_head.ah_len = strlen (txtptr);
287 status = audwrite(&audrec);
293 LogError(ReadCatalog(
294 MC_LOG_SET,MC_LOG_NOT_SUSER,MC_DEF_LOG_NOT_SUSER));
298 LogError(ReadCatalog(
299 MC_LOG_SET,MC_LOG_INV_EVENT,MC_DEF_LOG_INV_EVENT));
303 LogError(ReadCatalog(
304 MC_LOG_SET,MC_LOG_ERR_ERRNO,MC_DEF_LOG_ERR_ERRNO),
321 /***************************************************************************
323 * CountUsers (HPUX only)
325 * see if new user has exceeded the maximum.
326 ***************************************************************************/
331 CountUsers( int added_users )
333 int count[NCOUNT], nusers, i;
336 for (i=0; i<NCOUNT; i++)
339 count[added_users]++;
341 while ( (entry = getutent()) != NULL) {
342 if (entry->ut_type == USER_PROCESS) {
343 i = entry->how_to_count;
344 if (i < 0 || i >= NCOUNT)
345 i = 1; /* if out of range, then count */
346 /* as ordinary user */
354 * [0] does not count at all
355 * [1] counts as real user
356 * [2] logins via a pty which have not gone trough login. These
357 * collectively count as 1 user IF count[3] is 0, otherwise,
358 * they are not counted. Starting with HP-UX 8.0 they are
359 * no longer counted at all.
360 * [3] logins via a pty which have been logged through login (i.e.
361 * rlogin and telnet). these count as 1 "real" user per
363 * [4-15] may be used for groups of users which collectively
368 #if OSMAJORVERSION < 8
369 for (i=2; i<NCOUNT; i++)
371 for (i=3; i<NCOUNT; i++)
382 /***************************************************************************
384 * CountUsersStrict (HPUX only)
386 * see if new user has exceeded the maximum.
387 ***************************************************************************/
390 CountUsersStrict( char *new_user )
392 char pty_users[MAX_STRICT_USERS][8];
393 int count[NCOUNT], nusers, i, cnt, pty_off = -1, uname_off;
397 * Initialize count array...
399 for (i = 0; i < NCOUNT; i++)
403 * Add in the new user (we know it's not a pty)...
407 while ( (entry = getutent()) != NULL ) {
408 if (entry->ut_type == USER_PROCESS) {
409 i = entry->how_to_count;
411 /* if out of range, then count as ordinary user logged in
413 if (i == 1 || (i < 0 || i >= NCOUNT))
415 /* See if it is a pty login granted by login program */
418 /* See if user is already logged in via login pty */
420 for (cnt = 0; cnt <= pty_off; cnt++)
421 if (strncmp(pty_users[cnt], entry->ut_user, 8) == 0)
424 if (uname_off == -1) { /* user is not logged in via pty yet */
426 if (pty_off >= MAX_STRICT_USERS) /* cannot add any
428 return(MAX_STRICT_USERS + 1);
429 /* add the user name to the array of pty users */
431 strncpy(pty_users[++pty_off], entry->ut_user, 8);
433 } /* end if (i == 3) */
436 } /* end if entry->ut_type == USER_PROCESS */
437 } /* end while (entry = getutent()) */
442 * [0] does not count at all
443 * [1] counts as "real" user
444 * [2] logins via a pty which have not gone trough login. These
445 * collectively count as 1 user IF count[3] is 0, otherwise,
446 * they are not counted. Starting with HP-UX 8.0 they are
447 * no longer counted at all.
448 * [3] logins via a pty which have been logged through login (i.e.
449 * rlogin and telnet). these count as 1 "real" user per
451 * [4-15] may be used for groups of users which collectively count
455 nusers = pty_off + 1 + count[1]; /* Current number of users is sum of
456 users logged in via tty + the
457 number of unique users logged in
458 via pty which have gone through
461 #if OSMAJORVERSION < 8
462 if ((count[3] == 0) && (count[2] != 0))
463 nusers++; /* Add 1 user for all pty logins IF
464 none of pty logins have been
465 granted by the login program */
468 * Don't count any hpterm logins (exit status of 2). We already
469 * counted all pty logins granted by the login program.
473 for (i = 4; i < NCOUNT; i++)
482 /***************************************************************************
484 * PasswordAged (HPUX)
486 * see if password has aged
487 ***************************************************************************/
488 #define SECONDS_IN_WEEK 604800L
491 PasswordAged( struct passwd *pw )
493 long change_week; /* week password was changed (1/1/70 = Week 0) */
494 long last_week; /* week after which password must change */
495 long first_week; /* week before which password can't change */
496 long this_week; /* this week derived from time() */
498 char *passwdAge; /* password aging time */
505 passwdAge = pw->pw_age;
509 passwdAge = s_pwd->pw_age;
514 /* Account validity checks: If we were able to connect to the network
515 * registry, then we've acquired account and policy data and can perform
516 * account/password checking
519 lrgy = rgy_$using_local_registry();
522 /* Check for password expiration or invalidity */
523 if ( rgy_$is_passwd_expired(&user_part, &policy ) != 0 ) {
531 if (*passwdAge == NULL)
534 first_week = last_week = change_week = (long) a64l(passwdAge);
535 last_week &= 0x3f; /* first six bits */
536 first_week = (first_week >> 6) & 0x3f; /* next six bits */
537 change_week >>= 12; /* everything else */
539 this_week = (long) time((long *) 0) / SECONDS_IN_WEEK;
542 ** Password aging conditions:
543 ** * if the last week is less than the first week (e.g., the aging
544 ** field looks like "./"), only the superuser can change the
545 ** password. We don't request a new password.
546 ** * if the week the password was last changed is after this week,
547 ** we have a problem, and request a new password.
548 ** * if this week is after the specified aging time, we request
551 if (last_week < first_week)
554 if (change_week <= this_week && this_week <= (change_week + last_week))
564 /***************************************************************************
566 * CheckPassword (HPUX only)
568 * Check validity of user password. One of several authentication schemes
569 * can be used, including Kerberos, AFS 3, HP BLS and traditional
570 * /etc/passwd. These are selectable via a resource in Dtlogin.
572 * Domain registry authentication (PasswdEtc) can also be compiled in as
573 * the only authentication scheme used.
575 ***************************************************************************/
578 CheckPassword( char *name, char *passwd, struct passwd **ppwd )
587 char realm[REALM_SZ];
589 #endif /* __KERBEROS */
594 * validate that user has an entry in the shadow password file on an
595 * HP-UX C2 trusted system. Keep info in a global structure.
599 s_pwd = getspwnam(name);
609 * look up user's regular account information...
614 * look up entry from registry...
616 * need getpwnam_full to get policy data for passwd expiration
619 p = getpwnam_full(name, &user_part, &admin_part, &policy);
627 if ( p == NULL || strlen(name) == 0 )
634 * AFS password authentication...
637 if ( vg_IsVerifyName(VN_AFS) ) {
639 if ( ka_UserAuthenticateGeneral(
640 KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
641 p->pw_name, /* kerberos name */
642 (char *)0, /* instance */
643 (char *)0, /* realm */
644 passwd, /* password */
645 0, /* default lifetime */
648 &reason) == 0 ) { /* error string */
650 if (strcmp(p->pw_passwd, "*") == 0)
657 LogError(ReadCatalog(
658 MC_LOG_SET,MC_LOG_AFS_FAILATH,MC_DEF_LOG_AFS_FAILATH),reason);
667 * Kerberos password authentication...
670 if ( vg_IsVerifyName(VN_KRB) ) {
672 (void)krb_get_lrealm(realm, 1);
674 setresuid(p->pw_uid, p->pw_uid, -1);
675 kerno = krb_get_pw_in_tkt(p->pw_name,
685 if (kerno == KSUCCESS)
686 if (strcmp(p->pw_passwd, "*") == 0)
692 #endif /* __KERBEROS */
697 * traditional password verification...
700 if (strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd) == 0)
706 * If regular passwd check fails, try old-style SR
709 if (rgy_$is_des(passwd, strlen(passwd), p->pw_passwd) == TRUE)
715 * all password checks failed...
725 /***************************************************************************
727 * Authenticate (HPUX)
731 * return codes indicate authentication results.
732 ***************************************************************************/
734 #define MAXATTEMPTS 3
736 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
739 Authenticate( struct display *d, char *name, char *passwd, char **msg )
742 static int login_attempts = 0; /* # failed authentications */
744 struct passwd *p = NULL; /* password structure */
746 struct utsname utsnam;
752 * Nothing to do if no name provided.
759 if (strlen(name) == 0)
763 return(VF_CHALLENGE);
770 * Save provided password.
773 if (!passwd) passwd = "";
777 * turn on self auditing...
780 if (audswitch(AUD_SUSPEND) == -1)
786 * set the secure flag if SECUREPASS exists. If so, we
787 * are using it for authentication instead of /etc/passwd...
790 secure = (stat(SECUREPASS, &s_pfile) < 0) ? 0:1;
794 * set the audit process flag unconditionally on since we want
795 * to log all logins regardless of whether the user's audit
800 setaudproc(AUD_PROC);
806 * validate password...
809 if ( CheckPassword(name, passwd, &p) == FALSE) {
813 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
818 Audit(p, " Failed login (bailout)", 1);
822 return(origpw ? VF_INVALID : VF_CHALLENGE);
827 * check restricted license...
829 * Note: This only applies to local displays. Foreign displays
830 * (i.e. X-terminals) apparently do not count.
833 /* Get the version info via uname. If it doesn't look right,
834 * assume the smallest user configuration
837 if (uname(&utsnam) < 0)
838 utsnam.version[0] = MIN_VERSION;
850 if ((!strncmp(utsnam.machine, "9000/834", UTSLEN)) ||
851 (!strncmp(utsnam.machine, "9000/844", UTSLEN)) ||
852 (!strncmp(utsnam.machine, "9000/836", UTSLEN)) ||
853 (!strncmp(utsnam.machine, "9000/846", UTSLEN)) ||
854 (!strncmp(utsnam.machine, "9000/843", UTSLEN)) ||
855 (!strncmp(utsnam.machine, "9000/853", UTSLEN))) {
857 /* strict_count = 1;*/
858 if (CountUsersStrict(name) > MAX_STRICT_USERS) {
860 " attempted to login - too many users on the system",
863 return(VF_MAX_USERS);
867 if (utsnam.version[0] != UNLIMITED) {
868 if ((utsnam.version[0]-'A' < 0) ||
869 (utsnam.version[0]-'A' > NUM_VERSIONS))
870 utsnam.version[0] = MIN_VERSION;
872 n = (int) utsnam.version[0] - 'A';
873 if (CountUsers(1) > num_users[n]) {
875 " attempted to login - too many users on the system",
878 return(VF_MAX_USERS);
886 * Check for account validity. Unfortunately, we have no graphical
887 * dialog for this at this time so the best we can do is log an
888 * error message and hope the system administrator sees it.
891 if ( !rgy_$using_local_registry() ) {
892 if (rgy_$is_acct_expired(&admin_part) != 0 ) {
893 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_ACC_EXP,MC_DEF_LOG_ACC_EXP),
901 * check password aging...
904 if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
908 * verify home directory exists...
911 if(chdir(p->pw_dir) < 0) {
912 Audit(p, " attempted to login - no home directory", 1);
919 * check audit flag and id...
924 if (secure && (p->pw_audflg > 1 || p->pw_audflg < 0)) {
925 Audit(p, " attempted to login - bad audit flag", 1);
926 return(VF_BAD_AFLAG);
929 if (secure && (setaudid(p->pw_audid) == -1 )) {
930 Audit(p, " attempted to login - bad audit id", 1);
937 * validate uid and gid...
940 if ((p->pw_gid < 0) ||
941 (p->pw_gid > MAXUID) ||
942 (setgid(p->pw_gid) == -1)) {
944 Audit(p, " attempted to login - bad group id", 1);
951 * ka_UserAuthenticateGeneral() sets the group access of this process
952 * to the proper PAG. Pick up these values and pass them back to
953 * Dtlogin to be put into the user's environment...
956 if ( vg_IsVerifyName(VN_AFS) ) {
957 groups[0] = groups[1] = 0;
958 getgroups(NGROUPS, groups);
964 if ((p->pw_uid < 0) ||
965 (p->pw_uid > MAXUID) ||
966 (setresuid(p->pw_uid, p->pw_uid, 0) == -1)) {
968 Audit(p, " attempted to login - bad user id", 1);
979 Audit(p, " Successful login", 0);
986 /***************************************************************************
990 * log bad login attempts
992 ***************************************************************************/
995 WriteBtmp( char *name )
998 struct utmp utmp, *u;
1002 bzero(&utmp, sizeof(struct utmp));
1004 utmp.ut_pid = getppid();
1005 while ((u = getutent()) != NULL) {
1006 if ( (u->ut_type == INIT_PROCESS ||
1007 u->ut_type == LOGIN_PROCESS ||
1008 u->ut_type == USER_PROCESS) &&
1009 u->ut_pid == utmp.ut_pid ) {
1018 * if no utmp entry, this may be an X-terminal. Construct a utmp
1023 strncpy(utmp.ut_id, "??", sizeof(utmp.ut_id));
1024 strncpy(utmp.ut_line, globalDisplayName, sizeof(utmp.ut_line));
1025 utmp.ut_type = LOGIN_PROCESS;
1027 strncpy(utmp.ut_host, globalDisplayName, sizeof(utmp.ut_host));
1034 * If btmp exists, then record the bad attempt
1036 if ( (fd = open(BTMP_FILE,O_WRONLY|O_APPEND)) >= 0) {
1037 strncpy(u->ut_user, name, sizeof(u->ut_user));
1038 (void) time(&u->ut_time);
1039 write(fd, (char *)u, sizeof(utmp));
1043 endutent(); /* Close utmp file */
1046 /***************************************************************************
1048 * End authentication routines (HPUX)
1050 ***************************************************************************/
1054 /***************************************************************************
1055 ***************************************************************************
1056 ***************************************************************************
1057 ***************************************************************************
1058 ***************************************************************************
1059 ***************************************************************************
1060 ***************************************************************************
1061 ***************************************************************************/
1065 /***************************************************************************
1067 * Start authentication routines (SUN)
1069 ***************************************************************************/
1071 #include "solaris.h"
1073 #include <security/ia_appl.h>
1077 /***************************************************************************
1079 * Procedure declarations (SUN)
1081 ***************************************************************************/
1083 static void Audit( struct passwd *p, char *msg, int errnum) ;
1087 /***************************************************************************
1091 ***************************************************************************/
1094 Audit( struct passwd *p, char *msg, int errnum )
1098 * make sure program is back to super-user...
1103 Debug("Audit: %s\n", msg);
1109 /***************************************************************************
1111 * Authenticate (SUN)
1115 * return codes indicate authentication results.
1116 ***************************************************************************/
1119 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1122 char* ttyLine = d->gettyLine;
1125 * Nothing to do if no name provided.
1132 * Construct device line
1134 #ifdef DEF_NETWORK_DEV
1136 * If location is not local (remote XDMCP dtlogin) and
1137 * remote accouting is enabled (networkDev start with /dev/...)
1138 * Set tty line name to match network device for accouting.
1139 * Unless the resource was specifically set, default is value
1140 * of DEF_NETWORK_DEV define (/dev/dtremote)
1143 if ( d->displayType.location != Local &&
1144 networkDev && !strncmp(networkDev,"/dev/",5)) {
1145 ttyLine = networkDev+5;
1150 * Authenticate user and return status
1154 status = PamAuthenticate("dtlogin", d->name, passwd, name, ttyLine);
1160 case PAM_NEW_AUTHTOK_REQD:
1161 return(VF_PASSWD_AGED);
1164 return(passwd ? VF_INVALID : VF_CHALLENGE);
1167 status = solaris_authenticate("dtlogin", d->name, passwd, name, ttyLine);
1173 case IA_NEWTOK_REQD:
1174 return(VF_PASSWD_AGED);
1177 return(passwd ? VF_INVALID : VF_CHALLENGE);
1184 /***************************************************************************
1186 * End authentication routines (SUN)
1188 ***************************************************************************/
1191 /***************************************************************************
1192 ***************************************************************************
1193 ***************************************************************************
1194 ***************************************************************************
1195 ***************************************************************************/
1197 /***************************************************************************
1201 * get the information from the display about local/remote login and
1202 * create a dummy tty name for loginrestrictions.
1204 ***************************************************************************/
1206 GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname)
1210 CleanUpName(d->name, workarea, 128);
1211 sprintf(ttyName, "/dev/dtlogin/%s", workarea);
1213 if (d->displayType.location == Foreign) {
1214 *loginType = S_RLOGIN;
1215 *hostname = d->name;
1216 Debug("Login Info - Remote user on tty=%s.\n", ttyName);
1218 *loginType = S_LOGIN;
1220 Debug("Login Info - Local user on tty=%s.\n", ttyName);
1224 /***************************************************************************
1226 * Authenticate (AIX version 4.1)
1230 * return codes indicate authentication results.
1231 ***************************************************************************/
1232 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1238 static char *msgpending;
1243 GetLoginInfo(d, &loginType, tty, &hostname);
1253 * No more challenges. User failed login.
1256 loginfailed(name, hostname, tty);
1261 * Authenticate with response to last challenge.
1263 rc = authenticate(name, passwd, &reenter, msg);
1268 * System has presented user with new challenge.
1270 return(VF_CHALLENGE);
1273 if (rc && errno == ENOENT)
1276 * User is unknown to the system. Simulate a password
1277 * challenge, but save message for display for next call.
1280 return(VF_CHALLENGE);
1286 * No more challenges. User failed login.
1288 loginfailed(name, hostname, tty);
1293 * User authenticated. Check login restrictions.
1295 rc = loginrestrictions(name, loginType, tty, msg);
1300 * Login restrictions disallow login.
1302 loginfailed(name, hostname, tty);
1307 * Check password expiration.
1309 rc = passwdexpired(name, msg);
1314 * Login succeeded, but password expired.
1316 return(VF_PASSWD_AGED);
1322 loginsuccess(name, hostname, tty, msg);
1329 /***************************************************************************
1331 * Start authentication routines (AIX)
1333 ***************************************************************************/
1336 #include <sys/types.h>
1337 #include <sys/errno.h>
1338 #include <usersec.h>
1340 #include <userconf.h>
1344 /***************************************************************************
1346 * External declarations (AIX)
1348 ***************************************************************************/
1353 /***************************************************************************
1355 * Procedure declarations (AIX)
1357 ***************************************************************************/
1359 static void Audit( struct passwd *p, char *msg, int errnum) ;
1360 static int PasswordAged(char *name, struct passwd *pw) ;
1361 static void WriteBtmp( char *name) ;
1366 /***************************************************************************
1368 * Global variables (AIX)
1370 ***************************************************************************/
1375 /***************************************************************************
1379 ***************************************************************************/
1382 Audit( struct passwd *p, char *msg, int errnum )
1386 * make sure program is back to super-user...
1390 if ( (auditwrite ("USER_Login", AUDIT_OK,
1391 p->pw_name, strlen (p->pw_name) + 1,
1392 msg, strlen (msg) + 1, NULL)) == -1 )
1393 Debug(" Could not do Auditing\n");
1400 /***************************************************************************
1404 * log bad login attempts to /etc/security/failedlogin file
1407 ***************************************************************************/
1410 WriteBtmp( char *name )
1415 if( (fd = open("/etc/security/failedlogin",O_CREAT|O_RDWR,0644)) != -1) {
1416 bzero(&ut,sizeof(struct utmp));
1418 strncpy(ut.ut_user, name, sizeof ut.ut_user);
1419 ut.ut_type = USER_PROCESS;
1420 ut.ut_pid = getpid();
1421 ut.ut_time = time((time_t *)0);
1422 write(fd, (char *)&ut, sizeof(struct utmp));
1430 /***************************************************************************
1432 * PasswordAged (AIX)
1434 * see if password has aged
1435 ***************************************************************************/
1436 #define SECONDS_IN_WEEK 604800L
1439 PasswordAged(char *name, struct passwd *pw )
1441 struct userpw *pupw; /* authentication information from getuserpw() */
1442 struct userpw upw; /* working authentication information */
1443 int err; /* return code from getconfattr() */
1444 ulong maxage; /* maximun age from getconfattr() */
1445 ulong now; /* time now */
1451 * Determine user password aging criteria. Note that only
1452 * the 'lastupdate' and 'flags' fields are set by this operation.
1455 if ((pupw = getuserpw(name)) != NULL)
1457 upw.upw_lastupdate = pupw->upw_lastupdate;
1458 upw.upw_flags = pupw->upw_flags;
1462 upw.upw_lastupdate = 0;
1468 * Consider password as having not expired if nocheck set.
1470 if (upw.upw_flags & PW_NOCHECK) return(FALSE);
1473 * Get system password aging criteria.
1475 err = getconfattr (SC_SYS_PASSWD, SC_MAXAGE, (void *)&maxage, SEC_INT);
1479 * Change from weeks to seconds
1481 maxage = maxage * SECONDS_IN_WEEK;
1482 now = time ((long *) 0);
1484 if ((upw.upw_lastupdate + maxage) >= now)
1487 * Password has not expired.
1495 * Could not retrieve system password aging info or maxage set to
1496 * zero. In either case, consider password has having not expired.
1502 * We haven't returned by now, so indicate password has expired.
1508 /***************************************************************************
1509 * dt_failedlogin (AIX)
1511 * log failed login in /etc/security/lastlog
1512 ***************************************************************************/
1524 dt_lastlogin ( char * user, struct lastlogin * llogin);
1527 dt_failedlogin(char *name, char *ttyName, char *hostName)
1529 struct lastlogin last_login;
1531 last_login.stime = 0;
1533 time(&last_login.ftime);
1535 last_login.ftty = ttyName;
1537 last_login.fhost = (char *) malloc (MAXHOSTNAMELEN);
1538 if (hostName == NULL) {
1539 gethostname (last_login.fhost , MAXHOSTNAMELEN);
1541 strncpy(last_login.fhost, hostName, MAXHOSTNAMELEN);
1542 last_login.fhost[MAXHOSTNAMELEN -1] = '\0';
1545 Debug("logging failed lastlogin entry (user=%s)\n",name);
1546 dt_lastlogin(name, &last_login);
1547 free(last_login.fhost);
1552 /***************************************************************************
1554 * Authenticate (AIX)
1558 * return codes indicate authentication results.
1559 ***************************************************************************/
1561 #define MAXATTEMPTS 3
1563 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
1566 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1569 static int login_attempts = 0; /* # failed authentications */
1570 struct passwd *p; /* password structure */
1578 * Nothing to do if no name provided.
1584 * Save provided password.
1587 if (!passwd) passwd = "";
1589 if(strlen(name) > S_NAMELEN)
1592 GetLoginInfo(d, &loginType, tty, &hostname);
1596 if (!p || strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd)) {
1600 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
1605 Audit(p, " Failed login (bailout)", 1);
1609 dt_failedlogin(name, tty, hostname);
1610 return (VF_INVALID);
1612 return(VF_CHALLENGE);
1615 /* Note: The password should be checked if it is the first time
1616 the user is logging in or whether the sysadm has changed
1617 the password for the user. Code should be added here if
1618 this functionality should be supported. The "upw_flags"
1619 of the password structure gets set to PW_ADMCHG in this
1624 * check password aging...
1627 if ( PasswordAged(name,p) ) return(VF_PASSWD_AGED);
1630 /* Validate for User Account RK 09.13.93 */
1631 if(ckuseracct(name, loginType, tty) == -1) {
1632 dt_failedlogin(name, tty, hostname);
1638 * validate uid and gid...
1642 if ((p->pw_gid < 0) ||
1643 (setgid(p->pw_gid) == -1)) {
1645 Audit(p, " attempted to login - bad group id", 1);
1649 if ((p->pw_uid < 0)) {
1650 Audit(p, " attempted to login - bad user id", 1);
1654 /* Check for max number of logins RK 09.13.93 */
1655 if (tsm_check_login(p->pw_uid) == -1) {
1656 dt_failedlogin(name, tty, hostname);
1660 /* Check for /etc/nologin file RK 09.13.93 */
1661 if ( (access("/etc/nologin",R_OK) == 0) && (p->pw_uid != 0) ) {
1662 dt_failedlogin(name, tty, hostname);
1667 * verify home directory exists...
1670 if(chdir(p->pw_dir) < 0) {
1671 Audit(p, " attempted to login - no home directory", 1);
1679 Audit(p, " Successful login", 0);
1683 /**************************************************************************
1687 * Checks for max number of logins on the system. If the new user trying to
1688 * login exceeds the max limit then the user is not allowed to login.
1691 **************************************************************************/
1693 /**************************************************************************
1697 * Checks for max number of logins on the system. If the new user trying to
1698 * login exceeds the max limit then the user is not allowed to login.
1701 **************************************************************************/
1704 tsm_check_login(uid_t uid)
1711 struct stat stat_buf;
1712 static struct sembuf sop = { 0, -1, (SEM_UNDO|IPC_NOWAIT) };
1713 static struct sembuf initsop = { 0, 0, (IPC_NOWAIT) };
1716 * The login counter semaphore may not be set yet. See if it exists
1717 * and try creating it with the correct count if it doesn't. An
1718 * attempt is made to create the semaphore. Only if that attempt fails
1719 * is the semaphore set to maxlogins from login.cfg.
1724 * Don't Check if the user is already logged. ie running login
1728 * Generate the semaphore key from the init program.
1730 Debug("Start of maxlogin check\n");
1731 if ((key = ftok (CDE_INSTALLATION_TOP "/bin/dtlogin", 1)) != (key_t) -1) {
1732 Debug("key created\n");
1733 if ((semid = semget (key, 1, IPC_CREAT|IPC_EXCL|0600)) != -1) {
1735 Debug("Completed IPCkey\n");
1736 if (! getconfattr ("usw", "maxlogins", &i, SEC_INT)) {
1737 Debug("Max logins from login.cfg is :%d\n",i);
1739 i = 10000; /* a very large number */
1742 if (semop (semid, &initsop, 1))
1744 Debug("failed while decrementing\n");
1748 semctl (semid, 1, IPC_RMID, 0);
1753 * Only 'n' login sessions are allowed on the system.
1754 * This code block decrements a semaphore.
1755 * The semundo value will be set to adjust the
1756 * semaphore when tsm exits.
1758 * This code will be ignored if the appropriate
1759 * semaphore set does not exist.
1762 if ((semid = semget (key, 1, 0)) != -1) {
1763 Debug("getting key for maxlogins\n");
1765 * If the semaphore is zero and we are not
1766 * root, then we fail as there are already the
1767 * allotted number of login sessions on the
1770 if ((semop (semid, &sop, 1) == -1) && uid) {
1771 Debug("reached MAXLOGINS limit\n");
1779 #endif /* !_POWER */
1781 /***************************************************************************
1783 * End authentication routines (AIX)
1785 ***************************************************************************/
1787 /***************************************************************************
1788 ***************************************************************************
1789 ***************************************************************************
1790 ***************************************************************************
1791 ***************************************************************************
1792 ***************************************************************************
1793 ***************************************************************************
1794 ***************************************************************************/
1798 /***************************************************************************
1800 * Start authentication routines (generic)
1802 ***************************************************************************/
1805 /***************************************************************************
1807 * These are a set of routine to do simple password, home dir, uid, and gid
1808 * validation. They can be used as a first pass validation for future
1811 * When platform specific validation is developed, those routines should be
1812 * included in their own section and the use of these routines discontinued.
1814 ***************************************************************************/
1819 /***************************************************************************
1821 * External declarations (generic)
1823 ***************************************************************************/
1828 /***************************************************************************
1830 * Procedure declarations (generic)
1832 ***************************************************************************/
1834 static void Audit( struct passwd *p, char *msg, int errnum) ;
1835 static int PasswordAged( struct passwd *pw) ;
1836 static void WriteBtmp( char *name) ;
1841 /***************************************************************************
1843 * Global variables (generic)
1845 ***************************************************************************/
1850 /***************************************************************************
1854 ***************************************************************************/
1857 Audit( struct passwd *p, char *msg, int errnum )
1861 * make sure program is back to super-user...
1863 if(-1 == seteuid(0)) {
1864 perror(strerror(errno));
1873 /***************************************************************************
1875 * WriteBtmp (generic)
1877 * log bad login attempts
1879 ***************************************************************************/
1882 WriteBtmp( char *name )
1890 /***************************************************************************
1892 * PasswordAged (Generic)
1894 * see if password has aged
1895 ***************************************************************************/
1896 #define SECONDS_IN_WEEK 604800L
1899 PasswordAged( struct passwd *pw )
1906 /***************************************************************************
1908 * Authenticate (generic)
1912 * return codes indicate authentication results.
1913 ***************************************************************************/
1915 #define MAXATTEMPTS 3
1917 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
1920 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1923 static int login_attempts = 0; /* # failed authentications */
1925 struct passwd *p; /* password structure */
1933 * Nothing to do if no name provided.
1939 * Save provided password.
1942 if (!passwd) passwd = "";
1946 #if defined(__linux__)
1948 * Use the Linux Shadow Password system to get the crypt()ed password
1951 struct spwd *s = getspnam(name);
1953 p->pw_passwd = s->sp_pwdp;
1958 #if defined(__OpenBSD__) && OSMAJORVERSION > 5
1960 * Use the OpenBSD getpwnam_shadow function to get the crypt()ed password
1962 p = getpwnam_shadow(name);
1965 if (!p || strlen(name) == 0 ||
1966 strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd)) {
1970 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
1975 Audit(p, " Failed login (bailout)", 1);
1979 return(origpw ? VF_INVALID : VF_CHALLENGE);
1984 * check password aging...
1987 if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
1991 * verify home directory exists...
1994 if(chdir(p->pw_dir) < 0) {
1995 Audit(p, " attempted to login - no home directory", 1);
2001 * validate uid and gid...
2005 if (setgid(p->pw_gid) == -1) {
2007 Audit(p, " attempted to login - bad group id", 1);
2011 if (seteuid(p->pw_uid) == -1) {
2013 Audit(p, " attempted to login - bad user id", 1);
2023 Audit(p, " Successful login", 0);
2030 /***************************************************************************
2032 * End authentication routines (generic)
2034 ***************************************************************************/
2035 #endif /* generic */
2039 /***************************************************************************
2040 ***************************************************************************
2041 ***************************************************************************
2042 ***************************************************************************
2043 ***************************************************************************
2044 ***************************************************************************
2045 ***************************************************************************
2046 ***************************************************************************/