• 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
SSL with CFStreams
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

SSL with CFStreams


  • Subject: SSL with CFStreams
  • From: David Riggle <email@hidden>
  • Date: Wed, 20 Jun 2007 15:27:52 -0700

I'm a total SSL noob. I searched the archives, I looked for sample code, I even attended the networking lab at WWDC, but I still can't get SSL to work properly. Maybe someone here can help me with the dark arts.

I have a peer-to-peer photo sharing app. I'm using AsyncSocket, which is a wrapper for CFStream. I want to use SSL simply for encryption. Here's my "client" code to initiate a connection.

-(BOOL)onSocketWillConnect:(AsyncSocket *)sock
{
NSDictionary *sslProperties = [NSDictionary dictionaryWithObjectsAndKeys:
(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
kCFBooleanTrue, kCFStreamSSLAllowsAnyRoot,
kCFBooleanFalse, kCFStreamSSLValidatesCertificateChain,
kCFNull, kCFStreamSSLPeerName,
kCFBooleanFalse, kCFStreamSSLIsServer,
nil];


CFReadStreamSetProperty([sock getCFReadStream], kCFStreamPropertySSLSettings, sslProperties);
CFWriteStreamSetProperty([sock getCFWriteStream], kCFStreamPropertySSLSettings, sslProperties);
return YES;
}


Here is my "server" side code.

-(BOOL)onSocketWillConnect:(AsyncSocket *)sock
{
	SecKeychainRef keychainRef = nil;
	SecIdentitySearchRef searchRef = nil;
	SecIdentityRef mySSLIdentity = nil;
	OSStatus err;

err = SecKeychainCopyDefault(&keychainRef);
if (err != noErr) goto error;
err = SecIdentitySearchCreate(keychainRef, CSSM_KEYUSE_DECRYPT, &searchRef);
if (err != noErr) goto error;
err = SecIdentitySearchCopyNext(searchRef, &mySSLIdentity);
if (err == errSecItemNotFound) {
// create a certificate of our own
[SSLUtilities addSelfSignedCertToKeychain:keychainRef];
CFRelease(searchRef);
err = SecIdentitySearchCreate(keychainRef, CSSM_KEYUSE_DECRYPT, &searchRef);
if (err != noErr) goto error;
err = SecIdentitySearchCopyNext(searchRef, &mySSLIdentity);
}
if (err != noErr) goto error;

CFArrayRef ca = CFArrayCreate(NULL, (const void **)&mySSLIdentity, 1, NULL);


NSDictionary *sslProperties = [NSDictionary dictionaryWithObjectsAndKeys:
(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
kCFBooleanTrue, kCFStreamSSLAllowsAnyRoot,
kCFBooleanFalse, kCFStreamSSLValidatesCertificateChain,
kCFNull, kCFStreamSSLPeerName,
ca, kCFStreamSSLCertificates,
kCFBooleanTrue, kCFStreamSSLIsServer,
nil];


CFReadStreamSetProperty([sock getCFReadStream], kCFStreamPropertySSLSettings, sslProperties);
CFWriteStreamSetProperty([sock getCFWriteStream], kCFStreamPropertySSLSettings, sslProperties);


	CFRelease(ca);

error:
	if (keychainRef != nil) CFRelease(keychainRef);
	if (searchRef != nil) CFRelease(searchRef);
	if (mySSLIdentity != nil) CFRelease(mySSLIdentity);

	return YES;
}

+ (void)addSelfSignedCertToKeychain:(SecKeychainRef)keychain
{
// create a path to a temp file
NSString *tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tmpCert.pem"];
if (tmpPath == nil) return;


	// launch openssl to create the certificate
	NSTask *openSSLProcess = [[NSTask alloc] init];
	[openSSLProcess setLaunchPath:@"/usr/bin/openssl"];
	[openSSLProcess setArguments:[NSArray arrayWithObjects:
		@"req", @"-x509", @"-nodes", @"-days", @"3650",
		@"-subj", @"/C=US/ST=California/L=Los Altos/CN=com.myapp.test",
		@"-newkey", @"rsa:1024", @"-keyout", tmpPath, @"-out", tmpPath,
		@"-passin", @"pass:passphrase", nil]];
	[openSSLProcess launch];

	[openSSLProcess waitUntilExit];
	int status = [openSSLProcess terminationStatus];
	[openSSLProcess release];

if (status != 0) {
NSLog(@"openSSL task failed.");
return;
}

// add certificate to keychain
SecExternalFormat format = kSecFormatPEMSequence;
SecExternalItemType type = kSecItemTypeAggregate;
SecKeyImportExportParameters params;
memset(&params, 0, sizeof(params));

params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
params.passphrase = CFSTR("passphrase");
params.keyUsage = CSSM_KEYUSE_DECRYPT;
params.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;

OSStatus err = SecKeychainItemImport(
(CFDataRef) [NSData dataWithContentsOfFile:tmpPath],
(CFStringRef) tmpPath,
&format,
&type,
0,
&params,
keychain,
NULL);


	if (err != noErr) {
		NSLog(@"SecKeychainItemImport returned %d.", err);
	}

	[[NSFileManager defaultManager] removeFileAtPath:tmpPath handler:nil];
}

This code works on Tiger. However, on Leopard, I get a warning dialog about my app wanting to use the iChat item in my keychain. I guess SecIdentitySearch is finding the iChat identity and I'm going with that. How do I restrict SecIdentitySearch to find only my self- signed identity? Is that the right thing to do?

Maybe I'm making this overly complicated. Is there an easier way to add SSL encryption to my CFStream? A Leopard-only solution would be fine. Thanks!

Dave

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: SSL with CFStreams
      • From: David Riggle <email@hidden>
  • Prev by Date: (no subject)
  • Next by Date: 802.11 (Airport) Statistics
  • Previous by thread: Re: (no subject)
  • Next by thread: Re: SSL with CFStreams
  • Index(es):
    • Date
    • Thread