diff --git a/X. NU/custom/mach_ipc/client_server_XPC/Makefile b/X. NU/custom/mach_ipc/client_server_XPC/Makefile new file mode 100644 index 0000000..60a7139 --- /dev/null +++ b/X. NU/custom/mach_ipc/client_server_XPC/Makefile @@ -0,0 +1,58 @@ +# Compiler and flags +CC = gcc +CFLAGS = -Wall -Wextra -O2 # Enable warnings and basic optimization +FRAMEWORKS = -framework Foundation + +# Binary names and paths +SERVICE_NAME = crimson_xpc_service +CLIENT_NAME = crimson_xpc_client +INSTALL_PATH = /usr/local/bin +LAUNCHD_PATH = /Library/LaunchDaemons +PLIST_NAME = com.crimson.xpc.message_service.plist + +# Source files +SERVICE_SRC = crimson_xpc_service.c +CLIENT_SRC = crimson_xpc_client.c + +# Default target builds both executables +all: $(SERVICE_NAME) $(CLIENT_NAME) + +# Build the XPC service +$(SERVICE_NAME): $(SERVICE_SRC) + $(CC) $(CFLAGS) -o $@ $< $(FRAMEWORKS) + +# Build the XPC client +$(CLIENT_NAME): $(CLIENT_SRC) + $(CC) $(CFLAGS) -o $@ $< $(FRAMEWORKS) + +# Install everything (requires sudo) +install: all + @echo "Installing XPC service and client..." + sudo cp $(SERVICE_NAME) $(INSTALL_PATH)/ + sudo cp $(PLIST_NAME) $(LAUNCHD_PATH)/ + sudo launchctl unload $(LAUNCHD_PATH)/$(PLIST_NAME) 2>/dev/null || true + sudo launchctl load $(LAUNCHD_PATH)/$(PLIST_NAME) + @echo "Installation complete" + +# Clean up compiled files +clean: + rm -f $(SERVICE_NAME) $(CLIENT_NAME) + +# Uninstall everything (requires sudo) +uninstall: + @echo "Uninstalling XPC service and client..." + sudo launchctl unload $(LAUNCHD_PATH)/$(PLIST_NAME) 2>/dev/null || true + sudo rm -f $(INSTALL_PATH)/$(SERVICE_NAME) + sudo rm -f $(LAUNCHD_PATH)/$(PLIST_NAME) + @echo "Uninstallation complete" + +# Help target to show available commands +help: + @echo "Available targets:" + @echo " make all - Build both service and client" + @echo " make install - Install and load the service (requires sudo)" + @echo " make clean - Remove compiled files" + @echo " make uninstall - Remove installed files (requires sudo)" + +# Declare our phony targets (targets that don't create files) +.PHONY: all install clean uninstall help \ No newline at end of file diff --git a/X. NU/custom/mach_ipc/client_server_XPC/com.crimson.xpc.message_service.plist b/X. NU/custom/mach_ipc/client_server_XPC/com.crimson.xpc.message_service.plist new file mode 100644 index 0000000..65d8fb5 --- /dev/null +++ b/X. NU/custom/mach_ipc/client_server_XPC/com.crimson.xpc.message_service.plist @@ -0,0 +1,17 @@ + + + + + Label + com.crimson.xpc.message_service + Program + /usr/local/bin/crimson_xpc_service + MachServices + + com.crimson.xpc.message_service + + + KeepAlive + + + \ No newline at end of file diff --git a/X. NU/custom/mach_ipc/client_server_XPC/crimson_xpc_client.c b/X. NU/custom/mach_ipc/client_server_XPC/crimson_xpc_client.c new file mode 100644 index 0000000..0bda7d5 --- /dev/null +++ b/X. NU/custom/mach_ipc/client_server_XPC/crimson_xpc_client.c @@ -0,0 +1,62 @@ +// crimson_xpc_client.c +// This client demonstrates how to create and manage an XPC connection to communicate +// with a LaunchDaemon or LaunchAgent service + +#include // XPC framework for secure inter-process communication +#include // GCD for asynchronous operations and event handling +#include // Standard I/O for error reporting and status messages +#include // Standard library for program termination functions + +int main(void) { + // Initialize an XPC connection to a Mach service + // The service name must match the label in the service's plist file + // XPC_CONNECTION_MACH_SERVICE_PRIVILEGED indicates this client expects + // to connect to a privileged service (typically a LaunchDaemon) + xpc_connection_t conn = xpc_connection_create_mach_service( + "com.crimson.xpc.message_service", + dispatch_get_main_queue(), // Main queue handles all connection events + XPC_CONNECTION_MACH_SERVICE_PRIVILEGED + ); + + // Configure an event handler for connection-level events + // This handler processes XPC_TYPE_ERROR events, which occur on + // connection failures, service termination, or invalid messages + xpc_connection_set_event_handler(conn, ^(xpc_object_t event) { + if (xpc_get_type(event) == XPC_TYPE_ERROR) { + fprintf(stderr, "Connection error: %s\n", + xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); + } + }); + + // Activate the connection to begin processing events + // Must be called before any messages can be sent + xpc_connection_resume(conn); + + // Create an XPC dictionary to encapsulate the message data + // XPC dictionaries are the primary container type for XPC messages + xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_string(message, "message_data", "Hello from Crimson!"); + + // Send message and handle response asynchronously + // The reply block executes when the service responds or on timeout + xpc_connection_send_message_with_reply(conn, message, + dispatch_get_main_queue(), ^(xpc_object_t reply) { + if (xpc_get_type(reply) == XPC_TYPE_DICTIONARY) { + printf("Reply status: %s\n", + xpc_dictionary_get_string(reply, "status")); + } + // Schedule program termination after reply processing + // Using dispatch_async ensures clean shutdown + dispatch_async(dispatch_get_main_queue(), ^{ + exit(0); + }); + }); + + // Decrement the message object's reference count + // XPC uses manual reference counting for memory management + xpc_release(message); + + // Run the main dispatch loop to process asynchronous events + // This call never returns - program exits via the reply handler + dispatch_main(); +} \ No newline at end of file diff --git a/X. NU/custom/mach_ipc/client_server_XPC/crimson_xpc_service.c b/X. NU/custom/mach_ipc/client_server_XPC/crimson_xpc_service.c new file mode 100644 index 0000000..7c74212 --- /dev/null +++ b/X. NU/custom/mach_ipc/client_server_XPC/crimson_xpc_service.c @@ -0,0 +1,57 @@ +// crimson_xpc_service.c +// This implements an XPC service that can be launched as a LaunchDaemon or LaunchAgent +// It demonstrates basic XPC message handling and connection management patterns + +#include // XPC for inter-process communication +#include // GCD for asynchronous event handling +#include // Standard I/O for logging messages + +int main(void) { + // Initialize the XPC service listener + // XPC_CONNECTION_MACH_SERVICE_LISTENER indicates this process will accept incoming connections + // The service name must match both the client and the service's launchd plist MachServices entry + xpc_connection_t service = xpc_connection_create_mach_service( + "com.crimson.xpc.message_service", + dispatch_get_main_queue(), // Main queue handles all service events + XPC_CONNECTION_MACH_SERVICE_LISTENER + ); + + // Set up handler for new client connections + // This outer handler processes connection establishment events + // Each new client connection creates a new peer object + xpc_connection_set_event_handler(service, ^(xpc_object_t peer) { + // Security check: Validate connection object type + // Early return prevents processing of invalid connection attempts + if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) return; + + // Configure message handler for this specific client connection + // Each client gets its own message handler to maintain separation + xpc_connection_set_event_handler(peer, ^(xpc_object_t message) { + // Only process dictionary-type messages for protocol compliance + if (xpc_get_type(message) == XPC_TYPE_DICTIONARY) { + // Extract message data with bounds checking via len parameter + // This prevents buffer overflow vulnerabilities + size_t len; + const void* data = xpc_dictionary_get_data(message, "message_data", &len); + if (data) printf("Received: %.*s\n", (int)len, (char*)data); + + // Create and send reply to the client + // xpc_dictionary_create_reply maintains message context for proper routing + xpc_object_t reply = xpc_dictionary_create_reply(message); + xpc_dictionary_set_string(reply, "status", "received"); + xpc_connection_send_message(peer, reply); + xpc_release(reply); // Clean up reply object to prevent memory leaks + } + }); + + // Activate this client's connection to begin processing its messages + xpc_connection_resume(peer); + }); + + // Activate the service listener to begin accepting connections + xpc_connection_resume(service); + + // Run the main dispatch loop + // This service will continue running until terminated by launchd + dispatch_main(); +} \ No newline at end of file