Skip to content

Commit

Permalink
Merge pull request #66 from trilemma-dev/readme-release-update
Browse files Browse the repository at this point in the history
Update README.md for next version
  • Loading branch information
jakaplan authored Jan 25, 2022
2 parents 888c5a3 + a736334 commit fda1e98
Showing 1 changed file with 62 additions and 22 deletions.
84 changes: 62 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
SecureXPC provides an easy way to perform secure XPC Mach service communication.
[`Codable`](https://developer.apple.com/documentation/swift/codable) conforming types are used to send messages and
receive replies. This framework is ideal for communicating with helper tools installed via
[`SMJobBless`](https://developer.apple.com/documentation/servicemanagement/1431078-smjobbless).
Use pure Swift to easily and securely communicate with XPC services and XPC Mach services. A client-server model
enables you to use your own [`Codable`](https://developer.apple.com/documentation/swift/codable) conforming types to
send messages to routes you define and receive replies.

To see a runnable sample app using this framework, check out
[SwiftAuthorizationSample](https://github.com/trilemma-dev/SwiftAuthorizationSample).
SecureXPC uses [Swift concurrency](https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html) on macOS 10.15 and
later allowing clients to make non-blocking asynchronous calls to servers. A closure-based API is also available
providing compatibility back to OS X 10.10.

This framework is ideal for communicating with helper tools installed via
[`SMJobBless`](https://developer.apple.com/documentation/servicemanagement/1431078-smjobbless). It's built with
security in mind, minimizing the opportunities for
[exploits](https://objectivebythesea.com/v3/talks/OBTS_v3_wReguła.pdf). Server-side security checks are performed
against the actual calling process instead of relying on PIDs which are known to be
[insecure](https://saelo.github.io/presentations/warcon18_dont_trust_the_pid.pdf).

[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Ftrilemma-dev%2FSecureXPC%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/trilemma-dev/SecureXPC)

Expand All @@ -16,50 +23,83 @@ these routes.
## Routes
In a file shared by the client and server define one or more routes:
```swift
let route = XPCRouteWithMessageWithReply("bezaddle",
messageType: String.self,
replyType: Bool.self)
let route = XPCRoute.named("bedazzle")
.withMessageType(String.self)
.withReplyType(Bool.self)
```

## Server
In one program create a server, register those routes, and then start the server:
In one program retrieve a server, register those routes, and then start the server:
```swift
...
let server = XPCMachServer(machServiceName: "com.example.service",
clientRequirements: requirements)
let server = <# server retrieval here #>
server.registerRoute(route, handler: bedazzle)
server.start()
server.startAndBlock()
}

private func bedazzle(message: String) throws -> Bool {
<# implementation here #>
}
```

If this program is a helper tool installed by `SMJobBless`, then in many cases it can be initialized automatically:
On macOS 10.15 and later `async` functions and closures can also be registered as the handler for a route.

There are multiple types of servers which can be retrieved:
- `XPCServer.forThisXPCService()`
- For an XPC service, which is a private helper tool available only to the main application that contains it
- `XPCServer.forThisBlessedHelperTool()`
- For a helper tool installed via
[`SMJobBless`](https://developer.apple.com/documentation/servicemanagement/1431078-smjobbless)
- To see a sample app for this use case, check out
[SwiftAuthorizationSample](https://github.com/trilemma-dev/SwiftAuthorizationSample)
- `XPCServer.forThisMachService(named:clientRequirements:)`
- For
[Launch Daemons and Agents](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html)
as well as more advanced `SMJobBless` helper tool configurations
- `XPCServer.makeAnonymous()`
- Typically used for testing purposes
- `XPCServer.makeAnonymous(clientRequirements:)`
- Enables applications not managed by `launchd` to communicate with each other, see documentation for more details

## Client
In another program retrieve a client, then call one of the registered routes:
```swift
let server = XPCMachServer.forThisBlessedHelperTool()
let client = <# client retrieval here #>
let reply = try await client.sendMessage("Get Schwifty", route: route)
```

## Client
In another program create a client, then call one of those routes:
Closure-based variants are available for macOS 10.14 and earlier:
```swift
let client = XPCMachClient(machServiceName: "com.example.service")
try client.sendMessage("Get Schwifty", route: route, withReply: { result in
let client = <# client retrieval here #>
client.sendMessage("Get Schwifty", route: route, withResponse: { result in
switch result {
case let .success(reply):
case .success(let reply):
<# use the reply #>
case let .failure(error):
case .failure(let error):
<# handle the error #>
}
})
```

There are multiple types of clients which can be retrieved:
- `XPCClient.forXPCService(named:)`
- For communicating with an XPC service
- This corresponds to servers created with `XPCServer.forThisXPCService()`
- `XPCClient.forMachService(named:)`
- For communicating with an XPC Mach service
- This corresponds to servers created with `XPCServer.forThisBlessedHelperTool()` or
`XPCServer.forThisMachService(named:clientRequirements:)`
- `XPCClient.forEndpoint(_:)`
- This is the only way to communicate with an anonymous server
- This corresponds to servers created with `XPCServer.makeAnonymous()` or
`XPCServer.makeAnonymous(clientRequirements:)`
- It can also be used with an XPC Mach service

---

# `Codable` vs `NSSecureCoding`
SecureXPC uses types conforming to Swift's `Codable` protocol to serialize data across the XPC connection. Due to the
nature of how `Codable` is defined, it is not possible for the same instance to be referenced from multiple other
nature of how `Codable` is defined, it is not possible for the same instance to be referenced from multiple other
deserialized instances. This is in contrast to how
[`NSSecureCoding`](https://developer.apple.com/documentation/foundation/nssecurecoding) behaves, which is used by
[`NSXPCConnection`](https://developer.apple.com/documentation/foundation/nsxpcconnection) for serialization.
Expand Down

0 comments on commit fda1e98

Please sign in to comment.