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