source: trunk/src/sh_utmp.c@ 65

Last change on this file since 65 was 34, checked in by rainer, 19 years ago

Code cleanup and minor fixes

File size: 23.7 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 ()
464{
465 static int done = 0;
466
467 SL_ENTER(_("sh_utmp_init"));
468 if (ShUtmpActive == BAD)
469 SL_RETURN( (-1), _("sh_utmp_init"));
470
471 /* do not re-initialize after a re-configuration
472 */
473 if (done == 1) {
474 SL_RETURN( (0), _("sh_utmp_init"));
475 }
476 lastcheck = time (NULL);
477 userlist = NULL;
478 memset (&save_utmp, 0, sizeof(struct SH_UTMP_S));
479 sh_utmp_check_internal (2); /* current logins */
480 sh_utmp_check_internal (0);
481 done = 1;
482 SL_RETURN( (0), _("sh_utmp_init"));
483}
484
485/*************
486 *
487 * module cleanup
488 *
489 *************/
490#ifdef HAVE_UTTYPE
491static int sh_utmp_login_clean();
492#endif
493
494int sh_utmp_end ()
495{
496 struct log_user * user = userlist;
497 struct log_user * userold;
498
499 SL_ENTER(_("sh_utmp_end"));
500 while (user)
501 {
502 userold = user;
503 user = user->next;
504 SH_FREE(userold);
505 }
506 userlist = NULL;
507#ifdef HAVE_UTTYPE
508 (void) sh_utmp_login_clean();
509#endif
510 SL_RETURN( (0), _("sh_utmp_end"));
511}
512
513
514/*************
515 *
516 * module timer
517 *
518 *************/
519int sh_utmp_timer (time_t tcurrent)
520{
521 if ((time_t) (tcurrent - lastcheck) >= ShUtmpInterval)
522 {
523 lastcheck = tcurrent;
524 return (-1);
525 }
526 return 0;
527}
528
529/*************
530 *
531 * module check
532 *
533 *************/
534int sh_utmp_check ()
535{
536 SL_ENTER(_("sh_utmp_check"));
537 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK);
538 sh_utmp_check_internal (1);
539
540 SL_RETURN(0, _("sh_utmp_check"));
541}
542
543/*************
544 *
545 * module setup
546 *
547 *************/
548
549int sh_utmp_set_login_solo (char * c)
550{
551 int retval;
552 char tmp[32];
553
554 SL_ENTER(_("sh_utmp_set_login_solo"));
555 tmp[0] = '='; tmp[1] = '\0';
556 (void) sl_strlcat (tmp, c, 32);
557 retval = sh_error_set_level (tmp, &ShUtmpLoginSolo);
558 SL_RETURN(retval, _("sh_utmp_set_login_solo"));
559}
560
561int sh_utmp_set_login_multi (char * c)
562{
563 int retval;
564 char tmp[32];
565
566 SL_ENTER(_("sh_utmp_set_login_multi"));
567 tmp[0] = '='; tmp[1] = '\0';
568 (void) sl_strlcat (tmp, c, 32);
569 retval = sh_error_set_level (tmp, &ShUtmpLoginMulti);
570 SL_RETURN(retval, _("sh_utmp_set_login_multi"));
571}
572
573int sh_utmp_set_logout_good (char * c)
574{
575 int retval;
576 char tmp[32];
577
578 SL_ENTER(_("sh_utmp_set_logout_good"));
579 tmp[0] = '='; tmp[1] = '\0';
580 (void) sl_strlcat (tmp, c, 32);
581 retval = sh_error_set_level (tmp, &ShUtmpLogout);
582 SL_RETURN(retval, _("sh_utmp_set_logout_good"));
583}
584
585int sh_utmp_set_login_timer (char * c)
586{
587 int retval = 0;
588 long val;
589
590 SL_ENTER(_("sh_utmp_set_login_timer"));
591 val = strtol (c, (char **)NULL, 10);
592 if (val <= 0)
593 {
594 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
595 _("utmp timer"), c);
596 retval = -1;
597 }
598
599 val = (val <= 0 ? 60 : val);
600
601 ShUtmpInterval = (time_t) val;
602 SL_RETURN(0, _("sh_utmp_set_login_timer"));
603}
604
605int sh_utmp_set_login_activate (char * c)
606{
607 int i;
608 SL_ENTER(_("sh_utmp_set_login_activate"));
609 i = sh_util_flagval(c, &ShUtmpActive);
610 SL_RETURN(i, _("sh_utmp_set_login_activate"));
611}
612
613#ifdef HAVE_UTTYPE
614struct login_ct {
615 char name[UT_NAMESIZE+1];
616 int nlogin;
617 struct login_ct * next;
618};
619
620static struct login_ct * login_ct_list = NULL;
621
622static int sh_utmp_login_clean()
623{
624 struct login_ct * list = login_ct_list;
625 struct login_ct * old;
626
627 login_ct_list = NULL;
628
629 while (list)
630 {
631 old = list;
632 list = list->next;
633 SH_FREE(old);
634 }
635 return 0;
636}
637
638/* add a username to the list of logged-in users
639 */
640static int sh_utmp_login_a(char * str)
641{
642 struct login_ct * list = login_ct_list;
643
644 while (list)
645 {
646 if (0 == sl_strcmp(list->name, str))
647 {
648 ++(list->nlogin);
649 return list->nlogin;
650 }
651 list = list->next;
652 }
653 list = SH_ALLOC(sizeof(struct login_ct));
654 (void) sl_strlcpy(list->name, str, UT_NAMESIZE+1);
655 list->nlogin = 1;
656 list->next = login_ct_list;
657 login_ct_list = list;
658 return 1;
659}
660
661static int sh_utmp_login_r(char * str)
662{
663 struct login_ct * list = login_ct_list;
664 struct login_ct * old = login_ct_list;
665
666 while (list)
667 {
668 if (0 == sl_strcmp(list->name, str))
669 {
670 list->nlogin -= 1;
671 if (list->nlogin > 0)
672 {
673 return list->nlogin;
674 }
675 if (login_ct_list == list) /* modified Apr 4, 2004 */
676 {
677 login_ct_list = list->next;
678 SH_FREE(list);
679 }
680 else
681 {
682 old->next = list->next;
683 SH_FREE(list);
684 }
685 return 0;
686 }
687 old = list;
688 list = list->next;
689 }
690 return 0;
691}
692
693#endif
694
695
696/* for each login:
697 * - allocate a log record
698 * - link device.ut_record -> log_record
699 * - link user.ut_record -> log_record
700 */
701#ifdef HAVE_UTTYPE
702static int sh_utmp_is_virtual (char * in_utline, char * in_uthost)
703{
704 if (in_utline != NULL)
705 {
706 if (0 == sl_strncmp(in_utline, _("ttyp"), 4))
707 { return 0; }
708 else if (0 == sl_strncmp(in_utline, _("ttyq"), 4))
709 { return 0; }
710 }
711 if (in_uthost != NULL &&
712 in_uthost[0] == ':' &&
713 in_uthost[1] == '0' &&
714 in_uthost[2] == '\0')
715 {
716 /* return 0; */
717 return 1; /* actually does not seem portable, not even among linuxes */
718 }
719 return 1;
720}
721#endif
722
723static void sh_utmp_addlogin (struct SH_UTMP_S * ut)
724{
725 struct log_user * user = userlist;
726 struct log_user * userold = userlist;
727#ifdef HAVE_UTTYPE
728 struct log_user * username = userlist;
729#endif
730
731 char ttt[TIM_MAX];
732#ifdef HAVE_UTTYPE
733 int status;
734#endif
735
736 SL_ENTER(_("sh_utmp_addlogin"));
737
738 if (ut->ut_line[0] == '\0')
739 SL_RET0(_("sh_utmp_addlogin"));
740
741 /* for some stupid reason, AIX repeats the wtmp entry for logouts
742 * with ssh
743 */
744 if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0)
745 {
746 memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S));
747 SL_RET0(_("sh_utmp_addlogin"));
748 }
749 memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S));
750
751
752 /* ------- find user --------
753 */
754 while (user != NULL)
755 {
756 if (0 == sl_strncmp(user->ut_tty, ut->ut_line, UT_LINESIZE) )
757 break;
758 userold = user;
759 user = user->next;
760 }
761
762#ifdef HAVE_UTTYPE
763 while (username != NULL)
764 {
765 if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) )
766 break;
767 username = username->next;
768 }
769#endif
770
771#ifdef HAVE_UTTYPE
772 /* ---------- LOGIN -------------- */
773 if (ut->ut_type == USER_PROCESS)
774 {
775 if (user == NULL)
776 {
777 user = SH_ALLOC(sizeof(struct log_user));
778 user->next = userlist;
779 userlist = user;
780 }
781 (void) sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
782 (void) sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
783#ifdef HAVE_UTHOST
784 (void) sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
785#else
786 user->ut_host[0] = '\0';
787#endif
788#ifdef HAVE_UTADDR
789 /*@-type@*//* ut_addr does exist !!! */
790 (void) sl_strlcpy(user->ut_ship,
791 my_inet_ntoa(*(struct in_addr*)&(ut->ut_addr)), 16);
792 /*@+type@*/
793#endif
794 user->time = ut->ut_time;
795
796 if (username == NULL /* not yet logged in */
797 || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console */
798 || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console */
799 ) {
800 status = sh_utmp_login_a(user->name);
801 (void) sl_strlcpy(ttt, sh_unix_time (user->time), TIM_MAX);
802 sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
803#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
804 MSG_UT_LG1X,
805#elif defined(HAVE_UTHOST)
806 MSG_UT_LG1A,
807#else
808 MSG_UT_LG1B,
809#endif
810 user->name,
811 user->ut_tty,
812#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
813 user->ut_host,
814 user->ut_ship,
815#elif defined(HAVE_UTHOST)
816 user->ut_host,
817#endif
818 ttt,
819 status
820 );
821 } else
822 if (0 != sh_utmp_is_virtual(ut->ut_line, user->ut_host))
823 {
824 status = sh_utmp_login_a(user->name);
825 (void) sl_strlcpy(ttt, sh_unix_time (user->time), TIM_MAX);
826 sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0,
827#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
828 MSG_UT_LG2X,
829#elif defined(HAVE_UTHOST)
830 MSG_UT_LG2A,
831#else
832 MSG_UT_LG2B,
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 }
846
847 sh_utmp_login_morechecks(ut);
848 SL_RET0(_("sh_utmp_addlogin"));
849 }
850
851
852 /* --------- LOGOUT ---------------- */
853 else if (ut->ut_name[0] == '\0'
854 || ut->ut_type == DEAD_PROCESS /* solaris does not clear ut_name */
855 )
856 {
857 if (user != NULL)
858 {
859 status = sh_utmp_login_r(user->name);
860 /* sl_strlcpy(ttt, sh_unix_time (user->time), TIM_MAX); */
861 (void) sl_strlcpy(ttt, sh_unix_time (ut->ut_time), 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) sl_strlcpy(ttt, sh_unix_time (ut->ut_time), 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 sl_strlcpy(ttt, sh_unix_time (user->time), 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 sl_strlcpy(ttt, sh_unix_time (ut->ut_time), TIM_MAX);
949 /* sl_strlcpy(ttt, sh_unix_time (user->time), TIM_MAX); */
950
951 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
952#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
953 MSG_UT_LG2X,
954#elif defined(HAVE_UTHOST)
955 MSG_UT_LG2A,
956#else
957 MSG_UT_LG2B,
958#endif
959 user->name,
960 user->ut_tty,
961#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
962 user->ut_host,
963 user->ut_ship,
964#elif defined(HAVE_UTHOST)
965 user->ut_host,
966#endif
967 ttt,
968 1
969 );
970 sh_utmp_logout_morechecks(user);
971 userold->next = user->next;
972 if (user == userlist) /* inserted Apr 4, 2004 */
973 userlist = user->next;
974 SH_FREE(user);
975 user = NULL;
976 }
977
978 SL_RET0(_("sh_utmp_addlogin"));
979#endif
980}
981
982static time_t lastmod = 0;
983static off_t lastsize = 0;
984static unsigned long lastread = 0;
985
986static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
987
988static void sh_utmp_check_internal (int mode)
989{
990 struct stat buf;
991 int error;
992 struct SH_UTMP_S * ut;
993 unsigned long this_read = 0;
994
995 SL_ENTER(_("sh_utmp_check_internal"));
996
997 /* error if no access
998 */
999 if (0 != retry_lstat(FIL__, __LINE__, mode_path[mode], &buf))
1000 {
1001 error = errno;
1002 sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
1003 (long) sh.real.uid, mode_path[mode]);
1004 SL_RET0(_("sh_utmp_check_internal"));
1005 }
1006
1007 /* modification time
1008 */
1009 if (mode < 2)
1010 {
1011 if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/)
1012 {
1013 SL_RET0(_("sh_utmp_check_internal"));
1014 }
1015 else
1016 lastmod = buf.st_mtime;
1017 }
1018
1019 /* file size
1020 */
1021 if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2)
1022 {
1023 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT,
1024 mode_path[mode]);
1025 lastread = 0;
1026#ifndef USE_SETUTENT
1027 sh_utmp_feed_forward = 0L;
1028#endif
1029 }
1030
1031 if (mode < 2)
1032 lastsize = buf.st_size;
1033
1034 if (buf.st_size == 0)
1035 SL_RET0(_("sh_utmp_check_internal"));
1036
1037 sh_utmp_utmpname(mode_path[mode]);
1038 sh_utmp_setutent();
1039
1040 /*
1041 * feed forward if initializing
1042 * we need to do this here
1043 */
1044 if (mode < 2)
1045 {
1046 while (this_read < lastread) {
1047 ut = sh_utmp_getutent();
1048 ++this_read;
1049 }
1050 }
1051
1052 /* start reading
1053 */
1054 this_read = 0;
1055 while (1 == 1) {
1056 ut = sh_utmp_getutent();
1057 if (ut == NULL)
1058 break;
1059 /* modified: ut_user --> ut_name */
1060 if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0'
1061#ifdef HAVE_UTTYPE
1062 && ut->ut_type != DEAD_PROCESS
1063#endif
1064 ))
1065 sh_utmp_addlogin (ut);
1066 ++this_read;
1067 }
1068
1069 sh_utmp_endutent();
1070
1071 if (mode < 2)
1072 {
1073 lastread += this_read;
1074#ifndef USE_SETUTENT
1075 sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S));
1076 lastread = 0;
1077#endif
1078 }
1079
1080 SL_RET0(_("sh_utmp_check_internal"));
1081}
1082
1083
1084static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut)
1085{
1086 if (ut)
1087 return;
1088 return;
1089}
1090
1091static void sh_utmp_logout_morechecks(struct log_user * user)
1092{
1093 if (user)
1094 return;
1095 return;
1096}
1097
1098#endif
1099
1100
1101/* #ifdef SH_USE_UTMP */
1102#endif
1103
1104
1105
Note: See TracBrowser for help on using the repository browser.