1 /*
2 * ProFTPD - FTP server testsuite
3 * Copyright (c) 2008-2017 The ProFTPD Project team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 *
19 * As a special exemption, The ProFTPD Project team and other respective
20 * copyright holders give permission to link this program with OpenSSL, and
21 * distribute the resulting executable, without including the source code for
22 * OpenSSL in the source distribution.
23 */
24
25 /* Modules API tests */
26
27 #include "tests.h"
28
29 extern module *loaded_modules;
30
31 static pool *p = NULL;
32
set_up(void)33 static void set_up(void) {
34 if (p == NULL) {
35 p = permanent_pool = make_sub_pool(NULL);
36 }
37
38 modules_init();
39 }
40
tear_down(void)41 static void tear_down(void) {
42 loaded_modules = NULL;
43
44 if (p) {
45 destroy_pool(p);
46 p = permanent_pool = NULL;
47 }
48 }
49
50 /* Tests */
51
52 static int sess_init_eperm = FALSE;
53
module_sess_init_cb(void)54 static int module_sess_init_cb(void) {
55 if (sess_init_eperm) {
56 sess_init_eperm = FALSE;
57 errno = EPERM;
58 return -1;
59 }
60
61 return 0;
62 }
63
START_TEST(module_sess_init_test)64 START_TEST (module_sess_init_test) {
65 int res;
66 module m;
67
68 res = modules_session_init();
69 fail_unless(res == 0, "Failed to initialize modules: %s", strerror(errno));
70
71 memset(&m, 0, sizeof(m));
72 m.name = "testsuite";
73
74 loaded_modules = &m;
75 res = modules_session_init();
76 fail_unless(res == 0, "Failed to initialize modules: %s", strerror(errno));
77
78 m.sess_init = module_sess_init_cb;
79 res = modules_session_init();
80 fail_unless(res == 0, "Failed to initialize modules: %s", strerror(errno));
81
82 sess_init_eperm = TRUE;
83 res = modules_session_init();
84 fail_unless(res < 0, "Initialized modules unexpectedly");
85 fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
86 strerror(errno), errno);
87
88 loaded_modules = NULL;
89 }
90 END_TEST
91
START_TEST(module_command_exists_test)92 START_TEST (module_command_exists_test) {
93 int res;
94
95 res = command_exists(NULL);
96 fail_unless(res == FALSE, "Expected FALSE, got %d", res);
97 }
98 END_TEST
99
START_TEST(module_exists_test)100 START_TEST (module_exists_test) {
101 unsigned char res;
102 module m;
103
104 res = pr_module_exists(NULL);
105 fail_unless(res == FALSE, "Failed to handle null argument");
106 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
107 strerror(errno), errno);
108
109 res = pr_module_exists("mod_foo.c");
110 fail_unless(res == FALSE, "Failed to handle nonexistent module");
111 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
112 strerror(errno), errno);
113
114 memset(&m, 0, sizeof(m));
115 m.name = "bar";
116
117 loaded_modules = &m;
118
119 res = pr_module_exists("mod_foo.c");
120 fail_unless(res == FALSE, "Failed to handle nonexistent module");
121 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
122 strerror(errno), errno);
123
124 res = pr_module_exists("mod_bar.c");
125 fail_unless(res == TRUE, "Failed to detect existing module");
126
127 res = pr_module_exists("mod_BAR.c");
128 fail_unless(res == FALSE, "Failed to handle nonexistent module");
129 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
130 strerror(errno), errno);
131
132 loaded_modules = NULL;
133 }
134 END_TEST
135
START_TEST(module_get_test)136 START_TEST (module_get_test) {
137 module m, *res;
138
139 res = pr_module_get(NULL);
140 fail_unless(res == NULL, "Failed to handle null argument");
141 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
142 strerror(errno), errno);
143
144 res = pr_module_get("mod_foo.c");
145 fail_unless(res == NULL, "Failed to handle nonexistent module");
146 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
147 strerror(errno), errno);
148
149 memset(&m, 0, sizeof(m));
150 m.name = "bar";
151
152 loaded_modules = &m;
153
154 res = pr_module_get("mod_foo.c");
155 fail_unless(res == NULL, "Failed to handle nonexistent module");
156 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
157 strerror(errno), errno);
158
159 res = pr_module_get("mod_bar.c");
160 fail_unless(res != NULL, "Failed to detect existing module");
161 fail_unless(res == &m, "Expected %p, got %p", &m, res);
162
163 res = pr_module_get("mod_BAR.c");
164 fail_unless(res == NULL, "Failed to handle nonexistent module");
165 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
166 strerror(errno), errno);
167
168 loaded_modules = NULL;
169 }
170 END_TEST
171
172 static unsigned int listed = 0;
module_listf(const char * fmt,...)173 static int module_listf(const char *fmt, ...) {
174 listed++;
175 return 0;
176 }
177
START_TEST(module_list_test)178 START_TEST (module_list_test) {
179 module m, m2;
180
181 mark_point();
182 listed = 0;
183 modules_list2(module_listf, 0);
184 fail_unless(listed > 0, "Expected >0, got %u", listed);
185
186 memset(&m, 0, sizeof(m));
187 m.name = "testsuite";
188 m.module_version = "a.b";
189
190 memset(&m2, 0, sizeof(m2));
191 m2.name = "testsuite2";
192
193 m.next = &m2;
194 loaded_modules = &m;
195
196 mark_point();
197 listed = 0;
198 modules_list2(module_listf, PR_MODULES_LIST_FL_SHOW_STATIC);
199 fail_unless(listed > 0, "Expected >0, got %u", listed);
200
201 mark_point();
202 listed = 0;
203 modules_list2(module_listf, PR_MODULES_LIST_FL_SHOW_VERSION);
204 fail_unless(listed > 0, "Expected >0, got %u", listed);
205
206 mark_point();
207 modules_list(PR_MODULES_LIST_FL_SHOW_STATIC);
208
209 loaded_modules = NULL;
210 }
211 END_TEST
212
init_cb(void)213 static int init_cb(void) {
214 errno = EACCES;
215 return -1;
216 }
217
START_TEST(module_load_test)218 START_TEST (module_load_test) {
219 int res;
220 module m;
221
222 res = pr_module_load(NULL);
223 fail_unless(res < 0, "Failed to handle null argument");
224 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
225 strerror(errno), errno);
226
227 memset(&m, 0, sizeof(m));
228
229 res = pr_module_load(&m);
230 fail_unless(res < 0, "Failed to handle null name");
231 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
232 strerror(errno), errno);
233
234 m.name = "foo";
235
236 res = pr_module_load(&m);
237 fail_unless(res < 0, "Failed to handle badly versioned module");
238 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
239 strerror(errno), errno);
240
241 m.api_version = PR_MODULE_API_VERSION;
242 m.init = init_cb;
243
244 res = pr_module_load(&m);
245 fail_unless(res < 0, "Failed to handle bad module init callback");
246 fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
247 strerror(errno), errno);
248
249 m.init = NULL;
250
251 res = pr_module_load(&m);
252 fail_unless(res == 0, "Failed to load module: %s", strerror(errno));
253
254 res = pr_module_load(&m);
255 fail_unless(res < 0, "Failed to handle duplicate module load");
256 fail_unless(errno == EEXIST, "Expected EEXIST (%d), got %s (%d)", EEXIST,
257 strerror(errno), errno);
258 }
259 END_TEST
260
START_TEST(module_unload_test)261 START_TEST (module_unload_test) {
262 int res;
263 module m;
264 authtable authtab[] = {
265 { 0, "setpwent", NULL },
266 { 0, NULL, NULL }
267 };
268 cmdtable cmdtab[] = {
269 { CMD, C_RETR, G_READ, NULL, TRUE, FALSE, CL_READ },
270 { HOOK, "foo", G_READ, NULL, FALSE, FALSE },
271 { 0, NULL }
272 };
273 conftable conftab[] = {
274 { "TestSuite", NULL, NULL },
275 { NULL }
276 };
277
278 res = pr_module_unload(NULL);
279 fail_unless(res < 0, "Failed to handle null argument");
280 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
281 strerror(errno), errno);
282
283 memset(&m, 0, sizeof(m));
284
285 res = pr_module_unload(&m);
286 fail_unless(res < 0, "Failed to handle null module name");
287 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
288 strerror(errno), errno);
289
290 m.name = "bar";
291
292 res = pr_module_unload(&m);
293 fail_unless(res < 0, "Failed to handle nonexistent module");
294 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
295 strerror(errno), errno);
296
297 loaded_modules = &m;
298
299 res = pr_module_unload(&m);
300 fail_unless(res == 0, "Failed to unload module: %s", strerror(errno));
301
302 res = pr_module_unload(&m);
303 fail_unless(res < 0, "Failed to handle nonexistent module");
304 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
305 strerror(errno), errno);
306
307 m.authtable = authtab;
308 m.cmdtable = cmdtab;
309 m.conftable = conftab;
310 loaded_modules = &m;
311
312 res = pr_module_unload(&m);
313 fail_unless(res == 0, "Failed to unload module: %s", strerror(errno));
314
315 loaded_modules = NULL;
316 }
317 END_TEST
318
START_TEST(module_load_authtab_test)319 START_TEST (module_load_authtab_test) {
320 int res;
321 module m;
322 authtable authtab[] = {
323 { 0, "setpwent", NULL },
324 { 0, NULL, NULL }
325 };
326
327 res = pr_module_load_authtab(NULL);
328 fail_unless(res < 0, "Failed to handle null arguments");
329 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
330 strerror(errno), errno);
331
332 memset(&m, 0, sizeof(m));
333
334 res = pr_module_load_authtab(&m);
335 fail_unless(res < 0, "Failed to handle null module name");
336 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
337 strerror(errno), errno);
338
339 m.name = "testsuite";
340 res = pr_module_load_authtab(&m);
341 fail_unless(res == 0, "Failed to load module authtab: %s", strerror(errno));
342
343 pr_module_unload(&m);
344 fail_unless(res == 0, "Failed to unload module: %s", strerror(errno));
345
346 m.authtable = authtab;
347 res = pr_module_load_authtab(&m);
348 fail_unless(res == 0, "Failed to load module authtab: %s", strerror(errno));
349
350 pr_module_unload(&m);
351 fail_unless(res == 0, "Failed to unload module: %s", strerror(errno));
352 }
353 END_TEST
354
START_TEST(module_load_cmdtab_test)355 START_TEST (module_load_cmdtab_test) {
356 int res;
357 module m;
358 cmdtable cmdtab[] = {
359 { CMD, C_RETR, G_READ, NULL, TRUE, FALSE, CL_READ },
360 { HOOK, "foo", G_READ, NULL, FALSE, FALSE },
361 { 0, NULL }
362 };
363
364 res = pr_module_load_cmdtab(NULL);
365 fail_unless(res < 0, "Failed to handle null arguments");
366 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
367 strerror(errno), errno);
368
369 memset(&m, 0, sizeof(m));
370
371 res = pr_module_load_cmdtab(&m);
372 fail_unless(res < 0, "Failed to handle null module name");
373 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
374 strerror(errno), errno);
375
376 m.name = "testsuite";
377 res = pr_module_load_cmdtab(&m);
378 fail_unless(res == 0, "Failed to load module cmdtab: %s", strerror(errno));
379
380 pr_module_unload(&m);
381 fail_unless(res == 0, "Failed to unload module: %s", strerror(errno));
382
383 m.name = "testsuite";
384 m.cmdtable = cmdtab;
385 res = pr_module_load_cmdtab(&m);
386 fail_unless(res == 0, "Failed to load module cmdtab: %s", strerror(errno));
387
388 pr_module_unload(&m);
389 fail_unless(res == 0, "Failed to unload module: %s", strerror(errno));
390 }
391 END_TEST
392
START_TEST(module_load_conftab_test)393 START_TEST (module_load_conftab_test) {
394 int res;
395 module m;
396 conftable conftab[] = {
397 { "TestSuite", NULL, NULL },
398 { NULL }
399 };
400
401 res = pr_module_load_conftab(NULL);
402 fail_unless(res < 0, "Failed to handle null arguments");
403 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
404 strerror(errno), errno);
405
406 memset(&m, 0, sizeof(m));
407
408 res = pr_module_load_conftab(&m);
409 fail_unless(res < 0, "Failed to handle null module name");
410 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
411 strerror(errno), errno);
412
413 m.name = "testsuite";
414 res = pr_module_load_conftab(&m);
415 fail_unless(res == 0, "Failed to load module conftab: %s", strerror(errno));
416
417 pr_module_unload(&m);
418 fail_unless(res == 0, "Failed to unload module: %s", strerror(errno));
419
420 m.conftable = conftab;
421 res = pr_module_load_conftab(&m);
422 fail_unless(res == 0, "Failed to load module conftab: %s", strerror(errno));
423
424 pr_module_unload(&m);
425 fail_unless(res == 0, "Failed to unload module: %s", strerror(errno));
426 }
427 END_TEST
428
call_cb(cmd_rec * cmd)429 static modret_t *call_cb(cmd_rec *cmd) {
430 return PR_HANDLED(cmd);
431 }
432
START_TEST(module_call_test)433 START_TEST (module_call_test) {
434 modret_t *res;
435 module m;
436 cmd_rec *cmd;
437
438 res = pr_module_call(NULL, NULL, NULL);
439 fail_unless(res == NULL, "Failed to handle null arguments");
440 fail_unless(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
441 errno);
442
443 memset(&m, 0, sizeof(m));
444
445 res = pr_module_call(&m, NULL, NULL);
446 fail_unless(res == NULL, "Failed to handle null callback, cmd arguments");
447 fail_unless(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
448 errno);
449
450 res = pr_module_call(NULL, call_cb, NULL);
451 fail_unless(res == NULL, "Failed to handle null module, cmd arguments");
452 fail_unless(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
453 errno);
454
455 cmd = pcalloc(p, sizeof(cmd_rec));
456 cmd->pool = p;
457
458 res = pr_module_call(NULL, NULL, cmd);
459 fail_unless(res == NULL, "Failed to handle null module, callback arguments");
460 fail_unless(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
461 errno);
462
463 res = pr_module_call(&m, call_cb, NULL);
464 fail_unless(res == NULL, "Failed to handle null cmd argument");
465 fail_unless(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
466 errno);
467
468 res = pr_module_call(&m, NULL, cmd);
469 fail_unless(res == NULL, "Failed to handle null callback argument");
470 fail_unless(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
471 errno);
472
473 res = pr_module_call(NULL, call_cb, cmd);
474 fail_unless(res == NULL, "Failed to handle null module argument");
475 fail_unless(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
476 errno);
477
478 res = pr_module_call(&m, call_cb, cmd);
479 fail_unless(res != NULL, "Failed to call function: %s", strerror(errno));
480 fail_unless(MODRET_ISHANDLED(res), "Expected HANDLED result");
481 }
482 END_TEST
483
START_TEST(module_create_ret_test)484 START_TEST (module_create_ret_test) {
485 cmd_rec *cmd;
486 modret_t *mr;
487 char *numeric, *msg;
488
489 mr = mod_create_ret(NULL, 0, NULL, NULL);
490 fail_unless(mr == NULL, "Failed to handle null arguments");
491 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
492 strerror(errno), errno);
493
494 cmd = pr_cmd_alloc(p, 1, "testsuite");
495 mr = mod_create_ret(cmd, 1, NULL, NULL);
496 fail_unless(mr != NULL, "Failed to create modret: %s", strerror(errno));
497 fail_unless(mr->mr_error == 1, "Expected 1, got %d", mr->mr_error);
498 fail_unless(mr->mr_numeric == NULL, "Expected null, got '%s'",
499 mr->mr_numeric);
500 fail_unless(mr->mr_message == NULL, "Expected null, got '%s'",
501 mr->mr_message);
502
503 numeric = "foo";
504 msg = "bar";
505 mr = mod_create_ret(cmd, 1, numeric, msg);
506 fail_unless(mr != NULL, "Failed to create modret: %s", strerror(errno));
507 fail_unless(mr->mr_error == 1, "Expected 1, got %d", mr->mr_error);
508 fail_unless(mr->mr_numeric != NULL, "Expected '%s', got null");
509 fail_unless(strcmp(mr->mr_numeric, numeric) == 0,
510 "Expected '%s', got '%s'", numeric, mr->mr_numeric);
511 fail_unless(mr->mr_message != NULL, "Expected '%s', got null");
512 fail_unless(strcmp(mr->mr_message, msg) == 0,
513 "Expected '%s', got '%s'", msg, mr->mr_message);
514 }
515 END_TEST
516
START_TEST(module_create_error_test)517 START_TEST (module_create_error_test) {
518 cmd_rec *cmd;
519 modret_t *mr;
520
521 mr = mod_create_error(NULL, 0);
522 fail_unless(mr == NULL, "Failed to handle null arguments");
523 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
524 strerror(errno), errno);
525
526 cmd = pr_cmd_alloc(p, 1, "testsuite");
527 mr = mod_create_error(cmd, 1);
528 fail_unless(mr != NULL, "Failed to create modret: %s", strerror(errno));
529 fail_unless(mr->mr_error == 1, "Expected 1, got %d", mr->mr_error);
530 }
531 END_TEST
532
START_TEST(module_create_data_test)533 START_TEST (module_create_data_test) {
534 cmd_rec *cmd;
535 modret_t *mr;
536 int data = 1;
537
538 mr = mod_create_data(NULL, NULL);
539 fail_unless(mr == NULL, "Failed to handle null arguments");
540 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
541 strerror(errno), errno);
542
543 cmd = pr_cmd_alloc(p, 1, "testsuite");
544 mr = mod_create_data(cmd, &data);
545 fail_unless(mr != NULL, "Failed to create modret: %s", strerror(errno));
546 fail_unless(mr->data == &data, "Expected %p, got %p", &data, mr->data);
547 }
548 END_TEST
549
tests_get_modules_suite(void)550 Suite *tests_get_modules_suite(void) {
551 Suite *suite;
552 TCase *testcase;
553
554 suite = suite_create("modules");
555
556 testcase = tcase_create("module");
557 tcase_add_checked_fixture(testcase, set_up, tear_down);
558
559 tcase_add_test(testcase, module_sess_init_test);
560 tcase_add_test(testcase, module_command_exists_test);
561 tcase_add_test(testcase, module_exists_test);
562 tcase_add_test(testcase, module_get_test);
563 tcase_add_test(testcase, module_list_test);
564 tcase_add_test(testcase, module_load_test);
565 tcase_add_test(testcase, module_unload_test);
566 tcase_add_test(testcase, module_load_authtab_test);
567 tcase_add_test(testcase, module_load_cmdtab_test);
568 tcase_add_test(testcase, module_load_conftab_test);
569 tcase_add_test(testcase, module_call_test);
570
571 tcase_add_test(testcase, module_create_ret_test);
572 tcase_add_test(testcase, module_create_error_test);
573 tcase_add_test(testcase, module_create_data_test);
574
575 suite_add_tcase(suite, testcase);
576 return suite;
577 }
578