source: trunk/src/sh_utmp.c@ 141

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

Utility function for threaded modules.

File size: 23.6 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;
457
458/*************
459 *
460 * module init
461 *
462 *************/
463int sh_utmp_init (struct mod_type * arg)
464{
465 static int done = 0;
466 (void) arg;
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 (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 done = 1;
483 SL_RETURN( (0), _("sh_utmp_init"));
484}
485
486/*************
487 *
488 * module cleanup
489 *
490 *************/
491#ifdef HAVE_UTTYPE
492static int sh_utmp_login_clean();
493#endif
494
495int sh_utmp_end ()
496{
497 struct log_user * user = userlist;
498 struct log_user * userold;
499
500 SL_ENTER(_("sh_utmp_end"));
501 while (user)
502 {
503 userold = user;
504 user = user->next;
505 SH_FREE(userold);
506 }
507 userlist = NULL;
508#ifdef HAVE_UTTYPE
509 (void) sh_utmp_login_clean();
510#endif
511 SL_RETURN( (0), _("sh_utmp_end"));
512}
513
514
515/*************
516 *
517 * module timer
518 *
519 *************/
520int sh_utmp_timer (time_t tcurrent)
521{
522 if ((time_t) (tcurrent - lastcheck) >= ShUtmpInterval)
523 {
524 lastcheck = tcurrent;
525 return (-1);
526 }
527 return 0;
528}
529
530/*************
531 *
532 * module check
533 *
534 *************/
535int sh_utmp_check ()
536{
537 SL_ENTER(_("sh_utmp_check"));
538 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK);
539 sh_utmp_check_internal (1);
540
541 SL_RETURN(0, _("sh_utmp_check"));
542}
543
544/*************
545 *
546 * module setup
547 *
548 *************/
549
550int sh_utmp_set_login_solo (const char * c)
551{
552 int retval;
553 char tmp[32];
554
555 SL_ENTER(_("sh_utmp_set_login_solo"));
556 tmp[0] = '='; tmp[1] = '\0';
557 (void) sl_strlcat (tmp, c, 32);
558 retval = sh_error_set_level (tmp, &ShUtmpLoginSolo);
559 SL_RETURN(retval, _("sh_utmp_set_login_solo"));
560}
561
562int sh_utmp_set_login_multi (const char * c)
563{
564 int retval;
565 char tmp[32];
566
567 SL_ENTER(_("sh_utmp_set_login_multi"));
568 tmp[0] = '='; tmp[1] = '\0';
569 (void) sl_strlcat (tmp, c, 32);
570 retval = sh_error_set_level (tmp, &ShUtmpLoginMulti);
571 SL_RETURN(retval, _("sh_utmp_set_login_multi"));
572}
573
574int sh_utmp_set_logout_good (const char * c)
575{
576 int retval;
577 char tmp[32];
578
579 SL_ENTER(_("sh_utmp_set_logout_good"));
580 tmp[0] = '='; tmp[1] = '\0';
581 (void) sl_strlcat (tmp, c, 32);
582 retval = sh_error_set_level (tmp, &ShUtmpLogout);
583 SL_RETURN(retval, _("sh_utmp_set_logout_good"));
584}
585
586int sh_utmp_set_login_timer (const char * c)
587{
588 int retval = 0;
589 long val;
590
591 SL_ENTER(_("sh_utmp_set_login_timer"));
592 val = strtol (c, (char **)NULL, 10);
593 if (val <= 0)
594 {
595 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
596 _("utmp timer"), c);
597 retval = -1;
598 }
599
600 val = (val <= 0 ? 60 : val);
601
602 ShUtmpInterval = (time_t) val;
603 SL_RETURN(0, _("sh_utmp_set_login_timer"));
604}
605
606int sh_utmp_set_login_activate (const char * c)
607{
608 int i;
609 SL_ENTER(_("sh_utmp_set_login_activate"));
610 i = sh_util_flagval(c, &ShUtmpActive);
611 SL_RETURN(i, _("sh_utmp_set_login_activate"));
612}
613
614#ifdef HAVE_UTTYPE
615struct login_ct {
616 char name[UT_NAMESIZE+1];
617 int nlogin;
618 struct login_ct * next;
619};
620
621static struct login_ct * login_ct_list = NULL;
622
623static int sh_utmp_login_clean()
624{
625 struct login_ct * list = login_ct_list;
626 struct login_ct * old;
627
628 login_ct_list = NULL;
629
630 while (list)
631 {
632 old = list;
633 list = list->next;
634 SH_FREE(old);
635 }
636 return 0;
637}
638
639/* add a username to the list of logged-in users
640 */
641static int sh_utmp_login_a(char * str)
642{
643 struct login_ct * list = login_ct_list;
644
645 while (list)
646 {
647 if (0 == sl_strcmp(list->name, str))
648 {
649 ++(list->nlogin);
650 return list->nlogin;
651 }
652 list = list->next;
653 }
654 list = SH_ALLOC(sizeof(struct login_ct));
655 (void) sl_strlcpy(list->name, str, UT_NAMESIZE+1);
656 list->nlogin = 1;
657 list->next = login_ct_list;
658 login_ct_list = list;
659 return 1;
660}
661
662static int sh_utmp_login_r(char * str)
663{
664 struct login_ct * list = login_ct_list;
665 struct login_ct * old = login_ct_list;
666
667 while (list)
668 {
669 if (0 == sl_strcmp(list->name, str))
670 {
671 list->nlogin -= 1;
672 if (list->nlogin > 0)
673 {
674 return list->nlogin;
675 }
676 if (login_ct_list == list) /* modified Apr 4, 2004 */
677 {
678 login_ct_list = list->next;
679 SH_FREE(list);
680 }
681 else
682 {
683 old->next = list->next;
684 SH_FREE(list);
685 }
686 return 0;
687 }
688 old = list;
689 list = list->next;
690 }
691 return 0;
692}
693
694#endif
695
696
697/* for each login:
698 * - allocate a log record
699 * - link device.ut_record -> log_record
700 * - link user.ut_record -> log_record
701 */
702#ifdef HAVE_UTTYPE
703static int sh_utmp_is_virtual (char * in_utline, char * in_uthost)
704{
705 if (in_utline != NULL)
706 {
707 if (0 == sl_strncmp(in_utline, _("ttyp"), 4))
708 { return 0; }
709 else if (0 == sl_strncmp(in_utline, _("ttyq"), 4))
710 { return 0; }
711 }
712 if (in_uthost != NULL &&
713 in_uthost[0] == ':' &&
714 in_uthost[1] == '0' &&
715 in_uthost[2] == '\0')
716 {
717 /* return 0; */
718 return 1; /* actually does not seem portable, not even among linuxes */
719 }
720 return 1;
721}
722#endif
723
724static void sh_utmp_addlogin (struct SH_UTMP_S * ut)
725{
726 struct log_user * user = userlist;
727 struct log_user * userold = userlist;
728#ifdef HAVE_UTTYPE
729 struct log_user * username = userlist;
730#endif
731
732 char ttt[TIM_MAX];
733#ifdef HAVE_UTTYPE
734 int status;
735#endif
736
737 SL_ENTER(_("sh_utmp_addlogin"));
738
739 if (ut->ut_line[0] == '\0')
740 SL_RET0(_("sh_utmp_addlogin"));
741
742 /* for some stupid reason, AIX repeats the wtmp entry for logouts
743 * with ssh
744 */
745 if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0)
746 {
747 memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S));
748 SL_RET0(_("sh_utmp_addlogin"));
749 }
750 memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S));
751
752
753 /* ------- find user --------
754 */
755 while (user != NULL)
756 {
757 if (0 == sl_strncmp(user->ut_tty, ut->ut_line, UT_LINESIZE) )
758 break;
759 userold = user;
760 user = user->next;
761 }
762
763#ifdef HAVE_UTTYPE
764 while (username != NULL)
765 {
766 if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) )
767 break;
768 username = username->next;
769 }
770#endif
771
772#ifdef HAVE_UTTYPE
773 /* ---------- LOGIN -------------- */
774 if (ut->ut_type == USER_PROCESS)
775 {
776 if (user == NULL)
777 {
778 user = SH_ALLOC(sizeof(struct log_user));
779 user->next = userlist;
780 userlist = user;
781 }
782 (void) sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
783 (void) sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
784#ifdef HAVE_UTHOST
785 (void) sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
786#else
787 user->ut_host[0] = '\0';
788#endif
789#ifdef HAVE_UTADDR
790 /*@-type@*//* ut_addr does exist !!! */
791 (void) sl_strlcpy(user->ut_ship,
792 my_inet_ntoa(*(struct in_addr*)&(ut->ut_addr)), 16);
793 /*@+type@*/
794#endif
795 user->time = ut->ut_time;
796
797 if (username == NULL /* not yet logged in */
798 || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console */
799 || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console */
800 ) {
801 status = sh_utmp_login_a(user->name);
802 (void) sh_unix_time (user->time, ttt, TIM_MAX);
803 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
804#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
805 MSG_UT_LG1X,
806#elif defined(HAVE_UTHOST)
807 MSG_UT_LG1A,
808#else
809 MSG_UT_LG1B,
810#endif
811 user->name,
812 user->ut_tty,
813#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
814 user->ut_host,
815 user->ut_ship,
816#elif defined(HAVE_UTHOST)
817 user->ut_host,
818#endif
819 ttt,
820 status
821 );
822 } else
823 if (0 != sh_utmp_is_virtual(ut->ut_line, user->ut_host))
824 {
825 status = sh_utmp_login_a(user->name);
826 (void) sh_unix_time (user->time, ttt, TIM_MAX);
827 sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0,
828#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
829 MSG_UT_LG2X,
830#elif defined(HAVE_UTHOST)
831 MSG_UT_LG2A,
832#else
833 MSG_UT_LG2B,
834#endif
835 user->name,
836 user->ut_tty,
837#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
838 user->ut_host,
839 user->ut_ship,
840#elif defined(HAVE_UTHOST)
841 user->ut_host,
842#endif
843 ttt,
844 status
845 );
846 }
847
848 sh_utmp_login_morechecks(ut);
849 SL_RET0(_("sh_utmp_addlogin"));
850 }
851
852
853 /* --------- LOGOUT ---------------- */
854 else if (ut->ut_name[0] == '\0'
855 || ut->ut_type == DEAD_PROCESS /* solaris does not clear ut_name */
856 )
857 {
858 if (user != NULL)
859 {
860 status = sh_utmp_login_r(user->name);
861 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
862 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
863#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
864 MSG_UT_LG3X,
865#elif defined(HAVE_UTHOST)
866 MSG_UT_LG3A,
867#else
868 MSG_UT_LG3B,
869#endif
870 user->name,
871 user->ut_tty,
872#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
873 user->ut_host,
874 user->ut_ship,
875#elif defined(HAVE_UTHOST)
876 user->ut_host,
877#endif
878 ttt,
879 status
880 );
881 userold->next = user->next;
882 if (user == userlist)
883 userlist = user->next;
884 sh_utmp_logout_morechecks(user);
885 SH_FREE(user);
886 user = NULL;
887 }
888 else
889 {
890 (void) sl_strlcpy(terminated_line, ut->ut_line, UT_HOSTSIZE);
891 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
892 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
893 MSG_UT_LG3C,
894 terminated_line,
895 ttt, 0
896 );
897 }
898 SL_RET0(_("sh_utmp_addlogin"));
899 }
900
901 /* default */
902 SL_RET0(_("sh_utmp_addlogin"));
903
904 /* #ifdef HAVE_UTTYPE */
905#else
906
907 if (user == NULL) /* probably a login */
908 {
909 user = SH_ALLOC(sizeof(struct log_user));
910 sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
911 sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
912#ifdef HAVE_UTHOST
913 sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
914#endif
915#ifdef HAVE_UTADDR
916 sl_strlcpy(user->ut_ship,my_inet_ntoa((struct in_addr)ut->ut_addr),16);
917#endif
918 user->time = ut->ut_time;
919 user->next = userlist;
920 userlist = user;
921
922 (void) sh_unix_time (user->time, ttt, TIM_MAX);
923
924
925 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
926#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
927 MSG_UT_LG1X,
928#elif defined(HAVE_UTHOST)
929 MSG_UT_LG1A,
930#else
931 MSG_UT_LG1B,
932#endif
933 user->name,
934 user->ut_tty,
935#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
936 user->ut_host,
937 user->ut_ship,
938#elif defined(HAVE_UTHOST)
939 user->ut_host,
940#endif
941 ttt,
942 1
943 );
944 sh_utmp_login_morechecks(ut);
945 }
946 else /* probably a logout */
947 {
948 (void) sh_unix_time (ut->ut_time, ttt, 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 ++this_read;
1066 }
1067
1068 sh_utmp_endutent();
1069
1070 if (mode < 2)
1071 {
1072 lastread += this_read;
1073#ifndef USE_SETUTENT
1074 sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S));
1075 lastread = 0;
1076#endif
1077 }
1078
1079 SL_RET0(_("sh_utmp_check_internal"));
1080}
1081
1082
1083static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut)
1084{
1085 if (ut)
1086 return;
1087 return;
1088}
1089
1090static void sh_utmp_logout_morechecks(struct log_user * user)
1091{
1092 if (user)
1093 return;
1094 return;
1095}
1096
1097#endif
1098
1099
1100/* #ifdef SH_USE_UTMP */
1101#endif
1102
1103
1104
Note: See TracBrowser for help on using the repository browser.