source: trunk/src/sh_userfiles.c@ 50

Last change on this file since 50 was 27, checked in by rainer, 19 years ago

Support for server-to-server relay and more user policies

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