source: trunk/src/sh_login_track.c@ 327

Last change on this file since 327 was 299, checked in by katerina, 14 years ago

Fix AIX 5.3 compile error (ticket #223).

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)
299 {
300 n = fwrite(&(entry->data), sizeof(struct sh_track_entry_data), 1, fp);
301 entry = entry->next;
302 }
303 }
304 fclose(fp);
305 }
306 return;
307}
308
309static void save_data (struct sh_track * urecord, const char * user)
310{
311 char * path = build_path (user);
312
313 if (path)
314 {
315 save_data_int (urecord, path);
316 SH_FREE(path);
317 }
318 return;
319}
320
321/**************
322 *
323 * Configurable
324 *
325 **************/
326
327enum significance { SIG00, SIG01, SIG05 };
328enum checklevel { CHECK_NONE, CHECK_HOST, CHECK_DOMAIN };
329enum days { WORKDAYS = 0, SATURDAY, SUNDAY };
330#define LTRACK_NDAYS 3
331
332static int sig_level = SIG00;
333static int check_level = CHECK_NONE;
334static int check_date = S_FALSE;
335
336/* We use a bit array of SH_LTRACK_GTRES bits for allowed times
337 * (10 min resolution)
338 */
339#define BITARRSIZ(a) ((a + 7) / 8)
340
341static int global_init = S_FALSE;
342static char global_dates[LTRACK_NDAYS][BITARRSIZ(SH_LTRACK_GTRES)];
343
344struct sh_track_dates {
345 char user[SH_LTRACK_USIZE];
346 char dates[LTRACK_NDAYS][BITARRSIZ(SH_LTRACK_GTRES)];
347 struct sh_track_dates * next;
348};
349struct sh_track_dates * user_dates = NULL;
350
351static int set_dates (char bitarray[][BITARRSIZ(SH_LTRACK_GTRES)],
352 unsigned int size, const char * defstr);
353
354void sh_login_reset (void)
355{
356 int i, j;
357 struct sh_track_dates *u_old, *u;
358
359 u = user_dates;
360 user_dates = NULL;
361
362 while(u)
363 {
364 u_old = u;
365 u = u->next;
366 SH_FREE(u_old);
367 }
368
369 for (j = 0; j < LTRACK_NDAYS; ++j)
370 {
371 for (i = 0; i < SH_LTRACK_GTRES; ++i)
372 {
373 set_bool(global_dates[j], i, 0);
374 }
375 }
376 global_init = S_FALSE;
377
378 sig_level = SIG00;
379 check_level = CHECK_NONE;
380 check_date = S_FALSE;
381
382 return;
383}
384
385int sh_login_set_def_allow(const char * c)
386{
387 int res = set_dates(global_dates, SH_LTRACK_GTRES, c);
388
389 if (res == 0)
390 {
391 check_date = S_TRUE;
392 global_init = S_TRUE;
393 }
394 return res;
395}
396
397static struct sh_track_dates * find_user(const char * user)
398{
399 struct sh_track_dates * u = user_dates;
400
401 while(u)
402 {
403 if (0 == strcmp(user, u->user))
404 {
405 return u;
406 }
407 u = u->next;
408 }
409 return NULL;
410}
411
412int sh_login_set_user_allow(const char * c)
413{
414 unsigned int i = 0;
415 const char *p = c;
416 char user[SH_LTRACK_USIZE];
417
418 struct sh_track_dates * u;
419
420 while (p && *p && *p != ':' && *p != ' ' && *p != '\t')
421 {
422 user[i] = *p; ++p; ++i;
423
424 if (i == SH_LTRACK_USIZE)
425 return -1;
426 }
427
428 while (*p && (*p == ' ' || *p == '\t')) ++p;
429
430 if (*p && (i < SH_LTRACK_USIZE) && (*p == ':'))
431 {
432 user[i] = '\0';
433
434 ++p; while (*p && (*p == ' ' || *p == '\t')) ++p;
435
436 if (*p)
437 {
438 int res;
439 int flag = 0;
440
441 u = find_user(user);
442
443 if (!u)
444 {
445 u = SH_ALLOC(sizeof(struct sh_track_dates));
446 memset(u, '\0', sizeof(struct sh_track_dates));
447 sl_strlcpy(u->user, user, SH_LTRACK_USIZE);
448 flag = 1;
449 }
450
451 res = set_dates(u->dates, SH_LTRACK_GTRES, p);
452 if (res != 0)
453 {
454 if (flag == 1)
455 SH_FREE(u);
456 return -1;
457 }
458
459 if (flag == 1)
460 {
461 u->next = user_dates;
462 user_dates = u;
463 }
464
465 check_date = S_TRUE;
466 return 0;
467 }
468 }
469 return -1;
470}
471
472int sh_login_set_siglevel(const char * c)
473{
474 int ret = sh_util_flagval(c, &sig_level);
475
476 if (ret == 0)
477 {
478 sig_level = (sig_level == S_FALSE) ? SIG00 : SIG01;
479 return 0;
480 }
481 else
482 {
483 if (0 == strcmp(c, _("paranoid")))
484 {
485 sig_level = SIG05;
486 return 0;
487 }
488 }
489 sig_level = SIG00;
490 return -1;
491}
492
493int sh_login_set_checklevel(const char * c)
494{
495 int ret = sh_util_flagval(c, &check_level);
496
497 if (ret == 0)
498 {
499 check_level = (check_level == S_FALSE) ? CHECK_NONE : CHECK_HOST;
500 return 0;
501 }
502 else
503 {
504 if (0 == strcmp(c, _("domain")))
505 {
506 check_level = CHECK_DOMAIN;
507 return 0;
508 }
509 }
510 check_level = CHECK_NONE;
511 return -1;
512}
513
514static int eval_range(char * bitarray, unsigned int size, char * def)
515{
516 unsigned int h1, m1, h2, m2;
517
518 int res = sscanf(def, "%d:%d - %d:%d", &h1, &m1, &h2, &m2);
519
520 if (res == 4)
521 {
522 unsigned int t1 = 3600*h1 + 60*m1;
523 unsigned int t2 = 3600*h2 + 60*m2;
524 int hres = (60*60*24)/size;
525 unsigned int i;
526
527 if (t1 > t2 || t1 > 86340 || t2 > 86340)
528 return -1;
529
530 t1 = t1 / hres;
531 t2 = t2 / hres;
532 t1 = (t1 < size) ? t1 : (size-1);
533 t2 = (t2 < size) ? t2 : (size-1);
534
535 for (i = t1; i <= t2; ++i)
536 {
537 set_bool(bitarray, i, 1);
538 }
539 return 0;
540 }
541 return -1;
542}
543
544static int set_ranges(char * bitarray, unsigned int size,
545 char ** splits, unsigned int nfields)
546{
547 unsigned int i;
548 int retval = 0;
549
550 for (i = 0; i < nfields; ++i)
551 {
552 char * range = &(splits[i][0]);
553
554 if (0 != eval_range(bitarray, size, range))
555 retval = -1;
556 }
557 return retval;
558}
559
560/* 'always', 'never', workdays(list of ranges), (sun|satur)day(list of ranges)
561 */
562static int set_dates (char bitarray[][BITARRSIZ(SH_LTRACK_GTRES)],
563 unsigned int size,
564 const char * defstr)
565{
566 unsigned int i, j;
567 int retval = -1;
568
569 if (0 == strcmp(_("always"), defstr))
570 {
571 for (j = 0; j < LTRACK_NDAYS; ++j)
572 for (i = 0; i < size; ++i)
573 set_bool(bitarray[j], i, 1);
574 retval = 0;
575 }
576 else if (0 == strcmp(_("never"), defstr))
577 {
578 for (j = 0; j < LTRACK_NDAYS; ++j)
579 for (i = 0; i < size; ++i)
580 set_bool(bitarray[j], i, 0);
581 retval = 0;
582 }
583 else
584 {
585 unsigned int nfields = 24; /* list of ranges */
586 size_t lengths[24];
587 char * new = NULL;
588 char ** splits = NULL;
589
590 if (0 == strncmp(_("workdays"), defstr, 7))
591 {
592 new = sh_util_strdup(defstr);
593 splits = split_array_braced(new, _("workdays"),
594 &nfields, lengths);
595 j = WORKDAYS;
596 }
597 else if (0 == strncmp(_("saturday"), defstr, 8))
598 {
599 new = sh_util_strdup(defstr);
600 splits = split_array_braced(new, _("saturday"),
601 &nfields, lengths);
602 j = SATURDAY;
603 }
604 else if (0 == strncmp(_("sunday"), defstr, 6))
605 {
606 new = sh_util_strdup(defstr);
607 splits = split_array_braced(new, _("sunday"),
608 &nfields, lengths);
609 j = SUNDAY;
610 }
611 else
612 {
613 return -1;
614 }
615
616 if (new && splits && nfields > 0)
617 {
618 retval = set_ranges(bitarray[j], size, splits, nfields);
619 }
620
621 if (new) SH_FREE(new);
622 }
623 return retval;
624}
625
626
627
628/**************
629 *
630 * Report
631 *
632 **************/
633
634void report_generic(char * file, int line,
635 const char * user, time_t time, const char * host, int what)
636{
637 char ttt[TIM_MAX];
638
639 SH_MUTEX_LOCK(mutex_thread_nolog);
640 (void) sh_unix_time (time, ttt, TIM_MAX);
641 sh_error_handle ((-1), file, line, 0, what,
642 user, host, ttt);
643 SH_MUTEX_UNLOCK(mutex_thread_nolog);
644 return;
645}
646
647void report_bad_date(char * file, int line,
648 const char *user, time_t time, const char * host)
649{
650 report_generic(file, line, user, time, host, MSG_UT_BAD);
651}
652
653void report_first(char * file, int line,
654 const char *user, time_t time, const char * host)
655{
656 report_generic(file, line, user, time, host, MSG_UT_FIRST);
657}
658
659void report_outlier(char * file, int line,
660 const char *user, time_t time, const char * host)
661{
662 report_generic(file, line, user, time, host, MSG_UT_OUTLIER);
663}
664
665/**************
666 *
667 * Dates
668 *
669 **************/
670
671static int check_login_date(const char * user, unsigned int index, int wday)
672{
673 unsigned int i, j;
674 struct sh_track_dates * allowed = NULL;
675 int day;
676
677 /* Use an intermediate array 'char* b[m]' to cast 'char a[m][n]' to 'char** c' */
678 char * aux[LTRACK_NDAYS];
679 char **good = (char **) aux;
680
681 for (i = 0; i < LTRACK_NDAYS; ++i)
682 {
683 aux[i] = (char *) &global_dates[i][0];
684 /* + i * BITARRSIZ(SH_LTRACK_GTRES); */
685 }
686
687 if (wday > 0 && wday < 6)
688 day = WORKDAYS;
689 else if (wday == 6)
690 day = SATURDAY;
691 else
692 day = SUNDAY;
693
694 if (check_date != S_FALSE)
695 {
696 if (S_FALSE == global_init)
697 {
698 for (j = 0; j < LTRACK_NDAYS; ++j)
699 {
700 for (i = 0; i < SH_LTRACK_GTRES; ++i)
701 set_bool(global_dates[j], i, 1);
702 }
703 global_init = S_TRUE;
704 }
705
706 if (user) {
707 allowed = find_user(user);
708 }
709
710 if (allowed)
711 {
712 for (i = 0; i < LTRACK_NDAYS; ++i)
713 {
714 aux[i] = (char *)&(allowed->dates)[i][0];
715 /* + i*BITARRSIZ(SH_LTRACK_GTRES); */
716 }
717 }
718
719 if (0 == get_bool(good[day], index))
720 {
721 return -1;
722 }
723 }
724 return 0;
725}
726
727/**************
728 *
729 * Statistics
730 *
731 **************/
732
733/* Compute sqrt(s) using the babylonian algorithm
734 * (to avoid linking with -lm).
735 */
736static double sh_sqrt(double s)
737{
738 double eps = 1.0e-6;
739 double x0 = 1.0;
740 double xs = s;
741
742 double diff = xs - x0;
743 diff = (diff > 0.0) ? diff : -diff;
744
745 while (diff > eps)
746 {
747 xs = x0;
748 x0 = 0.5 * (x0 + (s/x0));
749 diff = xs - x0;
750 diff = (diff > 0.0) ? diff : -diff;
751 }
752 return x0;
753}
754
755static double M_crit(int n, int flag)
756{
757#define SH_MCSIZE 10
758 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 };
759 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 };
760 const int M_nn[SH_MCSIZE] = { 4, 5, 6, 7, 8, 9, 10, 12, 15, 20 };
761
762 if (n > M_nn[SH_MCSIZE-1])
763 {
764 return ((flag == SIG05) ? M_05[SH_MCSIZE-1] : M_01[SH_MCSIZE-1]);
765 }
766 else
767 {
768 unsigned int i;
769
770 for (i = 1; i < SH_MCSIZE; ++i)
771 {
772 if (n < M_nn[i])
773 {
774 return ((flag == SIG05) ? M_05[i-1] : M_01[i-1]);
775 }
776 }
777 }
778
779 return ((flag == SIG05) ? M_05[SH_MCSIZE-1] : M_01[SH_MCSIZE-1]);
780}
781
782static int check_statistics (unsigned int index, UINT32 * array, unsigned int size,
783 const double * costab, const double * sintab)
784{
785 double C = 0.0;
786 double S = 0.0;
787 double R, Rk, M;
788
789 unsigned int i, n = 0;
790
791 if (sig_level != SIG00)
792 {
793 for (i = 0; i < size; ++i)
794 {
795 n += array[i];
796 C += (array[i] * costab[i]);
797 S += (array[i] * sintab[i]);
798 }
799
800 if (n > 2) /* current is at least 4th datapoint */
801 {
802 R = sh_sqrt(S*S + C*C);
803
804 C += array[index] * costab[index];
805 S += array[index] * sintab[index];
806 Rk = sh_sqrt(S*S + C*C);
807 ++n;
808
809 M = (Rk - R + 1.0)/((double)n - R);
810
811 if (M > M_crit(n, sig_level))
812 {
813 return -1;
814 }
815 }
816 }
817 return 0;
818}
819
820static char * stripped_hostname (const char * host)
821{
822 char *p, *q;
823
824 if (sh_ipvx_is_numeric(host))
825 {
826 p = sh_util_strdup(host);
827 q = strrchr(p, '.');
828 if (q)
829 {
830 *q = '\0';
831 q = strrchr(p, '.');
832 if (q)
833 {
834 *q = '\0';
835 }
836 }
837 }
838 else
839 {
840 q = strchr(host, '.');
841 if (q && *q)
842 {
843 ++q;
844 p = sh_util_strdup(q);
845 }
846 else
847 {
848 p = sh_util_strdup(host);
849 }
850 }
851 return p;
852}
853
854static unsigned int time_to_index(struct tm * tp, int nbin)
855{
856 int hres = (60*60*24)/nbin;
857 int index = tp->tm_hour * 3600 + tp->tm_min * 60 + tp->tm_sec;
858 index = index / hres;
859 index = (index < nbin) ? index : (nbin-1);
860
861 return index;
862}
863
864static struct sh_track_entry * check_host(struct sh_track_entry * list,
865 const char * user, time_t time, const char * host,
866 struct tm * tp)
867{
868 unsigned int index = time_to_index(tp, SH_LTRACK_HTRES);
869 struct sh_track_entry * entry = list;
870
871 char * p = NULL;
872 const char * q;
873
874 if (check_level == CHECK_DOMAIN)
875 {
876 p = stripped_hostname(host);
877 q = p;
878 }
879 else
880 {
881 q = host;
882 }
883
884 while (entry)
885 {
886 if (0 == strncmp(q, (entry->data).hostname, SH_LTRACK_HSIZE))
887 break;
888 entry = entry->next;
889 }
890
891 if (entry)
892 {
893 int isAlert;
894
895 (entry->data).last_login = time;
896
897 /* Check host statistics here
898 */
899 isAlert = check_statistics (index, (entry->data).array, SH_LTRACK_HTRES,
900 costab_htres, sintab_htres);
901
902 if (isAlert != 0)
903 {
904 report_outlier(FIL__, __LINE__, user, time, host);
905 }
906
907 /* Update array afterwards
908 */
909 (entry->data).array[index] += 1;
910 }
911 else
912 {
913 entry = SH_ALLOC(sizeof(struct sh_track_entry));
914 memset(entry, '\0', sizeof(struct sh_track_entry));
915 (entry->data).last_login = time;
916 (entry->data).array[index] = 1;
917 sl_strlcpy((entry->data).hostname, q, SH_LTRACK_HSIZE);
918
919 /* Report first login from this host
920 */
921 if (check_level != CHECK_NONE)
922 {
923 report_first (FIL__, __LINE__, user, time, host);
924 }
925
926 if (p)
927 SH_FREE(p);
928 return entry;
929 }
930
931 if (p)
932 SH_FREE(p);
933 return NULL;
934}
935
936/********************************************************
937 *
938 * Public Function
939 *
940 ********************************************************/
941
942void sh_ltrack_check(struct SH_UTMP_S * ut)
943{
944 int gres;
945 const char * user;
946 time_t time;
947#if defined(HAVE_UTHOST)
948 const char * host;
949#else
950 const char * host;
951#endif
952 struct sh_track * urecord;
953 time_t last_login;
954
955 /* Just return if we are not supposed to do anything
956 */
957 if (sig_level == SIG00 && check_level == CHECK_NONE && check_date == S_FALSE)
958 return;
959
960
961#if defined(HAVE_UTHOST)
962 host = ut->ut_host;
963#else
964 host = sh_util_strdup(_("unknown"));
965#endif
966 time = ut->ut_time;
967 user = ut->ut_name;
968
969 gres = (60*60*24)/SH_LTRACK_GTRES;
970
971 urecord = load_data(user);
972 last_login = (urecord->head).last_login;
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.