Files
zftpd/include/ftp_protocol.h
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

165 lines
4.9 KiB
C

/*
MIT License
Copyright (c) 2026 Seregon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* @file ftp_protocol.h
* @brief FTP protocol parsing and command dispatch
*
* @author SeregonWar
* @version 1.0.0
* @date 2026-02-13
*
* PROTOCOL: RFC 959 (File Transfer Protocol)
* EXTENSIONS: RFC 3659 (MLST, MLSD, SIZE)
*
*/
#ifndef FTP_PROTOCOL_H
#define FTP_PROTOCOL_H
#include "ftp_types.h"
/*===========================================================================*
* COMMAND PARSING
*===========================================================================*/
/**
* @brief Parse FTP command line
*
* Splits "COMMAND arguments\r\n" into command and arguments.
*
* EXAMPLES:
* "USER anonymous\r\n" -> command="USER", args="anonymous"
* "PWD\r\n" -> command="PWD", args=NULL
* "CWD /home/user\r\n" -> command="CWD", args="/home/user"
*
* @param line Input command line (null-terminated)
* @param command Output buffer for command name
* @param args Output buffer for arguments (may be NULL)
* @param cmd_size Size of command buffer
* @param args_size Size of args buffer
*
* @return FTP_OK on success, negative error code on failure
* @retval FTP_OK Command parsed successfully
* @retval FTP_ERR_INVALID_PARAM Invalid parameters
* @retval FTP_ERR_PROTOCOL Malformed command line
*
* @pre line != NULL
* @pre command != NULL
* @pre cmd_size > 0
*
* @post command contains uppercase command name
* @post args is NULL or contains arguments (trimmed)
*
* @note Thread-safety: Safe (no shared state)
* @note WCET: O(n) where n = strlen(line)
*/
ftp_error_t ftp_parse_command_line(const char *line,
char *command,
char *args,
size_t cmd_size,
size_t args_size);
/**
* @brief Find command handler by name
*
* @param name Command name (case-insensitive)
*
* @return Pointer to command entry, or NULL if not found
*
* @pre name != NULL
*
* @note Thread-safety: Safe (command table is const)
* @note WCET: O(n) where n = number of commands (~30)
*/
const ftp_command_entry_t* ftp_find_command(const char *name);
/**
* @brief Validate command arguments
*
* Checks if arguments match command requirements:
* - ARGS_NONE: No arguments allowed
* - ARGS_REQUIRED: Arguments must be present
* - ARGS_OPTIONAL: Arguments optional
*
* @param cmd Command entry
* @param args Arguments string (NULL if none)
*
* @return FTP_OK if valid, negative error code otherwise
*
* @pre cmd != NULL
*/
ftp_error_t ftp_validate_command_args(const ftp_command_entry_t *cmd,
const char *args);
/**
* @brief Get command table
*
* @param count Output parameter for command count
*
* @return Pointer to command table
*
* @pre count != NULL
*
* @post *count contains number of commands
*/
const ftp_command_entry_t* ftp_get_command_table(size_t *count);
/*===========================================================================*
* REPLY FORMATTING
*===========================================================================*/
/**
* @brief Format FTP reply message
*
* Creates RFC 959-compliant reply: "CODE Message\r\n"
*
* @param code FTP reply code (200-599)
* @param message Reply message (NULL for default)
* @param buffer Output buffer
* @param size Size of output buffer
*
* @return Number of bytes written, or negative on error
*
* @pre buffer != NULL
* @pre size >= 64
*
* @post buffer contains formatted reply
*/
ssize_t ftp_format_reply(ftp_reply_code_t code,
const char *message,
char *buffer,
size_t size);
/**
* @brief Get default message for reply code
*
* @param code FTP reply code
*
* @return Default message string, or NULL if unknown
*/
const char* ftp_get_default_reply_message(ftp_reply_code_t code);
#endif /* FTP_PROTOCOL_H */