source: trunk/src/sh_utmp.c@ 291

Last change on this file since 291 was 290, checked in by katerina, 14 years ago

Fixes for tickets #215, #216, #217, #218, version bumped to 2.7.2

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