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