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 librararies 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>
139 /***************************************************************************
141 * Start authentication routines (HPUX)
143 ***************************************************************************/
145 #include <sys/param.h> /* for MAXUID macro */
146 #include <sys/types.h>
147 #include <sys/utsname.h>
154 # include <sys/audit.h>
155 # include <sys/errno.h>
156 # include <sys/stat.h>
157 # define SECUREPASS "/.secure/etc/passwd"
161 # include <sys/security.h>
166 #include <afs/kautils.h>
171 # define KRBLIFE 255 /* max lifetime */
172 #endif /* __KERBEROS */
175 # include "rgy_base.h"
180 #define how_to_count ut_exit.e_exit
183 int num_users[] = { 2, 32767 };
184 # define MIN_VERSION 'A'
185 # define UNLIMITED 'B'
187 int num_users[] = { 2, 16, 32, 64 , 8 };
188 # define MIN_VERSION 'A'
189 # define UNLIMITED 'U'
192 /* Maximum number of users allowed with restricted license */
193 #if OSMAJORVERSION < 8
194 # define MAX_STRICT_USERS 2
196 # define MAX_STRICT_USERS 8
199 #define NUM_VERSIONS (sizeof(num_users)/sizeof(num_users[0])) - 1
201 extern char *globalDisplayName;
203 /***************************************************************************
205 * External declarations (HPUX)
207 ***************************************************************************/
209 extern long groups[NGROUPS];
213 extern boolean rgy_$using_local_registry();
214 extern struct passwd * getpwnam_full();
215 extern boolean is_acct_expired();
216 extern boolean is_passwd_expired();
217 extern boolean is_passwd_invalid();
218 extern boolean rgy_$is_des();
223 /***************************************************************************
225 * Procedure declarations (HPUX)
227 ***************************************************************************/
229 static void Audit( struct passwd *p, char *msg, int errnum) ;
230 static int CheckPassword( char *name, char *passwd, struct passwd **ppwd );
231 static int CountUsers( int added_users) ;
232 static int CountUsersStrict( char *new_user) ;
233 static int PasswordAged( register struct passwd *pw) ;
234 static void WriteBtmp( char *name) ;
239 /***************************************************************************
241 * Global variables (HPUX)
243 ***************************************************************************/
246 struct s_passwd *s_pwd;
248 int secure; /* flag to denote existance of secure passwd file */
253 struct pr_passwd *b1_pwd;
257 rgy_$acct_admin_t admin_part;
258 rgy_$policy_t policy;
259 rgy_$acct_user_t user_part;
264 /***************************************************************************
268 * Construct self audit record for event and write to the audit trail.
269 * This routine assumes that the effective uid is currently 0. If auditing
270 * is not defined, this routine does nothing.
271 ***************************************************************************/
274 Audit( struct passwd *p, char *msg, int errnum )
280 struct self_audit_rec audrec;
285 * make sure program is back to super-user...
293 txtptr = (char *)audrec.aud_body.text;
294 sprintf(txtptr, "User= %s uid=%ld audid=%ld%s", p->pw_name,
295 (long)p->pw_uid, (long)p->pw_audid, msg);
296 audrec.aud_head.ah_pid = getpid();
297 audrec.aud_head.ah_error = errnum;
298 audrec.aud_head.ah_event = EN_LOGINS;
299 audrec.aud_head.ah_len = strlen (txtptr);
300 status = audwrite(&audrec);
306 LogError(ReadCatalog(
307 MC_LOG_SET,MC_LOG_NOT_SUSER,MC_DEF_LOG_NOT_SUSER));
311 LogError(ReadCatalog(
312 MC_LOG_SET,MC_LOG_INV_EVENT,MC_DEF_LOG_INV_EVENT));
316 LogError(ReadCatalog(
317 MC_LOG_SET,MC_LOG_ERR_ERRNO,MC_DEF_LOG_ERR_ERRNO),
334 /***************************************************************************
336 * CountUsers (HPUX only)
338 * see if new user has exceeded the maximum.
339 ***************************************************************************/
344 CountUsers( int added_users )
346 int count[NCOUNT], nusers, i;
349 for (i=0; i<NCOUNT; i++)
352 count[added_users]++;
354 while ( (entry = getutent()) != NULL) {
355 if (entry->ut_type == USER_PROCESS) {
356 i = entry->how_to_count;
357 if (i < 0 || i >= NCOUNT)
358 i = 1; /* if out of range, then count */
359 /* as ordinary user */
367 * [0] does not count at all
368 * [1] counts as real user
369 * [2] logins via a pty which have not gone trough login. These
370 * collectively count as 1 user IF count[3] is 0, otherwise,
371 * they are not counted. Starting with HP-UX 8.0 they are
372 * no longer counted at all.
373 * [3] logins via a pty which have been logged through login (i.e.
374 * rlogin and telnet). these count as 1 "real" user per
376 * [4-15] may be used for groups of users which collectively
381 #if OSMAJORVERSION < 8
382 for (i=2; i<NCOUNT; i++)
384 for (i=3; i<NCOUNT; i++)
395 /***************************************************************************
397 * CountUsersStrict (HPUX only)
399 * see if new user has exceeded the maximum.
400 ***************************************************************************/
403 CountUsersStrict( char *new_user )
405 char pty_users[MAX_STRICT_USERS][8];
406 int count[NCOUNT], nusers, i, cnt, pty_off = -1, uname_off;
410 * Initialize count array...
412 for (i = 0; i < NCOUNT; i++)
416 * Add in the new user (we know it's not a pty)...
420 while ( (entry = getutent()) != NULL ) {
421 if (entry->ut_type == USER_PROCESS) {
422 i = entry->how_to_count;
424 /* if out of range, then count as ordinary user logged in
426 if (i == 1 || (i < 0 || i >= NCOUNT))
428 /* See if it is a pty login granted by login program */
431 /* See if user is already logged in via login pty */
433 for (cnt = 0; cnt <= pty_off; cnt++)
434 if (strncmp(pty_users[cnt], entry->ut_user, 8) == 0)
437 if (uname_off == -1) { /* user is not logged in via pty yet */
439 if (pty_off >= MAX_STRICT_USERS) /* cannot add any
441 return(MAX_STRICT_USERS + 1);
442 /* add the user name to the array of pty users */
444 strncpy(pty_users[++pty_off], entry->ut_user, 8);
446 } /* end if (i == 3) */
449 } /* end if entry->ut_type == USER_PROCESS */
450 } /* end while (entry = getutent()) */
455 * [0] does not count at all
456 * [1] counts as "real" user
457 * [2] logins via a pty which have not gone trough login. These
458 * collectively count as 1 user IF count[3] is 0, otherwise,
459 * they are not counted. Starting with HP-UX 8.0 they are
460 * no longer counted at all.
461 * [3] logins via a pty which have been logged through login (i.e.
462 * rlogin and telnet). these count as 1 "real" user per
464 * [4-15] may be used for groups of users which collectively count
468 nusers = pty_off + 1 + count[1]; /* Current number of users is sum of
469 users logged in via tty + the
470 number of unique users logged in
471 via pty which have gone through
474 #if OSMAJORVERSION < 8
475 if ((count[3] == 0) && (count[2] != 0))
476 nusers++; /* Add 1 user for all pty logins IF
477 none of pty logins have been
478 granted by the login program */
481 * Don't count any hpterm logins (exit status of 2). We already
482 * counted all pty logins granted by the login program.
486 for (i = 4; i < NCOUNT; i++)
495 /***************************************************************************
497 * PasswordAged (HPUX)
499 * see if password has aged
500 ***************************************************************************/
501 #define SECONDS_IN_WEEK 604800L
504 PasswordAged( register struct passwd *pw )
506 long change_week; /* week password was changed (1/1/70 = Week 0) */
507 long last_week; /* week after which password must change */
508 long first_week; /* week before which password can't change */
509 long this_week; /* this week derived from time() */
511 char *passwdAge; /* password aging time */
518 passwdAge = pw->pw_age;
522 passwdAge = s_pwd->pw_age;
527 /* Account validity checks: If we were able to connect to the network
528 * registry, then we've acquired account and policy data and can perform
529 * account/password checking
532 lrgy = rgy_$using_local_registry();
535 /* Check for password expiration or invalidity */
536 if ( rgy_$is_passwd_expired(&user_part, &policy ) != 0 ) {
544 if (*passwdAge == NULL)
547 first_week = last_week = change_week = (long) a64l(passwdAge);
548 last_week &= 0x3f; /* first six bits */
549 first_week = (first_week >> 6) & 0x3f; /* next six bits */
550 change_week >>= 12; /* everything else */
552 this_week = (long) time((long *) 0) / SECONDS_IN_WEEK;
555 ** Password aging conditions:
556 ** * if the last week is less than the first week (e.g., the aging
557 ** field looks like "./"), only the superuser can change the
558 ** password. We don't request a new password.
559 ** * if the week the password was last changed is after this week,
560 ** we have a problem, and request a new password.
561 ** * if this week is after the specified aging time, we request
564 if (last_week < first_week)
567 if (change_week <= this_week && this_week <= (change_week + last_week))
577 /***************************************************************************
579 * CheckPassword (HPUX only)
581 * Check validity of user password. One of several authentication schemes
582 * can be used, including Kerberos, AFS 3, HP BLS and traditional
583 * /etc/passwd. These are selectable via a resource in Dtlogin.
585 * Domain registry authentication (PasswdEtc) can also be compiled in as
586 * the only authentication scheme used.
588 ***************************************************************************/
591 CheckPassword( char *name, char *passwd, struct passwd **ppwd )
600 char realm[REALM_SZ];
602 #endif /* __KERBEROS */
607 * validate that user has an entry in the shadow password file on an
608 * HP-UX C2 trusted system. Keep info in a global structure.
612 s_pwd = getspwnam(name);
622 * look up user's regular account information...
627 * look up entry from registry...
629 * need getpwnam_full to get policy data for passwd expiration
632 p = getpwnam_full(name, &user_part, &admin_part, &policy);
640 if ( p == NULL || strlen(name) == 0 )
647 * AFS password authentication...
650 if ( vg_IsVerifyName(VN_AFS) ) {
652 if ( ka_UserAuthenticateGeneral(
653 KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
654 p->pw_name, /* kerberos name */
655 (char *)0, /* instance */
656 (char *)0, /* realm */
657 passwd, /* password */
658 0, /* default lifetime */
661 &reason) == 0 ) { /* error string */
663 if (strcmp(p->pw_passwd, "*") == 0)
670 LogError(ReadCatalog(
671 MC_LOG_SET,MC_LOG_AFS_FAILATH,MC_DEF_LOG_AFS_FAILATH),reason);
680 * Kerberos password authentication...
683 if ( vg_IsVerifyName(VN_KRB) ) {
685 (void)krb_get_lrealm(realm, 1);
687 setresuid(p->pw_uid, p->pw_uid, -1);
688 kerno = krb_get_pw_in_tkt(p->pw_name,
698 if (kerno == KSUCCESS)
699 if (strcmp(p->pw_passwd, "*") == 0)
705 #endif /* __KERBEROS */
710 * traditional password verification...
713 if (strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd) == 0)
719 * If regular passwd check fails, try old-style Apollo SR
722 if (rgy_$is_des(passwd, strlen(passwd), p->pw_passwd) == TRUE)
728 * all password checks failed...
738 /***************************************************************************
740 * Authenticate (HPUX)
744 * return codes indicate authentication results.
745 ***************************************************************************/
747 #define MAXATTEMPTS 3
749 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
752 Authenticate( struct display *d, char *name, char *passwd, char **msg )
755 static int login_attempts = 0; /* # failed authentications */
757 struct passwd *p = NULL; /* password structure */
759 struct utsname utsnam;
765 * Nothing to do if no name provided.
772 if (strlen(name) == 0)
776 return(VF_CHALLENGE);
783 * Save provided password.
786 if (!passwd) passwd = "";
790 * turn on self auditing...
793 if (audswitch(AUD_SUSPEND) == -1)
799 * set the secure flag if SECUREPASS exists. If so, we
800 * are using it for authentication instead of /etc/passwd...
803 secure = (stat(SECUREPASS, &s_pfile) < 0) ? 0:1;
807 * set the audit process flag unconditionally on since we want
808 * to log all logins regardless of whether the user's audit
813 setaudproc(AUD_PROC);
819 * validate password...
822 if ( CheckPassword(name, passwd, &p) == FALSE) {
826 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
831 Audit(p, " Failed login (bailout)", 1);
835 return(origpw ? VF_INVALID : VF_CHALLENGE);
840 * check restricted license...
842 * Note: This only applies to local displays. Foreign displays
843 * (i.e. X-terminals) apparently do not count.
846 /* Get the version info via uname. If it doesn't look right,
847 * assume the smallest user configuration
850 if (uname(&utsnam) < 0)
851 utsnam.version[0] = MIN_VERSION;
863 if ((!strncmp(utsnam.machine, "9000/834", UTSLEN)) ||
864 (!strncmp(utsnam.machine, "9000/844", UTSLEN)) ||
865 (!strncmp(utsnam.machine, "9000/836", UTSLEN)) ||
866 (!strncmp(utsnam.machine, "9000/846", UTSLEN)) ||
867 (!strncmp(utsnam.machine, "9000/843", UTSLEN)) ||
868 (!strncmp(utsnam.machine, "9000/853", UTSLEN))) {
870 /* strict_count = 1;*/
871 if (CountUsersStrict(name) > MAX_STRICT_USERS) {
873 " attempted to login - too many users on the system",
876 return(VF_MAX_USERS);
880 if (utsnam.version[0] != UNLIMITED) {
881 if ((utsnam.version[0]-'A' < 0) ||
882 (utsnam.version[0]-'A' > NUM_VERSIONS))
883 utsnam.version[0] = MIN_VERSION;
885 n = (int) utsnam.version[0] - 'A';
886 if (CountUsers(1) > num_users[n]) {
888 " attempted to login - too many users on the system",
891 return(VF_MAX_USERS);
899 * Check for account validity. Unfortunately, we have no graphical
900 * dialog for this at this time so the best we can do is log an
901 * error message and hope the system administrator sees it.
904 if ( !rgy_$using_local_registry() ) {
905 if (rgy_$is_acct_expired(&admin_part) != 0 ) {
906 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_ACC_EXP,MC_DEF_LOG_ACC_EXP),
914 * check password aging...
917 if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
921 * verify home directory exists...
924 if(chdir(p->pw_dir) < 0) {
925 Audit(p, " attempted to login - no home directory", 1);
932 * check audit flag and id...
937 if (secure && (p->pw_audflg > 1 || p->pw_audflg < 0)) {
938 Audit(p, " attempted to login - bad audit flag", 1);
939 return(VF_BAD_AFLAG);
942 if (secure && (setaudid(p->pw_audid) == -1 )) {
943 Audit(p, " attempted to login - bad audit id", 1);
950 * validate uid and gid...
953 if ((p->pw_gid < 0) ||
954 (p->pw_gid > MAXUID) ||
955 (setgid(p->pw_gid) == -1)) {
957 Audit(p, " attempted to login - bad group id", 1);
964 * ka_UserAuthenticateGeneral() sets the group access of this process
965 * to the proper PAG. Pick up these values and pass them back to
966 * Dtlogin to be put into the user's environment...
969 if ( vg_IsVerifyName(VN_AFS) ) {
970 groups[0] = groups[1] = 0;
971 getgroups(NGROUPS, groups);
977 if ((p->pw_uid < 0) ||
978 (p->pw_uid > MAXUID) ||
979 (setresuid(p->pw_uid, p->pw_uid, 0) == -1)) {
981 Audit(p, " attempted to login - bad user id", 1);
992 Audit(p, " Successful login", 0);
999 /***************************************************************************
1003 * log bad login attempts
1005 ***************************************************************************/
1008 WriteBtmp( char *name )
1011 struct utmp utmp, *u;
1015 bzero(&utmp, sizeof(struct utmp));
1017 utmp.ut_pid = getppid();
1018 while ((u = getutent()) != NULL) {
1019 if ( (u->ut_type == INIT_PROCESS ||
1020 u->ut_type == LOGIN_PROCESS ||
1021 u->ut_type == USER_PROCESS) &&
1022 u->ut_pid == utmp.ut_pid ) {
1031 * if no utmp entry, this may be an X-terminal. Construct a utmp
1036 strncpy(utmp.ut_id, "??", sizeof(utmp.ut_id));
1037 strncpy(utmp.ut_line, globalDisplayName, sizeof(utmp.ut_line));
1038 utmp.ut_type = LOGIN_PROCESS;
1040 strncpy(utmp.ut_host, globalDisplayName, sizeof(utmp.ut_host));
1047 * If btmp exists, then record the bad attempt
1049 if ( (fd = open(BTMP_FILE,O_WRONLY|O_APPEND)) >= 0) {
1050 strncpy(u->ut_user, name, sizeof(u->ut_user));
1051 (void) time(&u->ut_time);
1052 write(fd, (char *)u, sizeof(utmp));
1056 endutent(); /* Close utmp file */
1059 /***************************************************************************
1061 * End authentication routines (HPUX)
1063 ***************************************************************************/
1067 /***************************************************************************
1068 ***************************************************************************
1069 ***************************************************************************
1070 ***************************************************************************
1071 ***************************************************************************
1072 ***************************************************************************
1073 ***************************************************************************
1074 ***************************************************************************/
1077 #if defined(__uxp__)
1079 /***************************************************************************
1081 * Start authentication routines (UXP)
1083 ***************************************************************************/
1088 /***************************************************************************
1090 * External declarations (UXP)
1092 ***************************************************************************/
1097 /***************************************************************************
1099 * Procedure declarations (UXP)
1101 ***************************************************************************/
1103 static void Audit( struct passwd *p, char *msg, int errnum) ;
1104 static int PasswordAged( register struct passwd *pw) ;
1105 static void WriteBtmp( char *name) ;
1110 /***************************************************************************
1112 * Global variables (UXP)
1114 ***************************************************************************/
1119 /***************************************************************************
1123 ***************************************************************************/
1126 Audit( struct passwd *p, char *msg, int errnum )
1130 * make sure program is back to super-user...
1141 /***************************************************************************
1145 * log bad login attempts
1147 ***************************************************************************/
1150 WriteBtmp( char *name )
1158 /***************************************************************************
1160 * PasswordAged (UXP)
1162 * see if password has aged
1163 ***************************************************************************/
1164 #define SECONDS_IN_WEEK 604800L
1167 PasswordAged( register struct passwd *pw )
1169 long change_week; /* week password was changed (1/1/70 = Week 0) */
1170 long last_week; /* week after which password must change */
1171 long first_week; /* week before which password can't change */
1172 long this_week; /* this week derived from time() */
1173 char *file; /* help file name */
1174 char *command; /* the /bin/passwd command string */
1176 if (*pw->pw_age == NULL)
1179 first_week = last_week = change_week = (long) a64l(pw->pw_age);
1180 last_week &= 0x3f; /* first six bits */
1181 first_week = (first_week >> 6) & 0x3f; /* next six bits */
1182 change_week >>= 12; /* everything else */
1184 this_week = (long) time((long *) 0) / SECONDS_IN_WEEK;
1187 ** Password aging conditions:
1188 ** * if the last week is less than the first week (e.g., the aging
1189 ** field looks like "./"), only the superuser can change the
1190 ** password. We don't request a new password.
1191 ** * if the week the password was last changed is after this week,
1192 ** we have a problem, and request a new password.
1193 ** * if this week is after the specified aging time, we request
1196 if (last_week < first_week)
1199 if (change_week <= this_week && this_week <= (change_week + last_week))
1208 /***************************************************************************
1210 * Authenticate (UXP)
1214 * return codes indicate authentication results.
1215 ***************************************************************************/
1217 #define MAXATTEMPTS 3
1219 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
1222 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1225 static int login_attempts = 0; /* # failed authentications */
1227 struct passwd *p; /* password structure */
1228 struct spwd *sp; /* shadow info */
1236 * Nothing to do if no name provided.
1242 * Save provided password.
1245 if (!passwd) passwd = "";
1249 sp = getspnam(name);
1251 if (!p || strlen(name) == 0 ||
1252 strcmp (crypt (passwd, sp->sp_pwdp), sp->sp_pwdp)) {
1256 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
1261 Audit(p, " Failed login (bailout)", 1);
1265 return(origpw ? VF_INVALID : VF_CHALLENGE);
1270 * check password aging...
1273 if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
1276 * verify home directory exists...
1279 if(chdir(p->pw_dir) < 0) {
1280 Audit(p, " attempted to login - no home directory", 1);
1286 * validate uid and gid...
1290 if ((p->pw_gid < 0) ||
1291 (setgid(p->pw_gid) == -1)) {
1293 Audit(p, " attempted to login - bad group id", 1);
1297 if ((p->pw_uid < 0) ||
1298 (seteuid(p->pw_uid) == -1)) {
1300 Audit(p, " attempted to login - bad user id", 1);
1310 Audit(p, " Successful login", 0);
1316 /***************************************************************************
1318 * End authentication routines (UXP)
1320 ***************************************************************************/
1323 /***************************************************************************
1324 ***************************************************************************
1325 ***************************************************************************
1326 ***************************************************************************
1327 ***************************************************************************
1328 ***************************************************************************
1329 ***************************************************************************
1330 ***************************************************************************/
1334 /***************************************************************************
1336 * Start authentication routines (SUN)
1338 ***************************************************************************/
1340 #include "solaris.h"
1342 #include <security/ia_appl.h>
1346 /***************************************************************************
1348 * Procedure declarations (SUN)
1350 ***************************************************************************/
1352 static void Audit( struct passwd *p, char *msg, int errnum) ;
1356 /***************************************************************************
1360 ***************************************************************************/
1363 Audit( struct passwd *p, char *msg, int errnum )
1367 * make sure program is back to super-user...
1372 Debug("Audit: %s\n", msg);
1378 /***************************************************************************
1380 * Authenticate (SUN)
1384 * return codes indicate authentication results.
1385 ***************************************************************************/
1388 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1391 char* ttyLine = d->gettyLine;
1394 * Nothing to do if no name provided.
1401 * Construct device line
1403 #ifdef DEF_NETWORK_DEV
1405 * If location is not local (remote XDMCP dtlogin) and
1406 * remote accouting is enabled (networkDev start with /dev/...)
1407 * Set tty line name to match network device for accouting.
1408 * Unless the resource was specifically set, default is value
1409 * of DEF_NETWORK_DEV define (/dev/dtremote)
1412 if ( d->displayType.location != Local &&
1413 networkDev && !strncmp(networkDev,"/dev/",5)) {
1414 ttyLine = networkDev+5;
1419 * Authenticate user and return status
1423 status = PamAuthenticate("dtlogin", d->name, passwd, name, ttyLine);
1429 case PAM_AUTHTOKEN_REQD:
1430 return(VF_PASSWD_AGED);
1433 return(passwd ? VF_INVALID : VF_CHALLENGE);
1436 status = solaris_authenticate("dtlogin", d->name, passwd, name, ttyLine);
1442 case IA_NEWTOK_REQD:
1443 return(VF_PASSWD_AGED);
1446 return(passwd ? VF_INVALID : VF_CHALLENGE);
1453 /***************************************************************************
1455 * End authentication routines (SUN)
1457 ***************************************************************************/
1460 /***************************************************************************
1461 ***************************************************************************
1462 ***************************************************************************
1463 ***************************************************************************
1464 ***************************************************************************/
1466 /***************************************************************************
1470 * get the information from the display about local/remote login and
1471 * create a dummy tty name for loginrestrictions.
1473 ***************************************************************************/
1475 GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname)
1479 CleanUpName(d->name, workarea, 128);
1480 sprintf(ttyName, "/dev/dtlogin/%s", workarea);
1482 if (d->displayType.location == Foreign) {
1483 *loginType = S_RLOGIN;
1484 *hostname = d->name;
1485 Debug("Login Info - Remote user on tty=%s.\n", ttyName);
1487 *loginType = S_LOGIN;
1489 Debug("Login Info - Local user on tty=%s.\n", ttyName);
1493 /***************************************************************************
1495 * Authenticate (AIX version 4.1)
1499 * return codes indicate authentication results.
1500 ***************************************************************************/
1501 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1507 static char *msgpending;
1512 GetLoginInfo(d, &loginType, tty, &hostname);
1522 * No more challenges. User failed login.
1525 loginfailed(name, hostname, tty);
1530 * Authenticate with response to last challenge.
1532 rc = authenticate(name, passwd, &reenter, msg);
1537 * System has presented user with new challenge.
1539 return(VF_CHALLENGE);
1542 if (rc && errno == ENOENT)
1545 * User is unknown to the system. Simulate a password
1546 * challenge, but save message for display for next call.
1549 return(VF_CHALLENGE);
1555 * No more challenges. User failed login.
1557 loginfailed(name, hostname, tty);
1562 * User authenticated. Check login restrictions.
1564 rc = loginrestrictions(name, loginType, tty, msg);
1569 * Login restrictions disallow login.
1571 loginfailed(name, hostname, tty);
1576 * Check password expiration.
1578 rc = passwdexpired(name, msg);
1583 * Login succeeded, but password expired.
1585 return(VF_PASSWD_AGED);
1591 loginsuccess(name, hostname, tty, msg);
1598 /***************************************************************************
1600 * Start authentication routines (AIX)
1602 ***************************************************************************/
1605 #include <sys/types.h>
1606 #include <sys/errno.h>
1607 #include <usersec.h>
1609 #include <userconf.h>
1613 /***************************************************************************
1615 * External declarations (AIX)
1617 ***************************************************************************/
1622 /***************************************************************************
1624 * Procedure declarations (AIX)
1626 ***************************************************************************/
1628 static void Audit( struct passwd *p, char *msg, int errnum) ;
1629 static int PasswordAged(char *name, register struct passwd *pw) ;
1630 static void WriteBtmp( char *name) ;
1635 /***************************************************************************
1637 * Global variables (AIX)
1639 ***************************************************************************/
1644 /***************************************************************************
1648 ***************************************************************************/
1651 Audit( struct passwd *p, char *msg, int errnum )
1655 * make sure program is back to super-user...
1659 if ( (auditwrite ("USER_Login", AUDIT_OK,
1660 p->pw_name, strlen (p->pw_name) + 1,
1661 msg, strlen (msg) + 1, NULL)) == -1 )
1662 Debug(" Could not do Auditing\n");
1669 /***************************************************************************
1673 * log bad login attempts to /etc/security/failedlogin file
1676 ***************************************************************************/
1679 WriteBtmp( char *name )
1684 if( (fd = open("/etc/security/failedlogin",O_CREAT|O_RDWR,0644)) != -1) {
1685 bzero(&ut,sizeof(struct utmp));
1687 strncpy(ut.ut_user, name, sizeof ut.ut_user);
1688 ut.ut_type = USER_PROCESS;
1689 ut.ut_pid = getpid();
1690 ut.ut_time = time((time_t *)0);
1691 write(fd, (char *)&ut, sizeof(struct utmp));
1699 /***************************************************************************
1701 * PasswordAged (AIX)
1703 * see if password has aged
1704 ***************************************************************************/
1705 #define SECONDS_IN_WEEK 604800L
1708 PasswordAged(char *name, register struct passwd *pw )
1710 struct userpw *pupw; /* authentication information from getuserpw() */
1711 struct userpw upw; /* working authentication information */
1712 int err; /* return code from getconfattr() */
1713 ulong maxage; /* maximun age from getconfattr() */
1714 ulong now; /* time now */
1720 * Determine user password aging criteria. Note that only
1721 * the 'lastupdate' and 'flags' fields are set by this operation.
1724 if ((pupw = getuserpw(name)) != NULL)
1726 upw.upw_lastupdate = pupw->upw_lastupdate;
1727 upw.upw_flags = pupw->upw_flags;
1731 upw.upw_lastupdate = 0;
1737 * Consider password as having not expired if nocheck set.
1739 if (upw.upw_flags & PW_NOCHECK) return(FALSE);
1742 * Get system password aging criteria.
1744 err = getconfattr (SC_SYS_PASSWD, SC_MAXAGE, (void *)&maxage, SEC_INT);
1748 * Change from weeks to seconds
1750 maxage = maxage * SECONDS_IN_WEEK;
1751 now = time ((long *) 0);
1753 if ((upw.upw_lastupdate + maxage) >= now)
1756 * Password has not expired.
1764 * Could not retrieve system password aging info or maxage set to
1765 * zero. In either case, consider password has having not expired.
1771 * We haven't returned by now, so indicate password has expired.
1777 /***************************************************************************
1778 * dt_failedlogin (AIX)
1780 * log failed login in /etc/security/lastlog
1781 ***************************************************************************/
1793 dt_lastlogin ( char * user, struct lastlogin * llogin);
1796 dt_failedlogin(char *name, char *ttyName, char *hostName)
1798 struct lastlogin last_login;
1800 last_login.stime = 0;
1802 time(&last_login.ftime);
1804 last_login.ftty = ttyName;
1806 last_login.fhost = (char *) malloc (MAXHOSTNAMELEN);
1807 if (hostName == NULL) {
1808 gethostname (last_login.fhost , MAXHOSTNAMELEN);
1810 strncpy(last_login.fhost, hostName, MAXHOSTNAMELEN);
1811 last_login.fhost[MAXHOSTNAMELEN -1] = '\0';
1814 Debug("logging failed lastlogin entry (user=%s)\n",name);
1815 dt_lastlogin(name, &last_login);
1816 free(last_login.fhost);
1821 /***************************************************************************
1823 * Authenticate (AIX)
1827 * return codes indicate authentication results.
1828 ***************************************************************************/
1830 #define MAXATTEMPTS 3
1832 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
1835 Authenticate( struct display *d, char *name, char *passwd, char **msg )
1838 static int login_attempts = 0; /* # failed authentications */
1839 struct passwd *p; /* password structure */
1847 * Nothing to do if no name provided.
1853 * Save provided password.
1856 if (!passwd) passwd = "";
1858 if(strlen(name) > S_NAMELEN)
1861 GetLoginInfo(d, &loginType, tty, &hostname);
1865 if (!p || strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd)) {
1869 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
1874 Audit(p, " Failed login (bailout)", 1);
1878 dt_failedlogin(name, tty, hostname);
1879 return (VF_INVALID);
1881 return(VF_CHALLENGE);
1884 /* Note: The password should be checked if it is the first time
1885 the user is logging in or whether the sysadm has changed
1886 the password for the user. Code should be added here if
1887 this functionality should be supported. The "upw_flags"
1888 of the password structure gets set to PW_ADMCHG in this
1893 * check password aging...
1896 if ( PasswordAged(name,p) ) return(VF_PASSWD_AGED);
1899 /* Validate for User Account RK 09.13.93 */
1900 if(ckuseracct(name, loginType, tty) == -1) {
1901 dt_failedlogin(name, tty, hostname);
1907 * validate uid and gid...
1911 if ((p->pw_gid < 0) ||
1912 (setgid(p->pw_gid) == -1)) {
1914 Audit(p, " attempted to login - bad group id", 1);
1918 if ((p->pw_uid < 0)) {
1919 Audit(p, " attempted to login - bad user id", 1);
1923 /* Check for max number of logins RK 09.13.93 */
1924 if (tsm_check_login(p->pw_uid) == -1) {
1925 dt_failedlogin(name, tty, hostname);
1929 /* Check for /etc/nologin file RK 09.13.93 */
1930 if ( (access("/etc/nologin",R_OK) == 0) && (p->pw_uid != 0) ) {
1931 dt_failedlogin(name, tty, hostname);
1936 * verify home directory exists...
1939 if(chdir(p->pw_dir) < 0) {
1940 Audit(p, " attempted to login - no home directory", 1);
1948 Audit(p, " Successful login", 0);
1952 /**************************************************************************
1956 * Checks for max number of logins on the system. If the new user trying to
1957 * login exceeds the max limit then the user is not allowed to login.
1960 **************************************************************************/
1962 /**************************************************************************
1966 * Checks for max number of logins on the system. If the new user trying to
1967 * login exceeds the max limit then the user is not allowed to login.
1970 **************************************************************************/
1973 tsm_check_login(uid_t uid)
1980 struct stat stat_buf;
1981 static struct sembuf sop = { 0, -1, (SEM_UNDO|IPC_NOWAIT) };
1982 static struct sembuf initsop = { 0, 0, (IPC_NOWAIT) };
1985 * The login counter semaphore may not be set yet. See if it exists
1986 * and try creating it with the correct count if it doesn't. An
1987 * attempt is made to create the semaphore. Only if that attempt fails
1988 * is the semaphore set to maxlogins from login.cfg.
1993 * Don't Check if the user is already logged. ie running login
1997 * Generate the semaphore key from the init program.
1999 Debug("Start of maxlogin check\n");
2000 if ((key = ftok (CDE_INSTALLATION_TOP "/bin/dtlogin", 1)) != (key_t) -1) {
2001 Debug("key created\n");
2002 if ((semid = semget (key, 1, IPC_CREAT|IPC_EXCL|0600)) != -1) {
2004 Debug("Completed IPCkey\n");
2005 if (! getconfattr ("usw", "maxlogins", &i, SEC_INT)) {
2006 Debug("Max logins from login.cfg is :%d\n",i);
2008 i = 10000; /* a very large number */
2011 if (semop (semid, &initsop, 1))
2013 Debug("failed while decrementing\n");
2017 semctl (semid, 1, IPC_RMID, 0);
2022 * Only 'n' login sessions are allowed on the system.
2023 * This code block decrements a semaphore.
2024 * The semundo value will be set to adjust the
2025 * semaphore when tsm exits.
2027 * This code will be ignored if the appropriate
2028 * semaphore set does not exist.
2031 if ((semid = semget (key, 1, 0)) != -1) {
2032 Debug("getting key for maxlogins\n");
2034 * If the semaphore is zero and we are not
2035 * root, then we fail as there are already the
2036 * allotted number of login sessions on the
2039 if ((semop (semid, &sop, 1) == -1) && uid) {
2040 Debug("reached MAXLOGINS limit\n");
2048 #endif /* !_POWER */
2050 /***************************************************************************
2052 * End authentication routines (AIX)
2054 ***************************************************************************/
2056 /***************************************************************************
2057 ***************************************************************************
2058 ***************************************************************************
2059 ***************************************************************************
2060 ***************************************************************************
2061 ***************************************************************************
2062 ***************************************************************************
2063 ***************************************************************************/
2067 /***************************************************************************
2069 * Start authentication routines (USL)
2071 ***************************************************************************/
2074 #define LOGIN_SUCCESS 0
2075 #define LOGIN_FAIL 1
2085 /***************************************************************************
2087 * External declarations (USL)
2089 ***************************************************************************/
2093 /***************************************************************************
2095 * Procedure declarations (USL)
2097 ***************************************************************************/
2100 static void Audit( struct passwd *p, char *msg, int errnum) ;
2101 static int PasswordAged( register struct passwd *pw) ;
2102 static void WriteBtmp( char *name) ;
2106 /***************************************************************************
2108 * Global variables (USL)
2110 ***************************************************************************/
2112 extern int Slaveptty_fd;
2115 /***************************************************************************
2119 ***************************************************************************/
2122 Audit( struct passwd *p, char *msg, int errnum )
2126 * make sure program is back to super-user...
2137 /***************************************************************************
2141 * log bad login attempts
2143 ***************************************************************************/
2146 WriteBtmp( char *name )
2154 /***************************************************************************
2156 * Authenticate (USL)
2160 * return codes indicate authentication results.
2161 ***************************************************************************/
2163 #define MAXATTEMPTS 3
2166 Authenticate( struct display *d, char *name, char *passwd, char **msg )
2179 * Nothing to do if no name provided.
2185 * Save provided password.
2188 if (!passwd) passwd = "";
2191 * Put the logname and the passwd on the ava stream
2193 if ((ret = dup2 (Slaveptty_fd, 0)) == -1)
2194 Debug ("Problem with dup2\n");
2196 ava = retava(Slaveptty_fd);
2198 (void) bzero (xlogname, strlen (xlogname));
2199 (void) sprintf (xlogname, "XLOGNAME=%s", name);
2200 if ((ava = putava (xlogname, ava)) == NULL)
2202 Debug ("Could not set logname ava\n");
2205 (void) bzero (xpasswd, strlen (xpasswd));
2206 (void) sprintf (xpasswd, "XPASSWD=%s", passwd);
2207 if ((ava = putava (xpasswd, ava)) == NULL)
2209 Debug ("Could not set passwd ava\n");
2212 (void) bzero (xtty, strlen (xtty));
2213 (void) sprintf (xtty, "XTTY=%s", ttyname(Slaveptty_fd));
2214 if ((ava = putava (xtty, ava)) == NULL)
2216 Debug ("Could not set tty ava\n");
2219 if (setava (Slaveptty_fd, ava) != 0)
2221 Debug ("Could not do setava\n");
2225 * invoke identification and authorizarion scheme
2228 switch (ret = invoke (Slaveptty_fd, "login"))
2232 Audit(p, " Successful login", 0);
2235 return(origpw ? VF_INVALID : VF_CHALLENGE);
2237 /* The next three cases need to define special return values */
2238 /* for the aged passwords and accounts. */
2242 /* PasswdAged (linfo); */
2243 return(VF_PASSWD_AGED);
2244 case EXPIRED: /* SS */
2245 /* AccountAged (linfo); */
2246 return(VF_PASSWD_AGED);
2248 /* These 3 cases should allow user to select a new password */
2249 /* after displaying a warrning, but current implementation */
2250 /* only displays the warning. */
2255 return(VF_PASSWD_AGED);
2257 return(VF_INVALID); /* SS */
2262 /***************************************************************************
2264 * End authentication routines (USL)
2266 ***************************************************************************/
2270 /***************************************************************************
2272 * Start authentication routines (generic)
2274 ***************************************************************************/
2277 /***************************************************************************
2279 * These are a set of routine to do simple password, home dir, uid, and gid
2280 * validation. They can be used as a first pass validation for future
2283 * When platform specific validation is developed, those routines should be
2284 * included in their own section and the use of these routines discontinued.
2286 ***************************************************************************/
2291 /***************************************************************************
2293 * External declarations (generic)
2295 ***************************************************************************/
2300 /***************************************************************************
2302 * Procedure declarations (generic)
2304 ***************************************************************************/
2306 static void Audit( struct passwd *p, char *msg, int errnum) ;
2307 static int PasswordAged( register struct passwd *pw) ;
2308 static void WriteBtmp( char *name) ;
2313 /***************************************************************************
2315 * Global variables (generic)
2317 ***************************************************************************/
2322 /***************************************************************************
2326 ***************************************************************************/
2329 Audit( struct passwd *p, char *msg, int errnum )
2333 * make sure program is back to super-user...
2344 /***************************************************************************
2346 * WriteBtmp (generic)
2348 * log bad login attempts
2350 ***************************************************************************/
2353 WriteBtmp( char *name )
2361 /***************************************************************************
2363 * PasswordAged (Generic)
2365 * see if password has aged
2366 ***************************************************************************/
2367 #define SECONDS_IN_WEEK 604800L
2370 PasswordAged( register struct passwd *pw )
2377 /***************************************************************************
2379 * Authenticate (generic)
2383 * return codes indicate authentication results.
2384 ***************************************************************************/
2386 #define MAXATTEMPTS 3
2388 struct passwd nouser = {"", "nope"}; /* invalid user password struct */
2391 Authenticate( struct display *d, char *name, char *passwd, char **msg )
2394 static int login_attempts = 0; /* # failed authentications */
2396 struct passwd *p; /* password structure */
2404 * Nothing to do if no name provided.
2410 * Save provided password.
2413 if (!passwd) passwd = "";
2417 if (!p || strlen(name) == 0 ||
2418 strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd)) {
2422 if ((++login_attempts % MAXATTEMPTS) == 0 ) {
2427 Audit(p, " Failed login (bailout)", 1);
2431 return(origpw ? VF_INVALID : VF_CHALLENGE);
2436 * check password aging...
2439 if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
2443 * verify home directory exists...
2446 if(chdir(p->pw_dir) < 0) {
2447 Audit(p, " attempted to login - no home directory", 1);
2453 * validate uid and gid...
2457 if ((p->pw_gid < 0) ||
2458 (setgid(p->pw_gid) == -1)) {
2460 Audit(p, " attempted to login - bad group id", 1);
2464 if ((p->pw_uid < 0) ||
2465 (seteuid(p->pw_uid) == -1)) {
2467 Audit(p, " attempted to login - bad user id", 1);
2477 Audit(p, " Successful login", 0);
2484 /***************************************************************************
2486 * End authentication routines (generic)
2488 ***************************************************************************/
2489 #endif /* generic */
2493 /***************************************************************************
2494 ***************************************************************************
2495 ***************************************************************************
2496 ***************************************************************************
2497 ***************************************************************************
2498 ***************************************************************************
2499 ***************************************************************************
2500 ***************************************************************************/