486 lines
17 KiB
C
486 lines
17 KiB
C
/*
|
|
* ==================================================================================
|
|
* 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 <file> -s <ip|hostname>
|
|
*
|
|
* - 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 */
|