X-Git-Url: https://git.saurik.com/apple/ipsec.git/blobdiff_plain/65c257469f746e64364e5df94f3ed8c6698a9d0a..e627a751fc4d26304657fc20440abb72632b1e6e:/ipsec-tools/racoon/session.c diff --git a/ipsec-tools/racoon/session.c b/ipsec-tools/racoon/session.c index f561076..208ff5d 100644 --- a/ipsec-tools/racoon/session.c +++ b/ipsec-tools/racoon/session.c @@ -68,10 +68,10 @@ #include #include -#include #include #include #include +#include #include "libpfkey.h" @@ -104,6 +104,9 @@ #include "sainfo.h" #include "power_mgmt.h" +#include +#include +#include extern pid_t racoon_pid; @@ -111,7 +114,6 @@ extern int launchdlaunched; static void close_session (int); static int init_signal (void); static int set_signal (int sig, RETSIGTYPE (*func) (int, siginfo_t *, void *)); -static void check_sigreq (void); static void check_flushsa_stub (void *); static void check_flushsa (void); static void auto_exit_do (void *); @@ -119,11 +121,14 @@ static int close_sockets (void); static volatile sig_atomic_t sigreq[NSIG + 1]; int terminated = 0; +int pending_signal_handle = 0; static int64_t racoon_keepalive = -1; dispatch_queue_t main_queue; +static NEPolicySessionRef policySession = NULL; + /* * This is used to (manually) update racoon's launchd keepalive, which is needed because racoon is (mostly) * launched on demand and for requires a keepalive on dirty/failure exits. @@ -146,6 +151,85 @@ launchd_update_racoon_keepalive (Boolean enabled) return racoon_keepalive; } +static CFUUIDRef +copy_racoon_proc_uuid(void) +{ + struct proc_uniqidentifierinfo procu; + CFUUIDBytes uuidBytes; + int size = 0; + + memset(&procu, 0, sizeof(procu)); + size = proc_pidinfo(getpid(), PROC_PIDUNIQIDENTIFIERINFO, 1, &procu, PROC_PIDUNIQIDENTIFIERINFO_SIZE); + if (size != PROC_PIDUNIQIDENTIFIERINFO_SIZE) { + return (NULL); + } + + memcpy(&uuidBytes, procu.p_uuid, sizeof(CFUUIDBytes)); + return CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, uuidBytes); +} + +static bool +policy_session_init(void) +{ + bool success = true; + policySession = NEPolicyCreateSession(kCFAllocatorDefault, CFSTR("racoon"), NULL, NULL); + if (policySession == NULL) { + return false; + } + + CFUUIDRef proc_uuid = copy_racoon_proc_uuid(); + if (proc_uuid == NULL) { + return false; + } + + CFMutableArrayRef conditions = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + if (conditions) { + CFMutableDictionaryRef uuidCondition = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (uuidCondition) { + CFDictionarySetValue(uuidCondition, kNEPolicyConditionType, kNEPolicyValPolicyConditionTypeApplication); + CFDictionarySetValue(uuidCondition, kNEPolicyApplicationUUID, proc_uuid); + CFArrayAppendValue(conditions, uuidCondition); + CFRelease(uuidCondition); + } else { + success = false; + } + + CFMutableDictionaryRef interfacesCondition = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (interfacesCondition) { + CFDictionarySetValue(interfacesCondition, kNEPolicyConditionType, kNEPolicyValPolicyConditionTypeAllInterfaces); + CFArrayAppendValue(conditions, interfacesCondition); + CFRelease(interfacesCondition); + } else { + success = false; + } + } else { + success = false; + } + + CFMutableDictionaryRef result = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (result) { + CFDictionaryAddValue(result, kNEPolicyResult, kNEPolicyValPolicyResultPass); + } else { + success = false; + } + + if (success) { + success = (NEPolicyAdd(policySession, 0, conditions, result, NULL) != kNEPolicyIDInvalid); + } + + if (result) { + CFRelease(result); + } + if (conditions) { + CFRelease(conditions); + } + if (proc_uuid) { + CFRelease(proc_uuid); + } + + return (success && NEPolicyApply(policySession)); +} + // // Session // @@ -176,6 +260,11 @@ session(void) plog(ASL_LEVEL_ERR, "failed to initialize route socket.\n"); exit(1); } + + if (!policy_session_init()) { + plog(ASL_LEVEL_ERR, "failed to initialize NEPolicy session.\n"); + } + if (initmyaddr()) { plog(ASL_LEVEL_ERR, "failed to initialize listening addresses.\n"); exit(1); @@ -225,6 +314,9 @@ session(void) "cannot open %s", pid_file); } } + + xpc_transaction_begin(); + #if !TARGET_OS_EMBEDDED // enable keepalive for recovery (from crashes and bad exits... after init) (void)launchd_update_racoon_keepalive(true); @@ -250,12 +342,14 @@ close_session(int error) ike_session_flush_all_phase1(false); close_sockets(); + xpc_transaction_end(); + #if !TARGET_OS_EMBEDDED // a clean exit, so disable launchd keepalive (void)launchd_update_racoon_keepalive(false); #endif // !TARGET_OS_EMBEDDED - plog(ASL_LEVEL_INFO, "racoon shutdown\n"); + plog(ASL_LEVEL_NOTICE, "racoon shutdown\n"); exit(0); } @@ -341,11 +435,15 @@ check_flushsa() void auto_exit_do(void *p) { - plog(ASL_LEVEL_DEBUG, + plog(ASL_LEVEL_NOTICE, "performing auto exit\n"); +#if ENABLE_NO_SA_FLUSH + close_session(0); +#else pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC); sched_new(1, check_flushsa_stub, NULL); dying(); +#endif /* ENABLE_NO_SA_FLUSH */ } void @@ -383,7 +481,7 @@ static int signals[] = { }; -static void +void check_sigreq() { int sig; @@ -439,13 +537,17 @@ check_sigreq() #if TARGET_OS_EMBEDDED if (no_remote_configs(TRUE)) { +#if ENABLE_NO_SA_FLUSH + close_session(0); +#else pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC); #ifdef ENABLE_FASTQUIT close_session(0); #else sched_new(1, check_flushsa_stub, NULL); -#endif +#endif /* ENABLE_FASTQUIT */ dying(); +#endif /* ENABLE_NO_SA_FLUSH */ } #endif @@ -453,9 +555,12 @@ check_sigreq() case SIGINT: case SIGTERM: - plog(ASL_LEVEL_INFO, + plog(ASL_LEVEL_NOTICE, "caught signal %d\n", sig); - pfkey_send_flush(lcconf->sock_pfkey, +#if ENABLE_NO_SA_FLUSH + close_session(0); +#else + pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC); if ( sig == SIGTERM ){ terminated = 1; /* in case if it hasn't been set yet */ @@ -465,10 +570,11 @@ check_sigreq() sched_new(1, check_flushsa_stub, NULL); dying(); +#endif /* ENABLE_NO_SA_FLUSH */ break; default: - plog(ASL_LEVEL_INFO, + plog(ASL_LEVEL_NOTICE, "caught signal %d\n", sig); break; } @@ -484,7 +590,7 @@ RETSIGTYPE signal_handler(int sig, siginfo_t *sigi, void *ctx) { #if 0 - plog(ASL_LEVEL_DEBUG, + plog(ASL_LEVEL_NOTICE, "%s received signal %d from pid %d uid %d\n\n", __FUNCTION__, sig, sigi->si_pid, sigi->si_uid); #endif @@ -496,9 +602,14 @@ signal_handler(int sig, siginfo_t *sigi, void *ctx) if ( sig == SIGTERM ){ terminated = 1; } + + pending_signal_handle = 1; dispatch_async(main_queue, ^{ - check_sigreq(); + if (pending_signal_handle) { + check_sigreq(); + pending_signal_handle = 0; + } }); }