TransceiverPtr IceObjC::StreamAcceptor::accept() { SOCKET fd = doAccept(_fd); setBlock(fd, false); setTcpBufSize(fd, _instance); // // Create the read/write streams // UniqueRef<CFReadStreamRef> readStream; UniqueRef<CFWriteStreamRef> writeStream; try { CFStreamCreatePairWithSocket(ICE_NULLPTR, fd, &readStream.get(), &writeStream.get()); _instance->setupStreams(readStream.get(), writeStream.get(), true, ""); return new StreamTransceiver(_instance, readStream.release(), writeStream.release(), fd); } catch(const Ice::LocalException& ex) { if(fd != INVALID_SOCKET) { closeSocketNoThrow(fd); } throw; } }
// // Imports a certificate private key and optionally add it to a keychain. // SecIdentityRef IceSSL::loadPrivateKey(const string& file, SecCertificateRef cert, SecKeychainRef keychain, const string& password, const PasswordPromptPtr& prompt, int retryMax) { // // Check if we already imported the certificate // UniqueRef<CFDataRef> hash; UniqueRef<CFDictionaryRef> subjectKeyProperty(getCertificateProperty(cert, kSecOIDSubjectKeyIdentifier)); if(subjectKeyProperty) { CFArrayRef values = (CFArrayRef)CFDictionaryGetValue(subjectKeyProperty.get(), kSecPropertyKeyValue); for(int i = 0; i < CFArrayGetCount(values); ++i) { CFDictionaryRef dict = (CFDictionaryRef)CFArrayGetValueAtIndex(values, i); if(CFEqual(CFDictionaryGetValue(dict, kSecPropertyKeyLabel), CFSTR("Key Identifier"))) { hash.retain(CFDictionaryGetValue(dict, kSecPropertyKeyValue)); break; } } } const void* values[] = { keychain }; UniqueRef<CFArrayRef> searchList(CFArrayCreate(kCFAllocatorDefault, values, 1, &kCFTypeArrayCallBacks)); UniqueRef<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate); CFDictionarySetValue(query.get(), kSecMatchLimit, kSecMatchLimitOne); CFDictionarySetValue(query.get(), kSecMatchSearchList, searchList.get()); CFDictionarySetValue(query.get(), kSecAttrSubjectKeyID, hash.get()); CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue); CFTypeRef value = 0; OSStatus err = SecItemCopyMatching(query.get(), &value); UniqueRef<SecCertificateRef> item(value); if(err == noErr) { // // If the certificate has already been imported, create the // identity. The key should also have been imported. // SecIdentityRef identity; err = SecIdentityCreateWithCertificate(keychain, item.get(), &identity); if(err != noErr) { ostringstream os; os << "IceSSL: error creating certificate identity:\n" << errorToString(err); throw CertificateReadException(__FILE__, __LINE__, os.str()); } return identity; } else if(err != errSecItemNotFound) { ostringstream os; os << "IceSSL: error searching for keychain items:\n" << errorToString(err); throw CertificateReadException(__FILE__, __LINE__, os.str()); } // // If the certificate isn't already in the keychain, load the // private key into the keychain and add the certificate. // UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypePrivateKey, keychain, password, prompt, retryMax)); int count = CFArrayGetCount(items.get()); UniqueRef<SecKeyRef> key; for(int i = 0; i < count; ++i) { SecKeychainItemRef item = (SecKeychainItemRef)CFArrayGetValueAtIndex(items.get(), 0); if(SecKeyGetTypeID() == CFGetTypeID(item)) { key.retain(item); break; } } if(!key) { throw CertificateReadException(__FILE__, __LINE__, "IceSSL: no key in file `" + file + "'"); } // // Add the certificate to the keychain // query.reset(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); CFDictionarySetValue(query.get(), kSecUseKeychain, keychain); CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate); CFDictionarySetValue(query.get(), kSecValueRef, cert); CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue); value = 0; err = SecItemAdd(query.get(), (CFTypeRef*)&value); UniqueRef<CFArrayRef> added(value); if(err != noErr) { ostringstream os; os << "IceSSL: failure adding certificate to keychain\n" << errorToString(err); throw CertificateReadException(__FILE__, __LINE__, os.str()); } item.retain(CFArrayGetValueAtIndex(added.get(), 0)); // // Create the association between the private key and the certificate, // kSecKeyLabel attribute should match the subject key identifier. // vector<SecKeychainAttribute> attributes; if(hash) { SecKeychainAttribute attr; attr.tag = kSecKeyLabel; attr.data = (void*)CFDataGetBytePtr(hash.get()); attr.length = CFDataGetLength(hash.get()); attributes.push_back(attr); } // // kSecKeyPrintName attribute correspond to the keychain display // name. // string label; CFStringRef commonName = 0; if(SecCertificateCopyCommonName(item.get(), &commonName) == noErr) { label = fromCFString(commonName); CFRelease(commonName); SecKeychainAttribute attr; attr.tag = kSecKeyPrintName; attr.data = (void*)label.c_str(); attr.length = label.size(); attributes.push_back(attr); } SecKeychainAttributeList attrs; attrs.attr = &attributes[0]; attrs.count = attributes.size(); SecKeychainItemModifyAttributesAndData((SecKeychainItemRef)key.get(), &attrs, 0, 0); SecIdentityRef identity; err = SecIdentityCreateWithCertificate(keychain, item.get(), &identity); if(err != noErr) { ostringstream os; os << "IceSSL: error creating certificate identity:\n" << errorToString(err); throw CertificateReadException(__FILE__, __LINE__, os.str()); } return identity; }