xpc: add Xcode project for a charon controlled through XPC

This commit is contained in:
Martin Willi 2013-04-24 10:38:19 +02:00
parent 61177388bd
commit 6f8c626b81
6 changed files with 584 additions and 0 deletions

2
src/frontends/osx/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
xcuserdata
*.xcworkspace

View File

@ -0,0 +1,40 @@
# strongSwan OS X App #
## Introduction ##
The strongSwan OS X App consists of two components:
* A frontend to configure and control connections
* A privileged helper daemon, controlled using XPC, called charon-xpc
The privileged helper daemon gets installed automatically using SMJobBless
functionality on its first use, and gets started automatically by Launchd when
needed.
charon-xpc is a special build linking statically against strongSwan components.
## Building strongSwan ##
strongSwan on OS X requires the libvstr library. The simplest way to install
it is using MacPorts. It gets statically linked to charon-xpc, hence it is not
needed to run the built App.
Before building the Xcode project, the strongSwan base tree must be built using
a monolithic and static build. This can be achieved on OS X by using:
LDFLAGS="-all_load" \
CFLAGS="-I/usr/include -DOPENSSL_NO_CMS -O2 -Wall -Wno-format -Wno-pointer-sign" \
./configure --prefix=/opt/local --disable-defaults --enable-openssl \
--enable-kernel-pfkey --enable-kernel-pfroute --enable-eap-mschapv2 \
--enable-eap-identity --enable-monolithic --enable-nonce --enable-random \
--enable-pkcs1 --enable-pem --enable-socket-default --enable-xauth-generic \
--enable-ikev1 --enable-ikev2 --enable-charon --disable-shared --enable-static
followed by calling make (no need to make install).
Building charon-xpc using the Xcode project yields a single binary without
any non OS X dependencies.
Both charon-xpc and the App must be code-signed to allow the installation of
the privileged helper. git-grep for "Joe Developer" to change the signing
identity.

View File

@ -0,0 +1,18 @@
<?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>CFBundleIdentifier</key>
<string>org.strongswan.charon-xpc</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>charon-xpc</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>SMAuthorizedClients</key>
<array>
<string>identifier org.strongswan.osx and certificate leaf[subject.CN] = "Joe Developer"</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,13 @@
<?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>org.strongswan.charon-xpc</string>
<key>MachServices</key>
<dict>
<key>org.strongswan.charon-xpc</key>
<true/>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,203 @@
/*
* Copyright (C) 2013 Martin Willi
* Copyright (C) 2013 revosec AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <stdio.h>
#include <xpc/xpc.h>
#include <library.h>
#include <hydra.h>
#include <daemon.h>
/**
* Loglevel configuration
*/
static level_t levels[DBG_MAX];
/**
* hook in library for debugging messages
*/
extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
/**
* Logging hook for library logs, using stderr output
*/
static void dbg_stderr(debug_t group, level_t level, char *fmt, ...)
{
va_list args;
if (level <= 1)
{
va_start(args, fmt);
fprintf(stderr, "00[%N] ", debug_names, group);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
}
}
/**
* Return version of this helper
*/
xpc_object_t get_version(xpc_object_t request, xpc_connection_t client)
{
xpc_object_t reply;
reply = xpc_dictionary_create_reply(request);
xpc_dictionary_set_string(reply, "version", PACKAGE_VERSION);
return reply;
}
/**
* XPC command dispatch table
*/
struct {
char *name;
xpc_object_t (*handler)(xpc_object_t request, xpc_connection_t client);
} commands[] = {
{ "get_version", get_version },
};
/**
* Handle a received XPC request message
*/
static void handle(xpc_object_t request)
{
xpc_connection_t client;
xpc_object_t reply;
const char *command;
int i;
client = xpc_dictionary_get_remote_connection(request);
command = xpc_dictionary_get_string(request, "command");
if (command)
{
for (i = 0; i < countof(commands); i++)
{
if (streq(commands[i].name, command))
{
reply = commands[i].handler(request, client);
if (reply)
{
xpc_connection_send_message(client, reply);
xpc_release(reply);
}
break;
}
}
}
}
/**
* Dispatch XPC commands
*/
static int dispatch()
{
xpc_connection_t service;
service = xpc_connection_create_mach_service("org.strongswan.charon-xpc",
NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
if (!service)
{
return EXIT_FAILURE;
}
xpc_connection_set_event_handler(service, ^(xpc_object_t conn) {
xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
if (xpc_get_type(event) == XPC_TYPE_ERROR)
{
if (event == XPC_ERROR_CONNECTION_INVALID ||
event == XPC_ERROR_TERMINATION_IMMINENT)
{
xpc_connection_cancel(conn);
}
}
else
{
handle(event);
}
});
xpc_connection_resume(conn);
});
xpc_connection_resume(service);
dispatch_main();
xpc_release(service);
}
/**
* Main function, starts the daemon.
*/
int main(int argc, char *argv[])
{
struct utsname utsname;
int group;
dbg = dbg_stderr;
atexit(library_deinit);
if (!library_init(NULL))
{
exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
}
if (lib->integrity)
{
if (!lib->integrity->check_file(lib->integrity, "charon-xpc", argv[0]))
{
exit(SS_RC_DAEMON_INTEGRITY);
}
}
atexit(libhydra_deinit);
if (!libhydra_init("charon-xpc"))
{
exit(SS_RC_INITIALIZATION_FAILED);
}
atexit(libcharon_deinit);
if (!libcharon_init("charon-xpc"))
{
exit(SS_RC_INITIALIZATION_FAILED);
}
for (group = 0; group < DBG_MAX; group++)
{
levels[group] = LEVEL_CTRL;
}
charon->load_loggers(charon, levels, TRUE);
lib->settings->set_default_str(lib->settings, "charon-cmd.port", "0");
lib->settings->set_default_str(lib->settings, "charon-cmd.port_nat_t", "0");
if (!charon->initialize(charon,
lib->settings->get_str(lib->settings, "charon-xpc.load",
"random nonce pem pkcs1 openssl kernel-pfkey kernel-pfroute "
"socket-default eap-identity eap-mschapv2")))
{
exit(SS_RC_INITIALIZATION_FAILED);
}
if (uname(&utsname) != 0)
{
memset(&utsname, 0, sizeof(utsname));
}
DBG1(DBG_DMN, "Starting charon-xpc IKE daemon (strongSwan %s, %s %s, %s)",
VERSION, utsname.sysname, utsname.release, utsname.machine);
charon->start(charon);
return dispatch();
}

