source: trunk/src/sh_utmp.c@ 148

Last change on this file since 148 was 144, checked in by rainer, 17 years ago

Fix some more queer compile problems.

File size: 25.5 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
229int sh_utmp_null()
230{
231 return 0;
232}
233
234
235
236
237#if defined (HAVE_SETUTENT) && defined (USE_SETUTENT)
238
239#ifdef HAVE_UTMPX_H
240
241#define sh_utmp_utmpname utmpxname
242#define sh_utmp_setutent setutxent
243#define sh_utmp_endutent endutxent
244#define sh_utmp_getutent getutxent
245#define sh_utmp_getutid getutxid
246#define sh_utmp_getutline getutxline
247
248#else
249
250#define sh_utmp_utmpname utmpname
251#define sh_utmp_setutent setutent
252#define sh_utmp_endutent endutent
253#define sh_utmp_getutent getutent
254#define sh_utmp_getutid getutid
255#define sh_utmp_getutline getutline
256
257#endif
258
259#else
260
261/* BSD lacks getutent() etc.
262 * utmpname(), setutent(), and endutent() return void,
263 * so we do not perform much error handling.
264 * Errors must be recognized by getutent() returning NULL.
265 * Apparently, the application cannot check whether wtmp is empty,
266 * or whether there was an fopen() error.
267 */
268
269static FILE * sh_utmpfile = NULL;
270static char sh_utmppath[80] = _PATH_UTMP;
271
272/* sh_utmp_feed_forward is for optimizing
273 * (fseek instead of getutent loop)
274 */
275static long sh_utmp_feed_forward = 0;
276
277static void sh_utmp_utmpname(const char * str)
278{
279 SL_ENTER(_("sh_utmp_utmpname"));
280 if (sh_utmpfile != NULL)
281 {
282 (void) fclose (sh_utmpfile);
283 sh_utmpfile = NULL;
284 }
285
286 (void) sl_strlcpy (sh_utmppath, str, 80);
287 SL_RET0(_("sh_utmp_utmpname"));
288}
289
290static void sh_utmp_setutent(void)
291{
292 int error;
293 int fd;
294
295 SL_ENTER(_("sh_utmp_setutent"));
296
297 ASSERT((sh_utmppath != NULL), _("sh_utmppath != NULL"));
298
299 if (sh_utmppath == NULL)
300 SL_RET0(_("sh_utmp_setutent"));
301
302 if (sh_utmpfile == NULL)
303 {
[143]304 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]305 fd = (int) aud_open (FIL__, __LINE__, SL_NOPRIV,
306 sh_utmppath, O_RDONLY, 0);
[143]307 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]308 if (fd >= 0)
309 {
310 sh_utmpfile = fdopen(fd, "r");
311 }
312
313 /* -- If (sh_utmpfile == NULL) then either the open() or the fdopen()
314 * has failed.
315 */
316 if (sh_utmpfile == NULL)
317 {
318 error = errno;
[143]319 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]320 sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
321 (long) sh.real.uid, sh_utmppath);
[143]322 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]323 SL_RET0(_("sh_utmp_setutent"));
324 }
325 }
326 (void) fseek (sh_utmpfile, 0L, SEEK_SET);
327 if (-1 == fseek (sh_utmpfile, sh_utmp_feed_forward, SEEK_CUR))
328 {
329 sh_utmp_feed_forward = 0; /* modified Apr 4, 2004 */
330 (void) fseek (sh_utmpfile, 0L, SEEK_SET);
331 }
332 clearerr (sh_utmpfile);
333 SL_RET0(_("sh_utmp_setutent"));
334}
335
336static void sh_utmp_endutent(void)
337{
338 SL_ENTER(_("sh_utmp_endutent"));
[30]339 if (NULL != sh_utmpfile)
340 (void) fclose(sh_utmpfile);
[1]341 sh_utmpfile = NULL;
342 SL_RET0(_("sh_utmp_endutent"));
343}
344
345static struct SH_UTMP_S * sh_utmp_getutent(void)
346{
347 size_t in;
348 static struct SH_UTMP_S out;
349
350 SL_ENTER(_("sh_utmp_getutent"));
351
352 ASSERT_RET((sh_utmpfile != NULL), _("sh_utmpfile != NULL"), (NULL))
353
354 in = fread (&out, sizeof(struct SH_UTMP_S), 1, sh_utmpfile);
355
356 if (in != 1)
357 {
358 if (ferror (sh_utmpfile) != 0)
359 {
360 clearerr (sh_utmpfile);
361 SL_RETURN(NULL, _("sh_utmp_getutent"));
362 }
363 else
364 {
365 SL_RETURN(NULL, _("sh_utmp_getutent"));
366 }
367 }
368 SL_RETURN(&out, _("sh_utmp_getutent"));
369}
370
371#ifdef USE_UNUSED
372
373static struct SH_UTMP_S * sh_utmp_getutline(struct SH_UTMP_S * ut)
374{
375 struct SH_UTMP_S * out;
376
377 while (1) {
378 if ((out = sh_utmp_getutent()) == NULL) {
379 return NULL;
380 }
381#ifdef HAVE_UTTYPE
382 if (out->ut_type == USER_PROCESS || out->ut_type == LOGIN_PROCESS)
383 if (sl_strcmp(ut->ut_line, out->ut_line) == 0)
384 return out;
385#else
386 if ( 0 != sl_strncmp (out->ut_name, "reboot", 6) &&
387 0 != sl_strncmp (out->ut_name, "shutdown", 8) &&
388 0 != sl_strncmp (out->ut_name, "date", 4) )
389 return out;
390#endif
391 }
392 return NULL;
393}
394
395static struct SH_UTMP_S * sh_utmp_getutid(struct SH_UTMP_S * ut)
396{
397#ifdef HAVE_UTTYPE
398 struct SH_UTMP_S * out;
399
400 if (ut->ut_type == RUN_LVL || ut->ut_type == BOOT_TIME ||
401 ut->ut_type == NEW_TIME || ut->ut_type == OLD_TIME)
402 {
403 while (1) {
404 if ((out = sh_utmp_getutent()) == NULL) {
405 return NULL;
406 }
407 if (out->ut_type == ut->ut_type)
408 return out;
409 }
410 }
411 else if (ut->ut_type == INIT_PROCESS || ut->ut_type == LOGIN_PROCESS ||
412 ut->ut_type == USER_PROCESS || ut->ut_type == DEAD_PROCESS )
413 {
414 while (1) {
415 if ((out = sh_utmp_getutent()) == NULL) {
416 return NULL;
417 }
418 if (sl_strcmp(ut->ut_id, out->ut_id) == 0)
419 return out;
420 }
421 }
422#endif
423 return NULL;
424}
425/* #ifdef USE_UNUSED */
426#endif
427
428/* #ifdef HAVE_SETUTENT */
429#endif
430
431#ifdef HAVE_UTADDR
432#ifdef HAVE_INET_ATON
433static char * my_inet_ntoa(struct in_addr in)
434{
435 return /*@-unrecog@*/inet_ntoa(in)/*@+unrecog@*/;
436}
437#else
438static char * my_inet_ntoa(struct in_addr in)
439{
440 unsigned char a, b, c, d;
441 static char foo[16];
442 char bar[4];
443 memcpy (bar, &(in.s_addr), 4); /* memory alignment (?) */
444 memcpy (&a, &bar[0], 1);
445 memcpy (&b, &bar[1], 1);
446 memcpy (&c, &bar[2], 1);
447 memcpy (&d, &bar[3], 1);
[34]448 sprintf(foo, _("%d.%d.%d.%d"), /* known to fit */
[1]449 (int) a, (int) b, (int) c, (int) d);
450 return foo;
451}
452#endif
453/* #ifdef HAVE_UTADDR */
454#endif
455
456#if defined(__linux__) && !defined(ut_addr)
457#define ut_addr ut_addr_v6[0]
458#endif
459
460
461static struct log_user * userlist = NULL;
462static time_t lastcheck;
[142]463static int init_done = 0;
[1]464
465/*************
466 *
467 * module init
468 *
469 *************/
[142]470
471static int sh_utmp_init_internal ()
[1]472{
473
474 SL_ENTER(_("sh_utmp_init"));
475 if (ShUtmpActive == BAD)
476 SL_RETURN( (-1), _("sh_utmp_init"));
477
478 /* do not re-initialize after a re-configuration
479 */
[142]480 if (init_done == 1) {
[1]481 SL_RETURN( (0), _("sh_utmp_init"));
482 }
483 lastcheck = time (NULL);
484 userlist = NULL;
485 memset (&save_utmp, 0, sizeof(struct SH_UTMP_S));
486 sh_utmp_check_internal (2); /* current logins */
487 sh_utmp_check_internal (0);
[142]488 init_done = 1;
[1]489 SL_RETURN( (0), _("sh_utmp_init"));
490}
491
[142]492int sh_utmp_init (struct mod_type * arg)
493{
494 if (ShUtmpActive == BAD)
495 return SH_MOD_FAILED;
496#ifdef HAVE_PTHREAD
[144]497 if (arg != NULL && arg->initval < 0 &&
498 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
[142]499 {
500 if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
501 return SH_MOD_THREAD;
502 else
503 return SH_MOD_FAILED;
504 }
505#endif
506 return sh_utmp_init_internal();
507}
508
[1]509/*************
510 *
511 * module cleanup
512 *
513 *************/
514#ifdef HAVE_UTTYPE
515static int sh_utmp_login_clean();
516#endif
517
518int sh_utmp_end ()
519{
520 struct log_user * user = userlist;
521 struct log_user * userold;
522
523 SL_ENTER(_("sh_utmp_end"));
524 while (user)
525 {
526 userold = user;
527 user = user->next;
528 SH_FREE(userold);
529 }
530 userlist = NULL;
531#ifdef HAVE_UTTYPE
532 (void) sh_utmp_login_clean();
533#endif
[142]534 /* Reset the flag, such that the module
535 * can be re-enabled.
536 */
537 ShUtmpActive = S_TRUE;
538 init_done = 0;
[1]539 SL_RETURN( (0), _("sh_utmp_end"));
540}
541
542
543/*************
544 *
545 * module timer
546 *
547 *************/
548int sh_utmp_timer (time_t tcurrent)
549{
550 if ((time_t) (tcurrent - lastcheck) >= ShUtmpInterval)
551 {
552 lastcheck = tcurrent;
553 return (-1);
554 }
555 return 0;
556}
557
558/*************
559 *
560 * module check
561 *
562 *************/
563int sh_utmp_check ()
564{
565 SL_ENTER(_("sh_utmp_check"));
[142]566 if (ShUtmpActive == BAD)
567 SL_RETURN( (-1), _("sh_utmp_check"));
[143]568 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]569 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK);
[143]570 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]571 sh_utmp_check_internal (1);
572
573 SL_RETURN(0, _("sh_utmp_check"));
574}
575
576/*************
577 *
578 * module setup
579 *
580 *************/
581
[68]582int sh_utmp_set_login_solo (const char * c)
[1]583{
584 int retval;
585 char tmp[32];
586
587 SL_ENTER(_("sh_utmp_set_login_solo"));
588 tmp[0] = '='; tmp[1] = '\0';
589 (void) sl_strlcat (tmp, c, 32);
[143]590 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]591 retval = sh_error_set_level (tmp, &ShUtmpLoginSolo);
[143]592 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]593 SL_RETURN(retval, _("sh_utmp_set_login_solo"));
594}
595
[68]596int sh_utmp_set_login_multi (const char * c)
[1]597{
598 int retval;
599 char tmp[32];
600
601 SL_ENTER(_("sh_utmp_set_login_multi"));
602 tmp[0] = '='; tmp[1] = '\0';
603 (void) sl_strlcat (tmp, c, 32);
[143]604 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]605 retval = sh_error_set_level (tmp, &ShUtmpLoginMulti);
[143]606 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]607 SL_RETURN(retval, _("sh_utmp_set_login_multi"));
608}
609
[68]610int sh_utmp_set_logout_good (const char * c)
[1]611{
612 int retval;
613 char tmp[32];
614
615 SL_ENTER(_("sh_utmp_set_logout_good"));
616 tmp[0] = '='; tmp[1] = '\0';
617 (void) sl_strlcat (tmp, c, 32);
[143]618 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]619 retval = sh_error_set_level (tmp, &ShUtmpLogout);
[143]620 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]621 SL_RETURN(retval, _("sh_utmp_set_logout_good"));
622}
623
[68]624int sh_utmp_set_login_timer (const char * c)
[1]625{
626 int retval = 0;
627 long val;
628
629 SL_ENTER(_("sh_utmp_set_login_timer"));
630 val = strtol (c, (char **)NULL, 10);
631 if (val <= 0)
632 {
[143]633 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]634 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
635 _("utmp timer"), c);
[143]636 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]637 retval = -1;
638 }
639
640 val = (val <= 0 ? 60 : val);
641
642 ShUtmpInterval = (time_t) val;
643 SL_RETURN(0, _("sh_utmp_set_login_timer"));
644}
645
[68]646int sh_utmp_set_login_activate (const char * c)
[1]647{
648 int i;
649 SL_ENTER(_("sh_utmp_set_login_activate"));
650 i = sh_util_flagval(c, &ShUtmpActive);
651 SL_RETURN(i, _("sh_utmp_set_login_activate"));
652}
653
654#ifdef HAVE_UTTYPE
655struct login_ct {
656 char name[UT_NAMESIZE+1];
657 int nlogin;
658 struct login_ct * next;
659};
660
661static struct login_ct * login_ct_list = NULL;
662
663static int sh_utmp_login_clean()
664{
665 struct login_ct * list = login_ct_list;
666 struct login_ct * old;
667
668 login_ct_list = NULL;
669
670 while (list)
671 {
672 old = list;
673 list = list->next;
674 SH_FREE(old);
675 }
676 return 0;
677}
678
679/* add a username to the list of logged-in users
680 */
681static int sh_utmp_login_a(char * str)
682{
683 struct login_ct * list = login_ct_list;
684
685 while (list)
686 {
687 if (0 == sl_strcmp(list->name, str))
688 {
689 ++(list->nlogin);
690 return list->nlogin;
691 }
692 list = list->next;
693 }
694 list = SH_ALLOC(sizeof(struct login_ct));
695 (void) sl_strlcpy(list->name, str, UT_NAMESIZE+1);
696 list->nlogin = 1;
697 list->next = login_ct_list;
698 login_ct_list = list;
699 return 1;
700}
701
702static int sh_utmp_login_r(char * str)
703{
704 struct login_ct * list = login_ct_list;
705 struct login_ct * old = login_ct_list;
706
707 while (list)
708 {
709 if (0 == sl_strcmp(list->name, str))
710 {
711 list->nlogin -= 1;
712 if (list->nlogin > 0)
713 {
714 return list->nlogin;
715 }
716 if (login_ct_list == list) /* modified Apr 4, 2004 */
717 {
718 login_ct_list = list->next;
719 SH_FREE(list);
720 }
721 else
722 {
723 old->next = list->next;
724 SH_FREE(list);
725 }
726 return 0;
727 }
728 old = list;
729 list = list->next;
730 }
731 return 0;
732}
733
734#endif
735
736
737/* for each login:
738 * - allocate a log record
739 * - link device.ut_record -> log_record
740 * - link user.ut_record -> log_record
741 */
742#ifdef HAVE_UTTYPE
743static int sh_utmp_is_virtual (char * in_utline, char * in_uthost)
744{
745 if (in_utline != NULL)
746 {
747 if (0 == sl_strncmp(in_utline, _("ttyp"), 4))
748 { return 0; }
749 else if (0 == sl_strncmp(in_utline, _("ttyq"), 4))
750 { return 0; }
751 }
752 if (in_uthost != NULL &&
753 in_uthost[0] == ':' &&
754 in_uthost[1] == '0' &&
755 in_uthost[2] == '\0')
756 {
757 /* return 0; */
758 return 1; /* actually does not seem portable, not even among linuxes */
759 }
760 return 1;
761}
762#endif
763
764static void sh_utmp_addlogin (struct SH_UTMP_S * ut)
765{
766 struct log_user * user = userlist;
767 struct log_user * userold = userlist;
768#ifdef HAVE_UTTYPE
769 struct log_user * username = userlist;
770#endif
771
772 char ttt[TIM_MAX];
773#ifdef HAVE_UTTYPE
774 int status;
775#endif
776
777 SL_ENTER(_("sh_utmp_addlogin"));
778
779 if (ut->ut_line[0] == '\0')
780 SL_RET0(_("sh_utmp_addlogin"));
781
782 /* for some stupid reason, AIX repeats the wtmp entry for logouts
783 * with ssh
784 */
785 if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0)
786 {
787 memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S));
788 SL_RET0(_("sh_utmp_addlogin"));
789 }
790 memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S));
791
792
793 /* ------- find user --------
794 */
795 while (user != NULL)
796 {
797 if (0 == sl_strncmp(user->ut_tty, ut->ut_line, UT_LINESIZE) )
798 break;
799 userold = user;
800 user = user->next;
801 }
802
803#ifdef HAVE_UTTYPE
804 while (username != NULL)
805 {
806 if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) )
807 break;
808 username = username->next;
809 }
810#endif
811
812#ifdef HAVE_UTTYPE
813 /* ---------- LOGIN -------------- */
814 if (ut->ut_type == USER_PROCESS)
815 {
816 if (user == NULL)
817 {
818 user = SH_ALLOC(sizeof(struct log_user));
819 user->next = userlist;
820 userlist = user;
821 }
822 (void) sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
823 (void) sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
824#ifdef HAVE_UTHOST
825 (void) sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
826#else
827 user->ut_host[0] = '\0';
828#endif
829#ifdef HAVE_UTADDR
830 /*@-type@*//* ut_addr does exist !!! */
831 (void) sl_strlcpy(user->ut_ship,
832 my_inet_ntoa(*(struct in_addr*)&(ut->ut_addr)), 16);
833 /*@+type@*/
834#endif
835 user->time = ut->ut_time;
836
837 if (username == NULL /* not yet logged in */
838 || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console */
839 || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console */
840 ) {
841 status = sh_utmp_login_a(user->name);
[143]842 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]843 (void) sh_unix_time (user->time, ttt, TIM_MAX);
[1]844 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
845#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
846 MSG_UT_LG1X,
847#elif defined(HAVE_UTHOST)
848 MSG_UT_LG1A,
849#else
850 MSG_UT_LG1B,
851#endif
852 user->name,
853 user->ut_tty,
854#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
855 user->ut_host,
856 user->ut_ship,
857#elif defined(HAVE_UTHOST)
858 user->ut_host,
859#endif
860 ttt,
861 status
862 );
[143]863 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]864 } else
865 if (0 != sh_utmp_is_virtual(ut->ut_line, user->ut_host))
866 {
867 status = sh_utmp_login_a(user->name);
[143]868 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]869 (void) sh_unix_time (user->time, ttt, TIM_MAX);
[1]870 sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0,
871#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
872 MSG_UT_LG2X,
873#elif defined(HAVE_UTHOST)
874 MSG_UT_LG2A,
875#else
876 MSG_UT_LG2B,
877#endif
878 user->name,
879 user->ut_tty,
880#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
881 user->ut_host,
882 user->ut_ship,
883#elif defined(HAVE_UTHOST)
884 user->ut_host,
885#endif
886 ttt,
887 status
888 );
[143]889 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]890 }
891
892 sh_utmp_login_morechecks(ut);
893 SL_RET0(_("sh_utmp_addlogin"));
894 }
895
896
897 /* --------- LOGOUT ---------------- */
898 else if (ut->ut_name[0] == '\0'
899 || ut->ut_type == DEAD_PROCESS /* solaris does not clear ut_name */
900 )
901 {
902 if (user != NULL)
903 {
904 status = sh_utmp_login_r(user->name);
[143]905 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]906 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
[1]907 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
908#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
909 MSG_UT_LG3X,
910#elif defined(HAVE_UTHOST)
911 MSG_UT_LG3A,
912#else
913 MSG_UT_LG3B,
914#endif
915 user->name,
916 user->ut_tty,
917#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
918 user->ut_host,
919 user->ut_ship,
920#elif defined(HAVE_UTHOST)
921 user->ut_host,
922#endif
923 ttt,
924 status
925 );
[143]926 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]927 userold->next = user->next;
928 if (user == userlist)
929 userlist = user->next;
930 sh_utmp_logout_morechecks(user);
931 SH_FREE(user);
932 user = NULL;
933 }
934 else
935 {
936 (void) sl_strlcpy(terminated_line, ut->ut_line, UT_HOSTSIZE);
[143]937 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]938 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
[1]939 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
940 MSG_UT_LG3C,
941 terminated_line,
942 ttt, 0
943 );
[143]944 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]945 }
946 SL_RET0(_("sh_utmp_addlogin"));
947 }
948
949 /* default */
950 SL_RET0(_("sh_utmp_addlogin"));
951
952 /* #ifdef HAVE_UTTYPE */
953#else
954
955 if (user == NULL) /* probably a login */
956 {
957 user = SH_ALLOC(sizeof(struct log_user));
958 sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
959 sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
960#ifdef HAVE_UTHOST
961 sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
962#endif
963#ifdef HAVE_UTADDR
964 sl_strlcpy(user->ut_ship,my_inet_ntoa((struct in_addr)ut->ut_addr),16);
965#endif
966 user->time = ut->ut_time;
967 user->next = userlist;
968 userlist = user;
969
[143]970 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]971 (void) sh_unix_time (user->time, ttt, TIM_MAX);
[1]972 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
973#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
974 MSG_UT_LG1X,
975#elif defined(HAVE_UTHOST)
976 MSG_UT_LG1A,
977#else
978 MSG_UT_LG1B,
979#endif
980 user->name,
981 user->ut_tty,
982#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
983 user->ut_host,
984 user->ut_ship,
985#elif defined(HAVE_UTHOST)
986 user->ut_host,
987#endif
988 ttt,
989 1
990 );
[143]991 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]992 sh_utmp_login_morechecks(ut);
993 }
994 else /* probably a logout */
995 {
[143]996 SH_MUTEX_LOCK(mutex_thread_nolog);
[132]997 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
[1]998 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
999#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1000 MSG_UT_LG2X,
1001#elif defined(HAVE_UTHOST)
1002 MSG_UT_LG2A,
1003#else
1004 MSG_UT_LG2B,
1005#endif
1006 user->name,
1007 user->ut_tty,
1008#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1009 user->ut_host,
1010 user->ut_ship,
1011#elif defined(HAVE_UTHOST)
1012 user->ut_host,
1013#endif
1014 ttt,
1015 1
1016 );
[143]1017 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]1018 sh_utmp_logout_morechecks(user);
1019 userold->next = user->next;
1020 if (user == userlist) /* inserted Apr 4, 2004 */
1021 userlist = user->next;
1022 SH_FREE(user);
1023 user = NULL;
1024 }
1025
1026 SL_RET0(_("sh_utmp_addlogin"));
1027#endif
1028}
1029
1030static time_t lastmod = 0;
1031static off_t lastsize = 0;
1032static unsigned long lastread = 0;
1033
1034static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
1035
1036static void sh_utmp_check_internal (int mode)
1037{
1038 struct stat buf;
1039 int error;
1040 struct SH_UTMP_S * ut;
1041 unsigned long this_read = 0;
[143]1042 int val_retry;
[1]1043
1044 SL_ENTER(_("sh_utmp_check_internal"));
1045
1046 /* error if no access
1047 */
[143]1048 do {
1049 val_retry = /*@-unrecog@*/lstat ( mode_path[mode], &buf)/*@+unrecog@*/;
1050 } while (val_retry < 0 && errno == EINTR);
1051
1052 if (0 != val_retry)
[1]1053 {
1054 error = errno;
[143]1055 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]1056 sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
1057 (long) sh.real.uid, mode_path[mode]);
[143]1058 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]1059 SL_RET0(_("sh_utmp_check_internal"));
1060 }
1061
1062 /* modification time
1063 */
1064 if (mode < 2)
1065 {
1066 if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/)
1067 {
1068 SL_RET0(_("sh_utmp_check_internal"));
1069 }
1070 else
1071 lastmod = buf.st_mtime;
1072 }
1073
1074 /* file size
1075 */
1076 if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2)
1077 {
[143]1078 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]1079 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT,
1080 mode_path[mode]);
[143]1081 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[1]1082 lastread = 0;
1083#ifndef USE_SETUTENT
1084 sh_utmp_feed_forward = 0L;
1085#endif
1086 }
1087
1088 if (mode < 2)
1089 lastsize = buf.st_size;
1090
1091 if (buf.st_size == 0)
1092 SL_RET0(_("sh_utmp_check_internal"));
1093
1094 sh_utmp_utmpname(mode_path[mode]);
1095 sh_utmp_setutent();
1096
1097 /*
1098 * feed forward if initializing
1099 * we need to do this here
1100 */
1101 if (mode < 2)
1102 {
1103 while (this_read < lastread) {
1104 ut = sh_utmp_getutent();
1105 ++this_read;
1106 }
1107 }
1108
1109 /* start reading
1110 */
1111 this_read = 0;
1112 while (1 == 1) {
1113 ut = sh_utmp_getutent();
1114 if (ut == NULL)
1115 break;
1116 /* modified: ut_user --> ut_name */
1117 if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0'
1118#ifdef HAVE_UTTYPE
1119 && ut->ut_type != DEAD_PROCESS
1120#endif
1121 ))
1122 sh_utmp_addlogin (ut);
1123 ++this_read;
1124 }
1125
1126 sh_utmp_endutent();
1127
1128 if (mode < 2)
1129 {
1130 lastread += this_read;
1131#ifndef USE_SETUTENT
1132 sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S));
1133 lastread = 0;
1134#endif
1135 }
1136
1137 SL_RET0(_("sh_utmp_check_internal"));
1138}
1139
1140
1141static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut)
1142{
1143 if (ut)
1144 return;
1145 return;
1146}
1147
1148static void sh_utmp_logout_morechecks(struct log_user * user)
1149{
1150 if (user)
1151 return;
1152 return;
1153}
1154
1155#endif
1156
1157
1158/* #ifdef SH_USE_UTMP */
1159#endif
1160
1161
1162
Note: See TracBrowser for help on using the repository browser.