Fixes for dtlogin and dtcm on FreeBSD.
[oweals/cde.git] / cde / programs / dtlogin / account.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: account.c /main/6 1996/10/30 11:12:13 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  *  account.c
32  *
33  *    routines for handling accounting
34  *
35  *    ex. utmp/wtmp/btmp, user-license restrictions,
36  *
37  */
38
39
40 /***************************************************************************
41  *
42  *  Includes
43  *
44  ***************************************************************************/
45
46
47 #ifdef __apollo
48 #include <X11/apollosys.h>        /* for pid_t struct in hp-ux sys/types.h */
49 #include        <sys/types.h>
50 #else
51 #include        <sys/types.h>
52 #include        <sys/stat.h>
53 #endif
54
55 #ifdef AIXV3
56 #include        <usersec.h>
57 #endif
58
59 #include        <fcntl.h>
60 #if defined(__FreeBSD__)
61 #include        <utmpx.h>
62 #else
63 #include        <utmp.h>
64 #endif
65
66 #include        <time.h>
67 #include        "dm.h"
68
69 #ifdef __PASSWD_ETC
70 #include        "rgy_base.h"
71 #endif
72
73
74 /***************************************************************************
75  *
76  *  External declarations
77  *
78  ***************************************************************************/
79 #if defined(AIXV3) && !defined(_POWER)
80 extern void
81 GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname);
82 #endif
83
84
85
86 /***************************************************************************
87  *
88  *  Procedure declarations
89  *
90  ***************************************************************************/
91 #if defined(AIXV3) && !defined(_POWER)
92 void dt_lastlogin ( char * user, struct lastlogin * llogin);
93 #endif
94
95
96
97
98 /***************************************************************************
99  *
100  *  Global variables
101  *
102  ***************************************************************************/
103
104 #ifdef __PASSWD_ETC
105 struct rtmp {
106          char              rt_line[8];       /* tty name */
107          rgy_$login_name_t rt_name;          /* user id (full SID) */
108          char              rt_host[16];      /* hostname, if remote */
109          long              rt_time;          /* time on */
110 };
111 #endif
112
113 #ifdef AIXV3
114 struct  lastlogin {
115         time_t  ftime;
116         time_t  stime;
117         int     fcount;
118         char    user[32];
119         char    *stty;
120         char    *ftty;
121         char    *shost;
122         char    *fhost;
123 };
124
125
126 static struct lastlogin last_login;
127 #endif
128
129
130
131 /***************************************************************************
132  *
133  *  Account
134  *
135  *  update utmp/wtmp files.  
136  ***************************************************************************/
137 void 
138 Account( struct display *d, char *user, char *line, pid_t pid,
139 #if NeedWidePrototypes
140         int type,
141 #else
142         short type,
143 #endif /* NeedWidePrototypes */
144         waitType exitcode )
145 {
146 #if !defined(CSRG_BASED) /* we cannot do this on BSD ... */
147     struct utmp utmp;           /* local struct for new entry              */
148     struct utmp *u;             /* pointer to entry in utmp file           */
149     int fd;
150     char        buf[32];
151     char* user_str = user ? user : "NULL";
152     char* line_str = line ? line : "NULL";
153             
154 #ifdef __PASSWD_ETC
155     struct rtmp rtmp;
156     struct rtmp *r;
157     int tty_slot;
158     int rtmp_fd;
159 #endif
160
161     if (d->utmpId == NULL) return;
162     
163     switch (type) {
164     
165     case INIT_PROCESS:  strcpy(buf, "INIT_PROCESS");    break;
166     case LOGIN_PROCESS: strcpy(buf, "LOGIN_PROCESS");   break;
167     case USER_PROCESS:  strcpy(buf, "USER_PROCESS");    break;
168     case DEAD_PROCESS:  strcpy(buf, "DEAD_PROCESS");    break;
169     default:            strcpy(buf, "UNKNOWN");         break;
170     }
171
172     Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n",
173            d->utmpId, user_str, line_str, pid, buf);
174
175 #ifdef PAM
176     PamAccounting("dtlogin", d->name, d->utmpId, user, 
177                         line, pid, type, exitcode);
178 #else
179 #   ifdef SUNAUTH
180        solaris_accounting("dtlogin", d->name, d->utmpId, user, 
181                            line, pid, type, exitcode);
182 #   endif
183 #endif
184
185 #ifdef sun
186     return;
187 #else
188     bzero(&utmp, sizeof(struct utmp));
189
190     strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id));
191     utmp.ut_type = LOGIN_PROCESS;
192     
193     setutent();
194     if ( (u = getutid(&utmp)) == NULL ) u = &utmp;
195
196     /*
197      *  make sure process ID's match if this is DEAD_PROCESS...
198      *  don't update an already DEAD_PROCESS...
199      */
200
201     if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) ||
202         (type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS)    ) {
203
204         endutent();
205         return;
206     }
207
208
209     /*
210      *  fill in required fields of utmp structure...
211      *
212      *  Note: for USER_PRCESS the "e_exit" field is overloaded to contain
213      *        the method for counting this user. This is used later to
214      *        determine if restricted user licenses have been exceeded.
215      *        Currently, an unlimited number of foreign displays can log in.
216      */
217      
218     if (user) strncpy(u->ut_user, user, sizeof(u->ut_user));
219     if (line) {
220 #ifdef _AIX
221 /*
222       For AIX the Init process writes the exact mapped device name for console
223       to the utmp file (like hft/0), if a getty on /dev/console record exists
224       in the Inittab file.Hitherto, we need to have a similar logic to make
225       sure for having the correct entry in the utmp file in order for the correct
226       operation of the GettyRunning function. It should be noted that by having
227       the correct value in the d->gettyLine field, the utmp file eventuallly
228       updated by the Account function in dm.c will have the right value. And
229       thus the GettyRunning function returns the appropriate value. So, it
230       is important that the following logic be included here for AIX platform
231       only.
232       Raghu Krovvidi         07.06.93
233  */
234
235         if (!strcmp(line,"console")) {
236              char *ttynm;
237              int fd=0;
238
239              fd = open("/dev/console",O_RDONLY);
240              ttynm = ttyname(fd);
241              ttynm += 5;
242              strcpy(u->ut_line,ttynm);
243              close(fd);
244         }
245         else
246              strncpy(u->ut_line, line, sizeof(u->ut_line));
247              
248 #else
249              strncpy(u->ut_line, line, sizeof(u->ut_line));
250 #endif
251     }
252     if (pid ) u->ut_pid = pid;
253     if (type) {
254         u->ut_type = type;
255         if (type == DEAD_PROCESS) {
256             u->ut_exit.e_termination = waitSig(exitcode);
257             u->ut_exit.e_exit = waitCode(exitcode);
258 #ifndef SVR4
259             (void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host));
260 #endif
261         }
262
263         if (type == LOGIN_PROCESS && d->displayType.location != Local ) {
264 #ifndef SVR4
265             strncpy(u->ut_host, d->name, sizeof(u->ut_host));
266 #endif
267 #ifdef __hpux
268             u->ut_addr = 0;
269 #endif
270         }
271                     
272         if (type == USER_PROCESS)
273             u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 );
274     }   
275
276     (void) time(&u->ut_time);
277
278     /* 
279      * write to utmp...  
280      *
281      * (Do not close utmp yet. If "u" points to the static structure, it is
282      *  cleared upon close. This does not bode well for the following write
283      *  to wtmp!)
284      */
285
286     pututline(u);
287
288
289     /*
290      *  write the same entry to wtmp...
291      */
292
293     if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) {
294         write(fd, u, sizeof(utmp));
295         close(fd);
296     }
297
298
299     /*
300      *  close utmp...
301      */
302      
303     endutent();
304
305 #ifdef __PASSWD_ETC
306     /* Now fill in the "rgy utmp" struct */
307     if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
308     bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
309     rtmp.rt_time = u->ut_time;
310     r = &rtmp;
311
312     /* Write entry to rtmp */
313     tty_slot = ttyslot();
314
315     if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
316          lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
317          write(rtmp_fd, (char *) r, sizeof(struct rtmp));
318          close(rtmp_fd);
319     }
320 #endif
321 #if defined(AIXV3) && !defined(_POWER)
322         /* Log the lastlogin data ..    RK  09.13.93  */
323         /** in AIX 4.1 this is taken care of during authentication **/
324     if(type == USER_PROCESS) {
325         int loginType;
326         char tempTtyName[128];
327         char *hostname;
328
329         GetLoginInfo(d, &loginType, tempTtyName, &hostname);
330         time(&last_login.stime);
331
332         if(line) {
333                 Debug("tty_last_login is (line=%s)\n",line);
334                 last_login.stty = (char *)malloc(strlen(line) + 1);
335                 strcpy(last_login.stty,line);
336         } else {
337             last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
338             strcpy(last_login.stty,tempTtyName);
339         }
340
341         last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
342         if (hostname == NULL) {
343             gethostname (last_login.shost , MAXHOSTNAMELEN);
344         } else {
345             strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
346             last_login.shost[MAXHOSTNAMELEN -1] = '\0';
347         }
348
349         Debug("logging lastlogin entry (user=%s)\n",user);
350         dt_lastlogin(user,&last_login); 
351         free(last_login.stty);
352         free(last_login.shost);
353     }
354 #endif
355
356 #endif /* !sun */
357 #endif /* !CSRG_BASED */
358 }
359
360
361
362
363 /***************************************************************************
364  *
365  *  UtmpIdOpen
366  *
367  *  see if a particular utmp ID is available
368  *
369  * return codes:  0 = ID is in use
370  *                1 = ID is open 
371  ***************************************************************************/
372
373 int 
374 UtmpIdOpen( char *utmpId )
375 {
376     struct utmp *u;             /* pointer to entry in utmp file           */
377     int    status = 1;          /* return code                             */
378
379 #if !defined(CSRG_BASED)
380     while ( (u = getutent()) != NULL ) {
381
382         if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
383              u->ut_type != DEAD_PROCESS ) {
384
385             status = 0;
386             break;
387         }
388     }
389     
390     endutent();
391 #endif
392     return (status);
393 }
394
395
396
397 #if defined(AIXV3) && !defined(_POWER)
398 void dt_lastlogin ( user, llogin)
399 char * user;
400 struct lastlogin * llogin;
401 {
402         char *tmp_char;
403         char *tmp_int;
404         /*
405          * We are loading all the lastlogin info into a struct and then dealing 
406          * with that so if the technique of storing the values is redone it 
407          * will be easy
408          */
409         /* set id back to root */
410         seteuid(0);
411                 /*
412                  * Open up the user data base
413                  */
414                 setuserdb(S_READ | S_WRITE);
415
416                 /*
417                  * setting new unsuccessful login attempts times
418                  */
419                 if (llogin->ftime) {
420                         /*
421                          * Get the old Failure count and increment it
422                          */
423                         if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
424                                 llogin->fcount = 0;
425                         else
426                                 llogin->fcount = (int)tmp_int;
427
428                         /*
429                          * put all the new data
430                          */
431                         putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
432                         llogin->fcount++;
433                         putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
434                                     SEC_INT);
435                         putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
436                                     SEC_INT);
437                         putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
438                         putuserattr(user, NULL, NULL, SEC_COMMIT);
439
440                         /*
441                          * Close data base and zero out indicator fields
442                          */
443                         llogin->ftime = 0;
444                         llogin->fcount = 0;
445                 }
446
447                 /*
448                  * New Successful login data
449                  */
450                 if (llogin->stime) {
451                         putuserattr(user, S_LASTTIME, (void *)llogin->stime,
452                                     SEC_INT);
453                         putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
454                         Debug("hostname logged is %s\n",llogin->shost);
455                         putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
456                         putuserattr(user, S_ULOGCNT, 0, SEC_INT);
457                         putuserattr(user, NULL, NULL, SEC_COMMIT);
458                 }
459         enduserdb();
460 }
461 #endif
462