source: trunk/src/sh_login_track.c@ 583

Last change on this file since 583 was 583, checked in by katerina, 33 hours ago

Fix for ticket #471 (autoreconf throws warnings/errors).

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