source: trunk/src/sh_utmp.c@ 142

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

Login watch runs in thread.

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