macosdistributed-objectsnsconnection

How to authenticate NSConnection requests?


(Let's ignore the fact that NSConnection is now deprecated.)

I have a tool that accepts connections to NSConnection over a service port. I have an application that launches the tool and then connects to it. That part works.

Now, I like to make sure that only my particular app can talk to the tool and that the tool rejects connections from any other tool/app.

How do I best accomplish this?

One idea I had:

Since the app starts the tool, it could pass a "secret" to the tool as an argument, and then I pass the same secret to the tool whenever I invoke one of its functions as an NSDistributedObject. However, that would mean I have to pass that extra argument to every call I make, and I think that's unnecessary overhead.

I would think that I could accept or reject the connection right when the app opens the connection to the tool, i.e. only once. There is the NSConnectionDelegate, and I suspect that I'd have to implement the authentication check in its authenticateComponents:withData: handler, but I cannot find any examples that would explain how to do that. I mean, is there any data in that connection attempt that would identify the app that's requesting the connection, such as its PID, for instance?


Solution

  • Do you establish a connection for every call? I wouldn't think so but, if not, why do you think you'd have to pass the secret for every call? It's pretty common for the server to have a check-in method that clients have to call. You could validate the secret in that check-in method.

    A malicious client might try to just skip the check-in method. You can use the -connection:handleRequest: method of NSConnectionDelegate to force them to call the check-in method. Keep a flag for every connection indicating if you've seen the check-in method. If you have, that method can just return NO. If you haven't, then examine the NSDistantObjectRequest's invocation's selector. If it's the check-in method, set your flag and return NO. If it's not, then terminate the connection.

    I know the underlying ports (Mach or socket) have mechanisms for authenticating peers, but I don't see a way to get at that with the abstractions of NSConnection laid over them.

    Finally, you are apparently wedded to NSConnection but this is exactly the sort of thing that the NSXPCConnection API is for. Among other things, it will ensure that the service is only visible to the parent app.