source: trunk/src/sh_userfiles.c@ 71

Last change on this file since 71 was 68, checked in by rainer, 18 years ago

Update trunk to samhain 2.3

File size: 12.4 KB
Line 
1/*
2 * File: sh_userfiles.c
3 * Desc: A module for Samhain; adds files in user directories to the check list
4 * Auth: Jerry Connolly <jerry.connolly@eircom.net>
5 */
6/* This program is free software; you can redistribute it */
7/* and/or modify */
8/* it under the terms of the GNU General Public License as */
9/* published by */
10/* the Free Software Foundation; either version 2 of the License, or */
11/* (at your option) any later version. */
12/* */
13/* This program is distributed in the hope that it will be useful, */
14/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16/* GNU General Public License for more details. */
17/* */
18/* You should have received a copy of the GNU General Public License */
19/* along with this program; if not, write to the Free Software */
20/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22#include "config_xor.h"
23
24#include <stdio.h>
25#include <string.h>
26#include <ctype.h>
27#include <limits.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <pwd.h>
31
32
33#include "samhain.h"
34#include "sh_modules.h"
35#include "sh_userfiles.h"
36#include "sh_utils.h"
37#include "sh_schedule.h"
38#include "sh_error.h"
39#include "sh_hash.h"
40#include "sh_files.h"
41
42#ifdef SH_USE_USERFILES
43
44#define FIL__ _("sh_userfiles.c")
45
46/* We won't want to build this into yule */
47#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
48
49static int ShUserfilesActive = S_TRUE;
50
51struct userfileslist {
52 char filename[PATH_MAX];
53 int level;
54
55 struct userfileslist *next;
56};
57
58struct userhomeslist {
59 char *pw_dir;
60
61 struct userhomeslist *next;
62};
63
64struct useruidlist {
65 unsigned long lower;
66 unsigned long upper;
67 struct useruidlist *next;
68};
69
70static struct userfileslist *userFiles = NULL;
71static struct userhomeslist *userHomes = NULL;
72static struct useruidlist *userUids = NULL;
73
74static void sh_userfiles_free_fileslist(struct userfileslist *head);
75static void sh_userfiles_free_homeslist(struct userhomeslist *head);
76static void sh_userfiles_free_uidslist (struct useruidlist *head);
77
78sh_rconf sh_userfiles_table[] = {
79 {
80 N_("userfilesname"),
81 sh_userfiles_add_file,
82 },
83 {
84 N_("userfilesactive"),
85 sh_userfiles_set_active,
86 },
87 {
88 N_("userfilescheckuids"),
89 sh_userfiles_set_uid,
90 },
91 {
92 NULL,
93 NULL
94 }
95};
96
97static int sh_userfiles_check_uid (unsigned long uid)
98{
99 struct useruidlist * uids = userUids;
100
101 /* default is to include all
102 */
103 if (userUids == NULL)
104 return 1;
105
106 while (uids)
107 {
108 if ((uids->upper != 0) && (uid >= uids->lower) && (uid <= uids->upper))
109 return 1;
110 if ((uids->upper == 0) && (uid == uids->lower))
111 return 1;
112 uids = uids->next;
113 }
114 return 0;
115}
116
117int sh_userfiles_set_uid (const char * str)
118{
119 char * end;
120 const char * p = str;
121 unsigned long lower;
122 unsigned long upper = 0;
123 struct useruidlist * uids;
124
125 while ((p != NULL) && (*p != '\0'))
126 {
127 lower = strtoul(p, &end, 10);
128 if ( (lower == ULONG_MAX) || (end == p))
129 return -1;
130 p = end;
131 if (*p == '-')
132 {
133 ++p;
134 if (*p == '\0')
135 {
136 upper = ULONG_MAX;
137 p = NULL;
138 }
139 else
140 {
141 upper = strtoul(p, &end, 10);
142 if ( (upper == ULONG_MAX) || (end == p))
143 return -1;
144 p = end;
145 if ( (*p != ',') && (*p != '\0'))
146 return -1;
147 if (*p != '\0')
148 ++p;
149 }
150 }
151 else if (*p == '\0')
152 {
153 upper = 0;
154 p = NULL;
155 }
156 else if ((*p == ',') || (*p == ' ') || (*p == '\t'))
157 {
158 upper = 0;
159 ++p;
160 }
161 else
162 {
163 upper = strtoul(p, &end, 10);
164 if ( (upper == ULONG_MAX) || (end == p))
165 return -1;
166 p = end;
167 if ( (*p != ',') && (*p != ' ') && (*p != '\t') && (*p != '\0') )
168 return -1;
169 if (*p != '\0')
170 ++p;
171 }
172 uids = SH_ALLOC(sizeof(struct useruidlist));
173 uids->lower = lower;
174 uids->upper = upper;
175 uids->next = userUids;
176 userUids = uids;
177 /* fprintf(stderr, "range %lu %lu\n", lower, upper); */
178 }
179 return 0;
180}
181
182/* Add 'c' to the list of files (userFiles) relative to any given HOME
183 * directory that should be checked. */
184
185int sh_userfiles_add_file(const char *c) {
186 struct userfileslist *new;
187 char *s, *orig;
188 char *user_filename;
189
190 int default_level = SH_LEVEL_NOIGNORE;
191 char *separator = " ";
192
193 SL_ENTER(_("sh_userfiles_add_file"));
194
195 if( c == NULL )
196 SL_RETURN(-1, _("sh_userfiles_add_file") );
197
198 s = sh_util_strdup(c); /* Maybe c is needed elsewhere */
199 orig = s;
200
201 user_filename = sh_util_strsep(&s, separator);
202
203 if( user_filename == NULL || strlen(user_filename) > PATH_MAX )
204 SL_RETURN(-1, _("sh_userfiles_add_file") );
205
206 new = SH_ALLOC(sizeof(struct userfileslist));
207
208 (void) sl_strlcpy(new->filename, user_filename, PATH_MAX);
209 new->next = userFiles;
210 userFiles = new;
211
212 /* order is important here, since 'log' would match on 'glog'
213 * So, compare longest strings first */
214 if( s == NULL ) /* The default */ new->level = default_level;
215 else if ( strstr(s, "attributes")!= NULL ) new->level = SH_LEVEL_ATTRIBUTES;
216 else if ( strstr(s, "allignore") != NULL ) new->level = SH_LEVEL_ALLIGNORE;
217 else if ( strstr(s, "noignore") != NULL ) new->level = SH_LEVEL_NOIGNORE;
218 else if ( strstr(s, "logfiles") != NULL ) new->level = SH_LEVEL_LOGFILES;
219 else if ( strstr(s, "readonly") != NULL ) new->level = SH_LEVEL_READONLY;
220 else if ( strstr(s, "loggrow") != NULL ) new->level = SH_LEVEL_LOGGROW;
221 else if ( strstr(s, "user0") != NULL ) new->level = SH_LEVEL_USER0;
222 else if ( strstr(s, "user1") != NULL ) new->level = SH_LEVEL_USER1;
223 else if ( strstr(s, "user2") != NULL ) new->level = SH_LEVEL_USER2;
224 else if ( strstr(s, "user3") != NULL ) new->level = SH_LEVEL_USER3;
225 else if ( strstr(s, "user4") != NULL ) new->level = SH_LEVEL_USER4;
226 else if ( strstr(s, "prelink") != NULL ) new->level = SH_LEVEL_PRELINK;
227 else /* The default */ new->level = default_level;
228
229 SH_FREE(orig);
230
231 SL_RETURN(0, _("sh_userfiles_add_file") );
232}
233
234/* Decide if we're active.
235 */
236int sh_userfiles_set_active(const char *c) {
237 int value;
238
239 SL_ENTER(_("sh_userfiles_set_active"));
240 value = sh_util_flagval(c, &ShUserfilesActive);
241 SL_RETURN((value), _("sh_userfiles_set_active"));
242}
243
244/* Build the list of users, then use this to construct the filenames to
245 * be checked. */
246int sh_userfiles_init(void) {
247 struct passwd *cur_user;
248 struct userhomeslist *end;
249 struct userhomeslist *new;
250 struct userhomeslist *homes;
251
252 SL_ENTER(_("sh_userfiles_init"));
253
254 /* We need to free anything allocated by the configuration functions if
255 * we find that the module is to be left inactive - otherwise _reconf()
256 * won't quite work. */
257 if( ShUserfilesActive == S_FALSE ) {
258 sh_userfiles_free_homeslist(userHomes);
259 sh_userfiles_free_fileslist(userFiles);
260 userHomes = NULL;
261 userFiles = NULL;
262 SL_RETURN(-1, _("sh_userfiles_init"));
263 }
264
265 /* We build a list in here because the samhain internals want to use
266 * getpwent() too */
267 /*@-unrecog@*/
268 setpwent();
269 /*@+unrecog@*/
270 while( ( cur_user = /*@-unrecog@*/getpwent()/*@+unrecog@*/ ) != NULL ) {
271 int found = 0;
272
273 if (0 == sh_userfiles_check_uid( (unsigned long) cur_user->pw_uid))
274 continue;
275
276 for( end = userHomes; end != NULL; end = end->next ) {
277 if( sl_strcmp( end->pw_dir, cur_user->pw_dir) == 0 ) {
278 found = 1; /* Found a match, so flag it and stop searching */
279 break;
280 }
281 }
282
283 if( found == 0 ) {
284 /* Didn't find it, so add to the front of the list */
285 new = SH_ALLOC(sizeof(struct userhomeslist) );
286 new->next = userHomes;
287 new->pw_dir = sh_util_strdup(cur_user->pw_dir);
288
289 userHomes = new;
290 }
291 }
292
293 for (homes = userHomes; homes != NULL; homes = homes->next ) {
294 struct userfileslist *file_ptr;
295 char filepath[PATH_MAX];
296
297 for (file_ptr = userFiles; file_ptr != NULL; file_ptr = file_ptr->next) {
298 (void) sl_strncpy(filepath, homes->pw_dir, PATH_MAX);
299 (void) sl_strncat(filepath, "/", PATH_MAX);
300 (void) sl_strncat(filepath, file_ptr->filename, PATH_MAX);
301
302 switch(file_ptr->level) {
303 case SH_LEVEL_READONLY:
304 (void) sh_files_pushfile_ro(filepath);
305 break;
306 case SH_LEVEL_LOGFILES:
307 (void) sh_files_pushfile_log(filepath);
308 break;
309 case SH_LEVEL_LOGGROW:
310 (void) sh_files_pushfile_glog(filepath);
311 break;
312 case SH_LEVEL_NOIGNORE:
313 (void) sh_files_pushfile_noig(filepath);
314 break;
315 case SH_LEVEL_ALLIGNORE:
316 (void) sh_files_pushfile_allig(filepath);
317 break;
318 case SH_LEVEL_ATTRIBUTES:
319 (void) sh_files_pushfile_attr(filepath);
320 break;
321 case SH_LEVEL_USER0:
322 (void) sh_files_pushfile_user0(filepath);
323 break;
324 case SH_LEVEL_USER1:
325 (void) sh_files_pushfile_user1(filepath);
326 break;
327 case SH_LEVEL_USER2:
328 (void) sh_files_pushfile_user2(filepath);
329 break;
330 case SH_LEVEL_USER3:
331 (void) sh_files_pushfile_user3(filepath);
332 break;
333 case SH_LEVEL_USER4:
334 (void) sh_files_pushfile_user4(filepath);
335 break;
336 case SH_LEVEL_PRELINK:
337 (void) sh_files_pushfile_prelink(filepath);
338 break;
339 default: /* Should not reach here */
340 break;
341 }
342 }
343 }
344
345 SL_RETURN(0, _("sh_userfiles_init"));
346}
347
348/* This is pretty much NULL; we don't do anything in our checking routine,
349 * so we never need to run it. Just use tcurrent to avoid compiler warnings. */
350int sh_userfiles_timer(time_t tcurrent) {
351 SL_ENTER(_("sh_userfiles_timer"));
352 tcurrent = 0;
353 SL_RETURN((int)tcurrent, _("sh_userfiles_timer"));
354}
355
356int sh_userfiles_check(void) {
357 SL_ENTER(_("sh_userfiles_check"));
358 SL_RETURN(0, _("sh_userfiles_check"));
359}
360
361/* Free our lists and the associated memory */
362
363int sh_userfiles_cleanup(void) {
364 SL_ENTER(_("sh_userfiles_cleanup"));
365
366 sh_userfiles_free_homeslist(userHomes);
367 sh_userfiles_free_fileslist(userFiles);
368 sh_userfiles_free_uidslist (userUids);
369
370 SL_RETURN(0, _("sh_userfiles_cleanup"));
371}
372
373/* As with sh_userfiles_cleanup, but in preparation for re-reading the
374 * configuration files */
375
376int sh_userfiles_reconf(void) {
377 SL_ENTER(_("sh_userfiles_reconf"));
378
379 sh_userfiles_free_homeslist(userHomes);
380 sh_userfiles_free_fileslist(userFiles);
381 sh_userfiles_free_uidslist (userUids);
382
383 userHomes = NULL;
384 userFiles = NULL;
385
386 SL_RETURN(0, _("sh_userfiles_reconf"));
387}
388
389/* Recurse to the end of the list and then free the data as we return
390 * back up towards the start, making sure to free any strdupped strings
391 */
392
393static void sh_userfiles_free_homeslist(struct userhomeslist *head) {
394 if( head != NULL ) {
395 sh_userfiles_free_homeslist(head->next);
396 SH_FREE(head->pw_dir);
397 SH_FREE(head);
398 }
399}
400
401/* Recurse to the end of the list and then free the data as we return
402 * back up towards the start */
403
404static void sh_userfiles_free_fileslist(struct userfileslist *head) {
405 if( head != NULL ) {
406 sh_userfiles_free_fileslist(head->next);
407 SH_FREE(head);
408 }
409}
410
411/* Recurse to the end of the list and then free the data as we return
412 * back up towards the start */
413
414static void sh_userfiles_free_uidslist(struct useruidlist *head) {
415 if( head != NULL ) {
416 sh_userfiles_free_uidslist(head->next);
417 SH_FREE(head);
418 }
419}
420
421/* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
422#endif
423
424/* #ifdef SH_USE_USERFILES */
425#endif
Note: See TracBrowser for help on using the repository browser.