Seregon/zftpd

Zero-copy FTP/HTTP Daemon compatible with all POSIX systems

C/11.0 KB/No license
tests/test_path_security.c
zftpd / tests / test_path_security.c
1#include "ftp_path.h"
2#include "ftp_session.h"
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <sys/stat.h>
7#include <unistd.h>
8 
9static int mkdir_p(const char *path)
10{
11 if (mkdir(path, 0700) == 0) {
12 return 0;
13 }
14 return -1;
15}
16 
17int main(void)
18{
19 char tmpl[] = "/tmp/zftpd-test-XXXXXX";
20 char *base = mkdtemp(tmpl);
21 if (base == NULL) {
22 return 2;
23 }
24 
25 char root[FTP_PATH_MAX];
26 (void)snprintf(root, sizeof(root), "%s/root", base);
27 if (mkdir_p(root) != 0) {
28 return 2;
29 }
30 
31 char sub[FTP_PATH_MAX];
32 (void)snprintf(sub, sizeof(sub), "%s/sub", root);
33 if (mkdir_p(sub) != 0) {
34 return 2;
35 }
36 
37 char linkp[FTP_PATH_MAX];
38 (void)snprintf(linkp, sizeof(linkp), "%s/out", root);
39 (void)symlink("/", linkp);
40 
41 ftp_session_t s;
42 memset(&s, 0, sizeof(s));
43 char root_real[FTP_PATH_MAX];
44 if (realpath(root, root_real) == NULL) {
45 return 2;
46 }
47 (void)snprintf(s.root_path, sizeof(s.root_path), "%s", root_real);
48 (void)snprintf(s.cwd, sizeof(s.cwd), "%s", root_real);
49 
50 char out[FTP_PATH_MAX];
51 
52 ftp_error_t ok = ftp_path_resolve(&s, "sub", out, sizeof(out));
53 if (ok != FTP_OK) {
54 return 3;
55 }
56 if (ftp_path_is_within_root(out, s.root_path) != 1) {
57 return 4;
58 }
59 
60 ftp_error_t t1 = ftp_path_resolve(&s, "../", out, sizeof(out));
61 if (t1 != FTP_ERR_PATH_INVALID) {
62 return 5;
63 }
64 
65 ftp_error_t t2 = ftp_path_resolve(&s, "out/etc", out, sizeof(out));
66 if (t2 != FTP_ERR_PATH_INVALID) {
67 return 6;
68 }
69 
70 unlink(linkp);
71 rmdir(sub);
72 rmdir(root);
73 rmdir(base);
74 return 0;
75}
76