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