source: trunk/src/sh_utmp.c@ 173

Last change on this file since 173 was 170, checked in by katerina, 17 years ago

Plenty of compiler warnings fixed, SQL query length fixed, doc update.

File size: 26.4 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 (void)
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(void);
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 long val;
636
637 SL_ENTER(_("sh_utmp_set_login_timer"));
638 val = strtol (c, (char **)NULL, 10);
639 if (val <= 0)
640 {
641 SH_MUTEX_LOCK(mutex_thread_nolog);
642 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
643 _("utmp timer"), c);
644 SH_MUTEX_UNLOCK(mutex_thread_nolog);
645 SL_RETURN((-1), _("sh_utmp_set_login_timer"));
646 }
647
648 ShUtmpInterval = (time_t) val;
649 SL_RETURN(0, _("sh_utmp_set_login_timer"));
650}
651
652int sh_utmp_set_login_activate (const char * c)
653{
654 int i;
655 SL_ENTER(_("sh_utmp_set_login_activate"));
656 i = sh_util_flagval(c, &ShUtmpActive);
657 SL_RETURN(i, _("sh_utmp_set_login_activate"));
658}
659
660#ifdef HAVE_UTTYPE
661struct login_ct {
662 char name[UT_NAMESIZE+1];
663 int nlogin;
664 struct login_ct * next;
665};
666
667static struct login_ct * login_ct_list = NULL;
668
669static int sh_utmp_login_clean(void)
670{
671 struct login_ct * list = login_ct_list;
672 struct login_ct * old;
673
674 login_ct_list = NULL;
675
676 while (list)
677 {
678 old = list;
679 list = list->next;
680 SH_FREE(old);
681 }
682 return 0;
683}
684
685/* add a username to the list of logged-in users
686 */
687static int sh_utmp_login_a(char * str)
688{
689 struct login_ct * list = login_ct_list;
690
691 while (list)
692 {
693 if (0 == sl_strcmp(list->name, str))
694 {
695 ++(list->nlogin);
696 return list->nlogin;
697 }
698 list = list->next;
699 }
700 list = SH_ALLOC(sizeof(struct login_ct));
701 (void) sl_strlcpy(list->name, str, UT_NAMESIZE+1);
702 list->nlogin = 1;
703 list->next = login_ct_list;
704 login_ct_list = list;
705 return 1;
706}
707
708static int sh_utmp_login_r(char * str)
709{
710 struct login_ct * list = login_ct_list;
711 struct login_ct * old = login_ct_list;
712
713 while (list)
714 {
715 if (0 == sl_strcmp(list->name, str))
716 {
717 list->nlogin -= 1;
718 if (list->nlogin > 0)
719 {
720 return list->nlogin;
721 }
722 if (login_ct_list == list) /* modified Apr 4, 2004 */
723 {
724 login_ct_list = list->next;
725 SH_FREE(list);
726 }
727 else
728 {
729 old->next = list->next;
730 SH_FREE(list);
731 }
732 return 0;
733 }
734 old = list;
735 list = list->next;
736 }
737 return 0;
738}
739
740#endif
741
742
743/* for each login:
744 * - allocate a log record
745 * - link device.ut_record -> log_record
746 * - link user.ut_record -> log_record
747 */
748#ifdef HAVE_UTTYPE
749static int sh_utmp_is_virtual (char * in_utline, char * in_uthost)
750{
751 if (in_utline != NULL)
752 {
753 if (0 == sl_strncmp(in_utline, _("ttyp"), 4))
754 { return 0; }
755 else if (0 == sl_strncmp(in_utline, _("ttyq"), 4))
756 { return 0; }
757 }
758 if (in_uthost != NULL &&
759 in_uthost[0] == ':' &&
760 in_uthost[1] == '0' &&
761 in_uthost[2] == '\0')
762 {
763 /* return 0; */
764 return 1; /* actually does not seem portable, not even among linuxes */
765 }
766 return 1;
767}
768#endif
769
770/* These variables are not used anywhere. They only exist
771 * to assign &userold, &user to them, which keeps gcc from
772 * putting them into a register, and avoids the 'clobbered
773 * by longjmp' warning. And no, 'volatile' proved insufficient.
774 */
775static void * sh_dummy_userold = NULL;
776static void * sh_dummy_user = NULL;
777
778
779static void sh_utmp_addlogin (struct SH_UTMP_S * ut)
780{
781 struct log_user * user = userlist;
782 struct log_user * userold = userlist;
783#ifdef HAVE_UTTYPE
784 struct log_user * username = userlist;
785#endif
786
787 char ttt[TIM_MAX];
788#ifdef HAVE_UTTYPE
789 volatile int status;
790#endif
791
792 SL_ENTER(_("sh_utmp_addlogin"));
793
794 /* Take the address to keep gcc from putting them into registers.
795 * Avoids the 'clobbered by longjmp' warning.
796 */
797 sh_dummy_userold = (void*) &userold;
798 sh_dummy_user = (void*) &user;
799
800 if (ut->ut_line[0] == '\0')
801 SL_RET0(_("sh_utmp_addlogin"));
802
803 /* for some stupid reason, AIX repeats the wtmp entry for logouts
804 * with ssh
805 */
806 if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0)
807 {
808 memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S));
809 SL_RET0(_("sh_utmp_addlogin"));
810 }
811 memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S));
812
813
814 /* ------- find user --------
815 */
816 while (user != NULL)
817 {
818 if (0 == sl_strncmp((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE) )
819 break;
820 userold = user;
821 user = user->next;
822 }
823
824#ifdef HAVE_UTTYPE
825 while (username != NULL)
826 {
827 if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) )
828 break;
829 username = username->next;
830 }
831#endif
832
833#ifdef HAVE_UTTYPE
834 /* ---------- LOGIN -------------- */
835 if (ut->ut_type == USER_PROCESS)
836 {
837 if (user == NULL)
838 {
839 user = SH_ALLOC(sizeof(struct log_user));
840 user->next = userlist;
841 userlist = (struct log_user *) user;
842 }
843 (void) sl_strlcpy((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE+1);
844 (void) sl_strlcpy((char*)(user->name), ut->ut_name, UT_NAMESIZE+1);
845#ifdef HAVE_UTHOST
846 (void) sl_strlcpy((char*)(user->ut_host), ut->ut_host, UT_HOSTSIZE+1);
847#else
848 user->ut_host[0] = '\0';
849#endif
850#ifdef HAVE_UTADDR
851 /*@-type@*//* ut_addr does exist !!! */
852 (void) sl_strlcpy((char*)(user->ut_ship),
853 my_inet_ntoa(*(struct in_addr*)&(ut->ut_addr)), 16);
854 /*@+type@*/
855#endif
856 user->time = ut->ut_time;
857
858 if (username == NULL /* not yet logged in */
859 || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console */
860 || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console */
861 ) {
862 status = sh_utmp_login_a((char*)user->name);
863 SH_MUTEX_LOCK(mutex_thread_nolog);
864 (void) sh_unix_time (user->time, ttt, TIM_MAX);
865 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
866#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
867 MSG_UT_LG1X,
868#elif defined(HAVE_UTHOST)
869 MSG_UT_LG1A,
870#else
871 MSG_UT_LG1B,
872#endif
873 user->name,
874 user->ut_tty,
875#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
876 user->ut_host,
877 user->ut_ship,
878#elif defined(HAVE_UTHOST)
879 user->ut_host,
880#endif
881 ttt,
882 status
883 );
884 SH_MUTEX_UNLOCK(mutex_thread_nolog);
885 } else
886 if (0 != sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host))
887 {
888 status = sh_utmp_login_a((char*)user->name);
889 SH_MUTEX_LOCK(mutex_thread_nolog);
890 (void) sh_unix_time (user->time, ttt, TIM_MAX);
891 sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0,
892#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
893 MSG_UT_LG2X,
894#elif defined(HAVE_UTHOST)
895 MSG_UT_LG2A,
896#else
897 MSG_UT_LG2B,
898#endif
899 user->name,
900 user->ut_tty,
901#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
902 user->ut_host,
903 user->ut_ship,
904#elif defined(HAVE_UTHOST)
905 user->ut_host,
906#endif
907 ttt,
908 status
909 );
910 SH_MUTEX_UNLOCK(mutex_thread_nolog);
911 }
912
913 sh_utmp_login_morechecks(ut);
914 SL_RET0(_("sh_utmp_addlogin"));
915 }
916
917
918 /* --------- LOGOUT ---------------- */
919 else if (ut->ut_name[0] == '\0'
920 || ut->ut_type == DEAD_PROCESS /* solaris does not clear ut_name */
921 )
922 {
923 if (user != NULL)
924 {
925 status = sh_utmp_login_r((char*)user->name);
926 SH_MUTEX_LOCK(mutex_thread_nolog);
927 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
928 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
929#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
930 MSG_UT_LG3X,
931#elif defined(HAVE_UTHOST)
932 MSG_UT_LG3A,
933#else
934 MSG_UT_LG3B,
935#endif
936 user->name,
937 user->ut_tty,
938#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
939 user->ut_host,
940 user->ut_ship,
941#elif defined(HAVE_UTHOST)
942 user->ut_host,
943#endif
944 ttt,
945 status
946 );
947 SH_MUTEX_UNLOCK(mutex_thread_nolog);
948 userold->next = user->next;
949 if (user == userlist)
950 userlist = user->next;
951 sh_utmp_logout_morechecks((struct log_user *)user);
952 SH_FREE((struct log_user *)user);
953 user = NULL;
954 }
955 else
956 {
957 (void) sl_strlcpy(terminated_line, ut->ut_line, UT_HOSTSIZE);
958 SH_MUTEX_LOCK(mutex_thread_nolog);
959 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
960 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
961 MSG_UT_LG3C,
962 terminated_line,
963 ttt, 0
964 );
965 SH_MUTEX_UNLOCK(mutex_thread_nolog);
966 }
967 SL_RET0(_("sh_utmp_addlogin"));
968 }
969
970 /* default */
971 SL_RET0(_("sh_utmp_addlogin"));
972
973 /* #ifdef HAVE_UTTYPE */
974#else
975
976 if (user == NULL) /* probably a login */
977 {
978 user = SH_ALLOC(sizeof(struct log_user));
979 sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
980 sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
981#ifdef HAVE_UTHOST
982 sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
983#endif
984#ifdef HAVE_UTADDR
985 sl_strlcpy(user->ut_ship,my_inet_ntoa((struct in_addr)ut->ut_addr),16);
986#endif
987 user->time = ut->ut_time;
988 user->next = userlist;
989 userlist = user;
990
991 SH_MUTEX_LOCK(mutex_thread_nolog);
992 (void) sh_unix_time (user->time, ttt, TIM_MAX);
993 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
994#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
995 MSG_UT_LG1X,
996#elif defined(HAVE_UTHOST)
997 MSG_UT_LG1A,
998#else
999 MSG_UT_LG1B,
1000#endif
1001 user->name,
1002 user->ut_tty,
1003#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1004 user->ut_host,
1005 user->ut_ship,
1006#elif defined(HAVE_UTHOST)
1007 user->ut_host,
1008#endif
1009 ttt,
1010 1
1011 );
1012 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1013 sh_utmp_login_morechecks(ut);
1014 }
1015 else /* probably a logout */
1016 {
1017 SH_MUTEX_LOCK(mutex_thread_nolog);
1018 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
1019 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
1020#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1021 MSG_UT_LG2X,
1022#elif defined(HAVE_UTHOST)
1023 MSG_UT_LG2A,
1024#else
1025 MSG_UT_LG2B,
1026#endif
1027 user->name,
1028 user->ut_tty,
1029#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
1030 user->ut_host,
1031 user->ut_ship,
1032#elif defined(HAVE_UTHOST)
1033 user->ut_host,
1034#endif
1035 ttt,
1036 1
1037 );
1038 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1039 sh_utmp_logout_morechecks(user);
1040 userold->next = user->next;
1041 if (user == userlist) /* inserted Apr 4, 2004 */
1042 userlist = user->next;
1043 SH_FREE(user);
1044 user = NULL;
1045 }
1046
1047 SL_RET0(_("sh_utmp_addlogin"));
1048#endif
1049}
1050
1051static time_t lastmod = 0;
1052static off_t lastsize = 0;
1053static unsigned long lastread = 0;
1054
1055static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
1056
1057static void sh_utmp_check_internal (int mode)
1058{
1059 struct stat buf;
1060 int error;
1061 struct SH_UTMP_S * ut;
1062 unsigned long this_read;
1063 int val_retry;
1064
1065 SL_ENTER(_("sh_utmp_check_internal"));
1066
1067 /* error if no access
1068 */
1069 do {
1070 val_retry = /*@-unrecog@*/lstat ( mode_path[mode], &buf)/*@+unrecog@*/;
1071 } while (val_retry < 0 && errno == EINTR);
1072
1073 if (0 != val_retry)
1074 {
1075 error = errno;
1076 SH_MUTEX_LOCK(mutex_thread_nolog);
1077 sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
1078 (long) sh.real.uid, mode_path[mode]);
1079 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1080 SL_RET0(_("sh_utmp_check_internal"));
1081 }
1082
1083 /* modification time
1084 */
1085 if (mode < 2)
1086 {
1087 if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/)
1088 {
1089 SL_RET0(_("sh_utmp_check_internal"));
1090 }
1091 else
1092 lastmod = buf.st_mtime;
1093 }
1094
1095 /* file size
1096 */
1097 if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2)
1098 {
1099 SH_MUTEX_LOCK(mutex_thread_nolog);
1100 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT,
1101 mode_path[mode]);
1102 SH_MUTEX_UNLOCK(mutex_thread_nolog);
1103 lastread = 0;
1104#ifndef USE_SETUTENT
1105 sh_utmp_feed_forward = 0L;
1106#endif
1107 }
1108
1109 if (mode < 2)
1110 lastsize = buf.st_size;
1111
1112 if (buf.st_size == 0)
1113 SL_RET0(_("sh_utmp_check_internal"));
1114
1115 sh_utmp_utmpname(mode_path[mode]);
1116 sh_utmp_setutent();
1117
1118 /*
1119 * feed forward if initializing
1120 * we need to do this here
1121 */
1122 this_read = 0;
1123
1124 if (mode < 2)
1125 {
1126 while (this_read < lastread) {
1127 ut = sh_utmp_getutent();
1128 ++this_read;
1129 }
1130 }
1131
1132 /* start reading
1133 */
1134 this_read = 0;
1135 while (1 == 1) {
1136 ut = sh_utmp_getutent();
1137 if (ut == NULL)
1138 break;
1139 /* modified: ut_user --> ut_name */
1140 if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0'
1141#ifdef HAVE_UTTYPE
1142 && ut->ut_type != DEAD_PROCESS
1143#endif
1144 ))
1145 sh_utmp_addlogin (ut);
1146 ++this_read;
1147 }
1148
1149 sh_utmp_endutent();
1150
1151 if (mode < 2)
1152 {
1153 lastread += this_read;
1154#ifndef USE_SETUTENT
1155 sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S));
1156 lastread = 0;
1157#endif
1158 }
1159
1160 SL_RET0(_("sh_utmp_check_internal"));
1161}
1162
1163
1164static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut)
1165{
1166 if (ut)
1167 return;
1168 return;
1169}
1170
1171static void sh_utmp_logout_morechecks(struct log_user * user)
1172{
1173 if (user)
1174 return;
1175 return;
1176}
1177
1178#endif
1179
1180
1181/* #ifdef SH_USE_UTMP */
1182#endif
1183
1184
1185
Note: See TracBrowser for help on using the repository browser.