source: trunk/src/sh_utmp.c@ 151

Last change on this file since 151 was 149, checked in by katerina, 17 years ago

Make sh_hash.c thread-safe, remove plenty of tiny allocations, improve sh_mem_dump, modify port check to run as thread, and fix unsetting of sh_thread_pause_flag (was too early).

File size: 25.7 KB
Line 
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"
81#include "sh_pthread.h"
82
83SH_MUTEX_EXTERN(mutex_thread_nolog);
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
229static void set_defaults(void)
230{
231 ShUtmpLoginSolo = SH_ERR_INFO;
232 ShUtmpLoginMulti = SH_ERR_WARN;
233 ShUtmpLogout = SH_ERR_INFO;
234 ShUtmpActive = S_TRUE;
235 ShUtmpInterval = 300;
236 return;
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 {
307 SH_MUTEX_LOCK(mutex_thread_nolog);
308 fd = (int) aud_open (FIL__, __LINE__, SL_NOPRIV,
309 sh_utmppath, O_RDONLY, 0);
310 SH_MUTEX_UNLOCK(mutex_thread_nolog);
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;
322 SH_MUTEX_LOCK(mutex_thread_nolog);
323 sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
324 (long) sh.real.uid, sh_utmppath);
325 SH_MUTEX_UNLOCK(mutex_thread_nolog);
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"));
342 if (NULL != sh_utmpfile)
343 (void) fclose(sh_utmpfile);
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);
451 sprintf(foo, _("%d.%d.%d.%d"), /* known to fit */
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;
466static int init_done = 0;
467
468/*************
469 *
470 * module init
471 *
472 *************/
473
474static int sh_utmp_init_internal ()
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 */
483 if (init_done == 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);
491 init_done = 1;
492 SL_RETURN( (0), _("sh_utmp_init"));
493}
494
495int sh_utmp_init (struct mod_type * arg)
496{
497 if (ShUtmpActive == BAD)
498 return SH_MOD_FAILED;
499#ifdef HAVE_PTHREAD
500 if (arg != NULL && arg->initval < 0 &&
501 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
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
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
537 /* Reset the flag, such that the module
538 * can be re-enabled.
539 */
540 set_defaults();
541 init_done = 0;
542 SL_RETURN( (0), _("sh_utmp_end"));
543}
544
545int sh_utmp_reconf()
546{
547 set_defaults();
548 return 0;
549}
550
551
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"));
575 if (ShUtmpActive == BAD)
576 SL_RETURN( (-1), _("sh_utmp_check"));
577 SH_MUTEX_LOCK(mutex_thread_nolog);
578 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK);
579 SH_MUTEX_UNLOCK(mutex_thread_nolog);
580 sh_utmp_check_internal (1);
581
582 SL_RETURN(0, _("sh_utmp_check"));
583}
584
585/*************
586 *
587 * module setup
588 *
589 *************/
590
591int sh_utmp_set_login_solo (const char * c)
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);
599 SH_MUTEX_LOCK(mutex_thread_nolog);
600 retval = sh_error_set_level (tmp, &ShUtmpLoginSolo);
601 SH_MUTEX_UNLOCK(mutex_thread_nolog);
602 SL_RETURN(retval, _("sh_utmp_set_login_solo"));
603}
604
605int sh_utmp_set_login_multi (const char * c)
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);
613 SH_MUTEX_LOCK(mutex_thread_nolog);
614 retval = sh_error_set_level (tmp, &ShUtmpLoginMulti);
615 SH_MUTEX_UNLOCK(mutex_thread_nolog);
616 SL_RETURN(retval, _("sh_utmp_set_login_multi"));
617}
618
619int sh_utmp_set_logout_good (const char * c)
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);
627 SH_MUTEX_LOCK(mutex_thread_nolog);
628 retval = sh_error_set_level (tmp, &ShUtmpLogout);
629 SH_MUTEX_UNLOCK(mutex_thread_nolog);
630 SL_RETURN(retval, _("sh_utmp_set_logout_good"));
631}
632
633int sh_utmp_set_login_timer (const char * c)
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 {
642 SH_MUTEX_LOCK(mutex_thread_nolog);
643 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
644 _("utmp timer"), c);
645 SH_MUTEX_UNLOCK(mutex_thread_nolog);
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
655int sh_utmp_set_login_activate (const char * c)
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
773static void sh_utmp_addlogin (struct SH_UTMP_S * ut)
774{
775 struct log_user * user = userlist;
776 struct log_user * userold = userlist;
777#ifdef HAVE_UTTYPE
778 struct log_user * username = userlist;
779#endif
780
781 char ttt[TIM_MAX];
782#ifdef HAVE_UTTYPE
783 int status;
784#endif
785
786 SL_ENTER(_("sh_utmp_addlogin"));
787
788 if (ut->ut_line[0] == '\0')
789 SL_RET0(_("sh_utmp_addlogin"));
790
791 /* for some stupid reason, AIX repeats the wtmp entry for logouts
792 * with ssh
793 */
794 if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0)
795 {
796 memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S));
797 SL_RET0(_("sh_utmp_addlogin"));
798 }
799 memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S));
800
801
802 /* ------- find user --------
803 */
804 while (user != NULL)
805 {
806 if (0 == sl_strncmp(user->ut_tty, ut->ut_line, UT_LINESIZE) )
807 break;
808 userold = user;
809 user = user->next;
810 }
811
812#ifdef HAVE_UTTYPE
813 while (username != NULL)
814 {
815 if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) )
816 break;
817 username = username->next;
818 }
819#endif
820
821#ifdef HAVE_UTTYPE
822 /* ---------- LOGIN -------------- */
823 if (ut->ut_type == USER_PROCESS)
824 {
825 if (user == NULL)
826 {
827 user = SH_ALLOC(sizeof(struct log_user));
828 user->next = userlist;
829 userlist = user;
830 }
831 (void) sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
832 (void) sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
833#ifdef HAVE_UTHOST
834 (void) sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
835#else
836 user->ut_host[0] = '\0';
837#endif
838#ifdef HAVE_UTADDR
839 /*@-type@*//* ut_addr does exist !!! */
840 (void) sl_strlcpy(user->ut_ship,
841 my_inet_ntoa(*(struct in_addr*)&(ut->ut_addr)), 16);
842 /*@+type@*/
843#endif
844 user->time = ut->ut_time;
845
846 if (username == NULL /* not yet logged in */
847 || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console */
848 || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console */
849 ) {
850 status = sh_utmp_login_a(user->name);
851 SH_MUTEX_LOCK(mutex_thread_nolog);
852 (void) sh_unix_time (user->time, ttt, TIM_MAX);
853 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
854#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
855 MSG_UT_LG1X,
856#elif defined(HAVE_UTHOST)
857 MSG_UT_LG1A,
858#else
859 MSG_UT_LG1B,
860#endif
861 user->name,
862 user->ut_tty,
863#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
864 user->ut_host,
865 user->ut_ship,
866#elif defined(HAVE_UTHOST)
867 user->ut_host,
868#endif
869 ttt,
870 status
871 );
872 SH_MUTEX_UNLOCK(mutex_thread_nolog);
873 } else
874 if (0 != sh_utmp_is_virtual(ut->ut_line, user->ut_host))
875 {
876 status = sh_utmp_login_a(user->name);
877 SH_MUTEX_LOCK(mutex_thread_nolog);
878 (void) sh_unix_time (user->time, ttt, TIM_MAX);
879 sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0,
880#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
881 MSG_UT_LG2X,
882#elif defined(HAVE_UTHOST)
883 MSG_UT_LG2A,
884#else
885 MSG_UT_LG2B,
886#endif
887 user->name,
888 user->ut_tty,
889#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
890 user->ut_host,
891 user->ut_ship,
892#elif defined(HAVE_UTHOST)
893 user->ut_host,
894#endif
895 ttt,
896 status
897 );
898 SH_MUTEX_UNLOCK(mutex_thread_nolog);
899 }
900
901 sh_utmp_login_morechecks(ut);
902 SL_RET0(_("sh_utmp_addlogin"));
903 }
904
905
906 /* --------- LOGOUT ---------------- */
907 else if (ut->ut_name[0] == '\0'
908 || ut->ut_type == DEAD_PROCESS /* solaris does not clear ut_name */
909 )
910 {
911 if (user != NULL)
912 {
913 status = sh_utmp_login_r(user->name);
914 SH_MUTEX_LOCK(mutex_thread_nolog);
915 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
916 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
917#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
918 MSG_UT_LG3X,
919#elif defined(HAVE_UTHOST)
920 MSG_UT_LG3A,
921#else
922 MSG_UT_LG3B,
923#endif
924 user->name,
925 user->ut_tty,
926#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
927 user->ut_host,
928 user->ut_ship,
929#elif defined(HAVE_UTHOST)
930 user->ut_host,
931#endif
932 ttt,
933 status
934 );
935 SH_MUTEX_UNLOCK(mutex_thread_nolog);
936 userold->next = user->next;
937 if (user == userlist)
938 userlist = user->next;
939 sh_utmp_logout_morechecks(user);
940 SH_FREE(user);
941 user = NULL;
942 }
943 else
944 {
945 (void) sl_strlcpy(terminated_line, ut->ut_line, UT_HOSTSIZE);
946 SH_MUTEX_LOCK(mutex_thread_nolog);
947 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
948 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
949 MSG_UT_LG3C,
950 terminated_line,
951 ttt, 0
952 );
953 SH_MUTEX_UNLOCK(mutex_thread_nolog);
954 }
955 SL_RET0(_("sh_utmp_addlogin"));
956 }
957
958 /* default */
959 SL_RET0(_("sh_utmp_addlogin"));
960
961 /* #ifdef HAVE_UTTYPE */
962#else
963
964 if (user == NULL) /* probably a login */
965 {
966 user = SH_ALLOC(sizeof(struct log_user));
967 sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
968 sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
969#ifdef HAVE_UTHOST
970 sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
971#endif
972#ifdef HAVE_UTADDR
973 sl_strlcpy(user->ut_ship,my_inet_ntoa((struct in_addr)ut->ut_addr),16);
974#endif
975 user->time = ut->ut_time;
976 user->next = userlist;
977 userlist = user;
978
979 SH_MUTEX_LOCK(mutex_thread_nolog);
980 (void) sh_unix_time (user->time, ttt, TIM_MAX);
981 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
982#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
983 MSG_UT_LG1X,
984#elif defined(HAVE_UTHOST)
985 MSG_UT_LG1A,
986#else
987 MSG_UT_LG1B,
988#endif
989 user->name,
990 user->ut_tty,
991#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
992 user->ut_host,
993 user->ut_ship,
994#elif defined(HAVE_UTHOST)
995 user->ut_host,
996#endif
997 ttt,
998 1
999 );
1000 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1001 sh_utmp_login_morechecks(ut);
1002 }
1003 else /* probably a logout */
1004 {
1005 SH_MUTEX_LOCK(mutex_thread_nolog);
1006 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
1007 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
1008#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1009 MSG_UT_LG2X,
1010#elif defined(HAVE_UTHOST)
1011 MSG_UT_LG2A,
1012#else
1013 MSG_UT_LG2B,
1014#endif
1015 user->name,
1016 user->ut_tty,
1017#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1018 user->ut_host,
1019 user->ut_ship,
1020#elif defined(HAVE_UTHOST)
1021 user->ut_host,
1022#endif
1023 ttt,
1024 1
1025 );
1026 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1027 sh_utmp_logout_morechecks(user);
1028 userold->next = user->next;
1029 if (user == userlist) /* inserted Apr 4, 2004 */
1030 userlist = user->next;
1031 SH_FREE(user);
1032 user = NULL;
1033 }
1034
1035 SL_RET0(_("sh_utmp_addlogin"));
1036#endif
1037}
1038
1039static time_t lastmod = 0;
1040static off_t lastsize = 0;
1041static unsigned long lastread = 0;
1042
1043static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
1044
1045static void sh_utmp_check_internal (int mode)
1046{
1047 struct stat buf;
1048 int error;
1049 struct SH_UTMP_S * ut;
1050 unsigned long this_read = 0;
1051 int val_retry;
1052
1053 SL_ENTER(_("sh_utmp_check_internal"));
1054
1055 /* error if no access
1056 */
1057 do {
1058 val_retry = /*@-unrecog@*/lstat ( mode_path[mode], &buf)/*@+unrecog@*/;
1059 } while (val_retry < 0 && errno == EINTR);
1060
1061 if (0 != val_retry)
1062 {
1063 error = errno;
1064 SH_MUTEX_LOCK(mutex_thread_nolog);
1065 sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
1066 (long) sh.real.uid, mode_path[mode]);
1067 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1068 SL_RET0(_("sh_utmp_check_internal"));
1069 }
1070
1071 /* modification time
1072 */
1073 if (mode < 2)
1074 {
1075 if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/)
1076 {
1077 SL_RET0(_("sh_utmp_check_internal"));
1078 }
1079 else
1080 lastmod = buf.st_mtime;
1081 }
1082
1083 /* file size
1084 */
1085 if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2)
1086 {
1087 SH_MUTEX_LOCK(mutex_thread_nolog);
1088 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT,
1089 mode_path[mode]);
1090 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1091 lastread = 0;
1092#ifndef USE_SETUTENT
1093 sh_utmp_feed_forward = 0L;
1094#endif
1095 }
1096
1097 if (mode < 2)
1098 lastsize = buf.st_size;
1099
1100 if (buf.st_size == 0)
1101 SL_RET0(_("sh_utmp_check_internal"));
1102
1103 sh_utmp_utmpname(mode_path[mode]);
1104 sh_utmp_setutent();
1105
1106 /*
1107 * feed forward if initializing
1108 * we need to do this here
1109 */
1110 if (mode < 2)
1111 {
1112 while (this_read < lastread) {
1113 ut = sh_utmp_getutent();
1114 ++this_read;
1115 }
1116 }
1117
1118 /* start reading
1119 */
1120 this_read = 0;
1121 while (1 == 1) {
1122 ut = sh_utmp_getutent();
1123 if (ut == NULL)
1124 break;
1125 /* modified: ut_user --> ut_name */
1126 if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0'
1127#ifdef HAVE_UTTYPE
1128 && ut->ut_type != DEAD_PROCESS
1129#endif
1130 ))
1131 sh_utmp_addlogin (ut);
1132 ++this_read;
1133 }
1134
1135 sh_utmp_endutent();
1136
1137 if (mode < 2)
1138 {
1139 lastread += this_read;
1140#ifndef USE_SETUTENT
1141 sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S));
1142 lastread = 0;
1143#endif
1144 }
1145
1146 SL_RET0(_("sh_utmp_check_internal"));
1147}
1148
1149
1150static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut)
1151{
1152 if (ut)
1153 return;
1154 return;
1155}
1156
1157static void sh_utmp_logout_morechecks(struct log_user * user)
1158{
1159 if (user)
1160 return;
1161 return;
1162}
1163
1164#endif
1165
1166
1167/* #ifdef SH_USE_UTMP */
1168#endif
1169
1170
1171
Note: See TracBrowser for help on using the repository browser.