Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtlogin / vgauth.c
1 /* $XConsortium: vgauth.c /main/4 1996/10/04 16:56:33 drk $ */
2 /*                                                                      *
3  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
4  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
5  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
6  * (c) Copyright 1993, 1994 Novell, Inc.                                *
7  */
8 /************************************<+>*************************************
9  ****************************************************************************
10  **
11  **   File:        vgauth.h
12  **
13  **   Project:     HP Visual User Environment (DT)
14  **
15  **   Description: Dtgreet user authentication routines
16  **
17  **                These routines validate the user; checking name, password,
18  **                number of users on the system, password aging, etc.
19  **
20  **
21  **   (c) Copyright 1987, 1988, 1989 by Hewlett-Packard Company
22  **
23  **
24  **     Conditional compiles for HPUX:
25  **
26  **     OSMAJORVERSION < 8
27  **                 HP-UX 7.0/7.03 restricted license counting algorithms
28  **                 are used. Otherwise HP-UX 8.0 and beyond is used
29  **
30  **     AUDIT       HP C2 security enhancements; checks for existence of
31  **                 SECUREPASSWD file and authenticates user against
32  **                 password contained in that file. Also performs
33  **                 self-auditing of login actions.  Incompatible with 
34  **                 #ifdef SecureWare
35  **
36  **     BLS         HP BLS B1 simple authentication.
37  **
38  **     __AFS        AFS 3 authentication mechanism
39  **     __KERBEROS   Kerberos authentication mechanism
40  **     __PASSWD_ETC Domain/OS Registry from HP-UX authentication mechanism
41  **
42  **     Platform identification:
43  **
44  **     __hpux      HP-UX OS only
45  **     __apollo    Domain OS only
46  **     __hp_osf    HP OSF/1 OS only
47  **     sun         SUN OS only
48  **     USL         USL OS only
49  **     SVR4        SUN OS and USL
50  **     _AIX        AIX only
51  **
52  ****************************************************************************
53  ************************************<+>*************************************/
54
55
56 /***************************************************************************
57  *
58  *  Includes & Defines
59  *
60  ***************************************************************************/
61
62 #include        <stdio.h>
63 #include        <fcntl.h>
64 #include        <stdlib.h>
65 #include        <pwd.h>
66
67 /* necessary for bzero */
68 #ifdef SVR4
69 #include        <X11/Xfuncs.h>
70 #ifdef  sun
71 #include        <shadow.h>
72 #endif
73 #endif
74
75 #include        "vg.h"
76 #include        "vgmsg.h"
77
78 /*
79  * Define as generic those without platform specific code.
80  */
81 #if !(defined(__hpux)   || \
82       defined(__apollo) || \
83       defined(_AIX)     || \
84       defined(sun))
85 #define generic
86 #endif
87
88 #ifdef __hpux
89 /***************************************************************************
90  *
91  *  Start authentication routines (HPUX)
92  *
93  ***************************************************************************/
94
95 #include        <sys/param.h>     /* for MAXUID macro */
96 #include        <sys/types.h>
97 #include        <sys/utsname.h>
98 #include        <string.h>
99 #include        <utmp.h>
100 #include        <time.h>
101
102
103 #ifdef AUDIT
104 #    include <sys/audit.h>
105 #    include <sys/errno.h>
106 #    include <sys/stat.h>
107 #    define SECUREPASS  "/.secure/etc/passwd"
108 #endif
109
110 #ifdef BLS
111 #    include <sys/security.h>
112 #    include <prot.h>
113 #endif
114
115 #ifdef __AFS
116 #include        <afs/kautils.h>
117 #endif /* __AFS */
118
119 #ifdef __KERBEROS
120 #    include <krb.h>
121 #    define KRBLIFE     255             /* max lifetime */
122 #endif /* __KERBEROS */
123
124 #ifdef __PASSWD_ETC
125 #    include    "rgy_base.h"
126 #endif
127
128
129
130 #define how_to_count ut_exit.e_exit
131
132 #ifdef __hp9000s300
133     int num_users[] = { 2, 32767 };
134 #   define MIN_VERSION     'A'
135 #   define UNLIMITED       'B'
136 #else
137     int num_users[] = { 2, 16, 32, 64 , 8 };
138 #   define MIN_VERSION  'A'
139 #   define UNLIMITED    'U'
140 #endif
141
142 /* Maximum number of users allowed with restricted license */
143 #if OSMAJORVERSION < 8
144 #    define MAX_STRICT_USERS 2  
145 #else
146 #    define MAX_STRICT_USERS 8
147 #endif
148
149 #define NUM_VERSIONS    (sizeof(num_users)/sizeof(num_users[0])) - 1
150
151
152
153 /***************************************************************************
154  *
155  *  External declarations (HPUX)
156  *
157  ***************************************************************************/
158
159 extern Widget focusWidget;              /* login or password text field    */
160
161 extern long     groups[NGROUPS];
162
163
164 #ifdef __PASSWD_ETC
165 extern boolean rgy_$using_local_registry();
166 extern struct passwd * getpwnam_full();
167 extern boolean is_acct_expired();
168 extern boolean is_passwd_expired();
169 extern boolean is_passwd_invalid();
170 extern boolean rgy_$is_des();
171 #endif
172
173
174
175 /***************************************************************************
176  *
177  *  Procedure declarations (HPUX)
178  *
179  ***************************************************************************/
180
181 static void     Audit( struct passwd *p, char *msg, int errnum) ;
182 static int      CheckPassword( char *name, char *passwd, struct passwd **ppwd );
183 static int      CountUsers( int added_users) ;
184 static int      CountUsersStrict( char *new_user) ;
185 static int      PasswordAged( register struct passwd *pw) ;
186 static void     WriteBtmp( char *name) ;
187
188
189
190
191 /***************************************************************************
192  *
193  *  Global variables (HPUX)
194  *
195  ***************************************************************************/
196
197 #ifdef AUDIT
198   struct s_passwd *s_pwd;
199   struct stat   s_pfile;
200   int           secure; /* flag to denote existance of secure passwd file */
201   Boolean       selfAuditOn;
202 #endif
203
204 #ifdef BLS
205    struct pr_passwd     *b1_pwd;
206 #endif
207
208 #ifdef __PASSWD_ETC
209 rgy_$acct_admin_t admin_part;
210 rgy_$policy_t     policy;
211 rgy_$acct_user_t  user_part;
212 #endif
213
214
215
216 /***************************************************************************
217  *
218  *  Audit (HPUX)
219  *
220  *  Construct self audit record for event and write to the audit trail. 
221  *  This routine assumes that the effective uid is currently 0. If auditing
222  *  is not defined, this routine does nothing.
223  ***************************************************************************/
224
225 static void 
226 Audit( struct passwd *p, char *msg, int errnum )
227 {
228
229
230 #ifdef AUDIT
231     char *txtptr;
232     struct self_audit_rec audrec;
233     int status;
234 #endif
235
236     /*
237      * make sure program is back to super-user...
238      */
239
240     setresuid(0,0,0);
241
242
243 #ifdef AUDIT
244     if (selfAuditOn) {
245         txtptr = (char *)audrec.aud_body.text;
246         sprintf(txtptr, "User= %s uid=%ld audid=%ld%s", p->pw_name,
247                 (long)p->pw_uid, (long)p->pw_audid, msg);
248         audrec.aud_head.ah_pid = getpid();
249         audrec.aud_head.ah_error = errnum;
250         audrec.aud_head.ah_event = EN_LOGINS;
251         audrec.aud_head.ah_len = strlen (txtptr);
252         status = audwrite(&audrec);
253
254         if ( status != 0 ) {
255             switch (errno) {
256             
257             case EPERM:
258                 LogError(ReadCatalog(
259                         MC_LOG_SET,MC_LOG_NOT_SUSER,MC_DEF_LOG_NOT_SUSER));
260                 break;
261             
262             case EINVAL:
263                 LogError(ReadCatalog(
264                         MC_LOG_SET,MC_LOG_INV_EVENT,MC_DEF_LOG_INV_EVENT));
265                 break;
266             
267             default:
268                 LogError(ReadCatalog(
269                         MC_LOG_SET,MC_LOG_ERR_ERRNO,MC_DEF_LOG_ERR_ERRNO),
270                         errno);
271                 break;
272             }
273         }
274     }
275
276 #else
277     return;
278 #endif
279 }
280
281
282
283
284
285  
286 /***************************************************************************
287  *
288  *  CountUsers (HPUX only)
289  *
290  *  see if new user has exceeded the maximum.
291  ***************************************************************************/
292
293 #define NCOUNT 16
294
295 static int 
296 CountUsers( int added_users )
297 {
298     int count[NCOUNT], nusers, i;
299     struct utmp *entry;
300
301     for (i=0; i<NCOUNT; i++)
302         count[i] = 0;
303
304     count[added_users]++;
305
306     while ( (entry = getutent()) != NULL) {
307         if (entry->ut_type == USER_PROCESS) {
308             i = entry->how_to_count;
309             if (i < 0 || i >= NCOUNT)
310                 i = 1;          /* if out of range, then count */
311                                 /* as ordinary user */
312             count[i]++;
313         }
314     }
315     endutent();
316
317     /*
318      * KEY:
319      *  [0]     does not count at all
320      *  [1]     counts as real user
321      *  [2]     logins via a pty which have not gone trough login.  These 
322      *          collectively count as 1 user IF count[3] is 0, otherwise,
323      *          they are not counted. Starting with HP-UX 8.0 they are
324      *          no longer counted at all.
325      *  [3]     logins via a pty which have been logged through login (i.e.
326      *          rlogin and telnet).  these count as 1 "real" user per
327      *          unique user name.
328      *  [4-15]  may be used for groups of users which collectively
329      *          count as 1
330      */
331     nusers = count[1];
332
333 #if OSMAJORVERSION < 8
334     for (i=2; i<NCOUNT; i++)
335 #else
336     for (i=3; i<NCOUNT; i++)
337 #endif
338         if (count[i] > 0)
339             nusers++;
340
341     return(nusers);
342 }
343
344
345
346
347 /***************************************************************************
348  *
349  *  CountUsersStrict (HPUX only)
350  *
351  *  see if new user has exceeded the maximum.
352  ***************************************************************************/
353
354 static int 
355 CountUsersStrict( char *new_user )
356 {
357     char pty_users[MAX_STRICT_USERS][8];
358     int count[NCOUNT], nusers, i, cnt, pty_off = -1, uname_off;
359     struct utmp *entry;
360
361     /*
362      *  Initialize count array...
363      */
364     for (i = 0; i < NCOUNT; i++)
365         count[i] = 0;
366
367     /*
368      *  Add in the new user (we know it's not a pty)...
369      */
370     count[1]++;
371
372     while ( (entry = getutent()) != NULL ) {
373         if (entry->ut_type == USER_PROCESS) {
374             i = entry->how_to_count;
375
376             /* if out of range, then count as ordinary user logged in 
377                via a tty */
378             if (i == 1 || (i < 0 || i >= NCOUNT))
379                 count[1]++;
380             /* See if it is a pty login granted by login program */
381             else if (i == 3) {
382                 count[3]++;
383                 /* See if user is already logged in via login pty */
384                 uname_off = -1;
385                 for (cnt = 0; cnt <= pty_off; cnt++)
386                         if (strncmp(pty_users[cnt], entry->ut_user, 8) == 0)
387                                 uname_off = cnt;
388
389                 if (uname_off == -1) { /* user is not logged in via pty yet */
390                         
391                     if (pty_off >= MAX_STRICT_USERS)  /* cannot add any
392                                                          more users */
393                         return(MAX_STRICT_USERS + 1);
394                     /* add the user name to the array of pty users */
395                     else
396                         strncpy(pty_users[++pty_off], entry->ut_user, 8);
397                 }
398             } /* end if (i == 3) */
399             else
400                 count[i]++;
401         } /* end if entry->ut_type == USER_PROCESS */
402     } /* end while (entry = getutent()) */
403
404     endutent();
405     /*
406      * KEY:
407      *  [0]     does not count at all
408      *  [1]     counts as "real" user
409      *  [2]     logins via a pty which have not gone trough login.  These 
410      *          collectively count as 1 user IF count[3] is 0, otherwise,
411      *          they are not counted. Starting with HP-UX 8.0 they are
412      *          no longer counted at all.
413      *  [3]     logins via a pty which have been logged through login (i.e.
414      *          rlogin and telnet).  these count as 1 "real" user per
415      *          unique user name.
416      *  [4-15]  may be used for groups of users which collectively count 
417      *          as 1
418      */
419
420      nusers = pty_off + 1 + count[1];  /* Current number of users is sum of
421                                           users logged in via tty + the
422                                           number of unique users logged in 
423                                           via pty which have gone through
424                                           login */
425
426 #if OSMAJORVERSION < 8
427     if ((count[3] == 0) && (count[2] != 0))
428         nusers++;                       /* Add 1 user for all pty logins IF
429                                            none of pty logins have been 
430                                            granted by the login program */
431 #else
432     /*
433      * Don't count any hpterm logins (exit status of 2).  We already
434      * counted all pty logins granted by the login program.
435      */
436 #endif
437
438     for (i = 4; i < NCOUNT; i++)
439         if (count[i] > 0)
440             nusers++;
441     return(nusers);
442 }
443
444
445
446
447 /***************************************************************************
448  *
449  *  PasswordAged (HPUX)
450  *
451  *  see if password has aged
452  ***************************************************************************/
453 #define SECONDS_IN_WEEK         604800L
454
455 static int 
456 PasswordAged( register struct passwd *pw )
457 {
458     long change_week;   /* week password was changed (1/1/70 = Week 0) */
459     long last_week;     /* week after which password must change */
460     long first_week;    /* week before which password can't change */
461     long this_week;     /* this week derived from time() */
462
463     char *passwdAge;    /* password aging time */
464
465 #ifdef __PASSWD_ETC
466     boolean lrgy;
467 #endif
468     
469
470     passwdAge = pw->pw_age;
471     
472 #ifdef AUDIT
473     if (secure)
474         passwdAge = s_pwd->pw_age;
475 #endif
476
477
478 #ifdef __PASSWD_ETC
479     /* Account validity checks:  If we were able to connect to the network
480      * registry, then we've acquired account and policy data and can perform
481      * account/password checking
482      */
483
484     lrgy = rgy_$using_local_registry();
485     if ( !lrgy ) { 
486
487         /* Check for password expiration or invalidity */
488         if ( rgy_$is_passwd_expired(&user_part, &policy ) != 0 ) {
489             return TRUE;
490         }
491     }
492    return FALSE;
493
494 #else
495
496     if (*passwdAge == NULL)
497         return(0);
498
499     first_week = last_week = change_week = (long) a64l(passwdAge);
500     last_week &= 0x3f;                          /* first six bits */
501     first_week = (first_week >> 6) & 0x3f;      /* next six bits */
502     change_week >>= 12;                         /* everything else */
503
504     this_week = (long) time((long *) 0) / SECONDS_IN_WEEK;
505
506 /*
507 **      Password aging conditions:
508 **      *   if the last week is less than the first week (e.g., the aging
509 **          field looks like "./"), only the superuser can change the
510 **          password.  We don't request a new password.
511 **      *   if the week the password was last changed is after this week,
512 **          we have a problem, and request a new password.
513 **      *   if this week is after the specified aging time, we request
514 **          a new password.
515 */
516     if (last_week < first_week)
517         return(0);
518
519     if (change_week <= this_week && this_week <= (change_week + last_week))
520         return(0);
521
522     return(1);
523
524 #endif
525 }
526
527
528
529 /***************************************************************************
530  *
531  *  CheckPassword (HPUX only)
532  *
533  *  Check validity of user password. One of several authentication schemes
534  *  can be used, including Kerberos, AFS 3, HP BLS and traditional 
535  *  /etc/passwd. These are selectable via a resource in Dtlogin.
536  *  
537  *  Domain registry authentication (PasswdEtc) can also be compiled in as
538  *  the only authentication scheme used.
539  *
540  ***************************************************************************/
541
542 static int
543 CheckPassword( char *name, char *passwd, struct passwd **ppwd )
544 {
545
546     char                *crypt();
547     struct passwd       *p;
548
549     char                *reason;
550     
551 #ifdef __KERBEROS
552     char                realm[REALM_SZ];
553     int                 kerno;
554 #endif /* __KERBEROS */
555
556
557 #ifdef AUDIT
558     /*
559      *  validate that user has an entry in the shadow password file on an 
560      *  HP-UX C2 trusted system. Keep info in a global structure.
561      */
562     if (secure) {
563         setspwent();
564         s_pwd = getspwnam(name);
565         endspwent();
566
567         if (s_pwd == NULL)
568             return(FALSE);      
569     }
570 #endif
571
572
573     /*
574      *  look up user's regular account information...
575      */
576
577 #ifdef __PASSWD_ETC
578     /*
579      *  look up entry from registry...
580      *
581      *  need getpwnam_full to get policy data for passwd expiration 
582      *  or invalidity...
583      */
584     p = getpwnam_full(name, &user_part, &admin_part, &policy);
585 #else
586     p = getpwnam(name);
587 #endif
588
589     endpwent();
590     *ppwd = p;
591     
592     if ( p == NULL || strlen(name) == 0 ) 
593         return(FALSE);
594
595
596 #ifdef __AFS
597
598     /*
599      *  AFS password authentication...
600      */
601      
602     if ( IsVerifyName(VN_AFS) ) {
603
604         if (focusWidget == login_text)
605             return(FALSE);
606
607         if ( ka_UserAuthenticateGeneral(
608                 KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG, 
609                 p->pw_name,             /* kerberos name */
610                 (char *)0,              /* instance */
611                 (char *)0,              /* realm */
612                 passwd,                 /* password */
613                 0,                      /* default lifetime */
614                 0,                      /* spare 1 */
615                 0,                      /* spare 2 */
616                 &reason) == 0 ) {       /* error string */
617
618             if (strcmp(p->pw_passwd, "*") == 0)
619                 return(FALSE);
620             else
621                 return(TRUE);
622         }
623
624         else {
625             LogError(ReadCatalog(
626                 MC_LOG_SET,MC_LOG_AFS_FAILATH,MC_DEF_LOG_AFS_FAILATH),reason);
627         }
628     }           
629 #endif /* __AFS */
630
631
632 #ifdef __KERBEROS
633
634     /*
635      *  Kerberos password authentication...
636      */
637      
638     if ( IsVerifyName(VN_KRB) ) {
639
640         if (focusWidget == login_text)
641             return(FALSE);
642         
643         (void)krb_get_lrealm(realm, 1);
644
645         setresuid(p->pw_uid, p->pw_uid, -1);
646         kerno = krb_get_pw_in_tkt(p->pw_name, 
647                                   "", 
648                                   realm, 
649                                   "krbtgt", 
650                                   realm, 
651                                   KRBLIFE, 
652                                   passwd);
653
654         setresuid(0, 0, -1);
655
656         if (kerno == KSUCCESS) 
657             if (strcmp(p->pw_passwd, "*") == 0)
658                 return(FALSE);
659             else
660                 return(TRUE);
661
662     }
663 #endif /* __KERBEROS */
664
665
666
667     /*
668      *  traditional password verification...
669      */
670      
671     if (strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd) == 0)
672         return(TRUE);
673         
674
675 #ifdef __PASSWD_ETC
676     /*
677      *   If regular passwd check fails, try old-style Apollo SR
678      */
679
680     if (rgy_$is_des(passwd, strlen(passwd), p->pw_passwd) == TRUE)
681         return (TRUE);
682 #endif
683
684
685     /*
686      *  all password checks failed...
687      */
688      
689     return (FALSE);
690
691 }
692
693
694
695
696 /***************************************************************************
697  *
698  *  Verify (HPUX)
699  *
700  *  verify the user
701  *
702  *  return codes indicate authentication results.
703  ***************************************************************************/
704
705 #define MAXATTEMPTS     3
706
707 struct  passwd nouser = {"", "nope"};   /* invalid user password struct    */
708
709 int 
710 Verify( char *name, char *passwd )
711 {
712
713     static int          login_attempts = 0; /* # failed authentications    */
714     
715     struct passwd       *p;             /* password structure */
716
717     struct utsname      utsnam;
718     int                 n;
719
720     
721
722 #ifdef AUDIT
723     /* 
724      * turn on self auditing...
725      */
726
727     if (audswitch(AUD_SUSPEND) == -1)
728         selfAuditOn = FALSE;
729     else
730         selfAuditOn = TRUE;
731
732     /*
733      *  set the secure flag if SECUREPASS exists. If so, we
734      *  are using it for authentication instead of /etc/passwd...
735      */
736
737     secure = (stat(SECUREPASS, &s_pfile) < 0) ? 0:1;
738
739
740     /*
741      * set the audit process flag unconditionally on since we want 
742      * to log all logins regardless of whether the user's audit 
743      * flag is set...
744      */
745
746     if (secure)
747         setaudproc(AUD_PROC);
748
749 #endif /* AUDIT */
750
751
752     /*
753      *  validate password...
754      */
755      
756     if ( CheckPassword(name, passwd, &p) == FALSE) {
757         if ( focusWidget == passwd_text ) {
758         
759             WriteBtmp(name);
760
761             if ((++login_attempts % MAXATTEMPTS) == 0 ) {
762
763                 if (p->pw_name == NULL )
764                     p = &nouser;
765
766                 Audit(p, " Failed login (bailout)", 1);
767
768             }
769         }
770         
771         return(VF_INVALID);
772     }
773
774
775     /*
776      *  check restricted license...
777      *
778      *  Note: This only applies to local displays. Foreign displays
779      *        (i.e. X-terminals) apparently do not count.
780      */
781
782     /* Get the version info via uname.  If it doesn't look right,
783      * assume the smallest user configuration
784      */
785
786     if (getenv(LOCATION) != NULL) {
787         if (uname(&utsnam) < 0)
788             utsnam.version[0] = MIN_VERSION;
789
790         /*
791          * Mappings:
792          *    834 -> 834
793          *    844 -> 844
794          *    836 -> 635
795          *    846 -> 645
796          *    843 -> 642
797          *    853 -> 652
798          */
799
800         if ((!strncmp(utsnam.machine, "9000/834", UTSLEN)) ||
801             (!strncmp(utsnam.machine, "9000/844", UTSLEN)) ||
802             (!strncmp(utsnam.machine, "9000/836", UTSLEN)) ||
803             (!strncmp(utsnam.machine, "9000/846", UTSLEN)) ||
804             (!strncmp(utsnam.machine, "9000/843", UTSLEN)) ||
805             (!strncmp(utsnam.machine, "9000/853", UTSLEN))) {
806
807 /*          strict_count = 1;*/
808             if (CountUsersStrict(name) > MAX_STRICT_USERS) {
809                 Audit(p,
810                       " attempted to login - too many users on the system",
811                       20);
812
813                 return(VF_MAX_USERS);
814             }
815         }
816         else {
817             if (utsnam.version[0] != UNLIMITED) {
818                 if ((utsnam.version[0]-'A' < 0) ||
819                     (utsnam.version[0]-'A' > NUM_VERSIONS))
820                     utsnam.version[0] = MIN_VERSION;
821
822                 n = (int) utsnam.version[0] - 'A';
823                 if (CountUsers(1) > num_users[n]) {
824                     Audit(p,
825                           " attempted to login - too many users on the system",
826                           20);
827
828                     return(VF_MAX_USERS);
829                 }
830             }
831         }
832     }
833
834 #ifdef __PASSWD_ETC
835     /*
836      * Check for account validity. Unfortunately, we have no graphical
837      * dialog for this at this time so the best we can do is log an
838      * error message and hope the system administrator sees it.
839      */
840
841     if ( !rgy_$using_local_registry() ) {
842         if (rgy_$is_acct_expired(&admin_part) != 0 ) {
843             LogError(ReadCatalog(MC_LOG_SET,MC_LOG_ACC_EXP,MC_DEF_LOG_ACC_EXP), 
844                       name);
845             return(VF_INVALID);
846         }
847     }
848 #endif
849
850     /*
851      *  check password aging...
852      */
853
854      if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
855          
856
857     /*
858      *  verify home directory exists...
859      */
860
861     if(chdir(p->pw_dir) < 0) {
862         Audit(p, " attempted to login - no home directory", 1);
863         return(VF_HOME);
864     }
865
866
867 #ifdef AUDIT
868     /*
869      *  check audit flag and id...
870      */
871
872     setresuid(0,0,0);
873
874     if (secure && (p->pw_audflg > 1 || p->pw_audflg < 0)) {
875         Audit(p, " attempted to login - bad audit flag", 1);
876         return(VF_BAD_AFLAG);
877     }
878
879     if (secure && (setaudid(p->pw_audid) == -1 )) {
880         Audit(p, " attempted to login - bad audit id", 1);
881         return(VF_BAD_AID);
882     }
883 #endif /* AUDIT */
884
885
886     /*
887      *  validate uid and gid...
888      */
889
890     if ((p->pw_gid < 0)      || 
891         (p->pw_gid > MAXUID) ||
892         (setgid(p->pw_gid) == -1)) {
893
894         Audit(p, " attempted to login - bad group id", 1);
895         return(VF_BAD_GID);
896     }
897
898
899 #ifdef __AFS
900     /*
901      *  ka_UserAuthenticateGeneral() sets the group access of this process
902      *  to the proper PAG. Pick up these values and pass them back to
903      *  Dtlogin to be put into the user's environment...
904      */
905      
906     if ( IsVerifyName(VN_AFS) ) {
907         groups[0] = groups[1] = 0;
908         getgroups(NGROUPS, groups);
909     }
910
911 #endif /* __AFS */
912
913
914     if ((p->pw_uid < 0)      || 
915         (p->pw_uid > MAXUID) ||
916         (setresuid(p->pw_uid, p->pw_uid, 0) == -1)) {
917
918         Audit(p, " attempted to login - bad user id", 1);
919         return(VF_BAD_UID);
920     }
921
922
923
924
925     /*
926      * verify ok...
927      */
928
929     Audit(p, " Successful login", 0);
930     return(VF_OK);
931 }
932
933
934
935
936 /***************************************************************************
937  *
938  *  WriteBtmp (HPUX)
939  *
940  *  log bad login attempts
941  *  
942  ***************************************************************************/
943
944 static void 
945 WriteBtmp( char *name )
946 {
947     int fd;
948     struct utmp utmp, *u;
949
950     Boolean found=FALSE;
951
952     bzero(&utmp, sizeof(struct utmp));
953
954     utmp.ut_pid = getppid();
955     while ((u = getutent()) != NULL) {
956         if ( (u->ut_type == INIT_PROCESS  ||
957               u->ut_type == LOGIN_PROCESS ||
958               u->ut_type == USER_PROCESS) && 
959               u->ut_pid == utmp.ut_pid ) {
960
961                 found = TRUE;
962                 break;
963         }
964     }
965
966
967     /*
968      *  if no utmp entry, this may be an X-terminal. Construct a utmp
969      *  entry for it...
970      */
971
972     if ( ! found ) {
973         strncpy(utmp.ut_id,   "??", sizeof(utmp.ut_id));
974         strncpy(utmp.ut_line, dpyinfo.name, sizeof(utmp.ut_line));
975         utmp.ut_type = LOGIN_PROCESS;
976 #ifndef SVR4
977         strncpy(utmp.ut_host, dpyinfo.name, sizeof(utmp.ut_host));
978 #endif
979         u = &utmp;
980     }
981     
982     
983     /*
984      * If btmp exists, then record the bad attempt
985      */
986     if ( (fd = open(BTMP_FILE,O_WRONLY|O_APPEND)) >= 0) {
987         strncpy(u->ut_user, name, sizeof(u->ut_user));
988         (void) time(&u->ut_time);
989         write(fd, (char *)u, sizeof(utmp));
990         (void) close(fd);
991     }
992
993     endutent();         /* Close utmp file */
994 }
995
996 /***************************************************************************
997  *
998  *  End authentication routines (HPUX)
999  *
1000  ***************************************************************************/
1001 #endif /* __hpux */
1002
1003
1004
1005 /***************************************************************************
1006  ***************************************************************************
1007  ***************************************************************************
1008  ***************************************************************************
1009  ***************************************************************************
1010  ***************************************************************************
1011  ***************************************************************************
1012  ***************************************************************************/
1013  
1014
1015 #ifdef sun
1016 /***************************************************************************
1017  *
1018  *  Start authentication routines (SUN)
1019  *
1020  ***************************************************************************/
1021
1022
1023
1024
1025 /***************************************************************************
1026  *
1027  *  External declarations (SUN)
1028  *
1029  ***************************************************************************/
1030
1031
1032
1033
1034 /***************************************************************************
1035  *
1036  *  Procedure declarations (SUN)
1037  *
1038  ***************************************************************************/
1039
1040 static void Audit( struct passwd *p, char *msg, int errnum) ;
1041 static int  PasswordAged( register struct passwd *pw) ;
1042 static void WriteBtmp( char *name) ;
1043
1044
1045
1046
1047 /***************************************************************************
1048  *
1049  *  Global variables (SUN)
1050  *
1051  ***************************************************************************/
1052
1053
1054
1055
1056 /***************************************************************************
1057  *
1058  *  Audit (SUN)
1059  *
1060  ***************************************************************************/
1061
1062 static void 
1063 Audit( struct passwd *p, char *msg, int errnum )
1064 {
1065
1066     /*
1067      * make sure program is back to super-user...
1068      */
1069
1070     seteuid(0);
1071
1072     return;
1073 }
1074
1075
1076
1077
1078 /***************************************************************************
1079  *
1080  *  WriteBtmp (SUN)
1081  *
1082  *  log bad login attempts
1083  *  
1084  ***************************************************************************/
1085
1086 static void 
1087 WriteBtmp( char *name )
1088 {
1089     return;
1090 }
1091
1092
1093
1094
1095 /***************************************************************************
1096  *
1097  *  PasswordAged (SUN)
1098  *
1099  *  see if password has aged
1100  ***************************************************************************/
1101 #define SECONDS_IN_WEEK         604800L
1102
1103 static int 
1104 PasswordAged( register struct passwd *pw )
1105 {
1106     long change_week;   /* week password was changed (1/1/70 = Week 0) */
1107     long last_week;     /* week after which password must change */
1108     long first_week;    /* week before which password can't change */
1109     long this_week;     /* this week derived from time() */
1110     char *file;         /* help file name */
1111     char *command;      /* the /bin/passwd command string */
1112
1113     if (*pw->pw_age == NULL)
1114         return(0);
1115
1116     first_week = last_week = change_week = (long) a64l(pw->pw_age);
1117     last_week &= 0x3f;                          /* first six bits */
1118     first_week = (first_week >> 6) & 0x3f;      /* next six bits */
1119     change_week >>= 12;                         /* everything else */
1120
1121     this_week = (long) time((long *) 0) / SECONDS_IN_WEEK;
1122
1123 /*
1124 **      Password aging conditions:
1125 **      *   if the last week is less than the first week (e.g., the aging
1126 **          field looks like "./"), only the superuser can change the
1127 **          password.  We don't request a new password.
1128 **      *   if the week the password was last changed is after this week,
1129 **          we have a problem, and request a new password.
1130 **      *   if this week is after the specified aging time, we request
1131 **          a new password.
1132 */
1133     if (last_week < first_week)
1134         return(0);
1135
1136     if (change_week <= this_week && this_week <= (change_week + last_week))
1137         return(0);
1138
1139     return(1);
1140 }
1141
1142
1143     
1144
1145 /***************************************************************************
1146  *
1147  *  Verify (SUN)
1148  *
1149  *  verify the user
1150  *
1151  *  return codes indicate authentication results.
1152  ***************************************************************************/
1153
1154 #define MAXATTEMPTS     3
1155
1156 extern Widget focusWidget;              /* login or password text field    */
1157 struct  passwd nouser = {"", "nope"};   /* invalid user password struct    */
1158
1159 int 
1160 Verify( char *name, char *passwd )
1161 {
1162
1163     static int          login_attempts = 0; /* # failed authentications    */
1164     
1165     struct passwd       *p;             /* password structure */
1166     struct spwd         *sp;            /* shadow info */
1167     char                *crypt();
1168
1169     int                 n;
1170
1171     p = getpwnam(name);
1172     sp = getspnam(name);
1173     
1174     if (!p || strlen(name) == 0 ||
1175         strcmp (crypt (passwd, sp->sp_pwdp), sp->sp_pwdp)) {
1176
1177         if ( focusWidget == passwd_text ) {
1178         
1179             WriteBtmp(name);
1180
1181             if ((++login_attempts % MAXATTEMPTS) == 0 ) {
1182
1183                 if (p->pw_name == NULL )
1184                     p = &nouser;
1185
1186                 Audit(p, " Failed login (bailout)", 1);
1187
1188             }
1189         }
1190         
1191         return(VF_INVALID);
1192     }
1193
1194
1195     /*
1196      *  check password aging...
1197      */
1198
1199      if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
1200
1201     /*
1202      *  verify home directory exists...
1203      */
1204
1205     if(chdir(p->pw_dir) < 0) {
1206         Audit(p, " attempted to login - no home directory", 1);
1207         return(VF_HOME);
1208     }
1209
1210
1211     /*
1212      *  validate uid and gid...
1213      */
1214
1215
1216     if ((p->pw_gid < 0)      || 
1217         (setgid(p->pw_gid) == -1)) {
1218
1219         Audit(p, " attempted to login - bad group id", 1);
1220         return(VF_BAD_GID);
1221     }
1222
1223     if ((p->pw_uid < 0)      || 
1224         (seteuid(p->pw_uid) == -1)) {
1225
1226         Audit(p, " attempted to login - bad user id", 1);
1227         return(VF_BAD_UID);
1228     }
1229
1230
1231
1232     /*
1233      * verify ok...
1234      */
1235
1236     Audit(p, " Successful login", 0);
1237     return(VF_OK);
1238 }
1239
1240
1241
1242 /***************************************************************************
1243  *
1244  *  End authentication routines (SUN)
1245  *
1246  ***************************************************************************/
1247 #endif /* sun */
1248
1249 /***************************************************************************
1250  ***************************************************************************
1251  ***************************************************************************
1252  ***************************************************************************
1253  ***************************************************************************
1254  ***************************************************************************
1255  ***************************************************************************
1256  ***************************************************************************/
1257
1258 #ifdef _AIX 
1259 /***************************************************************************
1260  *
1261  *  Start authentication routines (AIX)
1262  *
1263  ***************************************************************************/
1264
1265 #include        <time.h>
1266 #include        <sys/types.h>
1267 #include        <usersec.h>
1268 #include        <userpw.h>
1269 #include        <userconf.h>
1270
1271 /***************************************************************************
1272  *
1273  *  External declarations (AIX)
1274  *
1275  ***************************************************************************/
1276
1277
1278
1279
1280 /***************************************************************************
1281  *
1282  *  Procedure declarations (AIX)
1283  *
1284  ***************************************************************************/
1285
1286 static void Audit( struct passwd *p, char *msg, int errnum) ;
1287 static int  PasswordAged(char *name, register struct passwd *pw) ;
1288 static void WriteBtmp( char *name) ;
1289
1290
1291
1292
1293 /***************************************************************************
1294  *
1295  *  Global variables (AIX)
1296  *
1297  ***************************************************************************/
1298
1299
1300
1301
1302 /***************************************************************************
1303  *
1304  *  Audit (AIX)
1305  *
1306  ***************************************************************************/
1307
1308 static void 
1309 Audit( struct passwd *p, char *msg, int errnum )
1310 {
1311
1312     /*
1313      * make sure program is back to super-user...
1314      */
1315
1316     seteuid(0);
1317
1318     return;
1319 }
1320
1321
1322
1323
1324 /***************************************************************************
1325  *
1326  *  WriteBtmp (AIX)
1327  *
1328  *  log bad login attempts
1329  *  
1330  ***************************************************************************/
1331
1332 static void 
1333 WriteBtmp( char *name )
1334 {
1335     return;
1336 }
1337
1338
1339
1340
1341 /***************************************************************************
1342  *
1343  *  PasswordAged (AIX)
1344  *
1345  *  see if password has aged
1346  ***************************************************************************/
1347 #define SECONDS_IN_WEEK         604800L
1348
1349 static int 
1350 PasswordAged(char *name, register struct passwd *pw )
1351 {
1352   struct userpw *pupw; /* authentication information from getuserpw() */
1353   struct userpw  upw;  /* working authentication information */
1354   int err;             /* return code from getconfattr() */
1355   ulong maxage;        /* maximun age from getconfattr() */
1356   ulong now;           /* time now */
1357
1358  /*
1359   * Determine user password aging criteria. Note that only
1360   * the 'lastupdate' and 'flags' fields are set by this operation.
1361   */
1362   setpwdb(S_READ);
1363   if ((pupw = getuserpw(name)) != NULL)
1364   {
1365     upw.upw_lastupdate = pupw->upw_lastupdate;
1366     upw.upw_flags = pupw->upw_flags;
1367   }
1368   else
1369   {
1370     upw.upw_lastupdate = 0;
1371     upw.upw_flags = 0;
1372   }
1373   endpwdb();
1374
1375  /*
1376   * Consider password as having not expired if nocheck set.
1377   */
1378   if (upw.upw_flags & PW_NOCHECK) return(FALSE);
1379
1380  /*
1381   * Get system password aging criteria.
1382   */
1383   err = getconfattr (SC_SYS_PASSWD, SC_MAXAGE, (void *)&maxage, SEC_INT);
1384   if (!err && maxage)
1385   {
1386    /*
1387     * Change from weeks to seconds
1388     */
1389     maxage = maxage * SECONDS_IN_WEEK;
1390     now = time ((long *) 0);
1391
1392     if ((upw.upw_lastupdate + maxage) >= now)
1393     {
1394      /*
1395       * Password has not expired.
1396       */
1397       return(FALSE);
1398     }
1399   }
1400   else
1401   {
1402    /*
1403     * Could not retrieve system password aging info or maxage set to
1404     * zero. In either case, consider password has having not expired.
1405     */
1406     return(FALSE);
1407   }
1408
1409  /* 
1410   * We haven't returned by now, so indicate password has expired.
1411   */
1412   return(TRUE);
1413 }
1414
1415     
1416
1417 /***************************************************************************
1418  *
1419  *  Verify (AIX)
1420  *
1421  *  verify the user
1422  *
1423  *  return codes indicate authentication results.
1424  ***************************************************************************/
1425
1426 #define MAXATTEMPTS     3
1427
1428 extern Widget focusWidget;              /* login or password text field    */
1429 struct  passwd nouser = {"", "nope"};   /* invalid user password struct    */
1430
1431 int 
1432 Verify( char *name, char *passwd )
1433 {
1434
1435     static int          login_attempts = 0; /* # failed authentications    */
1436     
1437     struct passwd       *p;             /* password structure */
1438     char                *crypt();
1439
1440     int                 n;
1441
1442     p = getpwnam(name);
1443     
1444     if (!p || strlen(name) == 0 ||
1445         strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd)) {
1446
1447         if ( focusWidget == passwd_text ) {
1448         
1449             WriteBtmp(name);
1450
1451             if ((++login_attempts % MAXATTEMPTS) == 0 ) {
1452
1453                 if (p->pw_name == NULL )
1454                     p = &nouser;
1455
1456                 Audit(p, " Failed login (bailout)", 1);
1457
1458             }
1459         }
1460         
1461         return(VF_INVALID);
1462     }
1463
1464
1465     /*
1466      *  check password aging...
1467      */
1468
1469      if ( PasswordAged(name,p) ) return(VF_PASSWD_AGED);
1470
1471     /*
1472      *  verify home directory exists...
1473      */
1474
1475     if(chdir(p->pw_dir) < 0) {
1476         Audit(p, " attempted to login - no home directory", 1);
1477         return(VF_HOME);
1478     }
1479
1480
1481     /*
1482      *  validate uid and gid...
1483      */
1484
1485
1486     if ((p->pw_gid < 0)      || 
1487         (setgid(p->pw_gid) == -1)) {
1488
1489         Audit(p, " attempted to login - bad group id", 1);
1490         return(VF_BAD_GID);
1491     }
1492
1493     if ((p->pw_uid < 0)) {
1494         Audit(p, " attempted to login - bad user id", 1);
1495         return(VF_BAD_UID);
1496     }
1497
1498
1499
1500     /*
1501      * verify ok...
1502      */
1503
1504     Audit(p, " Successful login", 0);
1505     return(VF_OK);
1506 }
1507
1508
1509
1510
1511 /***************************************************************************
1512  *
1513  *  End authentication routines (AIX)
1514  *
1515  ***************************************************************************/
1516 #endif /* _AIX */
1517
1518
1519 /***************************************************************************
1520  ***************************************************************************
1521  ***************************************************************************
1522  ***************************************************************************
1523  ***************************************************************************
1524  ***************************************************************************
1525  ***************************************************************************
1526  ***************************************************************************/
1527
1528 #ifdef generic
1529 /***************************************************************************
1530  *
1531  *  Start authentication routines (generic)
1532  *
1533  ***************************************************************************/
1534
1535
1536 /***************************************************************************
1537  *
1538  *  These are a set of routine to do simple password, home dir, uid, and gid
1539  *  validation. They can be used as a first pass validation for future
1540  *  porting efforts.
1541  *
1542  *  When platform specific validation is developed, those routines should be
1543  *  included in their own section and the use of these routines discontinued.
1544  *
1545  ***************************************************************************/
1546
1547
1548
1549
1550 /***************************************************************************
1551  *
1552  *  External declarations (generic)
1553  *
1554  ***************************************************************************/
1555
1556
1557
1558
1559 /***************************************************************************
1560  *
1561  *  Procedure declarations (generic)
1562  *
1563  ***************************************************************************/
1564
1565 static void Audit( struct passwd *p, char *msg, int errnum) ;
1566 static int  PasswordAged( register struct passwd *pw) ;
1567 static void WriteBtmp( char *name) ;
1568
1569
1570
1571
1572 /***************************************************************************
1573  *
1574  *  Global variables (generic)
1575  *
1576  ***************************************************************************/
1577
1578
1579
1580
1581 /***************************************************************************
1582  *
1583  *  Audit (generic)
1584  *
1585  ***************************************************************************/
1586
1587 static void 
1588 Audit( struct passwd *p, char *msg, int errnum )
1589 {
1590
1591     /*
1592      * make sure program is back to super-user...
1593      */
1594
1595     seteuid(0);
1596
1597     return;
1598 }
1599
1600
1601
1602
1603 /***************************************************************************
1604  *
1605  *  WriteBtmp (generic)
1606  *
1607  *  log bad login attempts
1608  *  
1609  ***************************************************************************/
1610
1611 static void 
1612 WriteBtmp( char *name )
1613 {
1614     return;
1615 }
1616
1617
1618
1619
1620 /***************************************************************************
1621  *
1622  *  PasswordAged (Generic)
1623  *
1624  *  see if password has aged
1625  ***************************************************************************/
1626 #define SECONDS_IN_WEEK         604800L
1627
1628 static int 
1629 PasswordAged( register struct passwd *pw )
1630 {
1631   return(FALSE);
1632 }
1633
1634     
1635
1636 /***************************************************************************
1637  *
1638  *  Verify (generic)
1639  *
1640  *  verify the user
1641  *
1642  *  return codes indicate authentication results.
1643  ***************************************************************************/
1644
1645 #define MAXATTEMPTS     3
1646
1647 extern Widget focusWidget;              /* login or password text field    */
1648 struct  passwd nouser = {"", "nope"};   /* invalid user password struct    */
1649
1650 int 
1651 Verify( char *name, char *passwd )
1652 {
1653
1654     static int          login_attempts = 0; /* # failed authentications    */
1655     
1656     struct passwd       *p;             /* password structure */
1657     char                *crypt();
1658
1659     int                 n;
1660
1661     p = getpwnam(name);
1662     
1663     if (!p || strlen(name) == 0 ||
1664         strcmp (crypt (passwd, p->pw_passwd), p->pw_passwd)) {
1665
1666         if ( focusWidget == passwd_text ) {
1667         
1668             WriteBtmp(name);
1669
1670             if ((++login_attempts % MAXATTEMPTS) == 0 ) {
1671
1672                 if (p->pw_name == NULL )
1673                     p = &nouser;
1674
1675                 Audit(p, " Failed login (bailout)", 1);
1676
1677             }
1678         }
1679         
1680         return(VF_INVALID);
1681     }
1682
1683
1684     /*
1685      *  check password aging...
1686      */
1687
1688      if ( PasswordAged(p) ) return(VF_PASSWD_AGED);
1689          
1690
1691     /*
1692      *  verify home directory exists...
1693      */
1694
1695     if(chdir(p->pw_dir) < 0) {
1696         Audit(p, " attempted to login - no home directory", 1);
1697         return(VF_HOME);
1698     }
1699
1700
1701     /*
1702      *  validate uid and gid...
1703      */
1704
1705
1706     if ((p->pw_gid < 0)      || 
1707         (setgid(p->pw_gid) == -1)) {
1708
1709         Audit(p, " attempted to login - bad group id", 1);
1710         return(VF_BAD_GID);
1711     }
1712
1713     if ((p->pw_uid < 0)      || 
1714         (seteuid(p->pw_uid) == -1)) {
1715
1716         Audit(p, " attempted to login - bad user id", 1);
1717         return(VF_BAD_UID);
1718     }
1719
1720
1721
1722     /*
1723      * verify ok...
1724      */
1725
1726     Audit(p, " Successful login", 0);
1727     return(VF_OK);
1728 }
1729
1730
1731
1732
1733 /***************************************************************************
1734  *
1735  *  End authentication routines (generic)
1736  *
1737  ***************************************************************************/
1738 #endif /* generic */
1739
1740
1741
1742 /***************************************************************************
1743  ***************************************************************************
1744  ***************************************************************************
1745  ***************************************************************************
1746  ***************************************************************************
1747  ***************************************************************************
1748  ***************************************************************************
1749  ***************************************************************************/