source: trunk/src/sh_utmp.c@ 254

Last change on this file since 254 was 252, checked in by katerina, 15 years ago

Add code to check for stale file records on close() and fclose(), fix sl_close() to handle open stream (ticket #163).

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