• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Security with Streams
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Security with Streams


  • Subject: Re: Security with Streams
  • From: "Gerriet M. Denkmann" <email@hidden>
  • Date: Sun, 26 Jun 2016 09:44:06 +0700

> On 26 Jun 2016, at 05:12, Jens Alfke <email@hidden> wrote:
>
>
>> On Jun 18, 2016, at 2:34 AM, Gerriet M. Denkmann <email@hidden> wrote:
>>
>> 1. (important) the client really wants to know that:
>> 	(1a) it is talking to the right server and not to some evil entity masquerading as the real server.
>> 	(1b) the data it receives has not been tampered with on the way.
>
> You want an SSL (aka TLS) connection, with the server providing a certificate (the typical setup.)
>
>> 2. (less important) the server might want to know that the client connecting to it is a valid client.
>> 	This might help if there are thousands of fake clients overwhelming the server with fake requests.
>> 	But this is a kind of unlikely scenario.
>
> For that you’d need the SSL client to provide a certificate too. This is supported by the CFStream APIs.
>
>> 3. (hardly important at all) no one can read the data exchanged.
>> 	The data exchanged it really not sensitive.
>
> Well, you get that for free with SSL anyway :)
>
> Accomplishing (1b) and (3) is straightforward, I think. The doc-comment for NSNetService says how to enable SSL/TLS for the sockets by setting the stream properties:


Following TN2326 I created a (self signed) Certificate Authority and a Digital Identity called "MyServerId".

The server gets MyServerId from my keychain:

- (void)netService:(NSNetService *)sender didAcceptConnectionWithInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream
{
	NSString *certificateName = @"MyServerId";
	NSDictionary *d =	@{	(__bridge id) kSecClass:            		(__bridge id) kSecClassIdentity,
							(__bridge id) kSecReturnRef:        		@YES,
							(__bridge id) kSecMatchSubjectWholeString:	certificateName,
						 };
	CFArrayRef copyMatchingResult;
	OSStatus status = SecItemCopyMatching( (__bridge CFDictionaryRef)di, (CFTypeRef *)&copyMatchingResult );
	if (status != errSecSuccess)	...

 	id mySecIdentityRef = (__bridge id)copyMatchingResult;
	NSArray *certs = @[ mySecIdentityRef ];
	NSDictionary *settings =	@{	(__bridge NSString *)kCFStreamSSLValidatesCertificateChain: @NO,
									(__bridge NSString *)kCFStreamSSLIsServer: 					@YES,
									(__bridge NSString *)kCFStreamSSLCertificates: 				certs,
								 };
	BOOL ok = [ inputStream setProperty: settings  forKey: (__bridge NSString *)kCFStreamPropertySSLSettings ];
	if ( !ok )	...

	... for both streams: scheduleInRunLoop, open
}


The client has a copy of MyServerId.cer (exported from my keychain) in its bundle.

- (void)netService:(NSNetService *)sender didAcceptConnectionWithInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream
{
	NSDictionary *settings = @{	(__bridge NSString *)kCFStreamSSLValidatesCertificateChain: @NO };
	BOOL ok = [ inputStream setProperty: settings  forKey: (__bridge NSString *)kCFStreamPropertySSLSettings ];
	if ( !ok )	...

	... for both streams: scheduleInRunLoop, open
}

The NSStreamDelegate of the client compares the certificate in inputStream with the certificate in its bundle:

- (void)stream:(NSStream *)aStream  handleEvent: (NSStreamEvent)streamEvent
{
	if ( streamEvent & NSStreamEventHasSpaceAvailable )
	{
		if ( firstTimeHere )
		{
			firstTimeHere = NO;

			NSString *kSSLPeerTrust = (__bridge NSString *)kCFStreamPropertySSLPeerTrust;
			id trusT = [ inputStream propertyForKey: kSSLPeerTrust ];
			if ( trusT == nil )	… error badServer

			SecTrustRef trust = (__bridge SecTrustRef)trusT;
			SecTrustResultType  trustResult;	//	will be: recoverable trust failure; probably because certificate is based on self signed Certificate Authority
			OSStatus err = SecTrustEvaluate(trust, &trustResult);
			if (err != errSecSuccess)	… error badServer

			if trustResult ≠ kSecTrustResultProceed, kSecTrustResultUnspecified, kSecTrustResultRecoverableTrustFailure	... error badServer

			SecCertificateRef certificate = SecTrustGetCertificateAtIndex ( trust, 0 );
			if ( certificate == nil )	... error badServer

			CFDataRef dac = SecCertificateCopyData( certificate );
			if ( dac == nil )	… error badServer

			NSData *certificateDataOfServer = (NSData *)CFBridgingRelease(dac);
			NSData *realCertificateData = get data from mainBundle;
			if ( ![ realCertificateData isEqualToData: certificateDataOfServer ] )	... error badServer

			//	trust the server
		};

		// write to aStream ...
	}

	...
}

Absolutely not sure whether the code above is correct, but it seems to be working.


> We are now falling into the rabbit hole that is peer-to-peer trust & identity. How is your server going to identify it so that a client will know that it’s the server it expects? I don’t know whether you’ve given any thought to this; the answer affects how you’d implement this part of the app.

I have thought about this, but I am not at all sure that my thoughts are correct.
Currently (as indicated in the code above) my client has a copy of the real server certificate and compares it with the certificate obtained from its inputStream.
I am not sure whether putting the server certificate into the client is ok or a breach of security.

That is: the client will accept any server which has signed with the server certificate.


When the server does AcceptConnectionWithInputStream I get a panel:

<name of app> wants to sign using key "MyServerId" in your keychain.
Do you want to allow access to this item?
Deny / Accept.

If <name of app> is “My Real Server" I will click "Accept".

If I have foolishly installed a malicious app calling itself “My Real Server”  the client will be out of luck.

Also: If the LAN the client is connected to (client runs on an iOS Device) has a malicious server app which somehow has obtained a copy of my server certificate, the client will be in trouble.

Not sure how to solve this problem.

Kind regards,

Gerriet.


_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden


  • Follow-Ups:
    • Re: Security with Streams
      • From: Jens Alfke <email@hidden>
    • Re: Security with Streams
      • From: Keary Suska <email@hidden>
References: 
 >Security with Streams (From: "Gerriet M. Denkmann" <email@hidden>)
 >Re: Security with Streams (From: Jens Alfke <email@hidden>)

  • Prev by Date: Re: Security with Streams
  • Next by Date: NSTask argument list
  • Previous by thread: Re: Security with Streams
  • Next by thread: Re: Security with Streams
  • Index(es):
    • Date
    • Thread