mirror of
https://github.com/Karmaz95/Snake_Apple.git
synced 2026-03-30 14:00:16 +02:00
Uploading LaunchDaemon XPC service example
This commit is contained in:
58
X. NU/custom/mach_ipc/client_server_XPC/Makefile
Normal file
58
X. NU/custom/mach_ipc/client_server_XPC/Makefile
Normal file
@@ -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
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.crimson.xpc.message_service</string>
|
||||
<key>Program</key>
|
||||
<string>/usr/local/bin/crimson_xpc_service</string>
|
||||
<key>MachServices</key>
|
||||
<dict>
|
||||
<key>com.crimson.xpc.message_service</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>KeepAlive</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
62
X. NU/custom/mach_ipc/client_server_XPC/crimson_xpc_client.c
Normal file
62
X. NU/custom/mach_ipc/client_server_XPC/crimson_xpc_client.c
Normal file
@@ -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/xpc.h> // XPC framework for secure inter-process communication
|
||||
#include <dispatch/dispatch.h> // GCD for asynchronous operations and event handling
|
||||
#include <stdio.h> // Standard I/O for error reporting and status messages
|
||||
#include <stdlib.h> // 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();
|
||||
}
|
||||
@@ -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/xpc.h> // XPC for inter-process communication
|
||||
#include <dispatch/dispatch.h> // GCD for asynchronous event handling
|
||||
#include <stdio.h> // 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();
|
||||
}
|
||||
Reference in New Issue
Block a user