Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtlogin / solaris.c
1 /* $XConsortium: solaris.c /main/4 1995/10/27 16:15:38 rswiston $ */
2 /*******************************************************************************
3 **
4 **  solaris.c 1.15 95/09/10
5 **
6 **  Copyright 1993, 1994, 1995 Sun Microsystems, Inc.  All rights reserved.
7 **  
8 **  This file contains procedures specific to Sun Solaris login
9 **
10 *******************************************************************************/
11 /*                                                                      *
12  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
13  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
14  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
15  * (c) Copyright 1993, 1994 Novell, Inc.                                *
16  */
17 /*******************************************************************************
18 **
19 **  RESTRICTED CONFIDENTIAL INFORMATION:
20 **
21 **  The information in this document is subject to special
22 **  restrictions in a confidential disclosure agreement between
23 **  HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
24 **  document outside HP, IBM, Sun, USL, SCO, or Univel without
25 **  Sun's specific written approval.  This document and all copies
26 **  and derivative works thereof must be returned or destroyed at
27 **  Sun's request.
28 **
29 **  Copyright 1994 Sun Microsystems, Inc.  All rights reserved.
30 **
31 *******************************************************************************/
32
33
34 /*
35  * Header Files
36  */
37
38 #include <sys/types.h>
39 #include <utmpx.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <dirent.h>
44 #include <sys/param.h>
45 #include <pwd.h>
46 #include "solaris.h"
47
48 #ifdef SUNAUTH
49 #include <security/ia_appl.h>
50 #endif
51
52
53 /*
54  * Local function declarations, structures, and variables
55  */
56
57 static char* create_devname(char* short_devname);
58 static void  dir_dev_acc(char *, uid_t, gid_t, mode_t, char *);
59 static void logindevperm(char *, uid_t, gid_t);
60 static void resetdevperm(char *);
61
62 #ifdef SUNAUTH
63 static int login_conv(int conv_id, int num_msg, struct ia_message **msg,
64                       struct ia_response **response, void *appdata_ptr);
65 static void end_conv();
66
67 static struct ia_conv ia_conv = {login_conv, login_conv, end_conv, NULL};
68 static char *saved_user_passwd;
69 #endif SUNAUTH
70
71
72 /****************************************************************************
73  * solaris_setdevperm
74  *
75  * Modify permission of devices as specified in Solaris /etc/logindevperm file
76  ****************************************************************************/
77
78 int 
79 solaris_setdevperm(char* gettyLine, uid_t uid, gid_t gid) 
80 {
81         char *devname = create_devname(gettyLine);
82
83         if (devname == NULL) { 
84             Debug ("solaris_setdevperm:  NULL devname\n");
85             return(0);
86         };
87
88         logindevperm(devname, uid, gid);
89         free(devname);
90         return(1);
91 }
92
93
94 /****************************************************************************
95  * solaris_resetdevperm
96  *
97  * Reset permission on devices specified in /etc/logindevperm file 
98  ****************************************************************************/
99
100 int 
101 solaris_resetdevperm(char* gettyLine) 
102 {
103         char *devname = create_devname(gettyLine);
104
105         if (devname == NULL) {
106             Debug ("solaris_resetdevperm:  NULL devname\n");
107             return(0);
108         }
109
110         resetdevperm(devname);
111         free(devname);
112         return(1);
113 }
114
115
116 #ifdef SUNAUTH 
117 /****************************************************************************
118  * solaris_authentication
119  *
120  * Authenticate that user / password combination is legal for this system
121  *
122  ****************************************************************************/
123
124 int
125 solaris_authenticate ( char*   prog_name,
126                        char*   display_name,
127                        char*   user_passwd,
128                        char*   user, 
129                        char*   line )
130 {
131         int status;
132         struct ia_status out;
133         void *iah;              /* PAM authentication handle */
134         char* user_str = user ? user : "NULL";
135         char* line_str = line ? line : "NULL";
136         char *line_dev = create_devname(line_str);  
137
138         Debug("solaris_authenticate: prog_name=%s\n", prog_name);
139         Debug("solaris_authenticate: display_name=%s\n", display_name);
140         Debug("solaris_authenticate: user=%s\n", user_str);
141         Debug("solaris_authenticate: line=%s\n", line_str);
142         Debug("solaris_authenticate: line_dev=%s\n", line_dev);
143
144         if (user_passwd) {
145             if (strlen(user_passwd) == 0) {
146                 Debug("solaris_authenticate: user passwd empty\n"); 
147             } else {
148                 Debug("solaris_authenticate: user passwd present\n"); 
149             }
150         }
151         else {
152             Debug("solaris_authenticate: user passwd NULL\n");
153
154             /* Password challenge required for solaris authentication */
155             return(IA_AUTHTEST_FAIL);
156         }
157         
158         /* Solaris BSM Audit trail */
159
160         audit_login_save_host(display_name);
161         audit_login_save_ttyn(line_dev);
162         audit_login_save_port();
163
164         /* Open Solaris PAM (Plugable Authentication module ) connection */
165
166         status = ia_start( prog_name, user, line_dev, 
167                            display_name, &ia_conv, &iah );
168
169         if (status == 0) {
170            int flags = AU_CHECK_PASSWD | AU_CONTINUE;
171            struct passwd *pwd;
172
173            saved_user_passwd = user_passwd;
174            status = ia_auth_user( iah, flags, &pwd, &out );
175                  
176            audit_login_save_pw(pwd);
177
178            if (status != 0) {
179               audit_login_bad_pw();
180               if (status == IA_MAXTRYS) {
181                  audit_login_maxtrys();
182               }
183            }
184         }
185
186         if (status != 0) {
187             Debug("solaris_authenticate: PAM error=%d\n", status);
188         }  
189
190         ia_end(iah);
191
192         return(status);
193 }
194
195
196
197
198 /****************************************************************************
199  * solaris_accounting
200  *
201  * Updates "utmp/utmpx: and "wtmp/wtmpx" system accounting entries
202  *
203  ****************************************************************************/
204
205 int
206 solaris_accounting( char*   prog_name,
207                     char*   display_name,
208                     char*   entry_id,
209                     char*   user, 
210                     char*   line, 
211                     pid_t   pid,
212                     int     entry_type,
213                     int     exitcode )
214 {
215         int session_type, status;
216         struct ia_status out;
217         void *iah;              /* PAM authentication handle */
218         char* user_str = user ? user : "NULL";
219         char* line_str = line ? line : "NULL";
220         char *line_dev = create_devname(line_str);  
221
222         Debug("solaris_accounting: prog_name=%s\n", prog_name);
223         Debug("solaris_accounting: display_name=%s\n", display_name);
224         Debug("solaris_accounting: entry_id=%c %c %c %c\n", entry_id[0],
225                                    entry_id[1], entry_id[2], entry_id[3]);
226         Debug("solaris_accounting: user=%s\n", user_str);
227         Debug("solaris_accounting: line=%s\n", line_str);
228         Debug("solaris_accounting: line_dev=%s\n", line_dev);
229         Debug("solaris_accounting: pid=%d\n", pid);
230         Debug("solaris_accounting: entry_type=%d\n", entry_type);
231         Debug("solaris_accounting: exitcode=%d\n", exitcode);
232
233
234         /* Open Solaris PAM (Plugable Authentication module ) connection */
235
236         if (entry_type == ACCOUNTING) {
237             status = ia_start(prog_name, user, line, 
238                               display_name, &ia_conv, &iah);
239         }
240         else {
241             status = ia_start(prog_name, user, line_dev, 
242                               display_name, &ia_conv, &iah);
243         }
244
245
246         /* Session accounting */
247
248         if (status != IA_SUCCESS) {
249             Debug("solaris_accounting: PAM error=%d)\n", status);
250         } 
251         else {
252             switch(entry_type) {
253
254             case USER_PROCESS:
255                 /* New user session, open session accounting logs */
256                 session_type = IS_LOGIN;
257                 status = ia_open_session(iah, session_type, 
258                                          entry_type, entry_id, &out); 
259                 if (status == IA_SUCCESS) audit_login_success();
260                 break;
261
262
263             case ACCOUNTING:
264                 /* 
265                  * User session has terminated, mark it DEAD and close 
266                  * the sessions accounting logs. 
267                  */
268                 entry_type = DEAD_PROCESS;
269                 session_type = IS_NOLOG;
270                 status = ia_open_session(iah, session_type, 
271                                          entry_type, entry_id, &out); 
272                 if (status != IA_SUCCESS) {
273                     Debug("solaris_accounting: PAM check seuser error=%d\n", 
274                            status);
275                 }
276                 /* Intentional fall thru */
277
278
279             case DEAD_PROCESS:
280                 /* Cleanup account files for dead processes */
281                 status = ia_close_session(iah, 0, pid, 
282                                           exitcode, entry_id, &out); 
283                 break;
284
285
286             case LOGIN_PROCESS:
287             default:    
288                 session_type = 0;
289                 status = ia_open_session(iah, session_type, 
290                                          entry_type, entry_id, &out); 
291                 break;
292             }
293         }
294
295         if (status != IA_SUCCESS) {
296             Debug("solaris_accounting: PAM session error=%d\n", status);
297         }
298
299         ia_end(iah);
300         free(line_dev);
301         return(status);
302 }
303
304
305
306 /****************************************************************************
307  * solaris_setcred
308  *
309  * Set Users login credentials: uid, gid, and group lists 
310  ****************************************************************************/
311
312 int
313 solaris_setcred(char* prog_name, char* user, uid_t uid, gid_t gid) 
314 {
315         int cred_type, status;
316         struct ia_status out;
317         void *iah;              /* PAM authentication handle */
318         char* user_str = user ? user : "NULL";
319
320         Debug("solaris_setcred: prog_name=%s\n", prog_name);
321         Debug("solaris_setcred: user=%s\n", user_str);
322         Debug("solaris_setcred: uid=%d\n", uid);
323         Debug("solaris_setcred: gid=%d\n", gid);
324
325
326         /* Open PAM connection */       
327
328         status = ia_start(prog_name, user, NULL, NULL, &ia_conv, &iah);
329         if (status != 0) {
330             Debug("solaris_setcred: PAM start error=%d\n", status);
331             return(status);
332         }
333
334         /* Set users credentials */
335
336         ia_set_item(iah, IA_AUTHTOK, saved_user_passwd);
337
338         cred_type = SC_INITGPS|SC_SETRID;
339         status = ia_setcred(iah, cred_type, uid, gid, 0, NULL, &out);
340
341         if (status != 0) {
342             Debug("solaris_setcred: user=%s, err=%d)\n", user, status);
343         }
344
345         ia_end(iah);
346
347         Debug("solaris_setcred: return status =%d\n", status);
348
349         return(status);
350 }
351 #endif SUNAUTH 
352
353
354 /***************************************************************************
355  * create_devname
356  *
357  * A utility function.  Takes short device name like "console" and returns 
358  * a long device name like "/dev/console"
359  ***************************************************************************/
360
361 static char* 
362 create_devname(char* short_devname)
363 {
364        char* long_devname;
365
366        if (short_devname == NULL)
367           short_devname = "";
368
369        long_devname = (char *) malloc (strlen(short_devname) + 5);
370
371        if (long_devname == NULL)
372           return(NULL); 
373
374        strcpy(long_devname,"/dev/");
375        strcat(long_devname, short_devname);
376         
377        return(long_devname);
378 }
379
380
381 /****************************************************************************
382  * logindevperm 
383  *
384  * change owner/group/permissions of devices list in /etc/logindevperm.
385  *
386  * This code is directly from Sun Solaris 5.3 login.  Eventually this will
387  * be a fuction in a Solaris library.  Till then, this is duplicate copy.  
388  ***************************************************************************/
389
390 #define LOGINDEVPERM    "/etc/logindevperm"
391 #define DIRWILD         "/*"                    /* directory wildcard */
392 #define DIRWLDLEN       2                       /* strlen(DIRWILD) */
393
394
395 static void
396 logindevperm(char *ttyn, uid_t uid, gid_t gid)
397 {
398         char *field_delims = " \t\n";
399         char *permfile = LOGINDEVPERM;
400         char line[MAXPATHLEN];
401         char *console;
402         char *mode_str;
403         char *dev_list;
404         char *device;
405         char *ptr;
406         int mode;
407         FILE *fp;
408         size_t l;
409         int lineno;
410
411         if ((fp = fopen(permfile, "r")) == NULL)
412                 return;
413
414         lineno = 0;
415         while (fgets(line, MAXPATHLEN, fp) != NULL) {
416                 lineno++;
417
418                 if ((ptr = strchr(line, '#')) != NULL)
419                         *ptr = '\0';    /* handle comments */
420
421                 if ((console = strtok(line, field_delims)) == NULL)
422                         continue;       /* ignore blank lines */
423
424                 if (strcmp(console, ttyn) != 0)
425                         continue;       /* not our tty, skip */
426
427                 mode_str = strtok((char *)NULL, field_delims);
428                 if (mode_str == NULL) {
429                         (void) fprintf(stderr,
430                             "%s: line %d, invalid entry -- %s\n", permfile,
431                             lineno, line);
432                         continue;
433                 }
434
435                 /* convert string to octal value */
436                 mode = strtol(mode_str, &ptr, 8);
437                 if (mode < 0 || mode > 0777 || *ptr != '\0') {
438                         (void) fprintf(stderr,
439                             "%s: line %d, invalid mode -- %s\n", permfile,
440                             lineno, mode_str);
441                         continue;
442                 }
443
444                 dev_list = strtok((char *)NULL, field_delims);
445                 if (dev_list == NULL) {
446                         (void) fprintf(stderr,
447                             "%s: line %d, %s -- empty device list\n",
448                             permfile, lineno, console);
449                         continue;
450                 }
451
452                 device = strtok(dev_list, ":");
453                 while (device != NULL) {
454                         l = strlen(device);
455                         ptr = &device[l - DIRWLDLEN];
456                         if ((l > DIRWLDLEN) && (strcmp(ptr, DIRWILD) == 0)) {
457                                 *ptr = '\0';    /* chop off wildcard */
458                                 dir_dev_acc(device, uid, gid, mode, permfile);
459                         } else {
460                                 /*
461                                  * change the owner/group/permission;
462                                  * nonexistent devices are ignored
463                                  */
464                                 if (chown(device, uid, gid) == -1) {
465                                         if (errno != ENOENT) {
466                                                 (void) fprintf(stderr, "%s: ",
467                                                     permfile);
468                                                 perror(device);
469                                         }
470                                 } else {
471                                         if ((chmod(device, mode) == -1) &&
472                                             (errno != ENOENT)) {
473                                                 (void) fprintf(stderr, "%s: ",
474                                                     permfile);
475                                                 perror(device);
476                                         }
477                                 }
478                         }
479                         device = strtok((char *)NULL, ":");
480                 }
481         }
482         (void) fclose(fp);
483 }
484
485 /***************************************************************************
486  * dir_dev_acc
487  *
488  * Apply owner/group/perms to all files (except "." and "..") in a directory.
489  *
490  * This code is directly Sun Solaris 5.3 login.   Eventually this will
491  * be internal to a Solaris library.  Till then, this is a duplicate copy.  
492  ***************************************************************************/
493
494 static void
495 dir_dev_acc(char *dir, uid_t uid, gid_t gid, mode_t mode, char *permfile)
496 {
497         DIR *dirp;
498         struct dirent *direntp;
499         char *name, path[MAXPATHLEN];
500
501         dirp = opendir(dir);
502         if (dirp == NULL)
503                 return;
504
505         while ((direntp = readdir(dirp)) != NULL) {
506                 name = direntp->d_name;
507                 if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))
508                         continue;
509
510                 (void) sprintf(path, "%s/%s", dir, name);
511                 if (chown(path, uid, gid) == -1) {
512                         if (errno != ENOENT) {
513                                 (void) fprintf(stderr, "%s: ", permfile);
514                                 perror(path);
515                         }
516                 } else {
517                         if ((chmod(path, mode) == -1) && (errno != ENOENT)) {
518                                 (void) fprintf(stderr, "%s: ", permfile);
519                                 perror(path);
520                         }
521                 }
522         }
523         (void) closedir(dirp);
524 }
525
526 /*****************************************************************************
527  * resetdevperm
528  *
529  * Clean up access of devices in /etc/logindevperm by resetting the
530  * owner/group/permissions back to the login pseudo user.
531  *
532  *****************************************************************************/
533
534 extern struct passwd   puser;   /* pseudo_user password entry   */
535
536 static void
537 resetdevperm(char *ttyn)
538 {
539         logindevperm(ttyn, puser.pw_uid, puser.pw_gid);
540 }
541
542 #ifdef SUNAUTH 
543 /*****************************************************************************
544  * login_conv():
545  *
546  * This is a conv (conversation) function called from the PAM 
547  * authentication scheme.  It returns the user's password when requested by
548  * internal PAM authentication modules and also logs any internal PAM error
549  * messages.
550  *****************************************************************************/
551
552 static int
553 login_conv(int conv_id, int num_msg, struct ia_message **msg,
554            struct ia_response **response, void *appdata_ptr)
555 {
556         struct ia_message       *m;
557         struct ia_response      *r;
558         char                    *temp;
559         int                     k;
560
561 #ifdef lint
562         conv_id = conv_id;
563 #endif
564         if (num_msg <= 0)
565                 return (IA_CONV_FAILURE);
566
567         *response = (struct ia_response*) 
568                                 calloc(num_msg, sizeof (struct ia_response));
569         if (*response == NULL)
570                 return (IA_CONV_FAILURE);
571
572         (void) memset(*response, 0, sizeof (struct ia_response));
573
574         k = num_msg;
575         m = *msg;
576         r = *response;
577         while (k--) {
578
579                 switch (m->msg_style) {
580
581                 case IA_PROMPT_ECHO_OFF:
582                     if (saved_user_passwd != NULL) {
583                         r->resp = (char *) malloc(strlen(saved_user_passwd)+1);
584                         if (r->resp == NULL) {
585                             free_resp(num_msg, *response);
586                             *response = NULL;
587                             return (IA_CONV_FAILURE);
588                         }
589                         (void) strcpy(r->resp, saved_user_passwd);
590                         r->resp_len = strlen(r->resp);
591                     }
592
593                     m++;
594                     r++;
595                     break;
596
597
598                 case IA_ERROR_MSG:
599                         if (m->msg != NULL) { 
600                             Debug ("login_conv: %s\n", m->msg); 
601                         }
602                         m++;
603                         r++;
604                         break;
605
606                 default:
607                         Debug ("login_conv: Unexpected case %d\n", 
608                                 m->msg_style);
609                         break;
610                 }
611         }
612         return (IA_SUCCESS);
613 }
614
615
616 /*****************************************************************************
617  * end_conv():
618  *
619  * End of conversation function.  Called from PAM.  
620  * Currently a noop for dtlogin.
621  *****************************************************************************/
622
623 static void
624 end_conv()
625 {}
626 #endif SUNAUTH 
627
628 #ifdef PAM
629 /****************************************************************************
630  * Following Solaris utmp management code was taken from portions of the 
631  * private libauth open and close session code.  There are no equivalent calls
632  * in libpam that replaces it, so the code is copied to here.  Eventually this
633  * code may become functions in either PAM or other appropriate libraries.
634  ***************************************************************************/
635
636 #define INIT_PROC_PID   1
637 #define PAMTXD          "SUNW_OST_SYSOSPAM"
638 #define SCPYN(a, b)     (void) strncpy(a, b, sizeof (a))
639
640 /* utility function to do UTMP/WTMP management */
641 int
642 solaris_setutmp_mgmt(
643         char *user,     /* user */
644         char *ttyn,     /* ttyn */
645         char *rhost,    /* remote hostname */
646         int flags,      /* Flags - see below */
647         int type,       /* type of utmp/wtmp entry */
648         char id[]       /* 4 byte id field for utmp */
649 );
650
651 /*
652  * solaris_reset_utmp_mgmt 
653  *              a utility function which terminates UTMP/WTMP mgmt
654  */
655 int
656 solaris_reset_utmp_mgmt(
657         char **user,    /* user */
658         char **ttyn,    /* tty name */
659         char **rhost,   /* remote host */
660         int flags,      /* flags - see below */
661         int status,     /* logout process status */
662         char id[]       /* logout ut_id (/etc/inittab id) */
663 );
664
665 /* flags for the flags field */
666 #define __NOOP  8       /* No utmp action desired */
667
668 /* __setproc_cred is a utility function to set process credentials */
669 int
670 __setproc_cred(
671         char *user,             /* user */
672         int flags,              /* flags - see below */
673         uid_t uid,              /* User ID to set for this process */
674         gid_t gid,              /* Group ID */
675         int ngroups,            /* Number of groups */
676         gid_t *grouplist        /* Group list */
677 );
678
679 /* flags indicates specific set credential actions */
680
681 #define __INITGROUPS    0x00000001      /* Request to initgroups() */
682 #define __SETGROUPS     0x00000002      /* Request to setgroups() */
683 #define __SETEGID       0x00000004      /* Set effective gid only */
684 #define __SETGID        0x00000008      /* Set real gid */
685 #define __SETEUID       0x00000010      /* Set effective uid only */
686 #define __SETUID        0x00000020      /* Set real uid */
687 #define __SETEID        (__SETEGID|__SETEUID)   /* Set effective ids only */
688 #define __SETRID        (__SETGID|__SETUID)     /* Set real ids */
689
690 /*
691  * solaris_setutmp_mgmt - A utility function used to do UTMP/WTMP management.
692  *
693  *      "user" is the current username.
694  *      "ttyn" is the tty name.
695  *      "rhost" is the remote hostname.
696  *      The following flags may be set in the "flags" field:
697  *
698  *      SOLARIS_UPDATE_ENTRY    No new entry will be created if utmp
699  *                              entry not found - return __NOENTRY
700  *      SOLARIS_NOLOG           Generate a wtmp/wtmpx entry only
701  *      SOLARIS_LOGIN           Caller is a login application - update
702  *                              utmp entry accordingly
703  *
704  *      "type" is used to indicate the type of utmp/wtmp entry written
705  *              (see also utmp.h and utmpx.h)
706  *      "id is an optional application-defined 4 byte array that represents
707  *      the /sbin/inittab id (created by the process that puts an entry in
708  *      utmp).
709  *
710  *      Upon successful completion, SOLARIS_SUCCESS is returned.
711  *      Error values may include:
712  *
713  *      SOLARIS_NOENTRY     An entry for the specified process was not found
714  *      SOLARIS_ENTRYFAIL   Could not make/remove entry for specified process
715  */
716
717 int
718 solaris_setutmp_mgmt(
719         char    *user,
720         char    *ttyn,
721         char    *rhost,
722         int     flags,
723         int     type,
724         char    id[])
725 {
726         int                     tmplen;
727         struct utmpx            *u = (struct utmpx *)0;
728         struct utmpx            utmp;
729         char                    *ttyntail;
730         int                     err = PAM_SUCCESS;
731
732         Debug("Enter: solaris_setutmp_mgmt()\n");
733
734         (void) memset((void *)&utmp, 0, sizeof (utmp));
735
736         (void) time(&utmp.ut_tv.tv_sec);
737         utmp.ut_pid = getpid();
738         if (rhost != NULL && rhost[0] != '\0') {
739                 (void) strcpy(utmp.ut_host, rhost);
740                 tmplen = strlen(rhost) + 1;
741                 if (tmplen < sizeof (utmp.ut_host))
742                         utmp.ut_syslen = tmplen;
743                 else
744                         utmp.ut_syslen = sizeof (utmp.ut_host);
745         } else {
746                 (void) memset(utmp.ut_host, 0, sizeof (utmp.ut_host));
747                 utmp.ut_syslen = 0;
748         }
749
750         (void) strcpy(utmp.ut_user, user);
751         /*
752          * Copy in the name of the tty minus the "/dev/" if a /dev/ is
753          * in the path name.
754          */
755
756         if (!(flags&SOLARIS_LOGIN))
757                 SCPYN(utmp.ut_line, ttyn);
758
759         ttyntail = ttyn;
760
761         utmp.ut_type = type;
762
763         if (id != NULL)
764                 (void) memcpy(utmp.ut_id, id, sizeof (utmp.ut_id));
765
766         if ((flags & SOLARIS_NOLOG) == SOLARIS_NOLOG) {
767                 updwtmpx(WTMPX_FILE, &utmp);
768         } else {
769                 /*
770                  * Go through each entry one by one, looking only at INIT,
771                  * LOGIN or USER Processes.  Use the entry found if flags == 0
772                  * and the line name matches, or if the process ID matches if
773                  * the UPDATE_ENTRY flag is set.  The UPDATE_ENTRY flag is
774                  * mainly for login which normally only wants to update an
775                  * entry if the pid fields matches.
776                  */
777
778                 if (flags & SOLARIS_LOGIN) {
779                     while ((u = getutxent()) != NULL) {
780                         if ((u->ut_type == INIT_PROCESS ||
781                             u->ut_type == LOGIN_PROCESS ||
782                             u->ut_type == USER_PROCESS) &&
783                             ((flags == SOLARIS_LOGIN && ttyn != NULL &&
784                                         strncmp(u->ut_line, ttyntail,
785                                                 sizeof (u->ut_line)) == 0) ||
786                             u->ut_pid == utmp.ut_pid)) {
787                                 if (ttyn)
788                                         SCPYN(utmp.ut_line,
789                                             (ttyn + sizeof ("/dev/") - 1));
790                                 if (id == NULL) {
791                                         (void) memcpy(utmp.ut_id, u->ut_id,
792                                                     sizeof (utmp.ut_id));
793                                 }
794                                 (void) pututxline(&utmp);
795                                 break;
796                         }
797                     }      /* end while */
798                     endutxent();                /* Close utmp file */
799                 }
800
801                 if (u == (struct utmpx *)NULL) {
802                         /* audit_login_main11(); */
803                         if (flags & SOLARIS_UPDATE_ENTRY)
804                                 err =  SOLARIS_NOENTRY;
805                         else
806                                 (void) makeutx(&utmp);
807                 }
808                 else
809                         updwtmpx(WTMPX_FILE, &utmp);
810         }
811         return (err);
812 }
813
814 /*
815  * solaris_reset_utmp_mgmt 
816  *              A utility function used to terminate  UTMP/WTMP mgmt.
817  *
818  *      "user" is the current username.
819  *      "ttyn" is the tty name.
820  *      "rhost" is the remote hostname.
821  *      The following flags may be set in the "flags" field:
822  *
823  *      SOLARIS_NOLOG           Write a wtmp/wtmpx entry only
824  *      SOLARIS_NOOP            Ignore utmp/wtmp processing
825  *
826  *      "status" is the logout process status.
827  *      "id is an optional application-defined 4 byte array that represents
828  *      the /sbin/inittab id (created by the process that puts an entry in
829  *      utmp).
830  *
831  *      Upon successful completion, PAM_SUCCESS is returned.
832  *      Error values may include:
833  *
834  *      SOLARIS_NOENTRY    An entry for the specified process was not found
835  *      SOLARIS_ENTRYFAIL  Could not make/remove entry for specified process
836  */
837
838 int
839 solaris_reset_utmp_mgmt(
840         char    **user,
841         char    **ttyn,
842         char    **rhost,
843         int     flags,
844         int     status,
845         char    id[])
846 {
847         struct utmpx            *up;
848         struct utmpx            ut;
849         int                     err = 0;
850         int                     pid;
851
852         Debug("Enter: solaris_reset_utmp_mgmt()\n");
853
854
855         pid = (int) getpid();
856
857         if ((flags & SOLARIS_NOLOG) == SOLARIS_NOLOG) { 
858                 /* only write to wtmp files */
859                         /* clear utmpx entry */
860                 (void) memset((char *)&ut, 0, sizeof (ut));
861
862                 if (id != NULL)
863                         (void) memcpy(ut.ut_id, id, sizeof (ut.ut_id));
864
865                 if (*ttyn != NULL && **ttyn != '\0') {
866                         if (strstr(*ttyn, "/dev/") != NULL)
867                         (void) strncpy(ut.ut_line, (*ttyn+sizeof ("/dev/")-1),
868                                                         sizeof (ut.ut_line));
869                         else
870                                 (void) strncpy(ut.ut_line, *ttyn,
871                                                         sizeof (ut.ut_line));
872                 }
873                 ut.ut_pid  = pid;
874                 ut.ut_type = DEAD_PROCESS;
875                 ut.ut_exit.e_termination = 0;
876                 ut.ut_exit.e_exit = 0;
877                 ut.ut_syslen = 1;
878                 (void) gettimeofday(&ut.ut_tv, NULL);
879                 updwtmpx(WTMPX_FILE, &ut);
880
881                 return (PAM_SUCCESS);
882         } else {
883                 setutxent();
884                 while (up = getutxent()) {
885                         if (up->ut_pid == pid) {
886                                 if (up->ut_type == DEAD_PROCESS) {
887                                         /*
888                                          * Cleaned up elsewhere.
889                                          */
890                                         endutxent();
891                                         return (0);
892                                 }
893                                 if ((*user = (char *) strdup (up->ut_user))
894                                                         == NULL ||
895                                     (*ttyn = (char *) strdup (up->ut_line))
896                                                         == NULL ||
897                                     (*rhost = (char *) strdup (up->ut_host))
898                                                         == NULL)
899                                         return (PAM_BUF_ERR);
900
901                                 up->ut_type = DEAD_PROCESS;
902                                 up->ut_exit.e_termination = status & 0xff;
903                                 up->ut_exit.e_exit = (status >> 8) & 0xff;
904                                 if (id != NULL)
905                                         (void) memcpy(up->ut_id, id,
906                                                 sizeof (up->ut_id));
907                                 (void) time(&up->ut_tv.tv_sec);
908
909                                 /*
910                                  * For init (Process ID 1) we don't write to
911                                  * init's pipe, since we are init.
912                                  */
913                                 if (getpid() == INIT_PROC_PID) {
914                                         (void) pututxline(up);
915                                         /*
916                                          * Now attempt to add to the end of the
917                                          * wtmp and wtmpx files.  Do not create
918                                          * if they don't already exist.
919                                          */
920                                         updwtmpx("wtmpx", up);
921                                 } else {
922                                         if (modutx(up) == NULL) {
923                                                 Debug("modutx failed\n");
924                                                 /*
925                                                  * Since modutx failed we'll
926                                                  * write out the new entry
927                                                  * ourselves.
928                                                  */
929                                                 (void) pututxline(up);
930                                                 updwtmpx("wtmpx", up);
931                                         }
932                                 }
933
934                                 endutxent();
935
936                                 return (PAM_SUCCESS);
937                         }
938                 }
939
940                 endutxent();
941                 return (SOLARIS_NOENTRY);
942         }
943
944 }
945
946 #endif PAM