Switch extension from a framework to an appex

pull/1688/head
Jason Rhinelander 3 years ago committed by Jeff Becker
parent faf8a699a6
commit 3ab117a03b
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -4,18 +4,33 @@ into the no-CI, no-help, undocumented, non-toy-apps-need-not-apply modern Apple
This is disgusting.
But it gets worse.
These two files, in particular, are the very worst manifestations of this Apple cancer: they are
required for proper permissions to run on macOS, are undocumented, and can only be regenerated
through the entirely closed source Apple Developer backend:
The following two files, in particular, are the very worst manifestations of this already toxic
Apple cancer: they are required for proper permissions to run on macOS, are undocumented, and can
only be regenerated through the entirely closed source Apple Developer backend, for which you have
to pay money first to get a team account (a personal account will not work), and they lock the
resulting binaries to only run on individually selected Apple computers selected at the time the
profile is provisioned (with no ability to allow it to run anywhere).
lokinet.provisionprofile
lokinet-extension.provisionprofile
This is actively hostile to open source development, but that is nothing new for Apple.
In order to make things work, you'll have to replace these provisioning profiles with your own
(after paying Apple for the privilege of developing on their platform, of course) and change all the
team/application/bundle IDs to reference your own team, matching the provisioning profiles. The
provisioning profiles must be a "macOS Development" provisioning profile, and must include the
signing keys and the authorized devices on which you want to run it. (The profiles bundled in this
repository contains the lokinet team's "Apple Development" keys associated with the Oxen project,
and mac dev boxes. This is *useless* for anyone else).
Also take note that you *must not* put a development build `lokinet.app` inside /Applications
because if you do, it won't work because *on top* of the ridiculous signing and entitlement bullshit
that Apple makes you jump through, the rules *also* differ for binaries placed in /Applications
versus binaries placed elsewhere, but like everything else here, it is entirely undocumented.
If you are reading this to try to build Lokinet for yourself for an Apple operating system and
simultaneously care about open source, privacy, or freedom then you, my friend, are a walking
contradiction: you are trying to get Lokinet to work on a platform that actively despises open

@ -2,31 +2,28 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider-systemextension</string>
<string>app-proxy-provider-systemextension</string>
<string>content-filter-provider-systemextension</string>
<string>dns-proxy-systemextension</string>
<string>dns-settings</string>
</array>
<key>com.apple.developer.networking.vpn.api</key>
<array>
<string>allow-vpn</string>
</array>
<key>com.apple.application-identifier</key>
<string>SUQ8J2PCT7.com.loki-project.lokinet.network-extension</string>
<key>keychain-access-groups</key>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>SUQ8J2PCT7.*</string>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.developer.team-identifier</key>
<string>SUQ8J2PCT7</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.get-task-allow</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
</plist>

@ -2,31 +2,21 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider-systemextension</string>
<string>app-proxy-provider-systemextension</string>
<string>content-filter-provider-systemextension</string>
<string>dns-proxy-systemextension</string>
<string>dns-settings</string>
</array>
<key>com.apple.developer.networking.vpn.api</key>
<array>
<string>allow-vpn</string>
</array>
<key>com.apple.application-identifier</key>
<string>SUQ8J2PCT7.com.loki-project.lokinet</string>
<key>keychain-access-groups</key>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>SUQ8J2PCT7.*</string>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.developer.team-identifier</key>
<string>SUQ8J2PCT7</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.get-task-allow</key>
<true/>
</dict>
</plist>

@ -1,10 +1,10 @@
#!/usr/bin/env bash
set -e
codesign --verbose=4 --force -s "@CODESIGN_KEY@" \
codesign --verbose=4 --force -s "@CODESIGN_DEV@" \
--entitlements "@PROJECT_SOURCE_DIR@/contrib/macos/lokinet-extension.entitlements.plist" \
--deep --strict --timestamp --options=runtime "@SIGN_TARGET@/Contents/Frameworks/lokinet-extension.framework"
--deep --strict --timestamp --options=runtime "@SIGN_TARGET@/Contents/PlugIns/lokinet-extension.appex"
for file in "@SIGN_TARGET@/Contents/MacOS/lokinet" "@SIGN_TARGET@" ; do
codesign --verbose=4 --force -s "@CODESIGN_KEY@" \
codesign --verbose=4 --force -s "@CODESIGN_APP@" \
--entitlements "@PROJECT_SOURCE_DIR@/contrib/macos/lokinet.entitlements.plist" \
--deep --strict --timestamp --options=runtime "$file"
done

