source: trunk/src/sh_utmp.c@ 136

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

Make utility functions thread-safe.

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 ()
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 (const 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 (const 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 (const 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 (const 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 (const 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) sh_unix_time (user->time, ttt, 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) sh_unix_time (user->time, ttt, 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 (void) sh_unix_time (ut->ut_time, ttt, 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) sh_unix_time (ut->ut_time, ttt, 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 (void) sh_unix_time (user->time, ttt, 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 (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
948
949 sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
950#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
951 MSG_UT_LG2X,
952#elif defined(HAVE_UTHOST)
953 MSG_UT_LG2A,
954#else
955 MSG_UT_LG2B,
956#endif
957 user->name,
958 user->ut_tty,
959#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
960 user->ut_host,
961 user->ut_ship,
962#elif defined(HAVE_UTHOST)
963 user->ut_host,
964#endif
965 ttt,
966 1
967 );
968 sh_utmp_logout_morechecks(user);
969 userold->next = user->next;
970 if (user == userlist) /* inserted Apr 4, 2004 */
971 userlist = user->next;
972 SH_FREE(user);
973 user = NULL;
974 }
975
976 SL_RET0(_("sh_utmp_addlogin"));
977#endif
978}
979
980static time_t lastmod = 0;
981static off_t lastsize = 0;
982static unsigned long lastread = 0;
983
984static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
985
986static void sh_utmp_check_internal (int mode)
987{
988 struct stat buf;
989 int error;
990 struct SH_UTMP_S * ut;
991 unsigned long this_read = 0;
992
993 SL_ENTER(_("sh_utmp_check_internal"));
994
995 /* error if no access
996 */
997 if (0 != retry_lstat(FIL__, __LINE__, mode_path[mode], &buf))
998 {
999 error = errno;
1000 sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
1001 (long) sh.real.uid, mode_path[mode]);
1002 SL_RET0(_("sh_utmp_check_internal"));
1003 }
1004
1005 /* modification time
1006 */
1007 if (mode < 2)
1008 {
1009 if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/)
1010 {
1011 SL_RET0(_("sh_utmp_check_internal"));
1012 }
1013 else
1014 lastmod = buf.st_mtime;
1015 }
1016
1017 /* file size
1018 */
1019 if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2)
1020 {
1021 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT,
1022 mode_path[mode]);
1023 lastread = 0;
1024#ifndef USE_SETUTENT
1025 sh_utmp_feed_forward = 0L;
1026#endif
1027 }
1028
1029 if (mode < 2)
1030 lastsize = buf.st_size;
1031
1032 if (buf.st_size == 0)
1033 SL_RET0(_("sh_utmp_check_internal"));
1034
1035 sh_utmp_utmpname(mode_path[mode]);
1036 sh_utmp_setutent();
1037
1038 /*
1039 * feed forward if initializing
1040 * we need to do this here
1041 */
1042 if (mode < 2)
1043 {
1044 while (this_read < lastread) {
1045 ut = sh_utmp_getutent();
1046 ++this_read;
1047 }
1048 }
1049
1050 /* start reading
1051 */
1052 this_read = 0;
1053 while (1 == 1) {
1054 ut = sh_utmp_getutent();
1055 if (ut == NULL)
1056 break;
1057 /* modified: ut_user --> ut_name */
1058 if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0'
1059#ifdef HAVE_UTTYPE
1060 && ut->ut_type != DEAD_PROCESS
1061#endif
1062 ))
1063 sh_utmp_addlogin (ut);
1064 ++this_read;
1065 }
1066
1067 sh_utmp_endutent();
1068
1069 if (mode < 2)
1070 {
1071 lastread += this_read;
1072#ifndef USE_SETUTENT
1073 sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S));
1074 lastread = 0;
1075#endif
1076 }
1077
1078 SL_RET0(_("sh_utmp_check_internal"));
1079}
1080
1081
1082static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut)
1083{
1084 if (ut)
1085 return;
1086 return;
1087}
1088
1089static void sh_utmp_logout_morechecks(struct log_user * user)
1090{
1091 if (user)
1092 return;
1093 return;
1094}
1095
1096#endif
1097
1098
1099/* #ifdef SH_USE_UTMP */
1100#endif
1101
1102
1103
Note: See TracBrowser for help on using the repository browser.