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
67 ** __apollo Domain OS only
68 ** __hp_osf HP OSF/1 OS only
71 ** SVR4 SUN OS and USL
73 ** _POWER AIX version 4 only
74 ** __uxp__ Fujitsu UXP/DS
76 ****************************************************************************
77 ************************************<+>*************************************/
80 /***************************************************************************
84 ***************************************************************************/
92 #include <security/pam_appl.h>
98 #include <sys/access.h>
100 #include <sys/stat.h>
102 #include <sys/audit.h>
105 /* necessary for bzero */
107 #include <X11/Xfuncs.h>
108 #if defined(sun) || defined(__uxp__)
123 * Define as generic those without platform specific code.
125 #if !(defined(__hpux) || \
126 defined(__apollo) || \
129 defined(__uxp__) || \
135 #include <sys/sysinfo.h>
143 /***************************************************************************
145 * Start authentication routines (HPUX)
147 ***************************************************************************/
149 #include <sys/param.h> /* for MAXUID macro */
150 #include <sys/types.h>
151 #include <sys/utsname.h>
158 # include <sys/audit.h>
159 # include <sys/errno.h>
160 # include <sys/stat.h>
161 # define SECUREPASS "/.secure/etc/passwd"
165 # include <sys/security.h>
170 #include <afs/kautils.h>
175 # define KRBLIFE 255 /* max lifetime */
176 #endif /* __KERBEROS */
179 # include "rgy_base.h"
184 #define how_to_count ut_exit.e_exit
187 int num_users[] = { 2, 32767 };
188 # define MIN_VERSION 'A'
189 # define UNLIMITED 'B'
191 int num_users[] = { 2, 16, 32, 64 , 8 };
192 # define MIN_VERSION 'A'
193 # define UNLIMITED 'U'
196 /* Maximum number of users allowed with restricted license */
197 #if OSMAJORVERSION < 8
198 # define MAX_STRICT_USERS 2
200 # define MAX_STRICT_USERS 8
203 #define NUM_VERSIONS (sizeof(num_users)/sizeof(num_users[0])) - 1
205 extern char *globalDisplayName;
207 /***************************************************************************
209 * External declarations (HPUX)
211 ***************************************************************************/
213 extern long groups[NGROUPS];
217 extern boolean rgy_$using_local_registry();
218 extern struct passwd * getpwnam_full();
219 extern boolean is_acct_expired();
220 extern boolean is_passwd_expired();
221 extern boolean is_passwd_invalid();
222 extern boolean rgy_$is_des();
227 /***************************************************************************
229 * Procedure declarations (HPUX)
231 ***************************************************************************/
233 static void Audit( struct passwd *p, char *msg, int errnum) ;
234 static int CheckPassword( char *name, char *passwd, struct passwd **ppwd );
235 static int CountUsers( int added_users) ;
236 static int CountUsersStrict( char *new_user) ;
237 static int PasswordAged( register struct passwd *pw) ;
238 static void WriteBtmp( char *name) ;
243 /***************************************************************************
245 * Global variables (HPUX)
247 ***************************************************************************/
250 struct s_passwd *s_pwd;
252 int secure; /* flag to denote existence of secure passwd file */
257 struct pr_passwd *b1_pwd;
261 rgy_$acct_admin_t admin_part;
262 rgy_$policy_t policy;
263 rgy_$acct_user_t user_part;
268 /***************************************************************************
272 * Construct self audit record for event and write to the audit trail.
273 * This routine assumes that the effective uid is currently 0. If auditing
274 * is not defined, this routine does nothing.
275 ***************************************************************************/
278 Audit( struct passwd *p, char *msg, int errnum )
284 struct self_audit_rec audrec;
289 * make sure program is back to super-user...
297 txtptr = (char *)audrec.aud_body.text;
298 sprintf(txtptr, "User= %s uid=%ld audid=%ld%s", p->pw_name,
299 (long)p->pw_uid, (long)p->pw_audid, msg);
300 audrec.aud_head.ah_pid = getpid();
301 audrec.aud_head.ah_error = errnum;
302 audrec.aud_head.ah_event = EN_LOGINS;
303 audrec.aud_head.ah_len = strlen (txtptr);
304 status = audwrite(&audrec);
310 LogError(ReadCatalog(
311 MC_LOG_SET,MC_LOG_NOT_SUSER,MC_DEF_LOG_NOT_SUSER));
315 LogError(ReadCatalog(
316 MC_LOG_SET,MC_LOG_INV_EVENT,MC_DEF_LOG_INV_EVENT));
320 LogError(ReadCatalog(
321 MC_LOG_SET,MC_LOG_ERR_ERRNO,MC_DEF_LOG_ERR_ERRNO),
338 /***************************************************************************
340 * CountUsers (HPUX only)
342 * see if new user has exceeded the maximum.
343 ***************************************************************************/
348 CountUsers( int added_users )
350 int count[NCOUNT], nusers, i;
353 for (i=0; i<NCOUNT; i++)
356 count[added_users]++;
358 while ( (entry = getutent()) != NULL) {
359 if (entry->ut_type == USER_PROCESS) {
360 i = entry->how_to_count;
361 if (i < 0 || i >= NCOUNT)
362 i = 1; /* if out of range, then count */
363 /* as ordinary user */
371 * [0] does not count at all
372 * [1] counts as real user
373 * [2] logins via a pty which have not gone trough login. These
374 * collectively count as 1 user IF count[3] is 0, otherwise,
375 * they are not counted. Starting with HP-UX 8.0 they are
376 * no longer counted at all.
377 * [3] logins via a pty which have been logged through login (i.e.
378 * rlogin and telnet). these count as 1 "real" user per
380 * [4-15] may be used for groups of users which collectively
385 #if OSMAJORVERSION < 8
386 for (i=2; i<NCOUNT; i++)
388 for (i=3; i<NCOUNT; i++)
399 /***************************************************************************
401 * CountUsersStrict (HPUX only)
403 * see if new user has exceeded the maximum.
404 ***************************************************************************/
407 CountUsersStrict( char *new_user )
409 char pty_users[MAX_STRICT_USERS][8];
410 int count[NCOUNT], nusers, i, cnt, pty_off = -1, uname_off;
414 * Initialize count array...
416 for (i = 0; i < NCOUNT; i++)
420 * Add in the new user (we know it's not a pty)...
424 while ( (entry = getutent()) != NULL ) {
425 if (entry->ut_type == USER_PROCESS) {
426 i = entry->how_to_count;
428 /* if out of range, then count as ordinary user logged in
430 if (i == 1 || (i < 0 || i >= NCOUNT))
432 /* See if it is a pty login granted by login program */
435 /* See if user is already logged in via login pty */
437 for (cnt = 0; cnt <= pty_off; cnt++)
438 if (strncmp(pty_users[cnt], entry->ut_user, 8) == 0)
441 if (uname_off == -1) { /* user is not logged in via pty yet */
443 if (pty_off >= MAX_STRICT_USERS) /* cannot add any
445 return(MAX_STRICT_USERS + 1);
446 /* add the user name to the array of pty users */
448 strncpy(pty_users[++pty_off], entry->ut_user, 8);
450 } /* end if (i == 3) */
453 } /* end if entry->ut_type == USER_PROCESS */
454 } /* end while (entry = getutent()) */
459 * [0] does not count at all
460 * [1] counts as "real" user
461 * [2] logins via a pty which have not gone trough login. These
462 * collectively count as 1 user IF count[3] is 0, otherwise,
463 * they are not counted. Starting with HP-UX 8.0 they are
464 * no longer counted at all.
465 * [3] logins via a pty which have been logged through login (i.e.
466 * rlogin and telnet). these count as 1 "real" user per
468 * [4-15] may be used for groups of users which collectively count
472 nusers = pty_off + 1 + count[1]; /* Current number of users is sum of
473 users logged in via tty + the
474 number of unique users logged in
475 via pty which have gone through
478 #if OSMAJORVERSION < 8
479 if ((count[3] == 0) && (count[2] != 0))
480 nusers++; /* Add 1 user for all pty logins IF
481 none of pty logins have been
482 granted by the login program */
485 * Don't count any hpterm logins (exit status of 2). We already
486 * counted all pty logins granted by the login program.
490 for (i = 4; i < NCOUNT; i++)
499 /***************************************************************************
501 * PasswordAged (HPUX)
503 * see if password has aged
504 ***************************************************************************/
505 #define SECONDS_IN_WEEK 604800L
508 PasswordAged( register struct passwd *pw )
510 long change_week; /* week password was changed (1/1/70 = Week 0) */
511 long last_week; /* week after which password must change */
512 long first_week; /* week before which password can't change */
513 long this_week; /* this week derived from time() */
515 char *passwdAge; /* password aging time */
522 passwdAge = pw->pw_age;
526 passwdAge = s_pwd->pw_age;
531 /* Account validity checks: If we were able to connect to the network
532 * registry, then we've acquired account and policy data and can perform
533 * account/password checking
536 lrgy = rgy_$using_local_registry();
539 /* Check for password expiration or invalidity */
540 if ( rgy_$is_passwd_expired(&user_part, &policy ) != 0 ) {
548 if (*passwdAge == NULL)
551 first_week = last_week = change_week = (long) a64l(passwdAge);
552 last_week &= 0x3f; /* first six bits */
553 first_week = (first_week >> 6) & 0x3f; /* next six bits */
554 change_week >>= 12; /* everything else */
556 this_week = (long) time((long *) 0) / SECONDS_IN_WEEK;
559 ** Password aging conditions:
560 ** * if the last week is less than the first week (e.g., the aging
561 ** field looks like "./"), only the superuser can change the
562 ** password. We don't request a new password.
563 ** * if the week the password was last changed is after this week,
564 ** we have a problem, and request a new password.
565 ** * if this week is after the specified aging time, we request
568 if (last_week < first_week)
571 if (change_week <= this_week && this_week <= (change_week + last_week))
581 /***************************************************************************
583 * CheckPassword (HPUX only)
585 * Check validity of user password. One of several authentication schemes
586 * can be used, including Kerberos, AFS 3, HP BLS and traditional
587 * /etc/passwd. These are selectable via a resource in Dtlogin.
589 * Domain registry authentication (PasswdEtc) can also be compiled in as
590 * the only authentication scheme used.
592 ***************************************************************************/
595 CheckPassword( char *name, char *passwd, struct passwd **ppwd )
604 char realm[REALM_SZ];
606 #endif /* __KERBEROS */
611 * validate that user has an entry in the shadow password file on an
612 * HP-UX C2 trusted system. Keep info in a global structure.
616 s_pwd = getspwnam(name);
626 * look up user's regular account information...
631 * look up entry from registry...
633 * need getpwnam_full to get policy data for passwd expiration
636 p = getpwnam_full(name, &user_part, &admin_part, &policy);
644 if ( p == NULL || strlen(name) == 0 )
651 * AFS password authentication...
654 if ( vg_IsVerifyName(VN_AFS) ) {
656 if ( ka_UserAuthenticateGeneral(
657 KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
658 p->pw_name, /* kerberos name */
659 (char *)0, /* instance */
660 (char *)0, /* realm */
661 passwd, /* password */
662 0, /* default lifetime */
665 &reason) == 0 ) { /* error string */
667 if (strcmp(p->pw_passwd, "*") == 0)
674 LogError(ReadCatalog(
675 MC_LOG_SET,MC_LOG_AFS_FAILATH,MC_DEF_LOG_AFS_FAILATH),reason);
684 * Kerberos password authentication...
687 if ( vg_IsVerifyName(VN_KRB) ) {
689 (void)krb_get_lrealm(realm, 1);
691 setresuid(p->pw_uid, p->pw_uid, -1);
692 kerno = krb_get_pw_in_tkt(p->pw_name,
702 if (kerno == KSUCCESS)
703 if (strcmp(p->pw_passwd, "*") == 0)
709 #endif /* __KERBEROS */
714 * traditional password verification...
717 if (strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd) == 0)
723 * If regular passwd check fails, try old-style Apollo SR
726 if (rgy_$is_des(passwd, strlen(passwd), p->pw_passwd) == TRUE)
732 * all password checks failed...
742 /***************************************************************************
744 * Authenticate (HPUX)
748 * return codes indicate authentication results.
749 ***************************************************************************/
751 #define MAXATTEMPTS 3
753 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
756 Authenticate( struct display *d, char *name, char *passwd, char **msg )
759 static int login_attempts = 0; /* # failed authentications */
761 struct passwd *p = NULL; /* password structure */
763 struct utsname utsnam;
769 * Nothing to do if no name provided.
776 if (strlen(name) == 0)
780 return(VF_CHALLENGE);
787 * Save provided password.
790 if (!passwd) passwd = "";
794 * turn on self auditing...
797 if (audswitch(AUD_SUSPEND) == -1)
803 * set the secure flag if SECUREPASS exists. If so, we
804 * are using it for authentication instead of /etc/passwd...
807 secure = (stat(SECUREPASS, &s_pfile) < 0) ? 0:1;
811 * set the audit process flag unconditionally on since we want
812 * to log all logins regardless of whether the user's audit
817 setaudproc(AUD_PROC);
823 * validate password...
826 if ( CheckPassword(name, passwd, &p) == FALSE) {
830 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
835 Audit(p, " Failed login (bailout)", 1);
839 return(origpw ? VF_INVALID : VF_CHALLENGE);
844 * check restricted license...
846 * Note: This only applies to local displays. Foreign displays
847 * (i.e. X-terminals) apparently do not count.
850 /* Get the version info via uname. If it doesn't look right,
851 * assume the smallest user configuration
854 if (uname(&utsnam) < 0)
855 utsnam.version[0] = MIN_VERSION;
867 if ((!strncmp(utsnam.machine, "9000/834", UTSLEN)) ||
868 (!strncmp(utsnam.machine, "9000/844", UTSLEN)) ||
869 (!strncmp(utsnam.machine, "9000/836", UTSLEN)) ||
870 (!strncmp(utsnam.machine, "9000/846", UTSLEN)) ||
871 (!strncmp(utsnam.machine, "9000/843", UTSLEN)) ||
872 (!strncmp(utsnam.machine, "9000/853", UTSLEN))) {
874 /* strict_count = 1;*/
875 if (CountUsersStrict(name) > MAX_STRICT_USERS) {
877 " attempted to login - too many users on the system",
880 return(VF_MAX_USERS);
884 if (utsnam.version[0] != UNLIMITED) {
885 if ((utsnam.version[0]-'A' < 0) ||
886 (utsnam.version[0]-'A' > NUM_VERSIONS))
887 utsnam.version[0] = MIN_VERSION;
889 n = (int) utsnam.version[0] - 'A';
890 if (CountUsers(1) > num_users[n]) {
892 " attempted to login - too many users on the system",
895 return(VF_MAX_USERS);
903 * Check for account validity. Unfortunately, we have no graphical
904 * dialog for this at this time so the best we can do is log an
905 * error message and hope the system administrator sees it.
908 if ( !rgy_$using_local_registry() ) {
909 if (rgy_$is_acct_expired(&admin_part) != 0 ) {
910 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_ACC_EXP,MC_DEF_LOG_ACC_EXP),
918 * check password aging...
921 if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
925 * verify home directory exists...
928 if(chdir(p->pw_dir) < 0) {
929 Audit(p, " attempted to login - no home directory", 1);
936 * check audit flag and id...
941 if (secure && (p->pw_audflg > 1 || p->pw_audflg < 0)) {
942 Audit(p, " attempted to login - bad audit flag", 1);
943 return(VF_BAD_AFLAG);
946 if (secure && (setaudid(p->pw_audid) == -1 )) {
947 Audit(p, " attempted to login - bad audit id", 1);
954 * validate uid and gid...
957 if ((p->pw_gid < 0) ||
958 (p->pw_gid > MAXUID) ||
959 (setgid(p->pw_gid) == -1)) {
961 Audit(p, " attempted to login - bad group id", 1);
968 * ka_UserAuthenticateGeneral() sets the group access of this process
969 * to the proper PAG. Pick up these values and pass them back to
970 * Dtlogin to be put into the user's environment...
973 if ( vg_IsVerifyName(VN_AFS) ) {
974 groups[0] = groups[1] = 0;
975 getgroups(NGROUPS, groups);
981 if ((p->pw_uid < 0) ||
982 (p->pw_uid > MAXUID) ||
983 (setresuid(p->pw_uid, p->pw_uid, 0) == -1)) {
985 Audit(p, " attempted to login - bad user id", 1);
996 Audit(p, " Successful login", 0);
1003 /***************************************************************************
1007 * log bad login attempts
1009 ***************************************************************************/
1012 WriteBtmp( char *name )
1015 struct utmp utmp, *u;
1019 bzero(&utmp, sizeof(struct utmp));
1021 utmp.ut_pid = getppid();
1022 while ((u = getutent()) != NULL) {
1023 if ( (u->ut_type == INIT_PROCESS ||
1024 u->ut_type == LOGIN_PROCESS ||
1025 u->ut_type == USER_PROCESS) &&
1026 u->ut_pid == utmp.ut_pid ) {
1035 * if no utmp entry, this may be an X-terminal. Construct a utmp
1040 strncpy(utmp.ut_id, "??", sizeof(utmp.ut_id));
1041 strncpy(utmp.ut_line, globalDisplayName, sizeof(utmp.ut_line));
1042 utmp.ut_type = LOGIN_PROCESS;
1044 strncpy(utmp.ut_host, globalDisplayName, sizeof(utmp.ut_host));
1051 * If btmp exists, then record the bad attempt
1053 if ( (fd = open(BTMP_FILE,O_WRONLY|O_APPEND)) >= 0) {
1054 strncpy(u->ut_user, name, sizeof(u->ut_user));
1055 (void) time(&u->ut_time);
1056 write(fd, (char *)u, sizeof(utmp));
1060 endutent(); /* Close utmp file */
1063 /***************************************************************************
1065 * End authentication routines (HPUX)
1067 ***************************************************************************/
1071 /***************************************************************************
1072 ***************************************************************************
1073 ***************************************************************************
1074 ***************************************************************************
1075 ***************************************************************************
1076 ***************************************************************************
1077 ***************************************************************************
1078 ***************************************************************************/
1081 #if defined(__uxp__)
1083 /***************************************************************************
1085 * Start authentication routines (UXP)
1087 ***************************************************************************/
1092 /***************************************************************************
1094 * External declarations (UXP)
1096 ***************************************************************************/
1101 /***************************************************************************
1103 * Procedure declarations (UXP)
1105 ***************************************************************************/
1107 static void Audit( struct passwd *p, char *msg, int errnum) ;
1108 static int PasswordAged( register struct passwd *pw) ;
1109 static void WriteBtmp( char *name) ;
1114 /***************************************************************************
1116 * Global variables (UXP)
1118 ***************************************************************************/
1123 /***************************************************************************
1127 ***************************************************************************/
1130 Audit( struct passwd *p, char *msg, int errnum )
1134 * make sure program is back to super-user...
1145 /***************************************************************************
1149 * log bad login attempts
1151 ***************************************************************************/
1154 WriteBtmp( char *name )
1162 /***************************************************************************
1164 * PasswordAged (UXP)
1166 * see if password has aged
1167 ***************************************************************************/
1168 #define SECONDS_IN_WEEK 604800L
1171 PasswordAged( register struct passwd *pw )
1173 long change_week; /* week password was changed (1/1/70 = Week 0) */
1174 long last_week; /* week after which password must change */
1175 long first_week; /* week before which password can't change */
1176 long this_week; /* this week derived from time() */
1177 char *file; /* help file name */
1178 char *command; /* the /bin/passwd command string */
1180 if (*pw->pw_age == NULL)
1183 first_week = last_week = change_week = (long) a64l(pw->pw_age);
1184 last_week &= 0x3f; /* first six bits */
1185 first_week = (first_week >> 6) & 0x3f; /* next six bits */
1186 change_week >>= 12; /* everything else */
1188 this_week = (long) time((long *) 0) / SECONDS_IN_WEEK;
1191 ** Password aging conditions:
1192 ** * if the last week is less than the first week (e.g., the aging
1193 ** field looks like "./"), only the superuser can change the
1194 ** password. We don't request a new password.
1195 ** * if the week the password was last changed is after this week,
1196 ** we have a problem, and request a new password.
1197 ** * if this week is after the specified aging time, we request
1200 if (last_week < first_week)
1203 if (change_week <= this_week && this_week <= (change_week + last_week))
1212 /***************************************************************************
1214 * Authenticate (UXP)
1218 * return codes indicate authentication results.
1219 ***************************************************************************/
1221 #define MAXATTEMPTS 3
1223 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
1226 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1229 static int login_attempts = 0; /* # failed authentications */
1231 struct passwd *p; /* password structure */
1232 struct spwd *sp; /* shadow info */
1240 * Nothing to do if no name provided.
1246 * Save provided password.
1249 if (!passwd) passwd = "";
1253 sp = getspnam(name);
1255 if (!p || strlen(name) == 0 ||
1256 strcmp (crypt (passwd, sp->sp_pwdp), sp->sp_pwdp)) {
1260 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
1265 Audit(p, " Failed login (bailout)", 1);
1269 return(origpw ? VF_INVALID : VF_CHALLENGE);
1274 * check password aging...
1277 if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
1280 * verify home directory exists...
1283 if(chdir(p->pw_dir) < 0) {
1284 Audit(p, " attempted to login - no home directory", 1);
1290 * validate uid and gid...
1294 if ((p->pw_gid < 0) ||
1295 (setgid(p->pw_gid) == -1)) {
1297 Audit(p, " attempted to login - bad group id", 1);
1301 if ((p->pw_uid < 0) ||
1302 (seteuid(p->pw_uid) == -1)) {
1304 Audit(p, " attempted to login - bad user id", 1);
1314 Audit(p, " Successful login", 0);
1320 /***************************************************************************
1322 * End authentication routines (UXP)
1324 ***************************************************************************/
1327 /***************************************************************************
1328 ***************************************************************************
1329 ***************************************************************************
1330 ***************************************************************************
1331 ***************************************************************************
1332 ***************************************************************************
1333 ***************************************************************************
1334 ***************************************************************************/
1338 /***************************************************************************
1340 * Start authentication routines (SUN)
1342 ***************************************************************************/
1344 #include "solaris.h"
1346 #include <security/ia_appl.h>
1350 /***************************************************************************
1352 * Procedure declarations (SUN)
1354 ***************************************************************************/
1356 static void Audit( struct passwd *p, char *msg, int errnum) ;
1360 /***************************************************************************
1364 ***************************************************************************/
1367 Audit( struct passwd *p, char *msg, int errnum )
1371 * make sure program is back to super-user...
1376 Debug("Audit: %s\n", msg);
1382 /***************************************************************************
1384 * Authenticate (SUN)
1388 * return codes indicate authentication results.
1389 ***************************************************************************/
1392 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1395 char* ttyLine = d->gettyLine;
1398 * Nothing to do if no name provided.
1405 * Construct device line
1407 #ifdef DEF_NETWORK_DEV
1409 * If location is not local (remote XDMCP dtlogin) and
1410 * remote accouting is enabled (networkDev start with /dev/...)
1411 * Set tty line name to match network device for accouting.
1412 * Unless the resource was specifically set, default is value
1413 * of DEF_NETWORK_DEV define (/dev/dtremote)
1416 if ( d->displayType.location != Local &&
1417 networkDev && !strncmp(networkDev,"/dev/",5)) {
1418 ttyLine = networkDev+5;
1423 * Authenticate user and return status
1427 status = PamAuthenticate("dtlogin", d->name, passwd, name, ttyLine);
1433 case PAM_NEW_AUTHTOK_REQD:
1434 return(VF_PASSWD_AGED);
1437 return(passwd ? VF_INVALID : VF_CHALLENGE);
1440 status = solaris_authenticate("dtlogin", d->name, passwd, name, ttyLine);
1446 case IA_NEWTOK_REQD:
1447 return(VF_PASSWD_AGED);
1450 return(passwd ? VF_INVALID : VF_CHALLENGE);
1457 /***************************************************************************
1459 * End authentication routines (SUN)
1461 ***************************************************************************/
1464 /***************************************************************************
1465 ***************************************************************************
1466 ***************************************************************************
1467 ***************************************************************************
1468 ***************************************************************************/
1470 /***************************************************************************
1474 * get the information from the display about local/remote login and
1475 * create a dummy tty name for loginrestrictions.
1477 ***************************************************************************/
1479 GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname)
1483 CleanUpName(d->name, workarea, 128);
1484 sprintf(ttyName, "/dev/dtlogin/%s", workarea);
1486 if (d->displayType.location == Foreign) {
1487 *loginType = S_RLOGIN;
1488 *hostname = d->name;
1489 Debug("Login Info - Remote user on tty=%s.\n", ttyName);
1491 *loginType = S_LOGIN;
1493 Debug("Login Info - Local user on tty=%s.\n", ttyName);
1497 /***************************************************************************
1499 * Authenticate (AIX version 4.1)
1503 * return codes indicate authentication results.
1504 ***************************************************************************/
1505 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1511 static char *msgpending;
1516 GetLoginInfo(d, &loginType, tty, &hostname);
1526 * No more challenges. User failed login.
1529 loginfailed(name, hostname, tty);
1534 * Authenticate with response to last challenge.
1536 rc = authenticate(name, passwd, &reenter, msg);
1541 * System has presented user with new challenge.
1543 return(VF_CHALLENGE);
1546 if (rc && errno == ENOENT)
1549 * User is unknown to the system. Simulate a password
1550 * challenge, but save message for display for next call.
1553 return(VF_CHALLENGE);
1559 * No more challenges. User failed login.
1561 loginfailed(name, hostname, tty);
1566 * User authenticated. Check login restrictions.
1568 rc = loginrestrictions(name, loginType, tty, msg);
1573 * Login restrictions disallow login.
1575 loginfailed(name, hostname, tty);
1580 * Check password expiration.
1582 rc = passwdexpired(name, msg);
1587 * Login succeeded, but password expired.
1589 return(VF_PASSWD_AGED);
1595 loginsuccess(name, hostname, tty, msg);
1602 /***************************************************************************
1604 * Start authentication routines (AIX)
1606 ***************************************************************************/
1609 #include <sys/types.h>
1610 #include <sys/errno.h>
1611 #include <usersec.h>
1613 #include <userconf.h>
1617 /***************************************************************************
1619 * External declarations (AIX)
1621 ***************************************************************************/
1626 /***************************************************************************
1628 * Procedure declarations (AIX)
1630 ***************************************************************************/
1632 static void Audit( struct passwd *p, char *msg, int errnum) ;
1633 static int PasswordAged(char *name, register struct passwd *pw) ;
1634 static void WriteBtmp( char *name) ;
1639 /***************************************************************************
1641 * Global variables (AIX)
1643 ***************************************************************************/
1648 /***************************************************************************
1652 ***************************************************************************/
1655 Audit( struct passwd *p, char *msg, int errnum )
1659 * make sure program is back to super-user...
1663 if ( (auditwrite ("USER_Login", AUDIT_OK,
1664 p->pw_name, strlen (p->pw_name) + 1,
1665 msg, strlen (msg) + 1, NULL)) == -1 )
1666 Debug(" Could not do Auditing\n");
1673 /***************************************************************************
1677 * log bad login attempts to /etc/security/failedlogin file
1680 ***************************************************************************/
1683 WriteBtmp( char *name )
1688 if( (fd = open("/etc/security/failedlogin",O_CREAT|O_RDWR,0644)) != -1) {
1689 bzero(&ut,sizeof(struct utmp));
1691 strncpy(ut.ut_user, name, sizeof ut.ut_user);
1692 ut.ut_type = USER_PROCESS;
1693 ut.ut_pid = getpid();
1694 ut.ut_time = time((time_t *)0);
1695 write(fd, (char *)&ut, sizeof(struct utmp));
1703 /***************************************************************************
1705 * PasswordAged (AIX)
1707 * see if password has aged
1708 ***************************************************************************/
1709 #define SECONDS_IN_WEEK 604800L
1712 PasswordAged(char *name, register struct passwd *pw )
1714 struct userpw *pupw; /* authentication information from getuserpw() */
1715 struct userpw upw; /* working authentication information */
1716 int err; /* return code from getconfattr() */
1717 ulong maxage; /* maximun age from getconfattr() */
1718 ulong now; /* time now */
1724 * Determine user password aging criteria. Note that only
1725 * the 'lastupdate' and 'flags' fields are set by this operation.
1728 if ((pupw = getuserpw(name)) != NULL)
1730 upw.upw_lastupdate = pupw->upw_lastupdate;
1731 upw.upw_flags = pupw->upw_flags;
1735 upw.upw_lastupdate = 0;
1741 * Consider password as having not expired if nocheck set.
1743 if (upw.upw_flags & PW_NOCHECK) return(FALSE);
1746 * Get system password aging criteria.
1748 err = getconfattr (SC_SYS_PASSWD, SC_MAXAGE, (void *)&maxage, SEC_INT);
1752 * Change from weeks to seconds
1754 maxage = maxage * SECONDS_IN_WEEK;
1755 now = time ((long *) 0);
1757 if ((upw.upw_lastupdate + maxage) >= now)
1760 * Password has not expired.
1768 * Could not retrieve system password aging info or maxage set to
1769 * zero. In either case, consider password has having not expired.
1775 * We haven't returned by now, so indicate password has expired.
1781 /***************************************************************************
1782 * dt_failedlogin (AIX)
1784 * log failed login in /etc/security/lastlog
1785 ***************************************************************************/
1797 dt_lastlogin ( char * user, struct lastlogin * llogin);
1800 dt_failedlogin(char *name, char *ttyName, char *hostName)
1802 struct lastlogin last_login;
1804 last_login.stime = 0;
1806 time(&last_login.ftime);
1808 last_login.ftty = ttyName;
1810 last_login.fhost = (char *) malloc (MAXHOSTNAMELEN);
1811 if (hostName == NULL) {
1812 gethostname (last_login.fhost , MAXHOSTNAMELEN);
1814 strncpy(last_login.fhost, hostName, MAXHOSTNAMELEN);
1815 last_login.fhost[MAXHOSTNAMELEN -1] = '\0';
1818 Debug("logging failed lastlogin entry (user=%s)\n",name);
1819 dt_lastlogin(name, &last_login);
1820 free(last_login.fhost);
1825 /***************************************************************************
1827 * Authenticate (AIX)
1831 * return codes indicate authentication results.
1832 ***************************************************************************/
1834 #define MAXATTEMPTS 3
1836 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
1839 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1842 static int login_attempts = 0; /* # failed authentications */
1843 struct passwd *p; /* password structure */
1851 * Nothing to do if no name provided.
1857 * Save provided password.
1860 if (!passwd) passwd = "";
1862 if(strlen(name) > S_NAMELEN)
1865 GetLoginInfo(d, &loginType, tty, &hostname);
1869 if (!p || strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd)) {
1873 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
1878 Audit(p, " Failed login (bailout)", 1);
1882 dt_failedlogin(name, tty, hostname);
1883 return (VF_INVALID);
1885 return(VF_CHALLENGE);
1888 /* Note: The password should be checked if it is the first time
1889 the user is logging in or whether the sysadm has changed
1890 the password for the user. Code should be added here if
1891 this functionality should be supported. The "upw_flags"
1892 of the password structure gets set to PW_ADMCHG in this
1897 * check password aging...
1900 if ( PasswordAged(name,p) ) return(VF_PASSWD_AGED);
1903 /* Validate for User Account RK 09.13.93 */
1904 if(ckuseracct(name, loginType, tty) == -1) {
1905 dt_failedlogin(name, tty, hostname);
1911 * validate uid and gid...
1915 if ((p->pw_gid < 0) ||
1916 (setgid(p->pw_gid) == -1)) {
1918 Audit(p, " attempted to login - bad group id", 1);
1922 if ((p->pw_uid < 0)) {
1923 Audit(p, " attempted to login - bad user id", 1);
1927 /* Check for max number of logins RK 09.13.93 */
1928 if (tsm_check_login(p->pw_uid) == -1) {
1929 dt_failedlogin(name, tty, hostname);
1933 /* Check for /etc/nologin file RK 09.13.93 */
1934 if ( (access("/etc/nologin",R_OK) == 0) && (p->pw_uid != 0) ) {
1935 dt_failedlogin(name, tty, hostname);
1940 * verify home directory exists...
1943 if(chdir(p->pw_dir) < 0) {
1944 Audit(p, " attempted to login - no home directory", 1);
1952 Audit(p, " Successful login", 0);
1956 /**************************************************************************
1960 * Checks for max number of logins on the system. If the new user trying to
1961 * login exceeds the max limit then the user is not allowed to login.
1964 **************************************************************************/
1966 /**************************************************************************
1970 * Checks for max number of logins on the system. If the new user trying to
1971 * login exceeds the max limit then the user is not allowed to login.
1974 **************************************************************************/
1977 tsm_check_login(uid_t uid)
1984 struct stat stat_buf;
1985 static struct sembuf sop = { 0, -1, (SEM_UNDO|IPC_NOWAIT) };
1986 static struct sembuf initsop = { 0, 0, (IPC_NOWAIT) };
1989 * The login counter semaphore may not be set yet. See if it exists
1990 * and try creating it with the correct count if it doesn't. An
1991 * attempt is made to create the semaphore. Only if that attempt fails
1992 * is the semaphore set to maxlogins from login.cfg.
1997 * Don't Check if the user is already logged. ie running login
2001 * Generate the semaphore key from the init program.
2003 Debug("Start of maxlogin check\n");
2004 if ((key = ftok (CDE_INSTALLATION_TOP "/bin/dtlogin", 1)) != (key_t) -1) {
2005 Debug("key created\n");
2006 if ((semid = semget (key, 1, IPC_CREAT|IPC_EXCL|0600)) != -1) {
2008 Debug("Completed IPCkey\n");
2009 if (! getconfattr ("usw", "maxlogins", &i, SEC_INT)) {
2010 Debug("Max logins from login.cfg is :%d\n",i);
2012 i = 10000; /* a very large number */
2015 if (semop (semid, &initsop, 1))
2017 Debug("failed while decrementing\n");
2021 semctl (semid, 1, IPC_RMID, 0);
2026 * Only 'n' login sessions are allowed on the system.
2027 * This code block decrements a semaphore.
2028 * The semundo value will be set to adjust the
2029 * semaphore when tsm exits.
2031 * This code will be ignored if the appropriate
2032 * semaphore set does not exist.
2035 if ((semid = semget (key, 1, 0)) != -1) {
2036 Debug("getting key for maxlogins\n");
2038 * If the semaphore is zero and we are not
2039 * root, then we fail as there are already the
2040 * allotted number of login sessions on the
2043 if ((semop (semid, &sop, 1) == -1) && uid) {
2044 Debug("reached MAXLOGINS limit\n");
2052 #endif /* !_POWER */
2054 /***************************************************************************
2056 * End authentication routines (AIX)
2058 ***************************************************************************/
2060 /***************************************************************************
2061 ***************************************************************************
2062 ***************************************************************************
2063 ***************************************************************************
2064 ***************************************************************************
2065 ***************************************************************************
2066 ***************************************************************************
2067 ***************************************************************************/
2071 /***************************************************************************
2073 * Start authentication routines (USL)
2075 ***************************************************************************/
2078 #define LOGIN_SUCCESS 0
2079 #define LOGIN_FAIL 1
2089 /***************************************************************************
2091 * External declarations (USL)
2093 ***************************************************************************/
2097 /***************************************************************************
2099 * Procedure declarations (USL)
2101 ***************************************************************************/
2104 static void Audit( struct passwd *p, char *msg, int errnum) ;
2105 static int PasswordAged( register struct passwd *pw) ;
2106 static void WriteBtmp( char *name) ;
2110 /***************************************************************************
2112 * Global variables (USL)
2114 ***************************************************************************/
2116 extern int Slaveptty_fd;
2119 /***************************************************************************
2123 ***************************************************************************/
2126 Audit( struct passwd *p, char *msg, int errnum )
2130 * make sure program is back to super-user...
2141 /***************************************************************************
2145 * log bad login attempts
2147 ***************************************************************************/
2150 WriteBtmp( char *name )
2158 /***************************************************************************
2160 * Authenticate (USL)
2164 * return codes indicate authentication results.
2165 ***************************************************************************/
2167 #define MAXATTEMPTS 3
2170 Authenticate( struct display *d, char *name, char *passwd, char **msg )
2183 * Nothing to do if no name provided.
2189 * Save provided password.
2192 if (!passwd) passwd = "";
2195 * Put the logname and the passwd on the ava stream
2197 if ((ret = dup2 (Slaveptty_fd, 0)) == -1)
2198 Debug ("Problem with dup2\n");
2200 ava = retava(Slaveptty_fd);
2202 (void) bzero (xlogname, strlen (xlogname));
2203 (void) sprintf (xlogname, "XLOGNAME=%s", name);
2204 if ((ava = putava (xlogname, ava)) == NULL)
2206 Debug ("Could not set logname ava\n");
2209 (void) bzero (xpasswd, strlen (xpasswd));
2210 (void) sprintf (xpasswd, "XPASSWD=%s", passwd);
2211 if ((ava = putava (xpasswd, ava)) == NULL)
2213 Debug ("Could not set passwd ava\n");
2216 (void) bzero (xtty, strlen (xtty));
2217 (void) sprintf (xtty, "XTTY=%s", ttyname(Slaveptty_fd));
2218 if ((ava = putava (xtty, ava)) == NULL)
2220 Debug ("Could not set tty ava\n");
2223 if (setava (Slaveptty_fd, ava) != 0)
2225 Debug ("Could not do setava\n");
2229 * invoke identification and authorizarion scheme
2232 switch (ret = invoke (Slaveptty_fd, "login"))
2236 Audit(p, " Successful login", 0);
2239 return(origpw ? VF_INVALID : VF_CHALLENGE);
2241 /* The next three cases need to define special return values */
2242 /* for the aged passwords and accounts. */
2246 /* PasswdAged (linfo); */
2247 return(VF_PASSWD_AGED);
2248 case EXPIRED: /* SS */
2249 /* AccountAged (linfo); */
2250 return(VF_PASSWD_AGED);
2252 /* These 3 cases should allow user to select a new password */
2253 /* after displaying a warning, but current implementation */
2254 /* only displays the warning. */
2259 return(VF_PASSWD_AGED);
2261 return(VF_INVALID); /* SS */
2266 /***************************************************************************
2268 * End authentication routines (USL)
2270 ***************************************************************************/
2274 /***************************************************************************
2276 * Start authentication routines (generic)
2278 ***************************************************************************/
2281 /***************************************************************************
2283 * These are a set of routine to do simple password, home dir, uid, and gid
2284 * validation. They can be used as a first pass validation for future
2287 * When platform specific validation is developed, those routines should be
2288 * included in their own section and the use of these routines discontinued.
2290 ***************************************************************************/
2295 /***************************************************************************
2297 * External declarations (generic)
2299 ***************************************************************************/
2304 /***************************************************************************
2306 * Procedure declarations (generic)
2308 ***************************************************************************/
2310 static void Audit( struct passwd *p, char *msg, int errnum) ;
2311 static int PasswordAged( register struct passwd *pw) ;
2312 static void WriteBtmp( char *name) ;
2317 /***************************************************************************
2319 * Global variables (generic)
2321 ***************************************************************************/
2326 /***************************************************************************
2330 ***************************************************************************/
2333 Audit( struct passwd *p, char *msg, int errnum )
2337 * make sure program is back to super-user...
2339 if(-1 == seteuid(0)) {
2340 perror(strerror(errno));
2349 /***************************************************************************
2351 * WriteBtmp (generic)
2353 * log bad login attempts
2355 ***************************************************************************/
2358 WriteBtmp( char *name )
2366 /***************************************************************************
2368 * PasswordAged (Generic)
2370 * see if password has aged
2371 ***************************************************************************/
2372 #define SECONDS_IN_WEEK 604800L
2375 PasswordAged( register struct passwd *pw )
2382 /***************************************************************************
2384 * Authenticate (generic)
2388 * return codes indicate authentication results.
2389 ***************************************************************************/
2391 #define MAXATTEMPTS 3
2393 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
2396 Authenticate( struct display *d, char *name, char *passwd, char **msg )
2399 static int login_attempts = 0; /* # failed authentications */
2401 struct passwd *p; /* password structure */
2409 * Nothing to do if no name provided.
2415 * Save provided password.
2418 if (!passwd) passwd = "";
2424 * Use the Linux Shadow Password system to get the crypt()ed password
2427 struct spwd *s = getspnam(name);
2429 p->pw_passwd = s->sp_pwdp;
2434 if (!p || strlen(name) == 0 ||
2435 strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd)) {
2439 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
2444 Audit(p, " Failed login (bailout)", 1);
2448 return(origpw ? VF_INVALID : VF_CHALLENGE);
2453 * check password aging...
2456 if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
2460 * verify home directory exists...
2463 if(chdir(p->pw_dir) < 0) {
2464 Audit(p, " attempted to login - no home directory", 1);
2470 * validate uid and gid...
2474 if (setgid(p->pw_gid) == -1) {
2476 Audit(p, " attempted to login - bad group id", 1);
2480 if (seteuid(p->pw_uid) == -1) {
2482 Audit(p, " attempted to login - bad user id", 1);
2492 Audit(p, " Successful login", 0);
2499 /***************************************************************************
2501 * End authentication routines (generic)
2503 ***************************************************************************/
2504 #endif /* generic */
2508 /***************************************************************************
2509 ***************************************************************************
2510 ***************************************************************************
2511 ***************************************************************************
2512 ***************************************************************************
2513 ***************************************************************************
2514 ***************************************************************************
2515 ***************************************************************************/