1 /* SAMHAIN file system integrity testing                                   */
2 /* Copyright (C) 1999, 2000 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 <string.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 
26 #if TIME_WITH_SYS_TIME
27 #include <sys/time.h>
28 #include <time.h>
29 #else
30 #if HAVE_SYS_TIME_H
31 #include <sys/time.h>
32 #else
33 #include <time.h>
34 #endif
35 #endif
36 #include <unistd.h>
37 
38 
39 #ifdef SH_WITH_SERVER
40 
41 
42 #include "samhain.h"
43 #include "sh_xfer.h"
44 #include "sh_error.h"
45 #include "sh_unix.h"
46 #include "sh_utils.h"
47 #include "sh_html.h"
48 
49 #undef  FIL__
50 #define FIL__  _("sh_html.c")
51 
52 
53 s_stat  server_status;
54 
55 
56 
57 static
replace_stat(char * line)58 char * replace_stat (char * line)
59 {
60   st_format rep_serv_tab[] = {
61     { 'T', S_FMT_TIME,  0, 0, NULL},
62     { 'S', S_FMT_TIME,  0, 0, NULL},
63     { 'L', S_FMT_TIME,  0, 0, NULL},
64     { 'O', S_FMT_ULONG, 0, 0, NULL},
65     { 'A', S_FMT_ULONG, 0, 0, NULL},
66     { 'M', S_FMT_ULONG, 0, 0, NULL},
67     {'\0', S_FMT_ULONG, 0, 0, NULL},
68   };
69 
70   rep_serv_tab[0].data_ulong = (unsigned long) time(NULL);
71   rep_serv_tab[1].data_ulong = server_status.start;
72   rep_serv_tab[2].data_ulong = server_status.last;
73   rep_serv_tab[3].data_ulong = server_status.conn_open;
74   rep_serv_tab[4].data_ulong = server_status.conn_total;
75   rep_serv_tab[5].data_ulong = server_status.conn_max;
76 
77   return (sh_util_formatted(line, rep_serv_tab));
78 }
79 
80 
81 static
sh_html_head(SL_TICKET ticket)82 int sh_html_head(SL_TICKET ticket)
83 {
84   long      status = SL_ENONE;
85   SL_TICKET fd = (-1);
86   char      line[512];
87   char      endhead[512];
88   char      outline[1024];
89   char      ts1[81];
90   char      ts2[81];
91   time_t    now;
92   struct tm   * time_ptr;
93 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
94   struct tm    time_tm;
95 #endif
96 
97   char    * formatted;
98   char    * qstr;
99 
100   char * p;
101 
102   SL_ENTER(_("sh_html_head"));
103 
104   p = sh_util_strconcat(DEFAULT_DATAROOT, _("/head.html"), NULL);
105 
106   if (p)
107     {
108       fd = sl_open_read (FIL__, __LINE__, p, SL_YESPRIV);
109       SH_FREE(p);
110     }
111 
112   if (!SL_ISERROR(fd))
113     {
114       while (!SL_ISERROR(status) && sh_unix_getline (fd, line, sizeof(line)) > 0)
115 	{
116 	  formatted = replace_stat (line);
117 	  if (formatted)
118 	    {
119 	      status = sl_write_line (ticket, formatted, sl_strlen(formatted));
120 	      SH_FREE(formatted);
121 	    }
122 	}
123       sl_close(fd);
124     }
125   else
126     {
127       qstr = sh_util_basename(DEFAULT_HTML_FILE);
128       if (qstr != NULL)
129 	{
130 	  sl_snprintf(endhead, 511,
131 		      _("<meta http-equiv=%crefresh%c content=%c120; URL=./%s%c></HEAD><BODY>"),
132 		      34, 34, 34, qstr, 34);
133 	  SH_FREE(qstr);
134 	}
135       else
136 	{
137 	  sl_snprintf(endhead, 511, _("</HEAD><BODY>"));
138 	}
139 
140       status =
141 	sl_write_line (ticket,
142 		       _("<HTML><HEAD><TITLE>Report</TITLE>"),
143 		       sizeof("<HTML><HEAD><TITLE>Report</TITLE>")-1);
144       if (!SL_ISERROR(status))
145 	status =
146 	  sl_write_line (ticket, endhead, strlen(endhead));
147       if (!SL_ISERROR(status))
148 	status =
149 	  sl_write_line (ticket,
150 			 _("<H1>Samhain Server Report</H1>"),
151 			 sizeof("<H1>Samhain Server Report</H1>")-1);
152       if (!SL_ISERROR(status))
153 	{
154 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
155 	  time_ptr   = localtime_r (&(server_status.start), &time_tm);
156 #else
157 	  time_ptr   = localtime (&(server_status.start));
158 #endif
159 	  if (time_ptr != NULL)
160 	    strftime (ts1, 80, _("%d-%m-%Y %H:%M:%S"), time_ptr);
161 	  else
162 	    sl_strlcpy(ts1, _("01-01-1970 00:00:00"), sizeof(ts1));
163 	  now = time(NULL);
164 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
165 	  time_ptr   = localtime_r (&now, &time_tm);
166 #else
167 	  time_ptr   = localtime (&now);
168 #endif
169 	  if (time_ptr != NULL)
170 	    strftime (ts2, 80, _("%d-%m-%Y %H:%M:%S"), time_ptr);
171 	  else
172 	    sl_strlcpy(ts2, _("01-01-1970 00:00:00"), sizeof(ts2));
173 
174 	  sl_snprintf(outline, 1023,
175 		      _("<p>Time:<BR>Now: %s<BR>Start: %s</p>"),
176 		      ts2, ts1);
177 	  status =
178 	    sl_write_line (ticket, outline, sl_strlen(outline));
179 	}
180       if (!SL_ISERROR(status))
181 	{
182 	  sl_snprintf(outline, 1023,
183 		      _("<p>Connections (max. %d simultaneous):"\
184 			"<BR>Now: %d<BR>Total: %ld</p>"),
185 		      server_status.conn_max,
186 		      server_status.conn_open,
187 		      server_status.conn_total);
188 	  status =
189 	    sl_write_line (ticket, outline, sl_strlen(outline));
190 	  if (server_status.last > (time_t) 0)
191 	    {
192 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
193 	      time_ptr   = localtime_r (&(server_status.last), &time_tm);
194 #else
195 	      time_ptr   = localtime (&(server_status.last));
196 #endif
197 	      if (time_ptr != NULL)
198 		strftime (ts1, 80, _("%d-%m-%Y %H:%M:%S"), time_ptr);
199 	      else
200 		sl_strlcpy(ts1, _("01-01-1970 00:00:00"), sizeof(ts1));
201 	      sl_snprintf(outline, 1023,
202 			  _("<p>Last connection at %s</p>"),
203 			  ts1);
204 	      status =
205 		sl_write_line (ticket, outline, sl_strlen(outline));
206 	    }
207 	}
208       if (!SL_ISERROR(status))
209 	status =
210 	  sl_write_line (ticket,
211 			 _("<center><table cellpadding=5 cellspacing=2 border=2>"),
212 			 sizeof("<center><table cellpadding=5 cellspacing=2 border=2>")-1);
213     }
214 
215   if (SL_ISERROR(status))
216     SL_RETURN((-1), _("sh_html_head"));
217 
218   SL_RETURN((0), _("sh_html_head"));
219 }
220 
221 static
sh_html_foot(SL_TICKET ticket)222 int sh_html_foot(SL_TICKET ticket)
223 {
224   long      status = SL_ENONE;
225   SL_TICKET fd = (-1);
226   char      line[512];
227   char * p;
228 
229   SL_ENTER(_("sh_html_foot"));
230 
231   p = sh_util_strconcat(DEFAULT_DATAROOT, _("/foot.html"), NULL);
232 
233   if (p)
234     {
235       fd = sl_open_read (FIL__, __LINE__, p, SL_YESPRIV);
236       SH_FREE(p);
237     }
238 
239   if (!SL_ISERROR(fd))
240     {
241       while (!SL_ISERROR(status) && sh_unix_getline (fd, line, sizeof(line)) > 0)
242 	{
243 	  status = sl_write_line (ticket, line, sl_strlen(line));
244 	}
245       sl_close(fd);
246     }
247   else
248     {
249       status =   sl_write_line (ticket, _("</table></center></BODY></HTML>"),
250 				sizeof("</table></center></BODY></HTML>")-1);
251     }
252   if (SL_ISERROR(status))
253     SL_RETURN((-1), _("sh_html_foot"));
254 
255   SL_RETURN((0), _("sh_html_foot"));
256 }
257 
258 
259 static
replace_tab(const char * line,char * host,char * status,char * timestamp)260 char * replace_tab (const char * line, char * host, char * status,
261 		    char * timestamp)
262 {
263   st_format rep_serv_tab[] = {
264     { 'H', S_FMT_STRING,  0, 0, NULL},
265     { 'S', S_FMT_STRING,  0, 0, NULL},
266     { 'T', S_FMT_STRING,  0, 0, NULL},
267     {'\0', S_FMT_ULONG,   0, 0, NULL},
268   };
269   char * p;
270 
271   SL_ENTER(_("replace_tab"));
272 
273   rep_serv_tab[0].data_str = host;
274   rep_serv_tab[1].data_str = status;
275   rep_serv_tab[2].data_str = timestamp;
276 
277   p = sh_util_formatted(line, rep_serv_tab);
278   SL_RETURN(p, _("replace_tab"));
279 }
280 
281 static char * entry_orig = NULL;
282 static size_t entry_size = 0;
283 
284 static
sh_html_get_entry(void)285 int sh_html_get_entry (void)
286 {
287   long      retval = SL_ENONE;
288   SL_TICKET fd = (-1);
289   char      line[512];
290   size_t    line_size;
291   size_t    add_size = 0;
292   char *    p;
293 
294   SL_ENTER(_("sh_html_get_entry"));
295 
296   p = sh_util_strconcat(DEFAULT_DATAROOT, _("/entry.html"), NULL);
297 
298   entry_size = 0;
299   if (entry_orig != NULL)
300     {
301       free (entry_orig);
302       entry_orig = NULL;
303       entry_size = 0;
304     }
305 
306   if (p)
307     {
308       fd = sl_open_read (FIL__, __LINE__, p, SL_YESPRIV);
309       SH_FREE(p);
310     }
311   if (!SL_ISERROR(fd))
312     {
313       while (!SL_ISERROR(retval) && sh_unix_getline (fd, line, sizeof(line)) > 0)
314 	{
315 	  line_size = sl_strlen(line);
316 	  add_size  = 0;
317 	  if (entry_orig != NULL)
318 	    {
319 	      char * ptr = realloc(entry_orig,           /* free() ok     */
320 				   entry_size + line_size + 1);
321 	      if (ptr) {
322 		entry_orig = ptr;
323 		add_size = line_size;
324 	      } else {
325 		{ free(entry_orig); entry_orig = NULL; }
326 	      }
327 	    }
328 	  else
329 	    {
330 	      entry_orig = calloc(1, line_size + 1);        /* free() ok     */
331 	      if (entry_orig) { entry_orig[0] = '\0'; add_size = line_size; }
332 	    }
333 	  if (!entry_orig)
334 	    {
335 	      entry_size = 0;
336 	      /* add_size   = 0; *//* never read */
337 	      SL_RETURN( 0, _("sh_html_get_entry"));
338 	    }
339 
340 	  sl_strlcat(&entry_orig[entry_size], line, line_size + 1);
341 	  entry_size += add_size;
342 	  SH_VALIDATE_EQ(entry_orig[entry_size], '\0');
343 	}
344       sl_close(fd);
345     }
346   SL_RETURN( entry_size, _("sh_html_get_entry"));
347 }
348 
349 static
sh_html_entry(SL_TICKET ticket,char * host,char * status,char * timestamp,int flag)350 int sh_html_entry (SL_TICKET ticket,
351 		   char * host, char * status, char * timestamp, int flag)
352 {
353   char      outline[1024];
354   long      retval = SL_ENONE;
355 
356   char    * formatted;
357 
358   SL_ENTER(_("sh_html_entry"));
359 
360   if (entry_size > 0 && entry_orig != NULL)
361     {
362       formatted = replace_tab(entry_orig, host, status, timestamp);
363       if (formatted)
364 	{
365 	  retval = sl_write_line (ticket, formatted, sl_strlen(formatted));
366 	  SH_FREE(formatted);
367 	}
368     }
369   else
370     {
371       sl_snprintf(outline, 1023,
372 		  _("<tr><td>%s</td><td>%s</td><td>%s</td></tr>"),
373 		  host, status, timestamp);
374       retval =  sl_write_line (ticket, outline, sl_strlen(outline));
375     }
376 
377   /* write a status line
378    */
379   if ((flag == 1) && (!SL_ISERROR(retval)))
380     {
381       sl_snprintf(outline, 1023,
382 		  _("<!-- \n[STATUS:] %s %s %s\n -->"),
383 		  host, status, timestamp);
384       retval =  sl_write_line (ticket, outline, sl_strlen(outline));
385     }
386 
387   if (SL_ISERROR(retval))
388     SL_RETURN((-1), _("sh_html_entry"));
389 
390   SL_RETURN((0), _("sh_html_entry"));
391 }
392 
393 typedef struct _sort_arr {
394   char msg[TIM_MAX];
395   char tim[TIM_MAX];
396 } sort_arr;
397 
398 static sort_arr sort_stat[CLT_MAX];
399 
400 static
comp_arr(const void * ao,const void * bo)401 int comp_arr (const void * ao, const void * bo)
402 {
403   const sort_arr * a;
404   const sort_arr * b;
405 
406   if (ao == NULL && bo == NULL)
407     return 0;
408   else if (ao == NULL && bo != NULL)
409     return (-1);
410   else if (ao != NULL && bo == NULL)
411     return (1);
412 
413   a = (const sort_arr *) ao;
414   b = (const sort_arr *) bo;
415 
416   return ((-1) * sl_strcmp(a->tim, b->tim));
417 }
418 
419 static
sh_html_print_one(SL_TICKET ticket,client_t * top)420 int sh_html_print_one (SL_TICKET ticket, client_t   * top)
421 {
422   int status;
423   int clt_status;
424   unsigned int i, n;
425 
426   SL_ENTER(_("sh_html_print_one"));
427 
428   if (top == NULL)
429     SL_RETURN((0), _("sh_html_print_one"));
430 
431   clt_status = top->status_now;
432   status = sh_html_entry (ticket,
433 			  top->hostname,
434 			  _(clt_stat[clt_status]),
435 			  top->timestamp[clt_status],
436 			  1);
437 
438   n = 0;
439 
440   if (clt_status != CLT_INACTIVE)
441     {
442       for (i = 1; i < CLT_MAX; ++i)
443 	{
444 	  if (top->status_arr[i] != CLT_INACTIVE)
445 	    {
446 	      clt_status = top->status_arr[i];
447 	      sl_strlcpy(sort_stat[n].msg, _(clt_stat[clt_status]),  TIM_MAX);
448 	      sl_strlcpy(sort_stat[n].tim, top->timestamp[clt_status],TIM_MAX);
449 	      ++n;
450 	    }
451 	}
452     }
453 
454   if (n > 0)
455     {
456       qsort(&(sort_stat[0]), n, sizeof(sort_arr), comp_arr);
457 
458       for (i = 1; i < n; ++i)
459 	{
460 	  status = sh_html_entry (ticket,
461 				  " ",
462 				  sort_stat[i].msg,
463 				  sort_stat[i].tim,
464 				  0);
465 	}
466     }
467 
468   if (SL_ISERROR(status))
469     SL_RETURN((-1), _("sh_html_print_one"));
470 
471   SL_RETURN((0), _("sh_html_print_one"));
472 }
473 
474 #include "zAVLTree.h"
475 
sh_html_write(void * inptr)476 int sh_html_write(void  * inptr)
477 {
478   long fd;
479   zAVLCursor avlcursor;
480   client_t * item;
481   zAVLTree * top = (zAVLTree *) inptr;
482 
483   SL_ENTER(_("sh_html_write"));
484 
485   if (0 != (fd = tf_trust_check (DEFAULT_HTML_FILE, SL_YESPRIV)))
486     {
487       sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_TRUST,
488 		      (long) sh.effective.uid,
489 		      DEFAULT_HTML_FILE);
490       SL_RETURN((-1), _("sh_html_write"));
491     }
492 
493 
494   fd = sl_open_write_trunc (FIL__, __LINE__, DEFAULT_HTML_FILE, SL_YESPRIV);
495 
496   if (SL_ISERROR(fd))
497     {
498       sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS,
499 		      (long) sh.effective.uid,
500 		      DEFAULT_HTML_FILE);
501       SL_RETURN((-1), _("sh_html_write"));
502     }
503 
504   sh_html_get_entry();
505 
506   sh_html_head(fd);
507   for (item = (client_t *) zAVLFirst(&avlcursor, top); item;
508        item = (client_t *) zAVLNext(&avlcursor))
509     sh_html_print_one (fd, item);
510   sh_html_foot(fd);
511   sl_close(fd);
512 
513   SL_RETURN((0), _("sh_html_write"));
514 }
515 
sh_html_zero()516 int sh_html_zero()
517 {
518   long fd;
519 
520   SL_ENTER(_("sh_html_zero"));
521 
522   if (0 != (fd = tf_trust_check (DEFAULT_HTML_FILE, SL_YESPRIV)))
523     {
524       SL_RETURN((-1), _("sh_html_zero"));
525     }
526 
527   fd = sl_open_write_trunc (FIL__, __LINE__, DEFAULT_HTML_FILE, SL_YESPRIV);
528 
529   if (SL_ISERROR(fd))
530     {
531      SL_RETURN((-1), _("sh_html_zero"));
532     }
533 
534   sh_html_head(fd);
535   sh_html_foot(fd);
536 
537   sl_close(fd);
538 
539   SL_RETURN((0), _("sh_html_zero"));
540 }
541 
542 /* SH_WITH_SERVER */
543 #endif
544 
545 
546 
547 
548 
549 
550 
551 
552 
553 
554 
555 
556 
557 
558 
559