source: trunk/src/sh_login_track.c@ 570

Last change on this file since 570 was 562, checked in by katerina, 3 years ago

Fix for ticket #450 (compiler warnings) and fixes for tests.

File size: 38.3 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2010 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#undef FIL__
23#define FIL__ _("sh_login_track.c")
24
25#if defined(SH_USE_UTMP) && (defined(SH_WITH_CLIENT) || defined (SH_STANDALONE))
26
27#include <string.h>
28
29#include "samhain.h"
30#include "sh_pthread.h"
31#include "sh_utils.h"
32#include "sh_unix.h"
33#include "sh_string.h"
34#include "sh_tools.h"
35#include "sh_ipvx.h"
36#include "sh_error_min.h"
37
38#ifdef HAVE_UTMPX_H
39
40#include <utmpx.h>
41#define SH_UTMP_S utmpx
42#undef ut_name
43#define ut_name ut_user
44#ifdef HAVE_UTXTIME
45#undef ut_time
46#define ut_time ut_xtime
47#else
48#undef ut_time
49#define ut_time ut_tv.tv_sec
50#endif
51
52#else
53
54#include <utmp.h>
55#define SH_UTMP_S utmp
56
57#endif
58
59
60#if TIME_WITH_SYS_TIME
61#include <sys/time.h>
62#include <time.h>
63#else
64#if HAVE_SYS_TIME_H
65#include <sys/time.h>
66#else
67#include <time.h>
68#endif
69#endif
70
71
72#define SH_LTRACK_VERSION 1
73
74#define SH_LTRACK_USIZE 32
75#define SH_LTRACK_HSIZE 256
76/* One hour (15 deg) */
77#define SH_LTRACK_HTRES 24
78/* Ten minutes (2.5 deg) */
79#define SH_LTRACK_GTRES 144
80
81/* Avoid compiling against lmath by including result tables for sin, cos
82 */
83const double sintab_htres[SH_LTRACK_HTRES] = {
84 0.13052619222005157340, 0.38268343236508978178, 0.60876142900872065589, 0.79335334029123516508, 0.92387953251128673848, 0.99144486137381038215,
85 0.99144486137381038215, 0.92387953251128673848, 0.79335334029123516508, 0.60876142900872087793, 0.38268343236508989280, 0.13052619222005157340,
86-0.13052619222005132360, -0.38268343236508967076, -0.60876142900872065589, -0.79335334029123494304, -0.92387953251128651644, -0.99144486137381038215,
87-0.99144486137381049318, -0.92387953251128662746, -0.79335334029123516508, -0.60876142900872087793, -0.38268343236509039240, -0.13052619222005168442,
88};
89const double costab_htres[SH_LTRACK_HTRES] = {
90 0.99144486137381038215, 0.92387953251128673848, 0.79335334029123516508, 0.60876142900872065589, 0.38268343236508983729, 0.13052619222005171218,
91-0.13052619222005160116, -0.38268343236508972627, -0.60876142900872065589, -0.79335334029123505406, -0.92387953251128673848, -0.99144486137381038215,
92-0.99144486137381049318, -0.92387953251128684951, -0.79335334029123516508, -0.60876142900872087793, -0.38268343236509033689, -0.13052619222005162891,
93 0.13052619222005126809, 0.38268343236509000382, 0.60876142900872054486, 0.79335334029123494304, 0.92387953251128651644, 0.99144486137381038215,
94};
95const double sintab_gtres[SH_LTRACK_GTRES] = {
96 0.02181488503456112046, 0.06540312923014306168, 0.10886687485196457070, 0.15212338618991669281, 0.19509032201612824808, 0.23768589232617309825,
97 0.27982901403099208482, 0.32143946530316158672, 0.36243803828370163567, 0.40274668985873718352, 0.44228869021900124592, 0.48098876891938763256,
98 0.51877325816052144436, 0.55557023301960217765, 0.59130964836358235193, 0.62592347218405908205, 0.65934581510006884386, 0.69151305578226940352,
99 0.72236396205975550444, 0.75183980747897738439, 0.77988448309288171956, 0.80644460426748254545, 0.83146961230254523567, 0.85491187067294649449,
100 0.87672675570750768781, 0.89687274153268836674, 0.91531147911944710227, 0.93200786928279844012, 0.94693012949510557696, 0.96004985438592871372,
101 0.97134206981326143282, 0.98078528040323043058, 0.98836151046776066220, 0.99405633822231964647, 0.99785892323860347908, 0.99976202707990913243,
102 0.99976202707990913243, 0.99785892323860347908, 0.99405633822231964647, 0.98836151046776066220, 0.98078528040323043058, 0.97134206981326143282,
103 0.96004985438592871372, 0.94693012949510568799, 0.93200786928279855115, 0.91531147911944721329, 0.89687274153268836674, 0.87672675570750779883,
104 0.85491187067294671653, 0.83146961230254545772, 0.80644460426748254545, 0.77988448309288183058, 0.75183980747897738439, 0.72236396205975561546,
105 0.69151305578226951454, 0.65934581510006895488, 0.62592347218405919307, 0.59130964836358257397, 0.55557023301960217765, 0.51877325816052133334,
106 0.48098876891938763256, 0.44228869021900130143, 0.40274668985873729454, 0.36243803828370174669, 0.32143946530316175325, 0.27982901403099230686,
107 0.23768589232617337581, 0.19509032201612860891, 0.15212338618991663730, 0.10886687485196457070, 0.06540312923014311719, 0.02181488503456121761,
108-0.02181488503456097475, -0.06540312923014286739, -0.10886687485196432090, -0.15212338618991641526, -0.19509032201612835911, -0.23768589232617312601,
109-0.27982901403099202930, -0.32143946530316153121, -0.36243803828370152464, -0.40274668985873707250, -0.44228869021900107938, -0.48098876891938741052,
110-0.51877325816052122232, -0.55557023301960195560, -0.59130964836358235193, -0.62592347218405908205, -0.65934581510006884386, -0.69151305578226929249,
111-0.72236396205975550444, -0.75183980747897727337, -0.77988448309288194160, -0.80644460426748265647, -0.83146961230254523567, -0.85491187067294660551,
112-0.87672675570750768781, -0.89687274153268825572, -0.91531147911944710227, -0.93200786928279844012, -0.94693012949510557696, -0.96004985438592860270,
113-0.97134206981326132180, -0.98078528040323031956, -0.98836151046776066220, -0.99405633822231953545, -0.99785892323860347908, -0.99976202707990913243,
114-0.99976202707990913243, -0.99785892323860347908, -0.99405633822231964647, -0.98836151046776066220, -0.98078528040323043058, -0.97134206981326143282,
115-0.96004985438592871372, -0.94693012949510568799, -0.93200786928279855115, -0.91531147911944721329, -0.89687274153268847776, -0.87672675570750790985,
116-0.85491187067294682755, -0.83146961230254545772, -0.80644460426748287851, -0.77988448309288216365, -0.75183980747897782848, -0.72236396205975605955,
117-0.69151305578226918147, -0.65934581510006873284, -0.62592347218405897102, -0.59130964836358235193, -0.55557023301960217765, -0.51877325816052144436,
118-0.48098876891938774358, -0.44228869021900141245, -0.40274668985873740557, -0.36243803828370185771, -0.32143946530316186427, -0.27982901403099241788,
119-0.23768589232617348683, -0.19509032201612871993, -0.15212338618991719241, -0.10886687485196513969, -0.06540312923014367230, -0.02181488503456178660
120};
121const double costab_gtres[SH_LTRACK_GTRES] = {
122 0.99976202707990913243, 0.99785892323860347908, 0.99405633822231964647, 0.98836151046776066220, 0.98078528040323043058, 0.97134206981326143282,
123 0.96004985438592871372, 0.94693012949510568799, 0.93200786928279855115, 0.91531147911944721329, 0.89687274153268836674, 0.87672675570750768781,
124 0.85491187067294660551, 0.83146961230254523567, 0.80644460426748265647, 0.77988448309288183058, 0.75183980747897738439, 0.72236396205975561546,
125 0.69151305578226940352, 0.65934581510006884386, 0.62592347218405908205, 0.59130964836358235193, 0.55557023301960228867, 0.51877325816052155538,
126 0.48098876891938774358, 0.44228869021900124592, 0.40274668985873723903, 0.36243803828370169118, 0.32143946530316169774, 0.27982901403099202930,
127 0.23768589232617309825, 0.19509032201612833135, 0.15212338618991680383, 0.10886687485196473724, 0.06540312923014304780, 0.02181488503456115863,
128-0.02181488503456103373, -0.06540312923014292290, -0.10886687485196461234, -0.15212338618991669281, -0.19509032201612819257, -0.23768589232617298723,
129-0.27982901403099191828, -0.32143946530316158672, -0.36243803828370158016, -0.40274668985873712801, -0.44228869021900113490, -0.48098876891938746603,
130-0.51877325816052122232, -0.55557023301960195560, -0.59130964836358246295, -0.62592347218405908205, -0.65934581510006884386, -0.69151305578226929249,
131-0.72236396205975550444, -0.75183980747897727337, -0.77988448309288160853, -0.80644460426748243442, -0.83146961230254534669, -0.85491187067294660551,
132-0.87672675570750768781, -0.89687274153268825572, -0.91531147911944710227, -0.93200786928279844012, -0.94693012949510557696, -0.96004985438592860270,
133-0.97134206981326132180, -0.98078528040323043058, -0.98836151046776066220, -0.99405633822231964647, -0.99785892323860347908, -0.99976202707990913243,
134-0.99976202707990913243, -0.99785892323860347908, -0.99405633822231964647, -0.98836151046776077322, -0.98078528040323043058, -0.97134206981326143282,
135-0.96004985438592871372, -0.94693012949510568799, -0.93200786928279855115, -0.91531147911944721329, -0.89687274153268836674, -0.87672675570750779883,
136-0.85491187067294671653, -0.83146961230254545772, -0.80644460426748254545, -0.77988448309288183058, -0.75183980747897749541, -0.72236396205975561546,
137-0.69151305578226951454, -0.65934581510006906591, -0.62592347218405897102, -0.59130964836358224090, -0.55557023301960217765, -0.51877325816052144436,
138-0.48098876891938768807, -0.44228869021900135694, -0.40274668985873735005, -0.36243803828370180220, -0.32143946530316180876, -0.27982901403099236237,
139-0.23768589232617343132, -0.19509032201612866442, -0.15212338618991713690, -0.10886687485196507030, -0.06540312923014361679, -0.02181488503456172415,
140 0.02181488503456135639, 0.06540312923014325597, 0.10886687485196470948, 0.15212338618991677608, 0.19509032201612830359, 0.23768589232617307050,
141 0.27982901403099197379, 0.32143946530316147570, 0.36243803828370146913, 0.40274668985873701699, 0.44228869021900102387, 0.48098876891938735501,
142 0.51877325816052111129, 0.55557023301960184458, 0.59130964836358201886, 0.62592347218405863796, 0.65934581510006839977, 0.69151305578226895943,
143 0.72236396205975572649, 0.75183980747897749541, 0.77988448309288183058, 0.80644460426748254545, 0.83146961230254523567, 0.85491187067294660551,
144 0.87672675570750768781, 0.89687274153268825572, 0.91531147911944710227, 0.93200786928279844012, 0.94693012949510557696, 0.96004985438592860270,
145 0.97134206981326132180, 0.98078528040323031956, 0.98836151046776066220, 0.99405633822231953545, 0.99785892323860347908, 0.99976202707990913243
146};
147
148struct sh_track_entry_data {
149 UINT64 last_login;
150 UINT32 array[SH_LTRACK_HTRES]; /* 1 h resolution */
151 char hostname[SH_LTRACK_HSIZE];
152};
153
154struct sh_track_entry {
155 struct sh_track_entry_data data;
156 struct sh_track_entry * next;
157};
158
159struct sh_track_head {
160 UINT32 version;
161 UINT32 n_entries;
162 UINT64 last_login;
163 char hostname[SH_LTRACK_HSIZE];
164 UINT32 array[SH_LTRACK_GTRES]; /* 10 min resolution */
165};
166
167struct sh_track {
168 struct sh_track_head head;
169 struct sh_track_entry * list;
170};
171
172
173/* Returns zero/nonzero
174 */
175static int get_bool(char *bitarray, unsigned int index)
176{
177 int bool;
178
179 bitarray += index / 8; /* skip to char */
180 bool = (*bitarray & (1 << (index % 8)));
181
182 return bool;
183}
184
185static void set_bool(char *bitarray, unsigned int index, int bool)
186{
187 bitarray += index / 8; /* skip to char */
188 if (bool)
189 *bitarray |= 1 << (index % 8);
190 else
191 *bitarray &= ~(1 << (index % 8));
192 return;
193}
194
195
196static char * build_path (const char * user)
197{
198 char * ui;
199
200 if (0 != sh_util_base64_enc_alloc (&ui, user, sl_strlen(user)))
201 {
202 char * path = sh_util_strconcat(DEFAULT_DATAROOT, "/", ui, NULL);
203
204 SH_FREE(ui);
205 return path;
206 }
207 return NULL;
208}
209
210static void destroy_loaded(struct sh_track * urecord)
211{
212 if (urecord)
213 {
214 struct sh_track_entry * entry = urecord->list;
215 struct sh_track_entry * entry_old;
216
217 while(entry)
218 {
219 entry_old = entry;
220 entry = entry->next;
221 SH_FREE(entry_old);
222 }
223 SH_FREE(urecord);
224 }
225 return;
226}
227
228static struct sh_track * load_data_int (char * path)
229{
230 struct sh_track_head * uhead;
231 struct sh_track * urecord;
232
233 urecord = SH_ALLOC(sizeof(struct sh_track));
234 memset(urecord, 0, sizeof(struct sh_track));
235
236 uhead = &(urecord->head);
237 uhead->version = SH_LTRACK_VERSION;
238
239 if (path)
240 {
241 FILE * fp = fopen(path, "rb");
242
243 if (fp)
244 {
245 size_t n;
246
247 n = fread(uhead, sizeof(struct sh_track_head), 1, fp);
248
249 if (n == 1)
250 {
251 struct sh_track_entry_data entry_data;
252 struct sh_track_entry * entry;
253
254 while (1 == fread(&entry_data, sizeof(entry_data), 1, fp))
255 {
256 entry = SH_ALLOC(sizeof(struct sh_track_entry));
257 memcpy(&(entry->data), &entry_data, sizeof(entry_data));
258 entry->next = urecord->list;
259 urecord->list = entry;
260 }
261 }
262 fclose(fp);
263 }
264 }
265
266 return urecord;
267}
268
269static struct sh_track * load_data (const char * user)
270{
271 char * path = build_path (user);
272 struct sh_track * res = load_data_int (path);
273
274 if (path)
275 SH_FREE(path);
276 return res;
277}
278
279static void save_data_int (struct sh_track * urecord, char * path)
280{
281 mode_t mask;
282 FILE * fp;
283
284 mask = umask(S_IWGRP | S_IWOTH);
285 fp = fopen(path, "wb");
286 (void) umask(mask);
287
288 if (fp)
289 {
290 size_t n;
291
292 n = fwrite(&(urecord->head), sizeof(struct sh_track_head), 1, fp);
293
294 if (n == 1)
295 {
296 struct sh_track_entry * entry = urecord->list;
297
298 while (entry && (n > 0))
299 {
300 n = fwrite(&(entry->data), sizeof(struct sh_track_entry_data),
301 1, fp);
302 entry = entry->next;
303 }
304 }
305 fclose(fp);
306 }
307 return;
308}
309
310static void save_data (struct sh_track * urecord, const char * user)
311{
312 char * path = build_path (user);
313
314 if (path)
315 {
316 save_data_int (urecord, path);
317 SH_FREE(path);
318 }
319 return;
320}
321
322/**************
323 *
324 * Configurable
325 *
326 **************/
327
328enum significance { SIG00, SIG01, SIG05 };
329enum checklevel { CHECK_NONE, CHECK_HOST, CHECK_DOMAIN };
330enum days { WORKDAYS = 0, SATURDAY, SUNDAY };
331#define LTRACK_NDAYS 3
332
333static int sig_level = SIG00;
334static int check_level = CHECK_NONE;
335static int check_date = S_FALSE;
336
337/* We use a bit array of SH_LTRACK_GTRES bits for allowed times
338 * (10 min resolution)
339 */
340#define BITARRSIZ(a) ((a + 7) / 8)
341
342static int global_init = S_FALSE;
343static char global_dates[LTRACK_NDAYS][BITARRSIZ(SH_LTRACK_GTRES)];
344
345struct sh_track_dates {
346 char user[SH_LTRACK_USIZE];
347 char dates[LTRACK_NDAYS][BITARRSIZ(SH_LTRACK_GTRES)];
348 struct sh_track_dates * next;
349};
350struct sh_track_dates * user_dates = NULL;
351
352static int set_dates (char bitarray[][BITARRSIZ(SH_LTRACK_GTRES)],
353 unsigned int size, const char * defstr);
354
355void sh_login_reset (void)
356{
357 int i, j;
358 struct sh_track_dates *u_old, *u;
359
360 u = user_dates;
361 user_dates = NULL;
362
363 while(u)
364 {
365 u_old = u;
366 u = u->next;
367 SH_FREE(u_old);
368 }
369
370 for (j = 0; j < LTRACK_NDAYS; ++j)
371 {
372 for (i = 0; i < SH_LTRACK_GTRES; ++i)
373 {
374 set_bool(global_dates[j], i, 0);
375 }
376 }
377 global_init = S_FALSE;
378
379 sig_level = SIG00;
380 check_level = CHECK_NONE;
381 check_date = S_FALSE;
382
383 return;
384}
385
386int sh_login_set_def_allow(const char * c)
387{
388 int res = set_dates(global_dates, SH_LTRACK_GTRES, c);
389
390 if (res == 0)
391 {
392 check_date = S_TRUE;
393 global_init = S_TRUE;
394 }
395 return res;
396}
397
398static struct sh_track_dates * find_user(const char * user)
399{
400 struct sh_track_dates * u = user_dates;
401
402 while(u)
403 {
404 if (0 == sl_strcmp(user, u->user))
405 {
406 return u;
407 }
408 u = u->next;
409 }
410 return NULL;
411}
412
413int sh_login_set_user_allow(const char * c)
414{
415 unsigned int i = 0;
416 const char *p = c;
417 char user[SH_LTRACK_USIZE];
418
419 struct sh_track_dates * u;
420
421 while (p && *p && *p != ':' && *p != ' ' && *p != '\t')
422 {
423 user[i] = *p; ++p; ++i;
424
425 if (i == SH_LTRACK_USIZE)
426 return -1;
427 }
428
429 while (p && *p && (*p == ' ' || *p == '\t')) ++p;
430
431 if (p && *p && (i < SH_LTRACK_USIZE) && (*p == ':'))
432 {
433 user[i] = '\0';
434
435 ++p; while (*p && (*p == ' ' || *p == '\t')) ++p;
436
437 if (*p)
438 {
439 int res;
440 int flag = 0;
441
442 u = find_user(user);
443
444 if (!u)
445 {
446 u = SH_ALLOC(sizeof(struct sh_track_dates));
447 memset(u, 0, sizeof(struct sh_track_dates));
448 sl_strlcpy(u->user, user, SH_LTRACK_USIZE);
449 flag = 1;
450 }
451
452 res = set_dates(u->dates, SH_LTRACK_GTRES, p);
453 if (res != 0)
454 {
455 if (flag == 1)
456 SH_FREE(u);
457 return -1;
458 }
459
460 if (flag == 1)
461 {
462 u->next = user_dates;
463 user_dates = u;
464 }
465
466 check_date = S_TRUE;
467 return 0;
468 }
469 }
470 return -1;
471}
472
473int sh_login_set_siglevel(const char * c)
474{
475 int ret = sh_util_flagval(c, &sig_level);
476
477 if (ret == 0)
478 {
479 sig_level = (sig_level == S_FALSE) ? SIG00 : SIG01;
480 return 0;
481 }
482 else
483 {
484 if (0 == strcmp(c, _("paranoid")))
485 {
486 sig_level = SIG05;
487 return 0;
488 }
489 }
490 sig_level = SIG00;
491 return -1;
492}
493
494int sh_login_set_checklevel(const char * c)
495{
496 int ret = sh_util_flagval(c, &check_level);
497
498 if (ret == 0)
499 {
500 check_level = (check_level == S_FALSE) ? CHECK_NONE : CHECK_HOST;
501 return 0;
502 }
503 else
504 {
505 if (0 == strcmp(c, _("domain")))
506 {
507 check_level = CHECK_DOMAIN;
508 return 0;
509 }
510 }
511 check_level = CHECK_NONE;
512 return -1;
513}
514
515static int eval_range(char * bitarray, unsigned int size, char * def)
516{
517 unsigned int h1, m1, h2, m2;
518
519 int res = sscanf(def, "%d:%d - %d:%d", &h1, &m1, &h2, &m2);
520
521 if (res == 4)
522 {
523 unsigned int t1 = 3600*h1 + 60*m1;
524 unsigned int t2 = 3600*h2 + 60*m2;
525 int hres = (60*60*24)/size;
526 unsigned int i;
527
528 if (t1 > t2 || t1 > 86340 || t2 > 86340)
529 return -1;
530
531 t1 = t1 / hres;
532 t2 = t2 / hres;
533 t1 = (t1 < size) ? t1 : (size-1);
534 t2 = (t2 < size) ? t2 : (size-1);
535
536 for (i = t1; i <= t2; ++i)
537 {
538 set_bool(bitarray, i, 1);
539 }
540 return 0;
541 }
542 return -1;
543}
544
545static int set_ranges(char * bitarray, unsigned int size,
546 char ** splits, unsigned int nfields)
547{
548 unsigned int i;
549 int retval = 0;
550
551 for (i = 0; i < nfields; ++i)
552 {
553 char * range = &(splits[i][0]);
554
555 if (0 != eval_range(bitarray, size, range))
556 retval = -1;
557 }
558 return retval;
559}
560
561/* 'always', 'never', workdays(list of ranges), (sun|satur)day(list of ranges)
562 */
563static int set_dates (char bitarray[][BITARRSIZ(SH_LTRACK_GTRES)],
564 unsigned int size,
565 const char * defstr)
566{
567 unsigned int i, j;
568 int retval = -1;
569
570 if (0 == strcmp(_("always"), defstr))
571 {
572 for (j = 0; j < LTRACK_NDAYS; ++j)
573 for (i = 0; i < size; ++i)
574 set_bool(bitarray[j], i, 1);
575 retval = 0;
576 }
577 else if (0 == strcmp(_("never"), defstr))
578 {
579 for (j = 0; j < LTRACK_NDAYS; ++j)
580 for (i = 0; i < size; ++i)
581 set_bool(bitarray[j], i, 0);
582 retval = 0;
583 }
584 else
585 {
586 unsigned int nfields = 24; /* list of ranges */
587 size_t lengths[24];
588 char * new = NULL;
589 char ** splits = NULL;
590
591 if (0 == strncmp(_("workdays"), defstr, 7))
592 {
593 new = sh_util_strdup(defstr);
594 splits = split_array_braced(new, _("workdays"),
595 &nfields, lengths);
596 j = WORKDAYS;
597 }
598 else if (0 == strncmp(_("saturday"), defstr, 8))
599 {
600 new = sh_util_strdup(defstr);
601 splits = split_array_braced(new, _("saturday"),
602 &nfields, lengths);
603 j = SATURDAY;
604 }
605 else if (0 == strncmp(_("sunday"), defstr, 6))
606 {
607 new = sh_util_strdup(defstr);
608 splits = split_array_braced(new, _("sunday"),
609 &nfields, lengths);
610 j = SUNDAY;
611 }
612 else
613 {
614 return -1;
615 }
616
617 if (new && splits && nfields > 0)
618 {
619 retval = set_ranges(bitarray[j], size, splits, nfields);
620 }
621
622 if (new) SH_FREE(new);
623 }
624 return retval;
625}
626
627
628
629/**************
630 *
631 * Report
632 *
633 **************/
634
635void report_generic(char * file, int line,
636 const char * user, time_t time, const char * host, int what)
637{
638 char ttt[TIM_MAX];
639
640 SH_MUTEX_LOCK(mutex_thread_nolog);
641 (void) sh_unix_time (time, ttt, TIM_MAX);
642 sh_error_handle ((-1), file, line, 0, what,
643 user, host, ttt);
644 SH_MUTEX_UNLOCK(mutex_thread_nolog);
645 return;
646}
647
648void report_bad_date(char * file, int line,
649 const char *user, time_t time, const char * host)
650{
651 report_generic(file, line, user, time, host, MSG_UT_BAD);
652}
653
654void report_first(char * file, int line,
655 const char *user, time_t time, const char * host)
656{
657 report_generic(file, line, user, time, host, MSG_UT_FIRST);
658}
659
660void report_outlier(char * file, int line,
661 const char *user, time_t time, const char * host)
662{
663 report_generic(file, line, user, time, host, MSG_UT_OUTLIER);
664}
665
666/**************
667 *
668 * Dates
669 *
670 **************/
671
672static int check_login_date(const char * user, unsigned int index, int wday)
673{
674 unsigned int i, j;
675 struct sh_track_dates * allowed = NULL;
676 int day;
677
678 /* Use an intermediate array 'char* b[m]' to cast 'char a[m][n]' to 'char** c' */
679 char * aux[LTRACK_NDAYS];
680 char **good = (char **) aux;
681
682 for (i = 0; i < LTRACK_NDAYS; ++i)
683 {
684 aux[i] = (char *) &global_dates[i][0];
685 /* + i * BITARRSIZ(SH_LTRACK_GTRES); */
686 }
687
688 if (wday > 0 && wday < 6)
689 day = WORKDAYS;
690 else if (wday == 6)
691 day = SATURDAY;
692 else
693 day = SUNDAY;
694
695 if (check_date != S_FALSE)
696 {
697 if (S_FALSE == global_init)
698 {
699 for (j = 0; j < LTRACK_NDAYS; ++j)
700 {
701 for (i = 0; i < SH_LTRACK_GTRES; ++i)
702 set_bool(global_dates[j], i, 1);
703 }
704 global_init = S_TRUE;
705 }
706
707 if (user) {
708 allowed = find_user(user);
709 }
710
711 if (allowed)
712 {
713 for (i = 0; i < LTRACK_NDAYS; ++i)
714 {
715 aux[i] = (char *)&(allowed->dates)[i][0];
716 /* + i*BITARRSIZ(SH_LTRACK_GTRES); */
717 }
718 }
719
720 if (0 == get_bool(good[day], index))
721 {
722 return -1;
723 }
724 }
725 return 0;
726}
727
728/**************
729 *
730 * Statistics
731 *
732 **************/
733
734/* Compute sqrt(s) using the babylonian algorithm
735 * (to avoid linking with -lm).
736 */
737static double sh_sqrt(double s)
738{
739 double eps = 1.0e-6;
740 double x0 = 1.0;
741 double xs = s;
742
743 double diff = xs - x0;
744 diff = (diff > 0.0) ? diff : -diff;
745
746 while (diff > eps)
747 {
748 xs = x0;
749 x0 = 0.5 * (x0 + (s/x0));
750 diff = xs - x0;
751 diff = (diff > 0.0) ? diff : -diff;
752 }
753 return x0;
754}
755
756static double M_crit(int n, int flag)
757{
758#define SH_MCSIZE 10
759 const double M_05[SH_MCSIZE] = { 0.975, 0.918, 0.855, 0.794, 0.739, 0.690, 0.647, 0.577, 0.497, 0.406 };
760 const double M_01[SH_MCSIZE] = { 0.995, 0.970, 0.934, 0.891, 0.845, 0.799, 0.760, 0.688, 0.603, 0.498 };
761 const int M_nn[SH_MCSIZE] = { 4, 5, 6, 7, 8, 9, 10, 12, 15, 20 };
762
763 if (n > M_nn[SH_MCSIZE-1])
764 {
765 return ((flag == SIG05) ? M_05[SH_MCSIZE-1] : M_01[SH_MCSIZE-1]);
766 }
767 else
768 {
769 unsigned int i;
770
771 for (i = 1; i < SH_MCSIZE; ++i)
772 {
773 if (n < M_nn[i])
774 {
775 return ((flag == SIG05) ? M_05[i-1] : M_01[i-1]);
776 }
777 }
778 }
779
780 return ((flag == SIG05) ? M_05[SH_MCSIZE-1] : M_01[SH_MCSIZE-1]);
781}
782
783static int check_statistics (unsigned int index, UINT32 * array, unsigned int size,
784 const double * costab, const double * sintab)
785{
786 double C = 0.0;
787 double S = 0.0;
788 double R, Rk, M;
789
790 unsigned int i, n = 0;
791
792 if (sig_level != SIG00)
793 {
794 for (i = 0; i < size; ++i)
795 {
796 n += array[i];
797 C += (array[i] * costab[i]);
798 S += (array[i] * sintab[i]);
799 }
800
801 if (n > 2) /* current is at least 4th datapoint */
802 {
803 R = sh_sqrt(S*S + C*C);
804
805 C += array[index] * costab[index];
806 S += array[index] * sintab[index];
807 Rk = sh_sqrt(S*S + C*C);
808 ++n;
809
810 M = (Rk - R + 1.0)/((double)n - R);
811
812 if (M > M_crit(n, sig_level))
813 {
814 return -1;
815 }
816 }
817 }
818 return 0;
819}
820
821static char * stripped_hostname (const char * host)
822{
823 char *p, *q;
824
825 if (sh_ipvx_is_numeric(host))
826 {
827 p = sh_util_strdup(host);
828 q = strrchr(p, '.');
829 if (q)
830 {
831 *q = '\0';
832 q = strrchr(p, '.');
833 if (q)
834 {
835 *q = '\0';
836 }
837 }
838 }
839 else
840 {
841 char * tmp = sh_util_strdup(host);
842 q = strchr(tmp, '.');
843 if (q && *q)
844 {
845 ++q;
846 p = sh_util_strdup(q);
847 SH_FREE(tmp);
848 }
849 else
850 {
851 p = tmp;
852 }
853 }
854 return p;
855}
856
857static unsigned int time_to_index(struct tm * tp, int nbin)
858{
859 int hres = (60*60*24)/nbin;
860 int index = tp->tm_hour * 3600 + tp->tm_min * 60 + tp->tm_sec;
861 index = index / hres;
862 index = (index < nbin) ? index : (nbin-1);
863
864 return index;
865}
866
867static struct sh_track_entry * check_host(struct sh_track_entry * list,
868 const char * user, time_t time, const char * host,
869 struct tm * tp)
870{
871 unsigned int index = time_to_index(tp, SH_LTRACK_HTRES);
872 struct sh_track_entry * entry = list;
873
874 char * p = NULL;
875 const char * q;
876
877 if (check_level == CHECK_DOMAIN)
878 {
879 p = stripped_hostname(host);
880 q = p;
881 }
882 else
883 {
884 q = host;
885 }
886
887 while (entry)
888 {
889 if (0 == strncmp(q, (entry->data).hostname, SH_LTRACK_HSIZE))
890 break;
891 entry = entry->next;
892 }
893
894 if (entry)
895 {
896 int isAlert;
897
898 (entry->data).last_login = time;
899
900 /* Check host statistics here
901 */
902 isAlert = check_statistics (index, (entry->data).array, SH_LTRACK_HTRES,
903 costab_htres, sintab_htres);
904
905 if (isAlert != 0)
906 {
907 report_outlier(FIL__, __LINE__, user, time, host);
908 }
909
910 /* Update array afterwards
911 */
912 (entry->data).array[index] += 1;
913 }
914 else
915 {
916 entry = SH_ALLOC(sizeof(struct sh_track_entry));
917 memset(entry, 0, sizeof(struct sh_track_entry));
918 (entry->data).last_login = time;
919 (entry->data).array[index] = 1;
920 sl_strlcpy((entry->data).hostname, q, SH_LTRACK_HSIZE);
921
922 /* Report first login from this host
923 */
924 if (check_level != CHECK_NONE)
925 {
926 report_first (FIL__, __LINE__, user, time, host);
927 }
928
929 if (p)
930 SH_FREE(p);
931 return entry;
932 }
933
934 if (p)
935 SH_FREE(p);
936 return NULL;
937}
938
939/********************************************************
940 *
941 * Public Function
942 *
943 ********************************************************/
944
945void sh_ltrack_check(struct SH_UTMP_S * ut)
946{
947 int gres;
948 const char * user;
949 time_t time;
950#if defined(HAVE_UTHOST)
951 const char * host;
952#else
953 const char * host;
954#endif
955 struct sh_track * urecord;
956 time_t last_login;
957
958 /* Just return if we are not supposed to do anything
959 */
960 if (sig_level == SIG00 && check_level == CHECK_NONE && check_date == S_FALSE)
961 return;
962
963
964#if defined(HAVE_UTHOST)
965 host = ut->ut_host;
966#else
967 host = sh_util_strdup(_("unknown"));
968#endif
969 time = ut->ut_time;
970 user = ut->ut_name;
971
972 gres = (60*60*24)/SH_LTRACK_GTRES;
973
974 urecord = load_data(user);
975 last_login = (urecord->head).last_login;
976
977 if ( last_login < time &&
978 ( (time - last_login) >= gres ||
979 0 != strcmp(host, (urecord->head).hostname)
980 )
981 )
982 {
983 struct tm ts;
984 unsigned int index;
985 int isAlert;
986 struct sh_track_entry * entry;
987
988 (urecord->head).last_login = time;
989 sl_strlcpy((urecord->head).hostname, host, SH_LTRACK_HSIZE);
990 (urecord->head).n_entries += 1;
991
992 memcpy(&ts, localtime(&time), sizeof(struct tm));
993 index = time_to_index(&ts, SH_LTRACK_GTRES);
994
995 /* Check global statistics here
996 */
997 isAlert = check_statistics (index, (urecord->head).array,
998 SH_LTRACK_GTRES,
999 costab_gtres, sintab_gtres);
1000
1001 if (isAlert != 0)
1002 {
1003 report_outlier(FIL__, __LINE__, user, time, host);
1004 }
1005
1006
1007 if (check_date != S_FALSE)
1008 {
1009 int isBad = check_login_date(user, index, ts.tm_wday);
1010
1011 if (isBad != 0)
1012 {
1013 report_bad_date(FIL__, __LINE__, user, time, host);
1014 }
1015 }
1016
1017 /* Update array afterwards
1018 */
1019 (urecord->head).array[index] += 1;
1020
1021 entry = check_host(urecord->list, user, time, host, &ts);
1022 if (entry)
1023 {
1024 entry->next = urecord->list;
1025 urecord->list = entry;
1026 }
1027
1028 save_data(urecord, user);
1029 }
1030
1031 destroy_loaded(urecord);
1032
1033#if !defined(HAVE_UTHOST)
1034 SH_FREE(host);
1035#endif
1036 return;
1037}
1038
1039#ifdef SH_CUTEST
1040#include <stdlib.h>
1041#include <sys/types.h>
1042#include <unistd.h>
1043
1044#include "CuTest.h"
1045
1046void Test_login (CuTest *tc) {
1047 char bitarr[10] = { 0,0,0,0,0,0,0,0,0,128 };
1048 unsigned int i;
1049 int j, k;
1050 char buf[1024];
1051 char *p, *q;
1052 size_t l1, l2;
1053
1054 /* Check bitarray */
1055
1056 for (i = 0; i < 72; ++i)
1057 {
1058 set_bool(bitarr, i, 1);
1059 }
1060 for (i = 72; i < 80; ++i)
1061 {
1062 set_bool(bitarr, i, 0);
1063 }
1064 for (i = 0; i < 80; ++i)
1065 {
1066 j = get_bool(bitarr, i);
1067 if (i < 72)
1068 CuAssertTrue(tc, j > 0);
1069 else
1070 CuAssertIntEquals(tc, 0, j);
1071 }
1072
1073 /* check build_path */
1074
1075 j = sl_strlcpy(buf, DEFAULT_DATAROOT, sizeof(buf));
1076 CuAssertIntEquals(tc, 0, j);
1077
1078 p = build_path("rainer");
1079 q = sh_util_dirname(p);
1080 j = strncmp(buf, q, strlen(buf));
1081 l1 = strlen(buf); l2 = strlen(q);
1082 CuAssertTrue(tc, l2 >= l1);
1083 CuAssertIntEquals(tc, 0, j);
1084
1085 q = sh_util_basename(p);
1086 CuAssertStrEquals(tc, q, "cmFpbmVy");
1087
1088 { /* Check load/save of user data */
1089 struct sh_track urecord, *precord;
1090 struct sh_track_entry uentry0, *pentry;
1091 struct sh_track_entry uentry1;
1092
1093 urecord.head.version = 40;
1094 urecord.head.n_entries = 41;
1095 urecord.head.last_login = 42;
1096 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1097 urecord.head.array[i] = 0;
1098 urecord.head.array[30] = 30;
1099
1100 urecord.list = &uentry0;
1101 uentry0.next = &uentry1;
1102 uentry1.next = NULL;
1103
1104 uentry0.data.last_login = 52;
1105 strcpy(uentry0.data.hostname, "host0");
1106 for (i = 0; i < SH_LTRACK_HTRES; ++i)
1107 uentry0.data.array[i] = 0;
1108 uentry0.data.array[5] = 50;
1109
1110 uentry1.data.last_login = 62;
1111 strcpy(uentry1.data.hostname, "host1");
1112 for (i = 0; i < SH_LTRACK_HTRES; ++i)
1113 uentry1.data.array[i] = 0;
1114 uentry1.data.array[6] = 60;
1115
1116 snprintf(buf, sizeof(buf), "cutest_%06d", (int) getpid());
1117
1118 save_data_int(&urecord, buf);
1119
1120 precord = load_data_int(buf);
1121
1122 CuAssertIntEquals(tc, urecord.head.version, (precord->head).version);
1123 CuAssertIntEquals(tc, urecord.head.n_entries, (precord->head).n_entries);
1124 CuAssertIntEquals(tc, urecord.head.last_login, (precord->head).last_login);
1125 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1126 CuAssertIntEquals(tc, urecord.head.array[i], (precord->head).array[i]);
1127
1128 CuAssertPtrNotNull(tc, precord->list);
1129 pentry = precord->list;
1130 CuAssertIntEquals(tc, uentry1.data.last_login, (pentry->data).last_login);
1131 CuAssertStrEquals(tc, uentry1.data.hostname, (pentry->data).hostname);
1132 for (i = 0; i < SH_LTRACK_HTRES; ++i)
1133 CuAssertIntEquals(tc, uentry1.data.array[i], (pentry->data).array[i]);
1134
1135 CuAssertPtrNotNull(tc, pentry->next);
1136 pentry = pentry->next;
1137 CuAssertIntEquals(tc, uentry0.data.last_login, (pentry->data).last_login);
1138 CuAssertStrEquals(tc, uentry0.data.hostname, (pentry->data).hostname);
1139 for (i = 0; i < SH_LTRACK_HTRES; ++i)
1140 CuAssertIntEquals(tc, uentry0.data.array[i], (pentry->data).array[i]);
1141
1142 CuAssertPtrEquals(tc, pentry->next, NULL);
1143 destroy_loaded(precord);
1144 unlink(buf);
1145
1146 precord = load_data_int("supacalifragilistic");
1147 CuAssertPtrNotNull(tc, precord);
1148 CuAssertPtrEquals(tc, precord->list, NULL);
1149 CuAssertIntEquals(tc, SH_LTRACK_VERSION, (precord->head).version);
1150 CuAssertIntEquals(tc, 0, (precord->head).n_entries);
1151 CuAssertIntEquals(tc, 0, (precord->head).last_login);
1152 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1153 CuAssertIntEquals(tc, 0, (precord->head).array[i]);
1154 destroy_loaded(precord);
1155
1156 precord = load_data_int(NULL);
1157 CuAssertPtrNotNull(tc, precord);
1158 CuAssertPtrEquals(tc, precord->list, NULL);
1159 CuAssertIntEquals(tc, SH_LTRACK_VERSION, (precord->head).version);
1160 CuAssertIntEquals(tc, 0, (precord->head).n_entries);
1161 CuAssertIntEquals(tc, 0, (precord->head).last_login);
1162 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1163 CuAssertIntEquals(tc, 0, (precord->head).array[i]);
1164 destroy_loaded(precord);
1165 }
1166
1167 /* check configuration */
1168
1169 j = sh_login_set_siglevel("duh");
1170 CuAssertIntEquals(tc, -1, j);
1171 CuAssertIntEquals(tc, SIG00, sig_level);
1172
1173 j = sh_login_set_siglevel("yes");
1174 CuAssertIntEquals(tc, 0, j);
1175 CuAssertIntEquals(tc, SIG01, sig_level);
1176 j = sh_login_set_siglevel("no");
1177 CuAssertIntEquals(tc, 0, j);
1178 CuAssertIntEquals(tc, SIG00, sig_level);
1179 j = sh_login_set_siglevel("paranoid");
1180 CuAssertIntEquals(tc, 0, j);
1181 CuAssertIntEquals(tc, SIG05, sig_level);
1182
1183 j = sh_login_set_checklevel("duh");
1184 CuAssertIntEquals(tc, -1, j);
1185 CuAssertIntEquals(tc, CHECK_NONE, check_level);
1186
1187 j = sh_login_set_checklevel("yes");
1188 CuAssertIntEquals(tc, 0, j);
1189 CuAssertIntEquals(tc, CHECK_HOST, check_level);
1190 j = sh_login_set_checklevel("no");
1191 CuAssertIntEquals(tc, 0, j);
1192 CuAssertIntEquals(tc, CHECK_NONE, check_level);
1193 j = sh_login_set_checklevel("domain");
1194 CuAssertIntEquals(tc, 0, j);
1195 CuAssertIntEquals(tc, CHECK_DOMAIN, check_level);
1196
1197 j = sh_login_set_def_allow("always");
1198 CuAssertIntEquals(tc, 0, j);
1199 for (j = 0; j < LTRACK_NDAYS; ++j)
1200 {
1201 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1202 {
1203 k = get_bool(global_dates[j], i);
1204 CuAssertTrue(tc, k > 0);
1205 }
1206 }
1207
1208 j = sh_login_set_def_allow("never");
1209 CuAssertIntEquals(tc, 0, j);
1210 for (j = 0; j < LTRACK_NDAYS; ++j)
1211 {
1212 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1213 {
1214 k = get_bool(global_dates[j], i);
1215 CuAssertIntEquals(tc, 0, k);
1216 }
1217 }
1218
1219 j = sh_login_set_def_allow("workdays( 0:12-1:30, 07:30-18:29,23:30-23:59)");
1220 CuAssertIntEquals(tc, 0, j);
1221 for (j = 0; j < LTRACK_NDAYS; ++j)
1222 {
1223 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1224 {
1225 k = get_bool(global_dates[j], i);
1226 // fprintf(stderr, "%d: %d: %d\n", j, i, k);
1227 if (j == WORKDAYS)
1228 {
1229 if ( (i>=1 && i<=9) || (i>=45 && i <=110) || (i>=141 && i<=143))
1230 CuAssertTrue(tc, k > 0);
1231 else
1232 CuAssertIntEquals(tc, 0, k);
1233 }
1234 else
1235 {
1236 CuAssertIntEquals(tc, 0, k);
1237 }
1238 }
1239 }
1240
1241 j = sh_login_set_user_allow("rainer :workdays( 0:12-1:30, 07:30-18:29,23:30-23:59)");
1242 CuAssertIntEquals(tc, 0, j);
1243 j = sh_login_set_user_allow("rainer :saturday( 0:0-23:59)");
1244 CuAssertIntEquals(tc, 0, j);
1245 j = sh_login_set_user_allow("rain : workdays(0:12-1:30, 07:30-18:29,23:30-23:59)");
1246 CuAssertIntEquals(tc, 0, j);
1247 j = sh_login_set_user_allow("cat: workdays( 0:12-1:30, 07:30-18:29,23:30-23:59 )");
1248 CuAssertIntEquals(tc, 0, j);
1249 j = sh_login_set_user_allow("cat: sunday(0:00-23:59)");
1250 CuAssertIntEquals(tc, 0, j);
1251
1252 {
1253 int count = 0;
1254 struct sh_track_dates * u = user_dates;
1255
1256 CuAssertPtrNotNull(tc, u);
1257
1258 do {
1259
1260 if (count == 0) {
1261 CuAssertStrEquals(tc, u->user, "cat");
1262 CuAssertPtrNotNull(tc, u->next);
1263 }
1264 else if (count == 1) {
1265 CuAssertStrEquals(tc, u->user, "rain");
1266 CuAssertPtrNotNull(tc, u->next);
1267 }
1268 else if (count == 2) {
1269 CuAssertStrEquals(tc, u->user, "rainer");
1270 CuAssertPtrEquals(tc, u->next, NULL);
1271 }
1272
1273 for (j = 0; j < LTRACK_NDAYS; ++j)
1274 {
1275 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1276 {
1277 k = get_bool(u->dates[j], i);
1278 // fprintf(stderr, "%d: %d: %d\n", j, i, k);
1279 if (j == WORKDAYS)
1280 {
1281 if ( (i>=1 && i<=9) || (i>=45 && i <=110) ||
1282 (i>=141 && i<=143) )
1283 {
1284 CuAssertTrue(tc, k > 0);
1285 }
1286 else
1287 {
1288 CuAssertIntEquals(tc, 0, k);
1289 }
1290 }
1291 else
1292 {
1293 if ((count == 0 && j == SUNDAY) ||
1294 (count == 2 && j == SATURDAY))
1295 CuAssertTrue(tc, k > 0);
1296 else
1297 CuAssertIntEquals(tc, 0, k);
1298 }
1299 }
1300 }
1301
1302 if (u->next == NULL)
1303 break;
1304
1305 u = u->next; ++count;
1306
1307 } while (1 == 1);
1308 }
1309
1310 sh_login_reset();
1311 CuAssertIntEquals(tc, SIG00, sig_level);
1312 CuAssertIntEquals(tc, CHECK_NONE, check_level);
1313
1314 /* check dates */
1315
1316 j = sh_login_set_def_allow("workdays( 0:12-1:30, 07:30-18:29,23:30-23:59)");
1317 CuAssertIntEquals(tc, 0, j);
1318
1319 j = check_login_date("rainer", 0, 2);
1320 CuAssertIntEquals(tc, -1, j);
1321 j = check_login_date("rainer", 1, 2);
1322 CuAssertIntEquals(tc, 0, j);
1323 j = check_login_date("rainer",50, 3);
1324 CuAssertIntEquals(tc, 0, j);
1325 j = check_login_date("rainer",142, 5);
1326 CuAssertIntEquals(tc, 0, j);
1327 j = check_login_date("rainer", 1, 0);
1328 CuAssertIntEquals(tc, -1, j);
1329 j = check_login_date("rainer", 1, 6);
1330 CuAssertIntEquals(tc, -1, j);
1331 j = sh_login_set_user_allow("rainer :saturday( 0:0-23:59)");
1332 CuAssertIntEquals(tc, 0, j);
1333 j = check_login_date("rainer", 1, 6);
1334 CuAssertIntEquals(tc, 0, j);
1335 j = sh_login_set_user_allow("mouse :sunday( 0:0-23:59)");
1336 CuAssertIntEquals(tc, 0, j);
1337 j = sh_login_set_user_allow("cat :saturday(0:0-23:59)");
1338 CuAssertIntEquals(tc, 0, j);
1339 j = check_login_date("rainer", 1, 6);
1340 CuAssertIntEquals(tc, 0, j);
1341 j = check_login_date("mouse", 1, 6);
1342 CuAssertIntEquals(tc, -1, j);
1343 j = check_login_date("mouse", 1, 0);
1344 CuAssertIntEquals(tc, 0, j);
1345 j = check_login_date("cat", 1, 6);
1346 CuAssertIntEquals(tc, 0, j);
1347 j = check_login_date("dog", 1, 6);
1348 CuAssertIntEquals(tc, -1, j);
1349
1350 sh_login_reset();
1351
1352 /* statistics, critical values */
1353 {
1354 double f;
1355
1356 f = M_crit(1, SIG05);
1357 CuAssertTrue(tc, f > 0.974 && f < 0.976);
1358 f = M_crit(13, SIG05);
1359 CuAssertTrue(tc, f > 0.576 && f < 0.578);
1360 f = M_crit(22, SIG05);
1361 CuAssertTrue(tc, f > 0.405 && f < 0.407);
1362 f = M_crit(10, SIG05);
1363 CuAssertTrue(tc, f > 0.646 && f < 0.648);
1364 f = M_crit(10, SIG01);
1365 CuAssertTrue(tc, f > 0.759 && f < 0.761);
1366 }
1367
1368 /* stripped hostname */
1369 p = stripped_hostname("127.20.120.100");
1370 CuAssertStrEquals(tc, "127.20", p);
1371
1372 p = stripped_hostname("foo.www.example.com");
1373 CuAssertStrEquals(tc, p, "www.example.com");
1374
1375 p = stripped_hostname("www.example.com");
1376 CuAssertStrEquals(tc, p, "example.com");
1377
1378 p = stripped_hostname("localhost");
1379 CuAssertStrEquals(tc, p, "localhost");
1380
1381 {
1382 struct tm tt;
1383
1384 tt.tm_hour = 0;
1385 tt.tm_min = 30;
1386 tt.tm_sec = 0;
1387
1388 for (i = 0; i < 24; ++i)
1389 {
1390 tt.tm_hour = i;
1391 j = time_to_index(&tt, SH_LTRACK_HTRES);
1392 CuAssertIntEquals(tc, j, i);
1393 }
1394
1395 tt.tm_min = 10;
1396
1397 for (i = 0; i < 24; ++i)
1398 {
1399 tt.tm_hour = i;
1400 j = time_to_index(&tt, SH_LTRACK_GTRES);
1401 CuAssertIntEquals(tc, 1+i*6, j);
1402 }
1403 }
1404}
1405/* #ifdef SH_CUTEST */
1406#endif
1407
1408#else
1409
1410#ifdef SH_CUTEST
1411#include <stdlib.h>
1412#include <sys/types.h>
1413#include <unistd.h>
1414
1415#include "CuTest.h"
1416
1417void Test_login (CuTest *tc) {
1418 (void) tc;
1419}
1420
1421/* #ifdef SH_CUTEST */
1422#endif
1423
1424#endif
Note: See TracBrowser for help on using the repository browser.