Projects/3BIT/winter-semester/ISA/include/common.h
2026-04-14 19:28:46 +02:00

414 lines
14 KiB
C

/*
* ==================================================================================
* 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 <stdio.h> /* Standard I/O (printf, fprintf, FILE) */
#include <stdlib.h> /* Memory allocation (malloc, free), exit codes */
#include <string.h> /* String operations (memcpy, strlen, strcmp) */
#include <unistd.h> /* POSIX API (getuid, access, close) */
#include <getopt.h> /* Command-line argument parsing (getopt) */
#include <errno.h> /* Error number definitions (errno) */
#include <signal.h> /* Signal handling (not currently used but available) */
#include <time.h> /* Time functions (time, localtime, strftime) */
#include <ctype.h> /* Character type checking (isalnum, isdigit) */
/* POSIX socket and system headers */
#include <sys/socket.h> /* Socket API (socket, bind, sendto, recvfrom) */
#include <sys/types.h> /* Data types (size_t, ssize_t, pid_t) */
#include <sys/time.h> /* Time structures (timeval for socket timeouts) */
#include <sys/stat.h> /* File status (stat, access) */
#include <fcntl.h> /* File control (open flags, fcntl for non-blocking) */
/* Network protocol headers - BSD sockets */
#include <netinet/in.h> /* Internet address structures (sockaddr_in, sockaddr_in6) */
#include <netinet/ip.h> /* IPv4 header structure (struct iphdr) */
#include <netinet/ip_icmp.h> /* ICMPv4 structures (struct icmphdr, ICMP_ECHO, ICMP_ECHOREPLY) */
#include <netinet/ip6.h> /* IPv6 header structure (struct ip6_hdr) */
#include <netinet/icmp6.h> /* ICMPv6 structures (struct icmp6_hdr, ICMP6_ECHO_REQUEST, ICMP6_ECHO_REPLY) */
#include <arpa/inet.h> /* Internet operations (inet_pton, inet_ntop, htons, ntohs) */
#include <netdb.h> /* 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 <file> -s <destination>
* - 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 */