source: branches/samhain_3_1/src/sh_login_track.c@ 555

Last change on this file since 555 was 405, checked in by katerina, 12 years ago

Fix for tickets #303, #304, #305. #306, and #307. Update version number.

File size: 38.2 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 == 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 q = strchr(host, '.');
842 if (q && *q)
843 {
844 ++q;
845 p = sh_util_strdup(q);
846 }
847 else
848 {
849 p = sh_util_strdup(host);
850 }
851 }
852 return p;
853}
854
855static unsigned int time_to_index(struct tm * tp, int nbin)
856{
857 int hres = (60*60*24)/nbin;
858 int index = tp->tm_hour * 3600 + tp->tm_min * 60 + tp->tm_sec;
859 index = index / hres;
860 index = (index < nbin) ? index : (nbin-1);
861
862 return index;
863}
864
865static struct sh_track_entry * check_host(struct sh_track_entry * list,
866 const char * user, time_t time, const char * host,
867 struct tm * tp)
868{
869 unsigned int index = time_to_index(tp, SH_LTRACK_HTRES);
870 struct sh_track_entry * entry = list;
871
872 char * p = NULL;
873 const char * q;
874
875 if (check_level == CHECK_DOMAIN)
876 {
877 p = stripped_hostname(host);
878 q = p;
879 }
880 else
881 {
882 q = host;
883 }
884
885 while (entry)
886 {
887 if (0 == strncmp(q, (entry->data).hostname, SH_LTRACK_HSIZE))
888 break;
889 entry = entry->next;
890 }
891
892 if (entry)
893 {
894 int isAlert;
895
896 (entry->data).last_login = time;
897
898 /* Check host statistics here
899 */
900 isAlert = check_statistics (index, (entry->data).array, SH_LTRACK_HTRES,
901 costab_htres, sintab_htres);
902
903 if (isAlert != 0)
904 {
905 report_outlier(FIL__, __LINE__, user, time, host);
906 }
907
908 /* Update array afterwards
909 */
910 (entry->data).array[index] += 1;
911 }
912 else
913 {
914 entry = SH_ALLOC(sizeof(struct sh_track_entry));
915 memset(entry, '\0', sizeof(struct sh_track_entry));
916 (entry->data).last_login = time;
917 (entry->data).array[index] = 1;
918 sl_strlcpy((entry->data).hostname, q, SH_LTRACK_HSIZE);
919
920 /* Report first login from this host
921 */
922 if (check_level != CHECK_NONE)
923 {
924 report_first (FIL__, __LINE__, user, time, host);
925 }
926
927 if (p)
928 SH_FREE(p);
929 return entry;
930 }
931
932 if (p)
933 SH_FREE(p);
934 return NULL;
935}
936
937/********************************************************
938 *
939 * Public Function
940 *
941 ********************************************************/
942
943void sh_ltrack_check(struct SH_UTMP_S * ut)
944{
945 int gres;
946 const char * user;
947 time_t time;
948#if defined(HAVE_UTHOST)
949 const char * host;
950#else
951 const char * host;
952#endif
953 struct sh_track * urecord;
954 time_t last_login;
955
956 /* Just return if we are not supposed to do anything
957 */
958 if (sig_level == SIG00 && check_level == CHECK_NONE && check_date == S_FALSE)
959 return;
960
961
962#if defined(HAVE_UTHOST)
963 host = ut->ut_host;
964#else
965 host = sh_util_strdup(_("unknown"));
966#endif
967 time = ut->ut_time;
968 user = ut->ut_name;
969
970 gres = (60*60*24)/SH_LTRACK_GTRES;
971
972 urecord = load_data(user);
973 last_login = (urecord->head).last_login;
974
975 if ( last_login < time &&
976 ( (time - last_login) >= gres ||
977 0 != strcmp(host, (urecord->head).hostname)
978 )
979 )
980 {
981 struct tm ts;
982 unsigned int index;
983 int isAlert;
984 struct sh_track_entry * entry;
985
986 (urecord->head).last_login = time;
987 sl_strlcpy((urecord->head).hostname, host, SH_LTRACK_HSIZE);
988 (urecord->head).n_entries += 1;
989
990 memcpy(&ts, localtime(&time), sizeof(struct tm));
991 index = time_to_index(&ts, SH_LTRACK_GTRES);
992
993 /* Check global statistics here
994 */
995 isAlert = check_statistics (index, (urecord->head).array,
996 SH_LTRACK_GTRES,
997 costab_gtres, sintab_gtres);
998
999 if (isAlert != 0)
1000 {
1001 report_outlier(FIL__, __LINE__, user, time, host);
1002 }
1003
1004
1005 if (check_date != S_FALSE)
1006 {
1007 int isBad = check_login_date(user, index, ts.tm_wday);
1008
1009 if (isBad != 0)
1010 {
1011 report_bad_date(FIL__, __LINE__, user, time, host);
1012 }
1013 }
1014
1015 /* Update array afterwards
1016 */
1017 (urecord->head).array[index] += 1;
1018
1019 entry = check_host(urecord->list, user, time, host, &ts);
1020 if (entry)
1021 {
1022 entry->next = urecord->list;
1023 urecord->list = entry;
1024 }
1025
1026 save_data(urecord, user);
1027 }
1028
1029 destroy_loaded(urecord);
1030
1031#if !defined(HAVE_UTHOST)
1032 SH_FREE(host);
1033#endif
1034 return;
1035}
1036
1037#ifdef SH_CUTEST
1038#include <stdlib.h>
1039#include <sys/types.h>
1040#include <unistd.h>
1041
1042#include "CuTest.h"
1043
1044void Test_login (CuTest *tc) {
1045 char bitarr[10] = { 0,0,0,0,0,0,0,0,0,128 };
1046 unsigned int i;
1047 int j, k;
1048 char buf[1024];
1049 char *p, *q;
1050 size_t l1, l2;
1051
1052 /* Check bitarray */
1053
1054 for (i = 0; i < 72; ++i)
1055 {
1056 set_bool(bitarr, i, 1);
1057 }
1058 for (i = 72; i < 80; ++i)
1059 {
1060 set_bool(bitarr, i, 0);
1061 }
1062 for (i = 0; i < 80; ++i)
1063 {
1064 j = get_bool(bitarr, i);
1065 if (i < 72)
1066 CuAssertTrue(tc, j > 0);
1067 else
1068 CuAssertIntEquals(tc, 0, j);
1069 }
1070
1071 /* check build_path */
1072
1073 j = sl_strlcpy(buf, DEFAULT_DATAROOT, sizeof(buf));
1074 CuAssertIntEquals(tc, 0, j);
1075
1076 p = build_path("rainer");
1077 q = sh_util_dirname(p);
1078 j = strncmp(buf, q, strlen(buf));
1079 l1 = strlen(buf); l2 = strlen(q);
1080 CuAssertTrue(tc, l2 >= l1);
1081 CuAssertIntEquals(tc, 0, j);
1082
1083 q = sh_util_basename(p);
1084 CuAssertStrEquals(tc, q, "cmFpbmVy");
1085
1086 { /* Check load/save of user data */
1087 struct sh_track urecord, *precord;
1088 struct sh_track_entry uentry0, *pentry;
1089 struct sh_track_entry uentry1;
1090
1091 urecord.head.version = 40;
1092 urecord.head.n_entries = 41;
1093 urecord.head.last_login = 42;
1094 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1095 urecord.head.array[i] = 0;
1096 urecord.head.array[30] = 30;
1097
1098 urecord.list = &uentry0;
1099 uentry0.next = &uentry1;
1100 uentry1.next = NULL;
1101
1102 uentry0.data.last_login = 52;
1103 strcpy(uentry0.data.hostname, "host0");
1104 for (i = 0; i < SH_LTRACK_HTRES; ++i)
1105 uentry0.data.array[i] = 0;
1106 uentry0.data.array[5] = 50;
1107
1108 uentry1.data.last_login = 62;
1109 strcpy(uentry1.data.hostname, "host1");
1110 for (i = 0; i < SH_LTRACK_HTRES; ++i)
1111 uentry1.data.array[i] = 0;
1112 uentry1.data.array[6] = 60;
1113
1114 snprintf(buf, sizeof(buf), "cutest_%06d", (int) getpid());
1115
1116 save_data_int(&urecord, buf);
1117
1118 precord = load_data_int(buf);
1119
1120 CuAssertIntEquals(tc, urecord.head.version, (precord->head).version);
1121 CuAssertIntEquals(tc, urecord.head.n_entries, (precord->head).n_entries);
1122 CuAssertIntEquals(tc, urecord.head.last_login, (precord->head).last_login);
1123 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1124 CuAssertIntEquals(tc, urecord.head.array[i], (precord->head).array[i]);
1125
1126 CuAssertPtrNotNull(tc, precord->list);
1127 pentry = precord->list;
1128 CuAssertIntEquals(tc, uentry1.data.last_login, (pentry->data).last_login);
1129 CuAssertStrEquals(tc, uentry1.data.hostname, (pentry->data).hostname);
1130 for (i = 0; i < SH_LTRACK_HTRES; ++i)
1131 CuAssertIntEquals(tc, uentry1.data.array[i], (pentry->data).array[i]);
1132
1133 CuAssertPtrNotNull(tc, pentry->next);
1134 pentry = pentry->next;
1135 CuAssertIntEquals(tc, uentry0.data.last_login, (pentry->data).last_login);
1136 CuAssertStrEquals(tc, uentry0.data.hostname, (pentry->data).hostname);
1137 for (i = 0; i < SH_LTRACK_HTRES; ++i)
1138 CuAssertIntEquals(tc, uentry0.data.array[i], (pentry->data).array[i]);
1139
1140 CuAssertPtrEquals(tc, pentry->next, NULL);
1141 destroy_loaded(precord);
1142 unlink(buf);
1143
1144 precord = load_data_int("supacalifragilistic");
1145 CuAssertPtrNotNull(tc, precord);
1146 CuAssertPtrEquals(tc, precord->list, NULL);
1147 CuAssertIntEquals(tc, SH_LTRACK_VERSION, (precord->head).version);
1148 CuAssertIntEquals(tc, 0, (precord->head).n_entries);
1149 CuAssertIntEquals(tc, 0, (precord->head).last_login);
1150 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1151 CuAssertIntEquals(tc, 0, (precord->head).array[i]);
1152 destroy_loaded(precord);
1153
1154 precord = load_data_int(NULL);
1155 CuAssertPtrNotNull(tc, precord);
1156 CuAssertPtrEquals(tc, precord->list, NULL);
1157 CuAssertIntEquals(tc, SH_LTRACK_VERSION, (precord->head).version);
1158 CuAssertIntEquals(tc, 0, (precord->head).n_entries);
1159 CuAssertIntEquals(tc, 0, (precord->head).last_login);
1160 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1161 CuAssertIntEquals(tc, 0, (precord->head).array[i]);
1162 destroy_loaded(precord);
1163 }
1164
1165 /* check configuration */
1166
1167 j = sh_login_set_siglevel("duh");
1168 CuAssertIntEquals(tc, -1, j);
1169 CuAssertIntEquals(tc, SIG00, sig_level);
1170
1171 j = sh_login_set_siglevel("yes");
1172 CuAssertIntEquals(tc, 0, j);
1173 CuAssertIntEquals(tc, SIG01, sig_level);
1174 j = sh_login_set_siglevel("no");
1175 CuAssertIntEquals(tc, 0, j);
1176 CuAssertIntEquals(tc, SIG00, sig_level);
1177 j = sh_login_set_siglevel("paranoid");
1178 CuAssertIntEquals(tc, 0, j);
1179 CuAssertIntEquals(tc, SIG05, sig_level);
1180
1181 j = sh_login_set_checklevel("duh");
1182 CuAssertIntEquals(tc, -1, j);
1183 CuAssertIntEquals(tc, CHECK_NONE, check_level);
1184
1185 j = sh_login_set_checklevel("yes");
1186 CuAssertIntEquals(tc, 0, j);
1187 CuAssertIntEquals(tc, CHECK_HOST, check_level);
1188 j = sh_login_set_checklevel("no");
1189 CuAssertIntEquals(tc, 0, j);
1190 CuAssertIntEquals(tc, CHECK_NONE, check_level);
1191 j = sh_login_set_checklevel("domain");
1192 CuAssertIntEquals(tc, 0, j);
1193 CuAssertIntEquals(tc, CHECK_DOMAIN, check_level);
1194
1195 j = sh_login_set_def_allow("always");
1196 CuAssertIntEquals(tc, 0, j);
1197 for (j = 0; j < LTRACK_NDAYS; ++j)
1198 {
1199 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1200 {
1201 k = get_bool(global_dates[j], i);
1202 CuAssertTrue(tc, k > 0);
1203 }
1204 }
1205
1206 j = sh_login_set_def_allow("never");
1207 CuAssertIntEquals(tc, 0, j);
1208 for (j = 0; j < LTRACK_NDAYS; ++j)
1209 {
1210 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1211 {
1212 k = get_bool(global_dates[j], i);
1213 CuAssertIntEquals(tc, 0, k);
1214 }
1215 }
1216
1217 j = sh_login_set_def_allow("workdays( 0:12-1:30, 07:30-18:29,23:30-23:59)");
1218 CuAssertIntEquals(tc, 0, j);
1219 for (j = 0; j < LTRACK_NDAYS; ++j)
1220 {
1221 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1222 {
1223 k = get_bool(global_dates[j], i);
1224 // fprintf(stderr, "%d: %d: %d\n", j, i, k);
1225 if (j == WORKDAYS)
1226 {
1227 if ( (i>=1 && i<=9) || (i>=45 && i <=110) || (i>=141 && i<=143))
1228 CuAssertTrue(tc, k > 0);
1229 else
1230 CuAssertIntEquals(tc, 0, k);
1231 }
1232 else
1233 {
1234 CuAssertIntEquals(tc, 0, k);
1235 }
1236 }
1237 }
1238
1239 j = sh_login_set_user_allow("rainer :workdays( 0:12-1:30, 07:30-18:29,23:30-23:59)");
1240 CuAssertIntEquals(tc, 0, j);
1241 j = sh_login_set_user_allow("rainer :saturday( 0:0-23:59)");
1242 CuAssertIntEquals(tc, 0, j);
1243 j = sh_login_set_user_allow("rain : workdays(0:12-1:30, 07:30-18:29,23:30-23:59)");
1244 CuAssertIntEquals(tc, 0, j);
1245 j = sh_login_set_user_allow("cat: 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: sunday(0:00-23:59)");
1248 CuAssertIntEquals(tc, 0, j);
1249
1250 {
1251 int count = 0;
1252 struct sh_track_dates * u = user_dates;
1253
1254 CuAssertPtrNotNull(tc, u);
1255
1256 do {
1257
1258 if (count == 0) {
1259 CuAssertStrEquals(tc, u->user, "cat");
1260 CuAssertPtrNotNull(tc, u->next);
1261 }
1262 else if (count == 1) {
1263 CuAssertStrEquals(tc, u->user, "rain");
1264 CuAssertPtrNotNull(tc, u->next);
1265 }
1266 else if (count == 2) {
1267 CuAssertStrEquals(tc, u->user, "rainer");
1268 CuAssertPtrEquals(tc, u->next, NULL);
1269 }
1270
1271 for (j = 0; j < LTRACK_NDAYS; ++j)
1272 {
1273 for (i = 0; i < SH_LTRACK_GTRES; ++i)
1274 {
1275 k = get_bool(u->dates[j], i);
1276 // fprintf(stderr, "%d: %d: %d\n", j, i, k);
1277 if (j == WORKDAYS)
1278 {
1279 if ( (i>=1 && i<=9) || (i>=45 && i <=110) ||
1280 (i>=141 && i<=143) )
1281 {
1282 CuAssertTrue(tc, k > 0);
1283 }
1284 else
1285 {
1286 CuAssertIntEquals(tc, 0, k);
1287 }
1288 }
1289 else
1290 {
1291 if ((count == 0 && j == SUNDAY) ||
1292 (count == 2 && j == SATURDAY))
1293 CuAssertTrue(tc, k > 0);
1294 else
1295 CuAssertIntEquals(tc, 0, k);
1296 }
1297 }
1298 }
1299
1300 if (u->next == NULL)
1301 break;
1302
1303 u = u->next; ++count;
1304
1305 } while (1 == 1);
1306 }
1307
1308 sh_login_reset();
1309 CuAssertIntEquals(tc, SIG00, sig_level);
1310 CuAssertIntEquals(tc, CHECK_NONE, check_level);
1311
1312 /* check dates */
1313
1314 j = sh_login_set_def_allow("workdays( 0:12-1:30, 07:30-18:29,23:30-23:59)");
1315 CuAssertIntEquals(tc, 0, j);
1316
1317 j = check_login_date("rainer", 0, 2);
1318 CuAssertIntEquals(tc, -1, j);
1319 j = check_login_date("rainer", 1, 2);
1320 CuAssertIntEquals(tc, 0, j);
1321 j = check_login_date("rainer",50, 3);
1322 CuAssertIntEquals(tc, 0, j);
1323 j = check_login_date("rainer",142, 5);
1324 CuAssertIntEquals(tc, 0, j);
1325 j = check_login_date("rainer", 1, 0);
1326 CuAssertIntEquals(tc, -1, j);
1327 j = check_login_date("rainer", 1, 6);
1328 CuAssertIntEquals(tc, -1, j);
1329 j = sh_login_set_user_allow("rainer :saturday( 0:0-23:59)");
1330 CuAssertIntEquals(tc, 0, j);
1331 j = check_login_date("rainer", 1, 6);
1332 CuAssertIntEquals(tc, 0, j);
1333 j = sh_login_set_user_allow("mouse :sunday( 0:0-23:59)");
1334 CuAssertIntEquals(tc, 0, j);
1335 j = sh_login_set_user_allow("cat :saturday(0:0-23:59)");
1336 CuAssertIntEquals(tc, 0, j);
1337 j = check_login_date("rainer", 1, 6);
1338 CuAssertIntEquals(tc, 0, j);
1339 j = check_login_date("mouse", 1, 6);
1340 CuAssertIntEquals(tc, -1, j);
1341 j = check_login_date("mouse", 1, 0);
1342 CuAssertIntEquals(tc, 0, j);
1343 j = check_login_date("cat", 1, 6);
1344 CuAssertIntEquals(tc, 0, j);
1345 j = check_login_date("dog", 1, 6);
1346 CuAssertIntEquals(tc, -1, j);
1347
1348 sh_login_reset();
1349
1350 /* statistics, critical values */
1351 {
1352 double f;
1353
1354 f = M_crit(1, SIG05);
1355 CuAssertTrue(tc, f > 0.974 && f < 0.976);
1356 f = M_crit(13, SIG05);
1357 CuAssertTrue(tc, f > 0.576 && f < 0.578);
1358 f = M_crit(22, SIG05);
1359 CuAssertTrue(tc, f > 0.405 && f < 0.407);
1360 f = M_crit(10, SIG05);
1361 CuAssertTrue(tc, f > 0.646 && f < 0.648);
1362 f = M_crit(10, SIG01);
1363 CuAssertTrue(tc, f > 0.759 && f < 0.761);
1364 }
1365
1366 /* stripped hostname */
1367 p = stripped_hostname("127.20.120.100");
1368 CuAssertStrEquals(tc, "127.20", p);
1369
1370 p = stripped_hostname("foo.www.example.com");
1371 CuAssertStrEquals(tc, p, "www.example.com");
1372
1373 p = stripped_hostname("www.example.com");
1374 CuAssertStrEquals(tc, p, "example.com");
1375
1376 p = stripped_hostname("localhost");
1377 CuAssertStrEquals(tc, p, "localhost");
1378
1379 {
1380 struct tm tt;
1381
1382 tt.tm_hour = 0;
1383 tt.tm_min = 30;
1384 tt.tm_sec = 0;
1385
1386 for (i = 0; i < 24; ++i)
1387 {
1388 tt.tm_hour = i;
1389 j = time_to_index(&tt, SH_LTRACK_HTRES);
1390 CuAssertIntEquals(tc, j, i);
1391 }
1392
1393 tt.tm_min = 10;
1394
1395 for (i = 0; i < 24; ++i)
1396 {
1397 tt.tm_hour = i;
1398 j = time_to_index(&tt, SH_LTRACK_GTRES);
1399 CuAssertIntEquals(tc, 1+i*6, j);
1400 }
1401 }
1402}
1403/* #ifdef SH_CUTEST */
1404#endif
1405
1406#else
1407
1408#ifdef SH_CUTEST
1409#include <stdlib.h>
1410#include <sys/types.h>
1411#include <unistd.h>
1412
1413#include "CuTest.h"
1414
1415void Test_login (CuTest *tc) {
1416 (void) tc;
1417}
1418
1419/* #ifdef SH_CUTEST */
1420#endif
1421
1422#endif
Note: See TracBrowser for help on using the repository browser.