source: trunk/src/sh_utmp.c@ 18

Last change on this file since 18 was 1, checked in by katerina, 19 years ago

Initial import

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