/* * ================================================================================== * Main Header - ICMP Covert Channel File Transfer Application * * ISA Project * Author: Roman Necas (xnecasr00) * Date: 13. October 2025 * * PURPOSE: * This is the main application header that aggregates all modular headers and * defines the high-level application structures and entry points. It serves as * the central include point for the entire application. * * ARCHITECTURE: * This application follows a modular architecture with 9 core modules: * * 1. secret.c - Main entry point and mode selection (client vs server) * 2. argument_parser.c - Command-line argument processing * 3. network_interface.c - Raw ICMP socket operations * 4. protocol.c - IFTP (ICMP File Transfer Protocol) implementation * 5. crypto_engine.c - AES-256-CBC encryption/decryption * 6. file_manager.c - Chunk-based file I/O * 7. client_engine.c - Client transfer logic * 8. server_engine.c - Server reception logic * 9. state_machine.c - Protocol state machines * 10. error.c - Centralized error handling * 11. utils.c - Utility functions * * HEADER ORGANIZATION: * - common.h: Shared includes, constants, macros, config_t structure * - error.h: Error codes and error handling functions * - crypto.h: Cryptographic types and functions (AES-256-CBC) * - network.h: Network interface types and ICMP operations * - protocol.h: IFTP protocol structures and functions * - file_io.h: File manager types and functions * - state_machine.h: State machine types and functions * - secret.h: This header - aggregates all above, defines server_session_t * * APPLICATION MODES: * - Client mode: Send file via ICMP to specified destination * Usage: secret -r -s * * - Server mode: Listen for ICMP file transfers, save to current directory * Usage: secret -l * * PROTOCOL OVERVIEW: * IFTP (ICMP File Transfer Protocol) is a custom protocol for reliable file * transfer over ICMP Echo-Request/Reply messages: * * 1. Client sends START packet with metadata (filename, size, IV, salt) * 2. Server responds with START-ACK * 3. Client sends DATA packets with encrypted file chunks * 4. Server responds with DATA-ACK for each chunk * 5. Client sends END packet when complete * 6. Server responds with END-ACK * * SECURITY FEATURES: * - AES-256-CBC encryption with PBKDF2 key derivation (600,000 iterations) * - CRC32 checksums for packet integrity * - Path traversal prevention (basename extraction) * - Secure session IDs (cryptographically random) * - Per-transfer unique IV and salt * ================================================================================== */ #ifndef SECRET_H #define SECRET_H /* * ================================================================================== * MODULAR HEADER INCLUDES * ================================================================================== */ /* * common.h - Common definitions, constants, and configuration structure * * Provides: * - Standard library includes (stdio.h, stdlib.h, string.h, etc.) * - Network includes (netinet/ip.h, netinet/icmp6.h, etc.) * - Application constants (MAX_PAYLOAD_SIZE, PBKDF2_ITERATIONS, etc.) * - Utility macros (SAFE_FREE, SAFE_CLOSE, MIN, MAX) * - config_t structure for command-line configuration */ #include "common.h" /* * error.h - Error handling and reporting * * Provides: * - error_code_t enum with all error codes (ERR_SUCCESS, ERR_MEMORY_ALLOC, etc.) * - ERROR_SET macro for setting error context * - error_print_last() for printing errors to stderr * - Thread-safe error context management */ #include "error.h" /* * crypto.h - Cryptographic operations * * Provides: * - crypto_engine_t structure for AES-256-CBC encryption state * - crypto_init(), crypto_encrypt(), crypto_decrypt() functions * - PBKDF2 key derivation with 600,000 iterations * - Secure memory wiping (crypto_secure_zero) */ #include "crypto.h" /* * network.h - Network interface and ICMP operations * * Provides: * - network_interface_t structure for raw socket management * - network_init(), network_send_packet(), network_recv_packet() functions * - Dual-stack IPv4/IPv6 support * - ICMP checksum calculation (IPv4 only, kernel handles IPv6) * - Network statistics tracking (network_stats_t) */ #include "network.h" /* * protocol.h - IFTP protocol implementation * * Provides: * - iftp_header_t structure (24-byte fixed-size header) * - iftp_metadata_t structure (filename, file_size, IV, salt) * - iftp_error_t enum for NACK error codes * - protocol_session_t structure for protocol state * - Message type constants (MSG_TYPE_START, MSG_TYPE_DATA, MSG_TYPE_END, etc.) * - protocol_create_*() functions for packet creation * - protocol_parse_*() functions for packet parsing * - CRC32 checksum validation */ #include "protocol.h" /* * file_io.h - File management and I/O * * Provides: * - file_manager_t structure for chunk-based file I/O * - file_manager_open_read(), file_manager_read_chunk() for client * - file_manager_open_write(), file_manager_write_chunk() for server * - Path security functions (path_is_safe, file_manager_get_basename) * - File transfer statistics (file_transfer_stats_t) */ #include "file_io.h" /* * state_machine.h - Protocol state machines * * Provides: * - client_state_machine_t for client-side state tracking * - server_state_machine_t for server-side state tracking * - client_state_t enum (CLIENT_IDLE, CLIENT_DATA_TRANSFER, etc.) * - server_state_t enum (SERVER_LISTENING, SERVER_RECEIVING_DATA, etc.) * - protocol_event_t enum (EVENT_TIMEOUT, EVENT_ACK_RECEIVED, etc.) * - State transition functions (client_sm_transition, server_sm_transition) * - Timeout handling with exponential backoff * - Error recovery logic */ #include "state_machine.h" /* * ================================================================================== * SERVER SESSION STRUCTURE * ================================================================================== */ /* * server_session_t - Server-side session state for client connection * * This structure maintains all state required for a single file transfer session * on the server side. The server can handle multiple sessions concurrently by * maintaining an array of server_session_t structures, indexed by session_id. * * LIFECYCLE: * 1. Created when START packet received from new client * 2. Initialized with metadata from START packet * 3. Updated as DATA packets received * 4. Cleaned up when END packet received or session times out * * USAGE (Server): * server_session_t sessions[MAX_SESSIONS]; * // On START packet: * server_session_t *session = find_free_session(sessions); * session->session_id = start_packet->session_id; * session->expected_seq = 0; * session->active = 1; * memcpy(&session->client_addr, &src_addr, sizeof(src_addr)); * // On DATA packet: * validate_session_id(packet, session); * validate_sequence_number(packet, session); * decrypt_and_write_chunk(packet, session); * session->expected_seq++; * // On END packet or timeout: * cleanup_session(session); * * THREAD SAFETY: * This structure is NOT thread-safe. If server uses multiple threads to handle * concurrent sessions, each session must be protected by a mutex. * * MEMORY MANAGEMENT: * - reassembly_buffer and received_fragments are dynamically allocated * - Must call cleanup function to free these before discarding structure */ typedef struct { /* * session_id - Unique session identifier (16-bit) * * Extracted from START packet's IFTP header. * Used to match DATA/END packets to this session. * * Range: 0 to 65535 * Generated by client using cryptographically secure random number. * * Multiple sessions can exist simultaneously if server handles multiple * clients concurrently. Each session MUST have unique session_id. */ uint16_t session_id; /* * expected_seq - Expected sequence number in next DATA packet * * Initialized to 0 when START packet received. * Incremented after each valid DATA packet processed. * * Used to: * - Validate received DATA packet has correct seq_num * - Detect duplicate packets (seq_num < expected_seq) → ignore or resend ACK * - Detect skipped packets (seq_num > expected_seq) → NACK with SEQUENCE_ERROR * * Range: 0 to UINT32_MAX */ uint32_t expected_seq; /* * reassembly_buffer - Buffer for reassembling fragmented packets * * Dynamically allocated buffer large enough to hold one complete chunk * (MAX_PAYLOAD_SIZE = 1400 bytes) that may arrive in multiple fragments. * * Allocation: malloc(MAX_PAYLOAD_SIZE) when session created * Deallocation: SAFE_FREE when session cleanup * * Usage: * - Fragment packets are assembled here before decryption * - Once all fragments for a chunk received, decrypt and write to file * - Buffer reused for each chunk * * Note: Current implementation may not use fragmentation (chunk_size ≤ 1400), * but this buffer enables future support for larger chunks. */ uint8_t *reassembly_buffer; /* * received_fragments - Bitmap tracking received fragment numbers * * Dynamically allocated bitmap to track which fragments have been received * for the current chunk. Each bit represents one fragment number. * * Allocation: malloc(fragment_total / 8 + 1) when chunk reception starts * Deallocation: SAFE_FREE when chunk complete or session cleanup * * Usage: * - Set bit N when fragment N received * - Check if all fragments received: count set bits == fragment_total * - Prevents duplicate fragment processing * * Example (fragment_total = 3): * - Initially: [0, 0, 0] * - Fragment 0 received: [1, 0, 0] * - Fragment 2 received: [1, 0, 1] * - Fragment 1 received: [1, 1, 1] → all received, decrypt chunk */ uint8_t *received_fragments; /* * file_size - Expected total file size in bytes * * Extracted from START packet metadata. * Used to: * - Validate transfer completion (bytes_written == file_size) * - Prevent buffer overflows (reject writes exceeding file_size) * - Calculate expected number of DATA packets * - Display progress percentage * * Range: 0 to UINT64_MAX (theoretical max ~16 exabytes) */ uint64_t file_size; /* * filename - Basename of file being received * * Extracted from START packet metadata using file_manager_get_basename(). * Directory components are stripped for security (path traversal prevention). * * Size: MAX_FILENAME_LEN + 1 (256 + 1 = 257 bytes) * Content: Null-terminated string, basename only * * Examples: * - Received: "/etc/passwd" → Stored: "passwd" * - Received: "../../../evil" → Stored: "evil" * - Received: "file.txt" → Stored: "file.txt" * * File is created in server's current working directory with this name. */ char filename[MAX_FILENAME_LEN + 1]; /* * crypto - Crypto engine for decryption * * Initialized when START packet received: * - Extracts IV and salt from metadata * - Derives key using PBKDF2 from login password * - Configures for decryption mode * * Used to decrypt each DATA packet payload. * * Must call crypto_cleanup() when session ends to securely wipe key material. */ crypto_engine_t crypto; /* * file_mgr - File manager for writing received chunks * * Initialized when START packet received: * - Opens file for writing (file_manager_open_write) * - Sets expected file_size from metadata * - Tracks bytes_written progress * * Used to write decrypted chunks to disk. * * Must call file_manager_cleanup() when session ends to close file. */ file_manager_t file_mgr; /* * client_addr - Source address of client * * Extracted from recvfrom() when START packet received. * Used to: * - Send ACK/NACK responses back to client * - Validate that DATA/END packets come from same client * (prevents session hijacking) * * Type: sockaddr_storage (polymorphic, holds IPv4 or IPv6) * Size: 128 bytes (platform-dependent) * * Cast to sockaddr_in or sockaddr_in6 based on client_addr.ss_family: * - AF_INET: IPv4 client * - AF_INET6: IPv6 client */ struct sockaddr_storage client_addr; /* * client_addr_len - Actual length of client_addr * * Typical values: * - IPv4: sizeof(struct sockaddr_in) = 16 bytes * - IPv6: sizeof(struct sockaddr_in6) = 28 bytes * * Used by sendto() when sending ACK/NACK to client. */ socklen_t client_addr_len; /* * active - Session active flag * * Values: * - 1: Session active, processing packets * - 0: Session inactive, slot available for new client * * Set to 1 when START packet received and session initialized. * Set to 0 when: * - END packet received and ACK sent (success) * - Session timeout (client disconnected) * - Error occurred (file write failure, decryption error, etc.) * * Used by find_free_session() to locate available session slot. */ int active; /* * session_start - Session start timestamp (Unix time) * * Set when START packet received using time(NULL). * Used to: * - Calculate total session duration * - Display session age * - Statistics reporting */ time_t session_start; /* * last_activity - Last packet received timestamp * * Updated when valid packet received from client (START, DATA, or END). * Used to detect session timeout: * if (time(NULL) - last_activity) > SESSION_TIMEOUT: * cleanup_session(session) * * Default timeout: SESSION_TIMEOUT (30 seconds) * * Prevents resource leaks from clients that crash or disconnect without * sending END packet. */ time_t last_activity; } server_session_t; /* * ================================================================================== * MAIN APPLICATION ENTRY POINTS * ================================================================================== */ /* * client_run - Execute client mode (send file) * * This function implements the complete client-side file transfer protocol: * 1. Initialize network interface (create raw ICMP socket) * 2. Open file for reading * 3. Initialize crypto engine (generate IV/salt, derive key) * 4. Send START packet with metadata * 5. Wait for START-ACK * 6. Loop: Read chunk → Encrypt → Send DATA → Wait for ACK * 7. Send END packet * 8. Wait for END-ACK * 9. Clean up resources * * ERROR HANDLING: * - Implements retry logic with exponential backoff (max 5 retries) * - Returns -1 on failure (network error, file error, max retries exceeded) * - Returns 0 on success * * REQUIRES: * - Root privileges (raw socket) * - Readable source file * - Network connectivity to destination * * @param config: Configuration structure with: * - config->filename: Path to file to send * - config->server_address: Destination IP or hostname * - config->timeout: Initial timeout in seconds (default: 2) * * @return: * 0: Success - file transferred successfully * -1: Failure - error details in error context (use error_print_last()) */ int client_run(const config_t *config); /* * server_run - Execute server mode (receive files) * * This function implements the complete server-side file reception protocol: * 1. Initialize network interface (create raw ICMP socket) * 2. Enter listening loop: * a. Poll for incoming ICMP packets (non-blocking) * b. Validate packet (magic number, CRC32) * c. Match packet to session (or create new session for START) * d. Process packet based on type: * - START: Create session, extract metadata, open file, send START-ACK * - DATA: Validate sequence, decrypt chunk, write to file, send DATA-ACK * - END: Finalize file, send END-ACK, clean up session * e. Check for session timeouts, clean up inactive sessions * 3. Handle signals (Ctrl+C) for graceful shutdown * 4. Clean up all active sessions before exit * * ERROR HANDLING: * - Sends NACK on recoverable errors (invalid sequence, checksum error) * - Cleans up session on unrecoverable errors (file write failure, decryption error) * - Continues listening after error (does not exit) * - Returns -1 only on fatal errors (socket creation failure) * * REQUIRES: * - Root privileges (raw socket) * - Write permission in current directory (for received files) * * @param config: Configuration structure (server_mode = 1) * * @return: * 0: Success - server shutdown gracefully * -1: Failure - fatal error occurred (use error_print_last()) */ int server_run(const config_t *config); #endif /* SECRET_H */