source: trunk/src/sh_userfiles.c@ 19

Last change on this file since 19 was 1, checked in by katerina, 19 years ago

Initial import

File size: 12.0 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 (char * str)
118{
119 char * end;
120 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(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, "prelink") != NULL ) new->level = SH_LEVEL_PRELINK;
224 else /* The default */ new->level = default_level;
225
226 SH_FREE(orig);
227
228 SL_RETURN(0, _("sh_userfiles_add_file") );
229}
230
231/* Decide if we're active. 1 means yes, all else means no */
232
233int sh_userfiles_set_active(char *c) {
234 int value;
235
236 SL_ENTER(_("sh_userfiles_set_active"));
237
238 value = sh_util_flagval(c, &ShUserfilesActive);
239
240 /*
241 if( value == 1 ) {
242 ShUserfilesActive = S_TRUE;
243 } else {
244 ShUserfilesActive = S_FALSE;
245 }
246 */
247
248 SL_RETURN((value), _("sh_userfiles_set_active"));
249}
250
251/* Build the list of users, then use this to construct the filenames to
252 * be checked. */
253int sh_userfiles_init(void) {
254 struct passwd *cur_user;
255 struct userhomeslist *end;
256 struct userhomeslist *new;
257 struct userhomeslist *homes;
258
259 SL_ENTER(_("sh_userfiles_init"));
260
261 /* We need to free anything allocated by the configuration functions if
262 * we find that the module is to be left inactive - otherwise _reconf()
263 * won't quite work. */
264 if( ShUserfilesActive == S_FALSE ) {
265 sh_userfiles_free_homeslist(userHomes);
266 sh_userfiles_free_fileslist(userFiles);
267 userHomes = NULL;
268 userFiles = NULL;
269 SL_RETURN(-1, _("sh_userfiles_init"));
270 }
271
272 /* We build a list in here because the samhain internals want to use
273 * getpwent() too */
274 /*@-unrecog@*/
275 setpwent();
276 /*@+unrecog@*/
277 while( ( cur_user = /*@-unrecog@*/getpwent()/*@+unrecog@*/ ) != NULL ) {
278 int found = 0;
279
280 if (0 == sh_userfiles_check_uid( (unsigned long) cur_user->pw_uid))
281 continue;
282
283 for( end = userHomes; end != NULL; end = end->next ) {
284 if( sl_strcmp( end->pw_dir, cur_user->pw_dir) == 0 ) {
285 found = 1; /* Found a match, so flag it and stop searching */
286 break;
287 }
288 }
289
290 if( found == 0 ) {
291 /* Didn't find it, so add to the front of the list */
292 new = SH_ALLOC(sizeof(struct userhomeslist) );
293 new->next = userHomes;
294 new->pw_dir = sh_util_strdup(cur_user->pw_dir);
295
296 userHomes = new;
297 }
298 }
299
300 for (homes = userHomes; homes != NULL; homes = homes->next ) {
301 struct userfileslist *file_ptr;
302 char filepath[PATH_MAX];
303
304 for (file_ptr = userFiles; file_ptr != NULL; file_ptr = file_ptr->next) {
305 (void) sl_strncpy(filepath, homes->pw_dir, PATH_MAX);
306 (void) sl_strncat(filepath, "/", PATH_MAX);
307 (void) sl_strncat(filepath, file_ptr->filename, PATH_MAX);
308
309 switch(file_ptr->level) {
310 case SH_LEVEL_READONLY:
311 (void) sh_files_pushfile_ro(filepath);
312 break;
313 case SH_LEVEL_LOGFILES:
314 (void) sh_files_pushfile_log(filepath);
315 break;
316 case SH_LEVEL_LOGGROW:
317 (void) sh_files_pushfile_glog(filepath);
318 break;
319 case SH_LEVEL_NOIGNORE:
320 (void) sh_files_pushfile_noig(filepath);
321 break;
322 case SH_LEVEL_ALLIGNORE:
323 (void) sh_files_pushfile_allig(filepath);
324 break;
325 case SH_LEVEL_ATTRIBUTES:
326 (void) sh_files_pushfile_attr(filepath);
327 break;
328 case SH_LEVEL_USER0:
329 (void) sh_files_pushfile_user0(filepath);
330 break;
331 case SH_LEVEL_USER1:
332 (void) sh_files_pushfile_user1(filepath);
333 break;
334 case SH_LEVEL_PRELINK:
335 (void) sh_files_pushfile_prelink(filepath);
336 break;
337 default: /* Should not reach here */
338 break;
339 }
340 }
341 }
342
343 SL_RETURN(0, _("sh_userfiles_init"));
344}
345
346/* This is pretty much NULL; we don't do anything in our checking routine,
347 * so we never need to run it. Just use tcurrent to avoid compiler warnings. */
348int sh_userfiles_timer(time_t tcurrent) {
349 SL_ENTER(_("sh_userfiles_timer"));
350 tcurrent = 0;
351 SL_RETURN((int)tcurrent, _("sh_userfiles_timer"));
352}
353
354int sh_userfiles_check(void) {
355 SL_ENTER(_("sh_userfiles_check"));
356 SL_RETURN(0, _("sh_userfiles_check"));
357}
358
359/* Free our lists and the associated memory */
360
361int sh_userfiles_cleanup(void) {
362 SL_ENTER(_("sh_userfiles_cleanup"));
363
364 sh_userfiles_free_homeslist(userHomes);
365 sh_userfiles_free_fileslist(userFiles);
366 sh_userfiles_free_uidslist (userUids);
367
368 SL_RETURN(0, _("sh_userfiles_cleanup"));
369}
370
371/* As with sh_userfiles_cleanup, but in preparation for re-reading the
372 * configuration files */
373
374int sh_userfiles_reconf(void) {
375 SL_ENTER(_("sh_userfiles_reconf"));
376
377 sh_userfiles_free_homeslist(userHomes);
378 sh_userfiles_free_fileslist(userFiles);
379 sh_userfiles_free_uidslist (userUids);
380
381 userHomes = NULL;
382 userFiles = NULL;
383
384 SL_RETURN(0, _("sh_userfiles_reconf"));
385}
386
387/* Recurse to the end of the list and then free the data as we return
388 * back up towards the start, making sure to free any strdupped strings
389 */
390
391static void sh_userfiles_free_homeslist(struct userhomeslist *head) {
392 if( head != NULL ) {
393 sh_userfiles_free_homeslist(head->next);
394 SH_FREE(head->pw_dir);
395 SH_FREE(head);
396 }
397}
398
399/* Recurse to the end of the list and then free the data as we return
400 * back up towards the start */
401
402static void sh_userfiles_free_fileslist(struct userfileslist *head) {
403 if( head != NULL ) {
404 sh_userfiles_free_fileslist(head->next);
405 SH_FREE(head);
406 }
407}
408
409/* Recurse to the end of the list and then free the data as we return
410 * back up towards the start */
411
412static void sh_userfiles_free_uidslist(struct useruidlist *head) {
413 if( head != NULL ) {
414 sh_userfiles_free_uidslist(head->next);
415 SH_FREE(head);
416 }
417}
418
419/* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
420#endif
421
422/* #ifdef SH_USE_USERFILES */
423#endif
Note: See TracBrowser for help on using the repository browser.