mirror of
https://github.com/seregonwar/zftpd.git
synced 2026-10-22 11:42:21 -05:00
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.
76 lines
1.6 KiB
C
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;
|
|
}
|