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