Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[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 libraries 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 #include        <sys/types.h>
47 #include        <sys/stat.h>
48
49 #ifdef AIXV3
50 #include        <usersec.h>
51 #endif
52
53 #include        <fcntl.h>
54 #if defined(__FreeBSD__) && OSMAJORVERSION > 8
55 #include        <utmpx.h>
56 #else
57 #include        <utmp.h>
58 #endif
59
60 #include        <time.h>
61 #include        "dm.h"
62
63 #ifdef __PASSWD_ETC
64 #include        "rgy_base.h"
65 #endif
66
67
68 /***************************************************************************
69  *
70  *  External declarations
71  *
72  ***************************************************************************/
73 #if defined(AIXV3) && !defined(_POWER)
74 extern void
75 GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname);
76 #endif
77
78
79
80 /***************************************************************************
81  *
82  *  Procedure declarations
83  *
84  ***************************************************************************/
85 #if defined(AIXV3) && !defined(_POWER)
86 void dt_lastlogin ( char * user, struct lastlogin * llogin);
87 #endif
88
89
90
91
92 /***************************************************************************
93  *
94  *  Global variables
95  *
96  ***************************************************************************/
97
98 #ifdef __PASSWD_ETC
99 struct rtmp {
100          char              rt_line[8];       /* tty name */
101          rgy_$login_name_t rt_name;          /* user id (full SID) */
102          char              rt_host[16];      /* hostname, if remote */
103          long              rt_time;          /* time on */
104 };
105 #endif
106
107 #ifdef AIXV3
108 struct  lastlogin {
109         time_t  ftime;
110         time_t  stime;
111         int     fcount;
112         char    user[32];
113         char    *stty;
114         char    *ftty;
115         char    *shost;
116         char    *fhost;
117 };
118
119
120 static struct lastlogin last_login;
121 #endif
122
123
124
125 /***************************************************************************
126  *
127  *  Account
128  *
129  *  update utmp/wtmp files.  
130  ***************************************************************************/
131 void 
132 Account( struct display *d, char *user, char *line, pid_t pid,
133 #if NeedWidePrototypes
134         int type,
135 #else
136         short type,
137 #endif /* NeedWidePrototypes */
138         waitType exitcode )
139 {
140 #if !defined(CSRG_BASED) /* we cannot do this on BSD ... */
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) - 1);
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) snprintf(u->ut_user, sizeof(u->ut_user), "%s", 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              snprintf(u->ut_line, sizeof(u->ut_line), "%s", line);
241              
242 #else
243              snprintf(u->ut_line, sizeof(u->ut_line), "%s", 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             snprintf(u->ut_host, sizeof(u->ut_host), "%s", d->name);
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         if(-1 == write(fd, u, sizeof(utmp))) {
289           perror(strerror(errno));
290         }
291         close(fd);
292     }
293
294
295     /*
296      *  close utmp...
297      */
298      
299     endutent();
300
301 #ifdef __PASSWD_ETC
302     /* Now fill in the "rgy utmp" struct */
303     if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
304     bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
305     rtmp.rt_time = u->ut_time;
306     r = &rtmp;
307
308     /* Write entry to rtmp */
309     tty_slot = ttyslot();
310
311     if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
312          lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
313          write(rtmp_fd, (char *) r, sizeof(struct rtmp));
314          close(rtmp_fd);
315     }
316 #endif
317 #if defined(AIXV3) && !defined(_POWER)
318         /* Log the lastlogin data ..    RK  09.13.93  */
319         /** in AIX 4.1 this is taken care of during authentication **/
320     if(type == USER_PROCESS) {
321         int loginType;
322         char tempTtyName[128];
323         char *hostname;
324
325         GetLoginInfo(d, &loginType, tempTtyName, &hostname);
326         time(&last_login.stime);
327
328         if(line) {
329                 Debug("tty_last_login is (line=%s)\n",line);
330                 last_login.stty = (char *)malloc(strlen(line) + 1);
331                 strcpy(last_login.stty,line);
332         } else {
333             last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
334             strcpy(last_login.stty,tempTtyName);
335         }
336
337         last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
338         if (hostname == NULL) {
339             gethostname (last_login.shost , MAXHOSTNAMELEN);
340         } else {
341             strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
342             last_login.shost[MAXHOSTNAMELEN -1] = '\0';
343         }
344
345         Debug("logging lastlogin entry (user=%s)\n",user);
346         dt_lastlogin(user,&last_login); 
347         free(last_login.stty);
348         free(last_login.shost);
349     }
350 #endif
351
352 #endif /* !sun */
353 #endif /* !CSRG_BASED */
354 }
355
356
357
358
359 /***************************************************************************
360  *
361  *  UtmpIdOpen
362  *
363  *  see if a particular utmp ID is available
364  *
365  * return codes:  0 = ID is in use
366  *                1 = ID is open 
367  ***************************************************************************/
368
369 int 
370 UtmpIdOpen( char *utmpId )
371 {
372     struct utmp *u;             /* pointer to entry in utmp file           */
373     int    status = 1;          /* return code                             */
374
375 #if !defined(CSRG_BASED)
376     while ( (u = getutent()) != NULL ) {
377
378         if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
379              u->ut_type != DEAD_PROCESS ) {
380
381             status = 0;
382             break;
383         }
384     }
385     
386     endutent();
387 #endif
388     return (status);
389 }
390
391
392
393 #if defined(AIXV3) && !defined(_POWER)
394 void dt_lastlogin ( user, llogin)
395 char * user;
396 struct lastlogin * llogin;
397 {
398         char *tmp_char;
399         char *tmp_int;
400         /*
401          * We are loading all the lastlogin info into a struct and then dealing 
402          * with that so if the technique of storing the values is redone it 
403          * will be easy
404          */
405         /* set id back to root */
406         seteuid(0);
407                 /*
408                  * Open up the user data base
409                  */
410                 setuserdb(S_READ | S_WRITE);
411
412                 /*
413                  * setting new unsuccessful login attempts times
414                  */
415                 if (llogin->ftime) {
416                         /*
417                          * Get the old Failure count and increment it
418                          */
419                         if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
420                                 llogin->fcount = 0;
421                         else
422                                 llogin->fcount = (int)tmp_int;
423
424                         /*
425                          * put all the new data
426                          */
427                         putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
428                         llogin->fcount++;
429                         putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
430                                     SEC_INT);
431                         putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
432                                     SEC_INT);
433                         putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
434                         putuserattr(user, NULL, NULL, SEC_COMMIT);
435
436                         /*
437                          * Close data base and zero out indicator fields
438                          */
439                         llogin->ftime = 0;
440                         llogin->fcount = 0;
441                 }
442
443                 /*
444                  * New Successful login data
445                  */
446                 if (llogin->stime) {
447                         putuserattr(user, S_LASTTIME, (void *)llogin->stime,
448                                     SEC_INT);
449                         putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
450                         Debug("hostname logged is %s\n",llogin->shost);
451                         putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
452                         putuserattr(user, S_ULOGCNT, 0, SEC_INT);
453                         putuserattr(user, NULL, NULL, SEC_COMMIT);
454                 }
455         enduserdb();
456 }
457 #endif
458