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