source: trunk/src/sh_userfiles.c@ 128

Last change on this file since 128 was 111, checked in by rainer, 17 years ago

Fix for ticket #69 (wrappers for name service routines not used everywhere).

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