@ -1,9 +1,7 @@
if(APPLE)
set(LOKINET_SWIFT_SOURCES lokinet.swift)
add_executable(lokinet ${LOKINET_SWIFT_SOURCES})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Lokinet.modulemap.in ${CMAKE_CURRENT_BINARY_DIR}/swift/LokinetExtension/module.modulemap ESCAPE_QUOTES @ONLY)
target_include_directories(lokinet PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/swift)
target_link_libraries(lokinet PUBLIC lokinet-extension)
else()
add_executable(lokinet lokinet.cpp)
add_executable(lokinet-vpn lokinet-vpn.cpp)
@ -71,7 +69,8 @@ endforeach()
if(APPLE)
set(CODESIGN_KEY "" CACHE STRING "codesign the macos app using this key identity")
set(CODESIGN_APP "" CACHE STRING "codesign the macos app using this key identity")
set(CODESIGN_DEV "" CACHE STRING "codesign the internal extension using this key identity")
add_custom_target(icons ALL
COMMAND ${PROJECT_SOURCE_DIR}/contrib/macos/mk-icns.sh ${PROJECT_SOURCE_DIR}/contrib/lokinet.svg ${CMAKE_CURRENT_BINARY_DIR}/lokinet.icns
@ -79,11 +78,8 @@ if(APPLE)
add_dependencies(lokinet icons lokinet-extension)
add_custom_command(TARGET lokinet
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "setting rpath"
COMMAND ${CMAKE_COMMAND} -E echo ${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/" $<TARGET_FILE:lokinet>
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/" $<TARGET_FILE:lokinet>
COMMAND mkdir -p $<TARGET_BUNDLE_DIR:lokinet>/Contents/Frameworks
COMMAND cp -au $<TARGET_BUNDLE_DIR:lokinet-extension> $<TARGET_BUNDLE_DIR:lokinet>/Contents/Frameworks/
COMMAND mkdir -p $<TARGET_BUNDLE_DIR:lokinet>/Contents/PlugIns
COMMAND cp -au $<TARGET_BUNDLE_DIR:lokinet-extension> $<TARGET_BUNDLE_DIR:lokinet>/Contents/PlugIns/
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_SOURCE_DIR}/contrib/macos/lokinet.provisionprofile
$<TARGET_BUNDLE_DIR:lokinet>/Contents/embedded.provisionprofile
)
@ -100,8 +96,8 @@ if(APPLE)
MACOSX_BUNDLE_INFO_PLIST "${PROJECT_SOURCE_DIR}/contrib/macos/Info.plist.in"
MACOSX_BUNDLE_ICON_FILE "${CMAKE_CURRENT_BINARY_DIR}/lokinet.icns"
MACOSX_BUNDLE_COPYRIGHT "© 2021, The Oxen Project")
if (CODESIGN_KEY)
message(STATUS "codesigning with ${CODESIGN_KEY}")
if (CODESIGN_APP AND CODESIGN_DEV)
message(STATUS "codesigning with ${CODESIGN_APP} (app) ${CODESIGN_DEV} (appex)")
set(SIGN_TARGET "${CMAKE_CURRENT_BINARY_DIR}/lokinet.app")
configure_file(
"${PROJECT_SOURCE_DIR}/contrib/macos/sign.sh.in"
@ -113,7 +109,7 @@ if(APPLE)
COMMAND "${PROJECT_BINARY_DIR}/sign.sh"
)
else()
message(WARNING "Not codesigning: CODESIGN_KEY is not set")
message(WARNING "Not codesigning: CODESIGN_APP (=${CODESIGN_APP}) and/or CODESIGN_DEV (=${CODESIGN_DEV}) are not set")
endif()
endif()

