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