source: trunk/src/sh_utmp.c@ 156

Last change on this file since 156 was 154, checked in by katerina, 17 years ago

Fix more compiler warnings, and a potential NULL dereference in the unix entropy collector.

File size: 26.4 KB
RevLine 
[1]1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28#include <errno.h>
29
30#ifdef HAVE_UTADDR
31#include <sys/socket.h>
32#include <netinet/in.h>
33#ifndef S_SPLINT_S
34#include <arpa/inet.h>
35#else
36#define AF_INET 2
37#endif
38#endif
39
40#ifdef SH_USE_UTMP
41
42#ifdef HAVE_UTMPX_H
43
44#ifdef S_SPLINT_S
45typedef pid_t __pid_t;
46#endif
47
48#include <utmpx.h>
49#define SH_UTMP_S utmpx
50#undef ut_name
51#define ut_name ut_user
52#ifdef HAVE_UTXTIME
53#undef ut_time
54#define ut_time ut_xtime
55#else
56#undef ut_time
57#define ut_time ut_tv.tv_sec
58#endif
59
60#else
61#include <utmp.h>
62#define SH_UTMP_S utmp
63#endif
64
65
66#ifdef HAVE_PATHS_H
67#include <paths.h>
68#endif
69
70#undef FIL__
71#define FIL__ _("sh_utmp.c")
72
73#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
74
75
76#include "samhain.h"
77#include "sh_utils.h"
78#include "sh_error.h"
79#include "sh_modules.h"
80#include "sh_utmp.h"
[143]81#include "sh_pthread.h"
[1]82
[143]83SH_MUTEX_EXTERN(mutex_thread_nolog);
[1]84
85#ifdef TM_IN_SYS_TIME
86#include <sys/time.h>
87#else
88#include <time.h>
89#endif
90
91#ifdef HAVE_UNISTD_H
92#include <unistd.h>
93#endif
94
95#ifdef HAVE_DIRENT_H
96#include <dirent.h>
97#define NAMLEN(dirent) sl_strlen((dirent)->d_name)
98#else
99#define dirent direct
100#define NAMLEN(dirent) (dirent)->d_namlen
101#ifdef HAVE_SYS_NDIR_H
102#include <sys/ndir.h>
103#endif
104#ifdef HAVE_SYS_DIR_H
105#include <sys/dir.h>
106#endif
107#ifdef HAVE_NDIR_H
108#include <ndir.h>
109#endif
110#endif
111
112#ifndef HAVE_LSTAT
113#define lstat stat
114#endif
115
116#ifndef UT_LINESIZE
117#ifndef __UT_LINESIZE
118#define UT_LINESIZE 12
119#else
120#define UT_LINESIZE __UT_LINESIZE
121#endif
122#endif
123
124#ifndef UT_NAMESIZE
125#ifndef __UT_NAMESIZE
126#define UT_NAMESIZE 8
127#else
128#define UT_NAMESIZE __UT_NAMESIZE
129#endif
130#endif
131
132#ifndef UT_HOSTSIZE
133#ifndef __UT_HOSTSIZE
134#define UT_HOSTSIZE 16
135#else
136#define UT_HOSTSIZE __UT_HOSTSIZE
137#endif
138#endif
139
140#ifdef HAVE_UTMPX_H
141
142#ifndef _PATH_UTMP
143#ifdef UTMPX_FILE
144#define _PATH_UTMP UTMPX_FILE
145#else
146#error You must define UTMPX_FILE in the file config.h
147#endif
148#endif
149#ifndef _PATH_WTMP
150#ifdef WTMPX_FILE
151#define _PATH_WTMP WTMPX_FILE
152#else
153#error You must define WTMPX_FILE in the file config.h
154#endif
155#endif
156
157#else
158
159#ifndef _PATH_UTMP
160#ifdef UTMP_FILE
161#define _PATH_UTMP UTMP_FILE
162#else
163#error You must define UTMP_FILE in the file config.h
164#endif
165#endif
166#ifndef _PATH_WTMP
167#ifdef WTMP_FILE
168#define _PATH_WTMP WTMP_FILE
169#else
170#error You must define WTMP_FILE in the file config.h
171#endif
172#endif
173
174#endif
175
176typedef struct log_user {
177 char ut_tty[UT_LINESIZE+1];
178 char name[UT_NAMESIZE+1];
179 char ut_host[UT_HOSTSIZE+1];
180 char ut_ship[16]; /* IP address */
181 time_t time;
182 struct log_user * next;
183} blah_utmp;
184
185#ifdef HAVE_UTTYPE
186static char terminated_line[UT_HOSTSIZE];
187#endif
188
189static struct SH_UTMP_S save_utmp;
190
191static void sh_utmp_logout_morechecks(struct log_user * user);
192static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut);
193static void sh_utmp_addlogin (struct SH_UTMP_S * ut);
194static void sh_utmp_check_internal(int mode);
195
196static int ShUtmpLoginSolo = SH_ERR_INFO;
197static int ShUtmpLoginMulti = SH_ERR_WARN;
198static int ShUtmpLogout = SH_ERR_INFO;
199static int ShUtmpActive = S_TRUE;
200static time_t ShUtmpInterval = 300;
201
202sh_rconf sh_utmp_table[] = {
203 {
204 N_("severityloginmulti"),
205 sh_utmp_set_login_multi
206 },
207 {
208 N_("severitylogin"),
209 sh_utmp_set_login_solo
210 },
211 {
212 N_("severitylogout"),
213 sh_utmp_set_logout_good
214 },
215 {
216 N_("logincheckactive"),
217 sh_utmp_set_login_activate
218 },
219 {
220 N_("logincheckinterval"),
221 sh_utmp_set_login_timer
222 },
223 {
224 NULL,
225 NULL
226 },
227};
228
[149]229static void set_defaults(void)
[1]230{
[149]231 ShUtmpLoginSolo = SH_ERR_INFO;
232 ShUtmpLoginMulti = SH_ERR_WARN;
233 ShUtmpLogout = SH_ERR_INFO;
234 ShUtmpActive = S_TRUE;
235 ShUtmpInterval = 300;
236 return;
[1]237}
238
239
240#if defined (HAVE_SETUTENT) && defined (USE_SETUTENT)
241
242#ifdef HAVE_UTMPX_H
243
244#define sh_utmp_utmpname utmpxname
245#define sh_utmp_setutent setutxent
246#define sh_utmp_endutent endutxent
247#define sh_utmp_getutent getutxent
248#define sh_utmp_getutid getutxid
249#define sh_utmp_getutline getutxline
250
251#else
252
253#define sh_utmp_utmpname utmpname
254#define sh_utmp_setutent setutent
255#define sh_utmp_endutent endutent
256#define sh_utmp_getutent getutent
257#define sh_utmp_getutid getutid
258#define sh_utmp_getutline getutline
259
260#endif
261
262#else
263
264/* BSD lacks getutent() etc.
265 * utmpname(), setutent(), and endutent() return void,
266 * so we do not perform much error handling.
267 * Errors must be recognized by getutent() returning NULL.
268 * Apparently, the application cannot check whether wtmp is empty,
269 * or whether there was an fopen() error.
270 */
271
272static FILE * sh_utmpfile = NULL;
273static char sh_utmppath[80] = _PATH_UTMP;
274
275/* sh_utmp_feed_forward is for optimizing
276 * (fseek instead of getutent loop)
277 */
278static long sh_utmp_feed_forward = 0;
279
280static void sh_utmp_utmpname(const char * str)
281{
282 SL_ENTER(_("sh_utmp_utmpname"));
283 if (sh_utmpfile != NULL)
284 {
285 (void) fclose (sh_utmpfile);
286 sh_utmpfile = NULL;
287 }
288
289 (void) sl_strlcpy (sh_utmppath, str, 80);
290 SL_RET0(_("sh_utmp_utmpname"));
291}
292
293static void sh_utmp_setutent(void)
294{
295 int error;
296 int fd;
297
298 SL_ENTER(_("sh_utmp_setutent"));
299
300 ASSERT((sh_utmppath != NULL), _("sh_utmppath != NULL"));
301
302 if (sh_utmppath == NULL)
303 SL_RET0(_("sh_utmp_setutent"));
304
305 if (sh_utmpfile == NULL)
306 {
[143]307 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]308 fd = (int) aud_open (FIL__, __LINE__, SL_NOPRIV,
309 sh_utmppath, O_RDONLY, 0);
[143]310 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]311 if (fd >= 0)
312 {
313 sh_utmpfile = fdopen(fd, "r");
314 }
315
316 /* -- If (sh_utmpfile == NULL) then either the open() or the fdopen()
317 * has failed.
318 */
319 if (sh_utmpfile == NULL)
320 {
321 error = errno;
[143]322 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]323 sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
324 (long) sh.real.uid, sh_utmppath);
[143]325 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]326 SL_RET0(_("sh_utmp_setutent"));
327 }
328 }
329 (void) fseek (sh_utmpfile, 0L, SEEK_SET);
330 if (-1 == fseek (sh_utmpfile, sh_utmp_feed_forward, SEEK_CUR))
331 {
332 sh_utmp_feed_forward = 0; /* modified Apr 4, 2004 */
333 (void) fseek (sh_utmpfile, 0L, SEEK_SET);
334 }
335 clearerr (sh_utmpfile);
336 SL_RET0(_("sh_utmp_setutent"));
337}
338
339static void sh_utmp_endutent(void)
340{
341 SL_ENTER(_("sh_utmp_endutent"));
[30]342 if (NULL != sh_utmpfile)
343 (void) fclose(sh_utmpfile);
[1]344 sh_utmpfile = NULL;
345 SL_RET0(_("sh_utmp_endutent"));
346}
347
348static struct SH_UTMP_S * sh_utmp_getutent(void)
349{
350 size_t in;
351 static struct SH_UTMP_S out;
352
353 SL_ENTER(_("sh_utmp_getutent"));
354
355 ASSERT_RET((sh_utmpfile != NULL), _("sh_utmpfile != NULL"), (NULL))
356
357 in = fread (&out, sizeof(struct SH_UTMP_S), 1, sh_utmpfile);
358
359 if (in != 1)
360 {
361 if (ferror (sh_utmpfile) != 0)
362 {
363 clearerr (sh_utmpfile);
364 SL_RETURN(NULL, _("sh_utmp_getutent"));
365 }
366 else
367 {
368 SL_RETURN(NULL, _("sh_utmp_getutent"));
369 }
370 }
371 SL_RETURN(&out, _("sh_utmp_getutent"));
372}
373
374#ifdef USE_UNUSED
375
376static struct SH_UTMP_S * sh_utmp_getutline(struct SH_UTMP_S * ut)
377{
378 struct SH_UTMP_S * out;
379
380 while (1) {
381 if ((out = sh_utmp_getutent()) == NULL) {
382 return NULL;
383 }
384#ifdef HAVE_UTTYPE
385 if (out->ut_type == USER_PROCESS || out->ut_type == LOGIN_PROCESS)
386 if (sl_strcmp(ut->ut_line, out->ut_line) == 0)
387 return out;
388#else
389 if ( 0 != sl_strncmp (out->ut_name, "reboot", 6) &&
390 0 != sl_strncmp (out->ut_name, "shutdown", 8) &&
391 0 != sl_strncmp (out->ut_name, "date", 4) )
392 return out;
393#endif
394 }
395 return NULL;
396}
397
398static struct SH_UTMP_S * sh_utmp_getutid(struct SH_UTMP_S * ut)
399{
400#ifdef HAVE_UTTYPE
401 struct SH_UTMP_S * out;
402
403 if (ut->ut_type == RUN_LVL || ut->ut_type == BOOT_TIME ||
404 ut->ut_type == NEW_TIME || ut->ut_type == OLD_TIME)
405 {
406 while (1) {
407 if ((out = sh_utmp_getutent()) == NULL) {
408 return NULL;
409 }
410 if (out->ut_type == ut->ut_type)
411 return out;
412 }
413 }
414 else if (ut->ut_type == INIT_PROCESS || ut->ut_type == LOGIN_PROCESS ||
415 ut->ut_type == USER_PROCESS || ut->ut_type == DEAD_PROCESS )
416 {
417 while (1) {
418 if ((out = sh_utmp_getutent()) == NULL) {
419 return NULL;
420 }
421 if (sl_strcmp(ut->ut_id, out->ut_id) == 0)
422 return out;
423 }
424 }
425#endif
426 return NULL;
427}
428/* #ifdef USE_UNUSED */
429#endif
430
431/* #ifdef HAVE_SETUTENT */
432#endif
433
434#ifdef HAVE_UTADDR
435#ifdef HAVE_INET_ATON
436static char * my_inet_ntoa(struct in_addr in)
437{
438 return /*@-unrecog@*/inet_ntoa(in)/*@+unrecog@*/;
439}
440#else
441static char * my_inet_ntoa(struct in_addr in)
442{
443 unsigned char a, b, c, d;
444 static char foo[16];
445 char bar[4];
446 memcpy (bar, &(in.s_addr), 4); /* memory alignment (?) */
447 memcpy (&a, &bar[0], 1);
448 memcpy (&b, &bar[1], 1);
449 memcpy (&c, &bar[2], 1);
450 memcpy (&d, &bar[3], 1);
[34]451 sprintf(foo, _("%d.%d.%d.%d"), /* known to fit */
[1]452 (int) a, (int) b, (int) c, (int) d);
453 return foo;
454}
455#endif
456/* #ifdef HAVE_UTADDR */
457#endif
458
459#if defined(__linux__) && !defined(ut_addr)
460#define ut_addr ut_addr_v6[0]
461#endif
462
463
464static struct log_user * userlist = NULL;
465static time_t lastcheck;
[142]466static int init_done = 0;
[1]467
468/*************
469 *
470 * module init
471 *
472 *************/
[142]473
474static int sh_utmp_init_internal ()
[1]475{
476
477 SL_ENTER(_("sh_utmp_init"));
478 if (ShUtmpActive == BAD)
479 SL_RETURN( (-1), _("sh_utmp_init"));
480
481 /* do not re-initialize after a re-configuration
482 */
[142]483 if (init_done == 1) {
[1]484 SL_RETURN( (0), _("sh_utmp_init"));
485 }
486 lastcheck = time (NULL);
487 userlist = NULL;
488 memset (&save_utmp, 0, sizeof(struct SH_UTMP_S));
489 sh_utmp_check_internal (2); /* current logins */
490 sh_utmp_check_internal (0);
[142]491 init_done = 1;
[1]492 SL_RETURN( (0), _("sh_utmp_init"));
493}
494
[142]495int sh_utmp_init (struct mod_type * arg)
496{
497 if (ShUtmpActive == BAD)
498 return SH_MOD_FAILED;
499#ifdef HAVE_PTHREAD
[144]500 if (arg != NULL && arg->initval < 0 &&
501 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
[142]502 {
503 if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
504 return SH_MOD_THREAD;
505 else
506 return SH_MOD_FAILED;
507 }
508#endif
509 return sh_utmp_init_internal();
510}
511
[1]512/*************
513 *
514 * module cleanup
515 *
516 *************/
517#ifdef HAVE_UTTYPE
518static int sh_utmp_login_clean();
519#endif
520
521int sh_utmp_end ()
522{
523 struct log_user * user = userlist;
524 struct log_user * userold;
525
526 SL_ENTER(_("sh_utmp_end"));
527 while (user)
528 {
529 userold = user;
530 user = user->next;
531 SH_FREE(userold);
532 }
533 userlist = NULL;
534#ifdef HAVE_UTTYPE
535 (void) sh_utmp_login_clean();
536#endif
[142]537 /* Reset the flag, such that the module
538 * can be re-enabled.
539 */
[149]540 set_defaults();
[142]541 init_done = 0;
[1]542 SL_RETURN( (0), _("sh_utmp_end"));
543}
544
[149]545int sh_utmp_reconf()
546{
547 set_defaults();
548 return 0;
549}
[1]550
[149]551
[1]552/*************
553 *
554 * module timer
555 *
556 *************/
557int sh_utmp_timer (time_t tcurrent)
558{
559 if ((time_t) (tcurrent - lastcheck) >= ShUtmpInterval)
560 {
561 lastcheck = tcurrent;
562 return (-1);
563 }
564 return 0;
565}
566
567/*************
568 *
569 * module check
570 *
571 *************/
572int sh_utmp_check ()
573{
574 SL_ENTER(_("sh_utmp_check"));
[142]575 if (ShUtmpActive == BAD)
576 SL_RETURN( (-1), _("sh_utmp_check"));
[143]577 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]578 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK);
[143]579 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]580 sh_utmp_check_internal (1);
581
582 SL_RETURN(0, _("sh_utmp_check"));
583}
584
585/*************
586 *
587 * module setup
588 *
589 *************/
590
[68]591int sh_utmp_set_login_solo (const char * c)
[1]592{
593 int retval;
594 char tmp[32];
595
596 SL_ENTER(_("sh_utmp_set_login_solo"));
597 tmp[0] = '='; tmp[1] = '\0';
598 (void) sl_strlcat (tmp, c, 32);
[143]599 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]600 retval = sh_error_set_level (tmp, &ShUtmpLoginSolo);
[143]601 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]602 SL_RETURN(retval, _("sh_utmp_set_login_solo"));
603}
604
[68]605int sh_utmp_set_login_multi (const char * c)
[1]606{
607 int retval;
608 char tmp[32];
609
610 SL_ENTER(_("sh_utmp_set_login_multi"));
611 tmp[0] = '='; tmp[1] = '\0';
612 (void) sl_strlcat (tmp, c, 32);
[143]613 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]614 retval = sh_error_set_level (tmp, &ShUtmpLoginMulti);
[143]615 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]616 SL_RETURN(retval, _("sh_utmp_set_login_multi"));
617}
618
[68]619int sh_utmp_set_logout_good (const char * c)
[1]620{
621 int retval;
622 char tmp[32];
623
624 SL_ENTER(_("sh_utmp_set_logout_good"));
625 tmp[0] = '='; tmp[1] = '\0';
626 (void) sl_strlcat (tmp, c, 32);
[143]627 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]628 retval = sh_error_set_level (tmp, &ShUtmpLogout);
[143]629 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]630 SL_RETURN(retval, _("sh_utmp_set_logout_good"));
631}
632
[68]633int sh_utmp_set_login_timer (const char * c)
[1]634{
635 int retval = 0;
636 long val;
637
638 SL_ENTER(_("sh_utmp_set_login_timer"));
639 val = strtol (c, (char **)NULL, 10);
640 if (val <= 0)
641 {
[143]642 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]643 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
644 _("utmp timer"), c);
[143]645 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]646 retval = -1;
647 }
648
649 val = (val <= 0 ? 60 : val);
650
651 ShUtmpInterval = (time_t) val;
652 SL_RETURN(0, _("sh_utmp_set_login_timer"));
653}
654
[68]655int sh_utmp_set_login_activate (const char * c)
[1]656{
657 int i;
658 SL_ENTER(_("sh_utmp_set_login_activate"));
659 i = sh_util_flagval(c, &ShUtmpActive);
660 SL_RETURN(i, _("sh_utmp_set_login_activate"));
661}
662
663#ifdef HAVE_UTTYPE
664struct login_ct {
665 char name[UT_NAMESIZE+1];
666 int nlogin;
667 struct login_ct * next;
668};
669
670static struct login_ct * login_ct_list = NULL;
671
672static int sh_utmp_login_clean()
673{
674 struct login_ct * list = login_ct_list;
675 struct login_ct * old;
676
677 login_ct_list = NULL;
678
679 while (list)
680 {
681 old = list;
682 list = list->next;
683 SH_FREE(old);
684 }
685 return 0;
686}
687
688/* add a username to the list of logged-in users
689 */
690static int sh_utmp_login_a(char * str)
691{
692 struct login_ct * list = login_ct_list;
693
694 while (list)
695 {
696 if (0 == sl_strcmp(list->name, str))
697 {
698 ++(list->nlogin);
699 return list->nlogin;
700 }
701 list = list->next;
702 }
703 list = SH_ALLOC(sizeof(struct login_ct));
704 (void) sl_strlcpy(list->name, str, UT_NAMESIZE+1);
705 list->nlogin = 1;
706 list->next = login_ct_list;
707 login_ct_list = list;
708 return 1;
709}
710
711static int sh_utmp_login_r(char * str)
712{
713 struct login_ct * list = login_ct_list;
714 struct login_ct * old = login_ct_list;
715
716 while (list)
717 {
718 if (0 == sl_strcmp(list->name, str))
719 {
720 list->nlogin -= 1;
721 if (list->nlogin > 0)
722 {
723 return list->nlogin;
724 }
725 if (login_ct_list == list) /* modified Apr 4, 2004 */
726 {
727 login_ct_list = list->next;
728 SH_FREE(list);
729 }
730 else
731 {
732 old->next = list->next;
733 SH_FREE(list);
734 }
735 return 0;
736 }
737 old = list;
738 list = list->next;
739 }
740 return 0;
741}
742
743#endif
744
745
746/* for each login:
747 * - allocate a log record
748 * - link device.ut_record -> log_record
749 * - link user.ut_record -> log_record
750 */
751#ifdef HAVE_UTTYPE
752static int sh_utmp_is_virtual (char * in_utline, char * in_uthost)
753{
754 if (in_utline != NULL)
755 {
756 if (0 == sl_strncmp(in_utline, _("ttyp"), 4))
757 { return 0; }
758 else if (0 == sl_strncmp(in_utline, _("ttyq"), 4))
759 { return 0; }
760 }
761 if (in_uthost != NULL &&
762 in_uthost[0] == ':' &&
763 in_uthost[1] == '0' &&
764 in_uthost[2] == '\0')
765 {
766 /* return 0; */
767 return 1; /* actually does not seem portable, not even among linuxes */
768 }
769 return 1;
770}
771#endif
772
[154]773/* These variables are not used anywhere. They only exist
774 * to assign &userold, &user to them, which keeps gcc from
775 * putting them into a register, and avoids the 'clobbered
776 * by longjmp' warning. And no, 'volatile' proved insufficient.
777 */
778void * sh_dummy_userold = NULL;
779void * sh_dummy_user = NULL;
780
781
[1]782static void sh_utmp_addlogin (struct SH_UTMP_S * ut)
783{
[154]784 struct log_user * user = userlist;
785 struct log_user * userold = userlist;
[1]786#ifdef HAVE_UTTYPE
787 struct log_user * username = userlist;
788#endif
789
790 char ttt[TIM_MAX];
791#ifdef HAVE_UTTYPE
[153]792 volatile int status;
[1]793#endif
794
795 SL_ENTER(_("sh_utmp_addlogin"));
796
[154]797 /* Take the address to keep gcc from putting them into registers.
798 * Avoids the 'clobbered by longjmp' warning.
799 */
800 sh_dummy_userold = (void*) &userold;
801 sh_dummy_user = (void*) &user;
802
[1]803 if (ut->ut_line[0] == '\0')
804 SL_RET0(_("sh_utmp_addlogin"));
805
806 /* for some stupid reason, AIX repeats the wtmp entry for logouts
807 * with ssh
808 */
809 if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0)
810 {
811 memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S));
812 SL_RET0(_("sh_utmp_addlogin"));
813 }
814 memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S));
815
816
817 /* ------- find user --------
818 */
819 while (user != NULL)
820 {
[154]821 if (0 == sl_strncmp((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE) )
[1]822 break;
823 userold = user;
824 user = user->next;
825 }
826
827#ifdef HAVE_UTTYPE
828 while (username != NULL)
829 {
830 if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) )
831 break;
832 username = username->next;
833 }
834#endif
835
836#ifdef HAVE_UTTYPE
837 /* ---------- LOGIN -------------- */
838 if (ut->ut_type == USER_PROCESS)
839 {
840 if (user == NULL)
841 {
842 user = SH_ALLOC(sizeof(struct log_user));
843 user->next = userlist;
[154]844 userlist = (struct log_user *) user;
[1]845 }
[154]846 (void) sl_strlcpy((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE+1);
847 (void) sl_strlcpy((char*)(user->name), ut->ut_name, UT_NAMESIZE+1);
[1]848#ifdef HAVE_UTHOST
[154]849 (void) sl_strlcpy((char*)(user->ut_host), ut->ut_host, UT_HOSTSIZE+1);
[1]850#else
851 user->ut_host[0] = '\0';
852#endif
853#ifdef HAVE_UTADDR
854 /*@-type@*//* ut_addr does exist !!! */
[154]855 (void) sl_strlcpy((char*)(user->ut_ship),
[1]856 my_inet_ntoa(*(struct in_addr*)&(ut->ut_addr)), 16);
857 /*@+type@*/
858#endif
859 user->time = ut->ut_time;
860
861 if (username == NULL /* not yet logged in */
862 || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console */
863 || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console */
864 ) {
[154]865 status = sh_utmp_login_a((char*)user->name);
[143]866 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]867 (void) sh_unix_time (user->time, ttt, TIM_MAX);
[1]868 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
869#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
870 MSG_UT_LG1X,
871#elif defined(HAVE_UTHOST)
872 MSG_UT_LG1A,
873#else
874 MSG_UT_LG1B,
875#endif
876 user->name,
877 user->ut_tty,
878#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
879 user->ut_host,
880 user->ut_ship,
881#elif defined(HAVE_UTHOST)
882 user->ut_host,
883#endif
884 ttt,
885 status
886 );
[143]887 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]888 } else
[154]889 if (0 != sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host))
[1]890 {
[154]891 status = sh_utmp_login_a((char*)user->name);
[143]892 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]893 (void) sh_unix_time (user->time, ttt, TIM_MAX);
[1]894 sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0,
895#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
896 MSG_UT_LG2X,
897#elif defined(HAVE_UTHOST)
898 MSG_UT_LG2A,
899#else
900 MSG_UT_LG2B,
901#endif
902 user->name,
903 user->ut_tty,
904#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
905 user->ut_host,
906 user->ut_ship,
907#elif defined(HAVE_UTHOST)
908 user->ut_host,
909#endif
910 ttt,
911 status
912 );
[143]913 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]914 }
915
916 sh_utmp_login_morechecks(ut);
917 SL_RET0(_("sh_utmp_addlogin"));
918 }
919
920
921 /* --------- LOGOUT ---------------- */
922 else if (ut->ut_name[0] == '\0'
923 || ut->ut_type == DEAD_PROCESS /* solaris does not clear ut_name */
924 )
925 {
926 if (user != NULL)
927 {
[154]928 status = sh_utmp_login_r((char*)user->name);
[143]929 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]930 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
[1]931 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
932#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
933 MSG_UT_LG3X,
934#elif defined(HAVE_UTHOST)
935 MSG_UT_LG3A,
936#else
937 MSG_UT_LG3B,
938#endif
939 user->name,
940 user->ut_tty,
941#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
942 user->ut_host,
943 user->ut_ship,
944#elif defined(HAVE_UTHOST)
945 user->ut_host,
946#endif
947 ttt,
948 status
949 );
[143]950 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]951 userold->next = user->next;
952 if (user == userlist)
953 userlist = user->next;
[154]954 sh_utmp_logout_morechecks((struct log_user *)user);
955 SH_FREE((struct log_user *)user);
[1]956 user = NULL;
957 }
958 else
959 {
960 (void) sl_strlcpy(terminated_line, ut->ut_line, UT_HOSTSIZE);
[143]961 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]962 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
[1]963 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
964 MSG_UT_LG3C,
965 terminated_line,
966 ttt, 0
967 );
[143]968 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]969 }
970 SL_RET0(_("sh_utmp_addlogin"));
971 }
972
973 /* default */
974 SL_RET0(_("sh_utmp_addlogin"));
975
976 /* #ifdef HAVE_UTTYPE */
977#else
978
979 if (user == NULL) /* probably a login */
980 {
981 user = SH_ALLOC(sizeof(struct log_user));
982 sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
983 sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
984#ifdef HAVE_UTHOST
985 sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
986#endif
987#ifdef HAVE_UTADDR
988 sl_strlcpy(user->ut_ship,my_inet_ntoa((struct in_addr)ut->ut_addr),16);
989#endif
990 user->time = ut->ut_time;
991 user->next = userlist;
992 userlist = user;
993
[143]994 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]995 (void) sh_unix_time (user->time, ttt, TIM_MAX);
[1]996 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
997#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
998 MSG_UT_LG1X,
999#elif defined(HAVE_UTHOST)
1000 MSG_UT_LG1A,
1001#else
1002 MSG_UT_LG1B,
1003#endif
1004 user->name,
1005 user->ut_tty,
1006#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1007 user->ut_host,
1008 user->ut_ship,
1009#elif defined(HAVE_UTHOST)
1010 user->ut_host,
1011#endif
1012 ttt,
1013 1
1014 );
[143]1015 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]1016 sh_utmp_login_morechecks(ut);
1017 }
1018 else /* probably a logout */
1019 {
[143]1020 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]1021 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
[1]1022 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
1023#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1024 MSG_UT_LG2X,
1025#elif defined(HAVE_UTHOST)
1026 MSG_UT_LG2A,
1027#else
1028 MSG_UT_LG2B,
1029#endif
1030 user->name,
1031 user->ut_tty,
1032#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1033 user->ut_host,
1034 user->ut_ship,
1035#elif defined(HAVE_UTHOST)
1036 user->ut_host,
1037#endif
1038 ttt,
1039 1
1040 );
[143]1041 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]1042 sh_utmp_logout_morechecks(user);
1043 userold->next = user->next;
1044 if (user == userlist) /* inserted Apr 4, 2004 */
1045 userlist = user->next;
1046 SH_FREE(user);
1047 user = NULL;
1048 }
1049
1050 SL_RET0(_("sh_utmp_addlogin"));
1051#endif
1052}
1053
1054static time_t lastmod = 0;
1055static off_t lastsize = 0;
1056static unsigned long lastread = 0;
1057
1058static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
1059
1060static void sh_utmp_check_internal (int mode)
1061{
1062 struct stat buf;
1063 int error;
1064 struct SH_UTMP_S * ut;
1065 unsigned long this_read = 0;
[143]1066 int val_retry;
[1]1067
1068 SL_ENTER(_("sh_utmp_check_internal"));
1069
1070 /* error if no access
1071 */
[143]1072 do {
1073 val_retry = /*@-unrecog@*/lstat ( mode_path[mode], &buf)/*@+unrecog@*/;
1074 } while (val_retry < 0 && errno == EINTR);
1075
1076 if (0 != val_retry)
[1]1077 {
1078 error = errno;
[143]1079 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]1080 sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
1081 (long) sh.real.uid, mode_path[mode]);
[143]1082 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]1083 SL_RET0(_("sh_utmp_check_internal"));
1084 }
1085
1086 /* modification time
1087 */
1088 if (mode < 2)
1089 {
1090 if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/)
1091 {
1092 SL_RET0(_("sh_utmp_check_internal"));
1093 }
1094 else
1095 lastmod = buf.st_mtime;
1096 }
1097
1098 /* file size
1099 */
1100 if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2)
1101 {
[143]1102 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]1103 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT,
1104 mode_path[mode]);
[143]1105 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]1106 lastread = 0;
1107#ifndef USE_SETUTENT
1108 sh_utmp_feed_forward = 0L;
1109#endif
1110 }
1111
1112 if (mode < 2)
1113 lastsize = buf.st_size;
1114
1115 if (buf.st_size == 0)
1116 SL_RET0(_("sh_utmp_check_internal"));
1117
1118 sh_utmp_utmpname(mode_path[mode]);
1119 sh_utmp_setutent();
1120
1121 /*
1122 * feed forward if initializing
1123 * we need to do this here
1124 */
1125 if (mode < 2)
1126 {
1127 while (this_read < lastread) {
1128 ut = sh_utmp_getutent();
1129 ++this_read;
1130 }
1131 }
1132
1133 /* start reading
1134 */
1135 this_read = 0;
1136 while (1 == 1) {
1137 ut = sh_utmp_getutent();
1138 if (ut == NULL)
1139 break;
1140 /* modified: ut_user --> ut_name */
1141 if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0'
1142#ifdef HAVE_UTTYPE
1143 && ut->ut_type != DEAD_PROCESS
1144#endif
1145 ))
1146 sh_utmp_addlogin (ut);
1147 ++this_read;
1148 }
1149
1150 sh_utmp_endutent();
1151
1152 if (mode < 2)
1153 {
1154 lastread += this_read;
1155#ifndef USE_SETUTENT
1156 sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S));
1157 lastread = 0;
1158#endif
1159 }
1160
1161 SL_RET0(_("sh_utmp_check_internal"));
1162}
1163
1164
1165static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut)
1166{
1167 if (ut)
1168 return;
1169 return;
1170}
1171
1172static void sh_utmp_logout_morechecks(struct log_user * user)
1173{
1174 if (user)
1175 return;
1176 return;
1177}
1178
1179#endif
1180
1181
1182/* #ifdef SH_USE_UTMP */
1183#endif
1184
1185
1186
Note: See TracBrowser for help on using the repository browser.