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