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