Files
zftpd/tests/test_path_security.c
T
Seregon ed3df54225 Add logging, tests, and session improvements
Add a lightweight logging subsystem and MIT headers, enable unit tests, and harden session/path handling.

Key changes:
- Introduce ftp_log.h and src/ftp_log.c for session/command logging and line logging.
- Add MIT license blocks and update file dates across many headers/sources.
- Makefile: include src/ftp_log.c, add LIB_OBJECTS (build objects without main) and multi-test support, PS5 link libSceNotification, and skip tests on unsupported targets.
- Add tests/tests: tests/test_security.c and tests/test_path_security.c and Makefile rules to build/run them.
- Extend ftp_session_t with root_path, control RX buffer, auth flags, and rate-limiter fields; initialize realpath(root) and set socket timeouts during init.
- Add compile-time config knobs in include/ftp_config.h (control/data timeouts, transfer rate limits and burst size).
- Improve RETR/STOR/APPE flows: aggregate bytes sent/received, use new logging hooks, prefer sendfile only when no rate limit, and unify data send path via ftp_session_send_data.
- Strengthen PORT/PASV handling: restrict PORT to same client IP, reuse/close previous pasv socket, bind PASV to INADDR_ANY, and robustly determine local IP for PASV response.
- Enhance path normalization and resolution (ftp_path.c): safer component parsing, realpath checks, and validation against session root to prevent traversal/symlink escapes.
- Add pal API additions in headers (pal_socket_set_timeouts, pal_send_all) and use pal_send_all for control replies.
- Add helper utilities in ftp_session.c (wait_fd_ready, monotonic_ns) and other misc cleanups.

Overall this commit focuses on observability, testability, and security/robustness of session, path and data handling.
2026-02-14 20:32:39 +01:00

76 lines
1.6 KiB
C

#include "ftp_path.h"
#include "ftp_session.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
static int mkdir_p(const char *path)
{
if (mkdir(path, 0700) == 0) {
return 0;
}
return -1;
}
int main(void)
{
char tmpl[] = "/tmp/zftpd-test-XXXXXX";
char *base = mkdtemp(tmpl);
if (base == NULL) {
return 2;
}
char root[FTP_PATH_MAX];
(void)snprintf(root, sizeof(root), "%s/root", base);
if (mkdir_p(root) != 0) {
return 2;
}
char sub[FTP_PATH_MAX];
(void)snprintf(sub, sizeof(sub), "%s/sub", root);
if (mkdir_p(sub) != 0) {
return 2;
}
char linkp[FTP_PATH_MAX];
(void)snprintf(linkp, sizeof(linkp), "%s/out", root);
(void)symlink("/", linkp);
ftp_session_t s;
memset(&s, 0, sizeof(s));
char root_real[FTP_PATH_MAX];
if (realpath(root, root_real) == NULL) {
return 2;
}
(void)snprintf(s.root_path, sizeof(s.root_path), "%s", root_real);
(void)snprintf(s.cwd, sizeof(s.cwd), "%s", root_real);
char out[FTP_PATH_MAX];
ftp_error_t ok = ftp_path_resolve(&s, "sub", out, sizeof(out));
if (ok != FTP_OK) {
return 3;
}
if (ftp_path_is_within_root(out, s.root_path) != 1) {
return 4;
}
ftp_error_t t1 = ftp_path_resolve(&s, "../", out, sizeof(out));
if (t1 != FTP_ERR_PATH_INVALID) {
return 5;
}
ftp_error_t t2 = ftp_path_resolve(&s, "out/etc", out, sizeof(out));
if (t2 != FTP_ERR_PATH_INVALID) {
return 6;
}
unlink(linkp);
rmdir(sub);
rmdir(root);
rmdir(base);
return 0;
}