@ -36,13 +36,16 @@ class LokinetMain: NSObject, NSApplicationDelegate {
}
}
let providerProtocol = NETunnelProviderProtocol()
providerProtocol.serverAddress = ""
providerProtocol.serverAddress = "loki.loki" // Needs to be set to some non-null dummy value
providerProtocol.username = "anonymous"
providerProtocol.providerBundleIdentifier = self.lokinetComponent
providerProtocol.includeAllNetworks = true
// macos seems to have trouble when this is true, and reports are that this breaks and
// doesn't do what it says on the tin in the first place. Needs more testing.
providerProtocol.includeAllNetworks = false
self.vpnManager.protocolConfiguration = providerProtocol
self.vpnManager.isEnabled = true
self.vpnManager.isOnDemandEnabled = true
self.vpnManager.localizedDescription = "lokinet"
self.vpnManager.saveToPreferences(completionHandler: { error -> Void in
if error != nil {
NSLog("Error saving to preferences")

@ -273,28 +273,28 @@ if(APPLE)
find_library(NETEXT NetworkExtension REQUIRED)
find_library(COREFOUNDATION CoreFoundation REQUIRED)
add_library(lokinet-extension SHARED
framework.mm)
add_executable(lokinet-extension MACOSX_BUNDLE framework.mm)
target_link_libraries(lokinet-extension PUBLIC
liblokinet
${COREFOUNDATION}
${NETEXT})
set_target_properties(lokinet-extension PROPERTIES
FRAMEWORK TRUE
FRAMEWORK_VERSION ${lokinet_VERSION}
MACOSX_FRAMEWORK_IDENTIFIER com.loki-project.lokinet.network-extension
MACOSX_FRAMEWORK_INFO_PLIST ${PROJECT_SOURCE_DIR}/contrib/macos/LokinetExtension.Info.plist.in
# "current version" in semantic format in Mach-O binary file
VERSION ${lokinet_VERSION}
# "compatibility version" in semantic format in Mach-O binary file
SOVERSION ${lokinet_VERSION}
PUBLIC_HEADER ${CMAKE_SOURCE_DIR}/include/lokinet-extension.hpp)
BUNDLE TRUE
BUNDLE_EXTENSION appex
MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/contrib/macos/LokinetExtension.Info.plist.in
XCODE_PRODUCT_TYPE com.apple.product-type.app-extension
)
# Not sure what -fapplication-extension does, but XCode puts it in so...
# -e _NSExtensionMain because it has that instead of a `main` function entry point, of course.
target_link_options(lokinet-extension PRIVATE -fapplication-extension -e _NSExtensionMain)
target_compile_options(lokinet-extension PRIVATE -fapplication-extension)
add_custom_command(TARGET lokinet-extension
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_SOURCE_DIR}/contrib/macos/lokinet-extension.provisionprofile
$<TARGET_BUNDLE_DIR:lokinet-extension>/Versions/Current/embedded.provisionprofile
$<TARGET_BUNDLE_DIR:lokinet-extension>/Contents/embedded.provisionprofile
)

@ -186,6 +186,7 @@ StringViewToData(std::string_view data)
- (void)startTunnelWithOptions:(NSDictionary<NSString*, NSObject*>*)options
completionHandler:(void (^)(NSError*))completionHandler
{
NSLog(@"OMG startTunnelWithOptions");
m_Context = new ContextWrapper{self};
m_Context->Start();
[self setTunnelNetworkSettings:nullptr completionHandler:completionHandler];
@ -194,6 +195,7 @@ StringViewToData(std::string_view data)
- (void)stopTunnelWithReason:(NEProviderStopReason)reason
completionHandler:(void (^)(void))completionHandler
{
NSLog(@"STOP TUNNEL");
if (m_Context)
{
m_Context->Stop();

Loading…
Cancel
Save