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