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