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