1 #include "../test.h"
2 #include "../builders/build_file.h"
3 #include "../../src/alloc.h"
4 #include "config.h"
5 #include "../../src/client/find.h"
6 #include "../../src/client/find_logic.h"
7 #include "../../src/conffile.h"
8 #include "../../src/fsops.h"
9 #include "../../src/prepend.h"
10 #include "../../src/server/protocol1/link.h"
11 
12 #define BASE		"utest_find"
13 #define CONFBASE	"utest_find_conf"
14 
15 static char fullpath[4096]; // absolute path to base
16 static struct strlist *e=NULL;
17 static struct strlist *expected=NULL;
18 
create_file(const char * path,size_t s)19 static void create_file(const char *path, size_t s)
20 {
21 	FILE *fp;
22 	fail_unless((fp=fopen(path, "wb+"))!=NULL);
23 	while(s-->0)
24 		fail_unless(fprintf(fp, "0")==1);
25 	fail_unless(!fclose(fp));
26 }
27 
send_file_callback(struct asfd * asfd,struct FF_PKT * ff,struct conf ** confs)28 static int send_file_callback(__attribute__ ((unused)) struct asfd *asfd,
29 	struct FF_PKT *ff, __attribute__ ((unused)) struct conf **confs)
30 {
31 	fail_unless(e!=NULL);
32 	fail_unless(!strcmp(e->path, ff->fname));
33 	fail_unless(e->flag==(long)ff->type);
34 	if(ff->type==FT_LNK_S || ff->type==FT_LNK_H)
35 	{
36 		// Putting the link target in the next strlist item.
37 		e=e->next;
38 		fail_unless(!strcmp(e->path, ff->link));
39 		fail_unless(!e->flag);
40 	}
41 	e=e->next;
42 	return 0;
43 }
44 
setup_conf(void)45 static struct conf **setup_conf(void)
46 {
47 	struct conf **confs=NULL;
48 	fail_unless((confs=confs_alloc())!=NULL);
49 	fail_unless(!confs_init(confs));
50 	return confs;
51 }
52 
setup(struct conf *** confs)53 static struct FF_PKT *setup(struct conf ***confs)
54 {
55 	struct FF_PKT *ff;
56 	fail_unless(!recursive_delete(BASE));
57 
58 	// Create the root directory, so that we can figure out the absolute
59 	// path to it, then delete it so that the root directory can be
60 	// included when setting up the expected file system.
61 	fail_unless(!mkdir(BASE, 0777));
62 	fail_unless(realpath(BASE, fullpath)!=NULL);
63 	fail_unless(!recursive_delete(BASE));
64 
65 	fail_unless((ff=find_files_init(send_file_callback))!=NULL);
66 	*confs=setup_conf();
67 	return ff;
68 }
69 
tear_down(struct FF_PKT ** ff,struct conf *** confs)70 static void tear_down(struct FF_PKT **ff, struct conf ***confs)
71 {
72 	fail_unless(e==NULL);
73 	find_files_free(ff);
74 	confs_free(confs);
75 	strlists_free(&expected);
76 	fail_unless(recursive_delete(BASE)==0);
77 	// cleanup our logic caches
78 	free_logic_cache();
79 	alloc_check();
80 }
81 
82 #define NOT_FOUND	0
83 #define FOUND		1
84 
add_file(int find,const char * path,size_t s)85 static void add_file(int find, const char *path, size_t s)
86 {
87 	char *tmp;
88 	fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
89 	create_file(tmp, s);
90 	if(find==FOUND)
91 		fail_unless(!strlist_add(&expected, tmp, (long)FT_REG));
92 	free_w(&tmp);
93 }
94 
add_dir(int find,const char * path)95 static void add_dir(int find, const char *path)
96 {
97 	char *tmp;
98 	fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
99 	fail_unless(!mkdir(tmp, 0777));
100 	if(find==FOUND)
101 		fail_unless(!strlist_add(&expected, tmp, (long)FT_DIR));
102 	free_w(&tmp);
103 }
104 
add_slnk_raw(int find,const char * path,const char * link)105 static void add_slnk_raw(int find, const char *path, const char *link)
106 {
107 	char *tmp;
108 	fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
109 	fail_unless(!symlink(link, tmp));
110 	if(find==FOUND)
111 	{
112 		fail_unless(!strlist_add(&expected, tmp, (long)FT_RAW));
113 	}
114 	free_w(&tmp);
115 }
116 
add_slnk(int find,const char * path,const char * link)117 static void add_slnk(int find, const char *path, const char *link)
118 {
119 	char *tmp;
120 	fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
121 	fail_unless(!symlink(link, tmp));
122 	if(find==FOUND)
123 	{
124 		fail_unless(!strlist_add(&expected, tmp, (long)FT_LNK_S));
125 		fail_unless(!strlist_add(&expected, link, 0));
126 	}
127 	free_w(&tmp);
128 }
129 
add_hlnk(int find,const char * path,const char * link)130 static void add_hlnk(int find, const char *path, const char *link)
131 {
132 	char *src;
133 	char *dst;
134 	fail_unless((src=prepend_s(fullpath, path))!=NULL);
135 	fail_unless((dst=prepend_s(fullpath, link))!=NULL);
136 	fail_unless(!do_link(dst, src, NULL, NULL, 0));
137 	if(find==FOUND)
138 	{
139 		fail_unless(!strlist_add(&expected, src, (long)FT_LNK_H));
140 		fail_unless(!strlist_add(&expected, dst, 0));
141 	}
142 	free_w(&src);
143 	free_w(&dst);
144 }
145 
add_nostat(int find,const char * path)146 static void add_nostat(int find, const char *path)
147 {
148 	char *tmp;
149 	fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
150 	if(find==FOUND)
151 		fail_unless(!strlist_add(&expected, tmp, (long)FT_NOSTAT));
152 	free_w(&tmp);
153 }
154 
add_sock(int find,const char * path)155 static void add_sock(int find, const char *path)
156 {
157 	char *tmp;
158 	long ftype=(long)FT_SPEC;
159 	fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
160 	fail_unless(!mksock(tmp));
161 	if(find==FOUND)
162 		fail_unless(!strlist_add(&expected, tmp, ftype));
163 	free_w(&tmp);
164 }
165 
do_add_fifo(int find,const char * path,mode_t mode,long ftype)166 static void do_add_fifo(int find, const char *path, mode_t mode, long ftype)
167 {
168 	char *tmp;
169 	fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
170 	fail_unless(!mkfifo(tmp, mode));
171 	if(find==FOUND)
172 		fail_unless(!strlist_add(&expected, tmp, ftype));
173 	free_w(&tmp);
174 }
175 
add_fifo(int find,const char * path)176 static void add_fifo(int find, const char *path)
177 {
178 	do_add_fifo(find, path, S_IFIFO, (long)FT_FIFO);
179 }
180 
add_fifo_special(int find,const char * path)181 static void add_fifo_special(int find, const char *path)
182 {
183 	do_add_fifo(find, path, S_IFIFO, (long)FT_SPEC);
184 }
185 
run_find(const char * buf,struct FF_PKT * ff,struct conf ** confs)186 static void run_find(const char *buf, struct FF_PKT *ff, struct conf **confs)
187 {
188 	struct strlist *l;
189 	const char *conffile=CONFBASE "/burp.conf";
190 	fail_unless(!recursive_delete(CONFBASE));
191 	build_file(conffile, buf);
192 	fail_unless(!conf_load_global_only(conffile, confs));
193 	for(l=get_strlist(confs[OPT_STARTDIR]); l; l=l->next) if(l->flag)
194                 fail_unless(!find_files_begin(NULL, ff, confs, l->path));
195 	fail_unless(!recursive_delete(CONFBASE));
196 }
197 
198 static char extra_config[8192]="";
199 
do_test(void setup_entries (void))200 static void do_test(void setup_entries(void))
201 {
202 	struct FF_PKT *ff;
203 	char *buf=NULL;
204 	struct conf **confs=NULL;
205 	ff=setup(&confs);
206 
207 	setup_entries();
208 	e=expected;
209 
210 	fail_unless(!astrcat(&buf, MIN_CLIENT_CONF, __func__));
211 	fail_unless(!astrcat(&buf, extra_config, __func__));
212 
213 	run_find(buf, ff, confs);
214 
215 	free_w(&buf);
216 	tear_down(&ff, &confs);
217 }
218 
simple_entries(void)219 static void simple_entries(void)
220 {
221 	add_dir( FOUND, "");
222 	add_file(FOUND, "a", 1);
223 	add_file(FOUND, "b", 2);
224 	add_file(FOUND, "c", 3);
225 	add_dir (FOUND, "d");
226 	add_slnk(FOUND, "e", "a");
227 	add_hlnk(FOUND, "f", "a");
228 	add_hlnk(FOUND, "g", "a");
229 	add_fifo_special(FOUND, "h");
230 	add_sock(FOUND, "i");
231 	snprintf(extra_config, sizeof(extra_config), "include=%s", fullpath);
232 }
233 
min_file_size(void)234 static void min_file_size(void)
235 {
236 	add_dir(     FOUND, "");
237 	add_file(NOT_FOUND, "a", 1);
238 	add_file(    FOUND, "b", 2);
239 	add_file(    FOUND, "c", 3);
240 	add_dir (    FOUND, "d");
241 	snprintf(extra_config, sizeof(extra_config),
242 		"include=%s\nmin_file_size=2", fullpath);
243 }
244 
max_file_size(void)245 static void max_file_size(void)
246 {
247 	add_dir(     FOUND, "");
248 	add_file(    FOUND, "a", 1);
249 	add_file(    FOUND, "b", 2);
250 	add_file(NOT_FOUND, "c", 3);
251 	add_dir (    FOUND, "d");
252 	snprintf(extra_config, sizeof(extra_config),
253 		"include=%s\nmax_file_size=2", fullpath);
254 }
255 
exclude_extension(void)256 static void exclude_extension(void)
257 {
258 	add_dir(     FOUND, "");
259 	add_file(NOT_FOUND, "a.c", 1);
260 	add_file(NOT_FOUND, "a.h", 2);
261 	add_file(    FOUND, "b",   2);
262 	add_file(    FOUND, "b.x", 2);
263 	add_file(NOT_FOUND, "c.c", 3);
264 	add_dir (    FOUND, "d");
265 	snprintf(extra_config, sizeof(extra_config),
266 		"include=%s\n"
267 		"exclude_ext=c\n"
268 		"exclude_ext=h\n", fullpath);
269 }
270 
include_extension(void)271 static void include_extension(void)
272 {
273 	add_dir(     FOUND, "");
274 	add_file(    FOUND, "a.c", 1);
275 	add_file(    FOUND, "a.h", 2);
276 	add_file(NOT_FOUND, "b",   2);
277 	add_file(NOT_FOUND, "b.x", 2);
278 	add_file(    FOUND, "c.c", 3);
279 	add_dir (NOT_FOUND, "d");
280 	add_file(    FOUND, "d/e.c", 3);
281 	snprintf(extra_config, sizeof(extra_config),
282 		"include=%s\n"
283 		"include_ext=c\n"
284 		"include_ext=h\n", fullpath);
285 }
286 
exclude_dir(void)287 static void exclude_dir(void)
288 {
289 	add_dir(     FOUND, "");
290 	add_file(    FOUND, "a",   1);
291 	add_dir (NOT_FOUND, "d");
292 	add_file(NOT_FOUND, "d/x", 1);
293 	add_file(    FOUND, "e",   3);
294 	snprintf(extra_config, sizeof(extra_config),
295 		"include=%s\n"
296 		"exclude=%s/d\n",
297 		fullpath, fullpath);
298 }
299 
include_inside_exclude(void)300 static void include_inside_exclude(void)
301 {
302 	add_dir(     FOUND, "");
303 	add_file(    FOUND, "a",       1);
304 	add_dir (NOT_FOUND, "d");
305 	add_file(NOT_FOUND, "d/b",     1);
306 	add_dir (    FOUND, "d/i");
307 	add_file(    FOUND, "d/i/m",   2);
308 	add_file(NOT_FOUND, "d/x",     1);
309 	add_file(    FOUND, "e",       3);
310 	snprintf(extra_config, sizeof(extra_config),
311 		"include=%s\n"
312 		"exclude=%s/d\n"
313 		"include=%s/d/i\n",
314 		fullpath, fullpath, fullpath);
315 }
316 
nobackup(void)317 static void nobackup(void)
318 {
319 	add_dir(     FOUND, "");
320 	add_file(    FOUND, "a",   1);
321 	add_dir (    FOUND, "d");
322 	add_file(NOT_FOUND, "d/.nobackup", 0);
323 	add_file(NOT_FOUND, "d/b", 1);
324 	add_dir (NOT_FOUND, "d/i");
325 	add_file(NOT_FOUND, "d/x", 1);
326 	add_file(    FOUND, "e",   3);
327 	add_dir (    FOUND, "f");
328 	add_file(NOT_FOUND, "f/.exclude", 0);
329 	add_file(NOT_FOUND, "f/b", 1);
330 	add_dir (    FOUND, "g");
331 	snprintf(extra_config, sizeof(extra_config),
332 		"include=%s\n"
333 		"nobackup=.nobackup\n"
334 		"nobackup=.exclude\n",
335 		fullpath);
336 }
337 
symlink_as_blockdev(void)338 static void symlink_as_blockdev(void)
339 {
340 	add_dir(     FOUND, "");
341 	add_file(    FOUND, "a",   1);
342 	add_slnk_raw(FOUND, "e", "a");
343 	add_slnk_raw(FOUND, "f", "a");
344 	snprintf(extra_config, sizeof(extra_config),
345 		"include=%s\n"
346 		"read_blockdev=%s/e\n"
347 		"read_blockdev=%s/f\n",
348 		fullpath, fullpath, fullpath);
349 }
350 
fifo_individual(void)351 static void fifo_individual(void)
352 {
353 	add_dir(     FOUND, "");
354 	add_fifo(    FOUND, "a");
355 	add_fifo(    FOUND, "b");
356 	add_fifo_special(FOUND, "c");
357 	snprintf(extra_config, sizeof(extra_config),
358 		"include=%s\n"
359 		"read_fifo=%s/a\n"
360 		"read_fifo=%s/b\n",
361 		fullpath, fullpath, fullpath);
362 }
363 
fifo_all(void)364 static void fifo_all(void)
365 {
366 	add_dir(     FOUND, "");
367 	add_fifo(    FOUND, "a");
368 	add_fifo(    FOUND, "b");
369 	snprintf(extra_config, sizeof(extra_config),
370 		"include=%s\n"
371 		"read_all_fifos=1\n",
372 		fullpath);
373 }
374 
exclude_regex(void)375 static void exclude_regex(void)
376 {
377 	add_dir(     FOUND, "");
378 	add_file(    FOUND, "a", 1);
379 	add_file(    FOUND, "b", 1);
380 	add_file(    FOUND, "c", 1);
381 	add_file(NOT_FOUND, "dnotthisone", 1);
382 	add_dir (    FOUND, "e");
383 	add_dir (NOT_FOUND, "e/fexc");
384 	add_file(NOT_FOUND, "fnotthisone", 1);
385 	snprintf(extra_config, sizeof(extra_config),
386 		"include=%s\n"
387 		"exclude_regex=not\n"
388 		"exclude_regex=exc\n",
389 		fullpath);
390 }
391 
include_regex(void)392 static void include_regex(void)
393 {
394 	add_dir( NOT_FOUND, "");
395 	add_file(    FOUND, "a", 1);
396 	add_file(NOT_FOUND, "blah", 1);
397 	add_file(    FOUND, "blahb", 1);
398 	add_file(    FOUND, "haaa", 1);
399 	add_file(NOT_FOUND, "x", 1);
400 	snprintf(extra_config, sizeof(extra_config),
401 		"include=%s\n"
402 		"include_regex=a$\n"
403 		"include_regex=b$\n",
404 		fullpath);
405 }
406 
exclude_logic(void)407 static void exclude_logic(void)
408 {
409 	add_dir(     FOUND, "");
410 	add_file(    FOUND, "a", 2);
411 	add_file(NOT_FOUND, "a.ost", 6);
412 	add_file(    FOUND, "b.ost", 2);
413 	add_file(NOT_FOUND, "caa", 15);
414 	add_file(NOT_FOUND, "cbb", 16);
415 	add_file(    FOUND, "cc", 15);
416 	add_file(    FOUND, "haaaab", 9);
417 	add_file(NOT_FOUND, "haaab", 8);
418 	add_file(NOT_FOUND, "y", 4);
419 	add_file(    FOUND, "z", 2);
420 	snprintf(extra_config, sizeof(extra_config),
421 		 "include=%s\n"
422 		 "exclude_logic=file_size>=5 and file_ext=ost\n"
423 		 "exclude_logic=(file_size>=3 and file_size<=5) or (file_size=8 and path_match=^%s/.*b$)\n"
424 		 "exclude_logic=(file_size>=10 and file_size<=20) and (file_ext=zoro or file_match='^c(a|b)')\n"
425 		 "exclude_logic=(file_size>=30 or file_size<2\n"
426 		 "exclude_logic=this expression isnt valid\n"
427 		 "exclude_logic=another unvalid expression\n",
428 		 fullpath, fullpath);
429 }
430 
multi_includes(void)431 static void multi_includes(void)
432 {
433 	add_dir( NOT_FOUND, "");
434 	add_file(    FOUND, "a", 1);
435 	add_file(NOT_FOUND, "b", 2);
436 	add_file(NOT_FOUND, "c", 3);
437 	add_dir (    FOUND, "d");
438 	add_dir (    FOUND, "d/a");
439 	add_dir (NOT_FOUND, "d/a/b");
440 	add_dir (    FOUND, "d/a/b/c");
441 	add_nostat(  FOUND, "d/a/b/c/d");
442 	add_nostat(  FOUND, "d/a/b/c/d/e");
443 	add_slnk(NOT_FOUND, "e", "a");
444 	add_hlnk(NOT_FOUND, "g", "a");
445 	snprintf(extra_config, sizeof(extra_config),
446 		"include=%s/a\n"
447 		"include=%s/d\n"
448 		"exclude=%s/d/a/b\n"
449 		"include=%s/d/a/b/c\n"
450 		"include=%s/d/a/b/c/d\n"
451 		"include=%s/d/a/b/c/d/e\n",
452 		fullpath, fullpath, fullpath, fullpath, fullpath, fullpath);
453 }
454 
START_TEST(test_find)455 START_TEST(test_find)
456 {
457 	do_test(simple_entries);
458 	do_test(min_file_size);
459 	do_test(max_file_size);
460 	do_test(exclude_extension);
461 	do_test(include_extension);
462 	do_test(exclude_dir);
463 	do_test(include_inside_exclude);
464 	do_test(nobackup);
465 	do_test(symlink_as_blockdev);
466 	do_test(fifo_individual);
467 	do_test(fifo_all);
468 	do_test(exclude_regex);
469 	do_test(include_regex);
470 	do_test(multi_includes);
471 	do_test(exclude_logic);
472 }
473 END_TEST
474 
START_TEST(test_large_file_support)475 START_TEST(test_large_file_support)
476 {
477 	// 32 bit machines need the correct build parameters to support
478 	// large files. Try to detect problems here.
479 	fail_unless(sizeof(off_t)>=8);
480 }
481 END_TEST
482 
START_TEST(test_file_is_included_no_incext)483 START_TEST(test_file_is_included_no_incext)
484 {
485 	struct conf **confs;
486 	confs=setup_conf();
487 	add_to_strlist(confs[OPT_INCEXCDIR], "/", 1);
488 	add_to_strlist(confs[OPT_INCEXCDIR], "/blah", 0);
489 	add_to_strlist(confs[OPT_INCEXCDIR], "/tmp", 0);
490 	add_to_strlist(confs[OPT_INCEXCDIR], "/tmp/some/sub/dir", 1);
491 
492 	fail_unless(file_is_included_no_incext(confs, "/blah2"));
493 	fail_unless(file_is_included_no_incext(confs, "/blah2/blah3"));
494 	fail_unless(file_is_included_no_incext(confs, "/tmp/some/sub/dir/1"));
495 	fail_unless(!file_is_included_no_incext(confs, "/tmp"));
496 	fail_unless(!file_is_included_no_incext(confs, "/tmp/blah"));
497 	fail_unless(!file_is_included_no_incext(confs, "/tmp/some/sub"));
498 
499 	confs_free(&confs);
500 	alloc_check();
501 }
502 END_TEST
503 
suite_client_find(void)504 Suite *suite_client_find(void)
505 {
506 	Suite *s;
507 	TCase *tc_core;
508 
509 	s=suite_create("client_find");
510 
511 	tc_core=tcase_create("Core");
512 
513 	tcase_add_test(tc_core, test_find);
514 	tcase_add_test(tc_core, test_large_file_support);
515 	tcase_add_test(tc_core, test_file_is_included_no_incext);
516 	suite_add_tcase(s, tc_core);
517 
518 	return s;
519 }
520