View File

@ -0,0 +1,308 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
5BD1CCD71726DB4000587077 /* charon-xpc.c in Sources */ = {isa = PBXBuildFile; fileRef = 5BD1CCD61726DB4000587077 /* charon-xpc.c */; };
5BF60F31173405A000E5D608 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BD1CCD31726DB4000587077 /* CoreFoundation.framework */; };
5BF60F33173405AC00E5D608 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BD1CCF21727DE3E00587077 /* Security.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
5BD1CCD11726DB4000587077 /* org.strongswan.charon-xpc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.objfile"; includeInIndex = 0; path = "org.strongswan.charon-xpc"; sourceTree = BUILT_PRODUCTS_DIR; };
5BD1CCD31726DB4000587077 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
5BD1CCD61726DB4000587077 /* charon-xpc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "charon-xpc.c"; sourceTree = "<group>"; };
5BD1CCE01726DCD000587077 /* charon-xpc-Launchd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "charon-xpc-Launchd.plist"; sourceTree = "<group>"; };
5BD1CCE11726DD9900587077 /* charon-xpc-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "charon-xpc-Info.plist"; sourceTree = "<group>"; };
5BD1CCEA1727CCA400587077 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.md; sourceTree = "<group>"; };
5BD1CCEC1727D7AF00587077 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
5BD1CCF21727DE3E00587077 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
5BD1CCCE1726DB4000587077 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5BF60F31173405A000E5D608 /* CoreFoundation.framework in Frameworks */,
5BF60F33173405AC00E5D608 /* Security.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
5BD1CCA11726DB0100587077 = {
isa = PBXGroup;
children = (
5BD1CCEA1727CCA400587077 /* README.md */,
5BD1CCD51726DB4000587077 /* charon-xpc */,
5BD1CCAF1726DB0100587077 /* Frameworks */,
5BD1CCAD1726DB0100587077 /* Products */,
);
sourceTree = "<group>";
};
5BD1CCAD1726DB0100587077 /* Products */ = {
isa = PBXGroup;
children = (
5BD1CCD11726DB4000587077 /* org.strongswan.charon-xpc */,
);
name = Products;
sourceTree = "<group>";
};
5BD1CCAF1726DB0100587077 /* Frameworks */ = {
isa = PBXGroup;
children = (
5BD1CCF21727DE3E00587077 /* Security.framework */,
5BD1CCEC1727D7AF00587077 /* ServiceManagement.framework */,
5BD1CCD31726DB4000587077 /* CoreFoundation.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
5BD1CCD51726DB4000587077 /* charon-xpc */ = {
isa = PBXGroup;
children = (
5BD1CCD61726DB4000587077 /* charon-xpc.c */,
5BD1CCE01726DCD000587077 /* charon-xpc-Launchd.plist */,
5BD1CCE11726DD9900587077 /* charon-xpc-Info.plist */,
);
path = "charon-xpc";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
5BD1CCD01726DB4000587077 /* charon-xpc */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5BD1CCDA1726DB4000587077 /* Build configuration list for PBXNativeTarget "charon-xpc" */;
buildPhases = (
5BD1CCCD1726DB4000587077 /* Sources */,
5BD1CCCE1726DB4000587077 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = "charon-xpc";
productName = "charon-xpc";
productReference = 5BD1CCD11726DB4000587077 /* org.strongswan.charon-xpc */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
5BD1CCA31726DB0100587077 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0450;
ORGANIZATIONNAME = "revosec AG";
};
buildConfigurationList = 5BD1CCA61726DB0100587077 /* Build configuration list for PBXProject "strongSwan" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 5BD1CCA11726DB0100587077;
productRefGroup = 5BD1CCAD1726DB0100587077 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
5BD1CCD01726DB4000587077 /* charon-xpc */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
5BD1CCCD1726DB4000587077 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5BD1CCD71726DB4000587077 /* charon-xpc.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
5BD1CCC81726DB0200587077 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.8;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
5BD1CCC91726DB0200587077 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.8;
SDKROOT = macosx;
};
name = Release;
};
5BD1CCDB1726DB4000587077 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Joe Developer";
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
HEADER_SEARCH_PATHS = (
/usr/include,
../../libstrongswan,
../../libcharon,
../../libhydra,
/opt/local/include,
);
INFOPLIST_FILE = "charon-xpc/charon-xpc-Info.plist";
INSTALL_PATH = /;
LIBRARY_SEARCH_PATHS = (
/usr/lib,
../../libstrongswan/.libs,
../../libcharon/.libs,
../../libhydra/.libs,
/opt/local/lib,
);
OTHER_CFLAGS = (
"-include",
../../../config.h,
);
OTHER_LDFLAGS = (
"-lcrypto",
/opt/local/lib/libvstr.a,
"-force_load",
../../libstrongswan/.libs/libstrongswan.a,
"-force_load",
../../libhydra/.libs/libhydra.a,
"-force_load",
../../libcharon/.libs/libcharon.a,
"-sectcreate",
__TEXT,
__info_plist,
"charon-xpc/charon-xpc-Info.plist",
"-sectcreate",
__TEXT,
__launchd_plist,
"charon-xpc/charon-xpc-Launchd.plist",
);
PRODUCT_NAME = "org.strongswan.charon-xpc";
PROVISIONING_PROFILE = "";
STRIP_STYLE = "non-global";
};
name = Debug;
};
5BD1CCDC1726DB4000587077 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Joe Developer";
COPY_PHASE_STRIP = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
HEADER_SEARCH_PATHS = (
/usr/include,
../../libstrongswan,
../../libcharon,
../../libhydra,
/opt/local/include,
);
INFOPLIST_FILE = "charon-xpc/charon-xpc-Info.plist";
INSTALL_PATH = /;
LIBRARY_SEARCH_PATHS = (
/usr/lib,
../../libstrongswan/.libs,
../../libcharon/.libs,
../../libhydra/.libs,
/opt/local/lib,
);
OTHER_CFLAGS = (
"-include",
../../../config.h,
);
OTHER_LDFLAGS = (
"-lcrypto",
/opt/local/lib/libvstr.a,
"-force_load",
../../libstrongswan/.libs/libstrongswan.a,
"-force_load",
../../libhydra/.libs/libhydra.a,
"-force_load",
../../libcharon/.libs/libcharon.a,
"-sectcreate",
__TEXT,
__info_plist,
"charon-xpc/charon-xpc-Info.plist",
"-sectcreate",
__TEXT,
__launchd_plist,
"charon-xpc/charon-xpc-Launchd.plist",
);
PRODUCT_NAME = "org.strongswan.charon-xpc";
PROVISIONING_PROFILE = "";
STRIP_STYLE = "non-global";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
5BD1CCA61726DB0100587077 /* Build configuration list for PBXProject "strongSwan" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5BD1CCC81726DB0200587077 /* Debug */,
5BD1CCC91726DB0200587077 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5BD1CCDA1726DB4000587077 /* Build configuration list for PBXNativeTarget "charon-xpc" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5BD1CCDB1726DB4000587077 /* Debug */,
5BD1CCDC1726DB4000587077 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 5BD1CCA31726DB0100587077 /* Project object */;
}