/* * ================================================================================== * Common Header - Shared definitions and utilities for ISA ICMP Covert Channel * * ISA Project * Author: Roman Necas (xnecasr00) * Date: 13. October 2025 * * PURPOSE: * This header file serves as the central repository for all common definitions, * constants, macros, and data structures used throughout the application. It is * included by virtually every module in the project. * * CONTENTS: * - System and POSIX includes * - Network-related includes (BSD sockets, ICMP) * - Application-wide constants and limits * - Common data structures (config_t) * - Utility macros (SAFE_FREE, SAFE_CLOSE, etc.) * - Global variable declarations * - Function prototypes for utility functions * ================================================================================== */ #ifndef COMMON_H #define COMMON_H /* * ================================================================================== * SYSTEM INCLUDES * ================================================================================== */ /* Enable GNU extensions and POSIX features */ #define _GNU_SOURCE /* Standard C library headers */ #include /* Standard I/O (printf, fprintf, FILE) */ #include /* Memory allocation (malloc, free), exit codes */ #include /* String operations (memcpy, strlen, strcmp) */ #include /* POSIX API (getuid, access, close) */ #include /* Command-line argument parsing (getopt) */ #include /* Error number definitions (errno) */ #include /* Signal handling (not currently used but available) */ #include /* Time functions (time, localtime, strftime) */ #include /* Character type checking (isalnum, isdigit) */ /* POSIX socket and system headers */ #include /* Socket API (socket, bind, sendto, recvfrom) */ #include /* Data types (size_t, ssize_t, pid_t) */ #include /* Time structures (timeval for socket timeouts) */ #include /* File status (stat, access) */ #include /* File control (open flags, fcntl for non-blocking) */ /* Network protocol headers - BSD sockets */ #include /* Internet address structures (sockaddr_in, sockaddr_in6) */ #include /* IPv4 header structure (struct iphdr) */ #include /* ICMPv4 structures (struct icmphdr, ICMP_ECHO, ICMP_ECHOREPLY) */ #include /* IPv6 header structure (struct ip6_hdr) */ #include /* ICMPv6 structures (struct icmp6_hdr, ICMP6_ECHO_REQUEST, ICMP6_ECHO_REPLY) */ #include /* Internet operations (inet_pton, inet_ntop, htons, ntohs) */ #include /* Network database (getaddrinfo for hostname resolution) */ /* * ================================================================================== * APPLICATION CONSTANTS * ================================================================================== */ /* Application identification */ #define APP_NAME "secret" /* Application binary name */ /* * BUFFER AND SIZE LIMITS * ---------------------- * These constants define the maximum sizes for various buffers and data structures. * They are carefully chosen to balance functionality with security and memory usage. */ /* Maximum ICMP payload size (1400 bytes) * This is chosen to stay well within the typical MTU (1500 bytes) while leaving * room for IP header (20 bytes IPv4/40 bytes IPv6) and ICMP header (8 bytes). * Formula: 1500 (MTU) - 20 (IP) - 8 (ICMP) - 48 (IFTP header) = 1424 bytes safe * We use 1400 for additional safety margin. */ #define MAX_PAYLOAD_SIZE 1400 /* Maximum filename length (255 bytes) * Matches the typical filesystem limit for filename components. This does not * include the directory path, only the filename itself. */ #define MAX_FILENAME_LEN 255 /* General-purpose buffer size (2048 bytes) * Used for temporary operations like packet reception, string formatting, etc. * Large enough to hold any ICMP packet including IP header and payload. */ #define MAX_BUFFER_SIZE 2048 /* Maximum path length (4096 bytes) * Matches Linux PATH_MAX constant. Used for validating file paths provided * by the user on the command line. */ #define MAX_PATH_LEN 4096 /* * NETWORK CONFIGURATION * --------------------- * Timeout and retry parameters for reliable communication over ICMP. */ /* Maximum number of retry attempts for failed transmissions * After this many retries, the operation is considered failed. */ #define MAX_RETRIES 5 /* Initial timeout value in seconds * Time to wait for ACK response before retrying. This value increases * exponentially with each retry (exponential backoff). */ #define INITIAL_TIMEOUT 2 /* Maximum timeout value in seconds * Upper limit for exponential backoff. Prevents waiting too long. */ #define MAX_TIMEOUT 30 /* * ================================================================================== * APPLICATION MODE ENUMERATION * ================================================================================== */ /* * app_mode_t - Operating mode of the application * * The application can run in one of two modes: * - CLIENT: Sends a file to a remote server via ICMP * - SERVER: Listens for incoming ICMP packets and receives files * * The mode is determined by command-line arguments: * - Client requires: -r -s * - Server requires: -l */ typedef enum { MODE_CLIENT = 0, /* Client mode: transmit file via ICMP Echo Request */ MODE_SERVER = 1 /* Server mode: listen for ICMP Echo Request and save file */ } app_mode_t; /* * ================================================================================== * UTILITY MACROS * ================================================================================== */ /* Get the number of elements in an array * Usage: ARRAY_SIZE(my_array) returns the element count * Note: Only works with arrays, not pointers */ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) /* Return the maximum of two values */ #define MAX(a, b) ((a) > (b) ? (a) : (b)) /* Return the minimum of two values */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) /* * SAFE MEMORY AND RESOURCE MANAGEMENT MACROS * ------------------------------------------- * These macros provide safe wrappers around common operations that prevent * common bugs like double-free and resource leaks. */ /* * SAFE_FREE - Safely free memory and set pointer to NULL * * This macro prevents double-free bugs by: * 1. Checking if the pointer is non-NULL * 2. Calling free() * 3. Setting the pointer to NULL * * After SAFE_FREE(ptr), the pointer is guaranteed to be NULL, making * subsequent SAFE_FREE calls safe (they become no-ops). * * Usage: * char *buffer = malloc(100); * SAFE_FREE(buffer); // buffer is now NULL * SAFE_FREE(buffer); // safe - does nothing */ #define SAFE_FREE(ptr) do { \ if (ptr) { \ free(ptr); \ ptr = NULL; \ } \ } while(0) /* * SAFE_CLOSE - Safely close file descriptor and set to -1 * * This macro prevents double-close bugs and resource leaks by: * 1. Checking if the file descriptor is valid (>= 0) * 2. Calling close() * 3. Setting the descriptor to -1 * * After SAFE_CLOSE(fd), the descriptor is -1, making subsequent * SAFE_CLOSE calls safe (they become no-ops). * * Usage: * int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); * SAFE_CLOSE(sockfd); // sockfd is now -1 * SAFE_CLOSE(sockfd); // safe - does nothing */ #define SAFE_CLOSE(fd) do { \ if (fd >= 0) { \ close(fd); \ fd = -1; \ } \ } while(0) /* * ================================================================================== * APPLICATION CONFIGURATION STRUCTURE * ================================================================================== */ /* * config_t - Application runtime configuration * * This structure holds all configuration parameters parsed from command-line * arguments. It is populated by parse_arguments() and passed to client_run() * or server_run() to control application behavior. * * LIFECYCLE: * 1. Initialized (zeroed) in main() * 2. Populated by parse_arguments() * 3. Used by client_run() or server_run() * 4. Cleaned up by cleanup_config() * * MEMORY MANAGEMENT: * Fields marked with (*) are dynamically allocated and must be freed. * Use cleanup_config() to properly release all resources. */ typedef struct { /* Source file path for transfer (CLIENT MODE ONLY) * (*) Dynamically allocated - freed by cleanup_config() * Example: "/home/user/document.pdf" */ char *source_file; /* Destination IP address or hostname (CLIENT MODE ONLY) * (*) Dynamically allocated - freed by cleanup_config() * Examples: "192.168.1.100", "::1", "hostname.example.com" */ char *dest_address; /* Operating mode - CLIENT or SERVER */ app_mode_t mode; /* Listen mode flag (1 = server mode, 0 = client mode) * This is redundant with 'mode' field but kept for backward compatibility */ int listen_mode; /* Timeout in seconds for network operations * Default: INITIAL_TIMEOUT (2 seconds) * Range: 1-300 seconds (validated by argument parser) */ int timeout_seconds; /* Maximum retry attempts for failed operations * Default: MAX_RETRIES (5 attempts) */ int max_retries; } config_t; /* * ================================================================================== * GLOBAL VARIABLES * ================================================================================== */ /* * login - User's login name used as encryption password * * SECURITY NOTE: * This global variable holds the login name which is used as the password * for PBKDF2 key derivation. In this implementation, it is hardcoded to * "xnecasr00" as required by the assignment specification. * * USAGE: * - Set in argument_parser.c during initialization * - Used by crypto_engine.c for AES-256 key derivation via PBKDF2 * - Both client and server must use the same login for successful decryption * * REQUIREMENT: * According to the assignment specification, the login name must be used * as the encryption key. This creates a shared secret between client and * server running under the same username. */ extern char *login; /* * ================================================================================== * FUNCTION DECLARATIONS * ================================================================================== */ /* * Command-line argument parsing * ------------------------------ */ /* * parse_arguments - Parse and validate command-line arguments * * Processes command-line arguments and populates the config structure. * Performs comprehensive validation of all inputs including: * - File existence and readability (client mode) * - IP address/hostname format validation * - Timeout range validation * - Root privilege verification * * @param argc: Argument count from main() * @param argv: Argument vector from main() * @param config: Configuration structure to populate (output parameter) * * @return: * >0 : Help was displayed (normal exit) * 0 : Arguments parsed successfully * -1 : Error occurred (details in error context) */ int parse_arguments(int argc, char *argv[], config_t *config); /* * print_usage - Display usage information to stderr * * Prints comprehensive help text including: * - Syntax and options * - Usage examples for client and server modes * - Security notes and requirements * * @param progname: Name of the program (typically argv[0]) */ void print_usage(const char *progname); /* * print_error - Print error message to stderr * * Convenience function that outputs an error message to stderr * and logs it to the error handling system. * * @param message: Error message to display */ void print_error(const char *message); /* * cleanup_config - Free resources allocated in config structure * * Releases all dynamically allocated memory in the config_t structure. * Safe to call multiple times (uses SAFE_FREE internally). * * @param config: Configuration structure to clean up */ void cleanup_config(config_t *config); /* * Filename validation and security * --------------------------------- */ /* * validate_filename - Validate filename for security * * Performs security checks on a filename to prevent: * - Path traversal attacks (.. sequences) * - Absolute path abuse * - Invalid characters * - Control characters * * This is critical for server-side security when receiving filenames * from untrusted clients. * * @param filename: Filename to validate * @return: 0 on success, -1 if filename is invalid */ int validate_filename(const char *filename); /* * get_safe_filename - Extract safe filename from path * * Extracts the basename from a path and ensures the resulting filename * is safe to use. If a file with that name already exists, appends a * numeric suffix (_1, _2, etc.) to avoid overwriting. * * SECURITY: * This function strips all directory components from the input path, * preventing directory traversal attacks. * * @param original_filename: Input filename (may include path) * @param safe_filename: Output buffer for safe filename * @param max_len: Maximum length of output buffer * @return: 0 on success, -1 on error */ int get_safe_filename(const char *original_filename, char *safe_filename, size_t max_len); /* * Session management * ------------------ */ /* * generate_secure_session_id - Generate cryptographically secure session ID * * Creates a random 16-bit session identifier using OpenSSL's RAND_bytes() * for cryptographic quality randomness. This ensures session IDs are * unpredictable and unique. * * SECURITY: * Uses RAND_bytes() from OpenSSL for cryptographic randomness. Falls back * to less secure rand() only if RAND_bytes() fails (extremely rare). * * @return: 16-bit session ID (never returns 0) */ uint16_t generate_secure_session_id(void); #endif /* COMMON_H */