OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password) { BEGIN_SECKCITEMAPI OSStatus result; // try to unlock the keychain with this password first SecKeychainRef kc = NULL; result = SecKeychainItemCopyKeychain(__itemImplRef, &kc); if(!result) { SecKeychainUnlock(kc, passwordLength, password, true); if(kc) { CFRelease(kc); } } // Create some credentials with this password CssmAutoData data(Allocator::standard(), password, passwordLength); AclFactory::PassphraseUnlockCredentials cred(data, Allocator::standard()); Access::required(accessRef)->editAccess(*aclBearer(reinterpret_cast<CFTypeRef>(__itemImplRef)), true, cred.getAccessCredentials()); ItemImpl::required(itemRef)->postItemEvent (kSecUpdateEvent); END_SECKCITEMAPI }
int unlockToken(const char *password) { OSStatus status = noErr; if (!password) return paramErr; CFArrayRef searchList = NULL; status = SecKeychainCopyDomainSearchList(kSecPreferencesDomainDynamic, &searchList); if (status) return status; CFIndex count = searchList ? CFArrayGetCount(searchList) : 0; if (count) { SecKeychainRef keychainRef = (SecKeychainRef)CFArrayGetValueAtIndex(searchList, 0); // only first dynamic keychain! status = SecKeychainUnlock(keychainRef, (UInt32)strlen(password), password, 1); if (keychainRef) CFRelease(keychainRef); } else status = errSecNoSuchKeychain; if (searchList) CFRelease(searchList); return status; }
static VALUE rb_keychain_unlock(int argc, VALUE *argv, VALUE self){ SecKeychainRef keychain=NULL; Data_Get_Struct(self, struct OpaqueSecKeychainRef, keychain); VALUE password; rb_scan_args(argc, argv, "01", &password); OSStatus result = noErr; if(password){ StringValue(password); password = rb_str_export_to_enc(password, rb_utf8_encoding()); result = SecKeychainUnlock(keychain, (UInt32)RSTRING_LEN(password), (UInt8*)RSTRING_PTR(password), true); }else{ result = SecKeychainUnlock(keychain,0,NULL,false); } CheckOSStatusOrRaise(result); return Qnil; }
int main(void) { OSStatus err; char passphrase[128]; /* attack default keychain */ SecKeychainRef keychain = NULL; /* argv[1] contains target keychain's name */ while(fgets(passphrase, 128, stdin) != NULL) { err = SecKeychainUnlock(keychain, strlen(password), password, TRUE); if (!err) { printf ("Password Found : %s\n", password); exit(0); } } }
int main(int argc, char **argv) { bool verbose = false; int arg; while ((arg = getopt(argc, argv, "vh")) != -1) { switch (arg) { case 'v': verbose = true; break; case 'h': usage(argv); } } if(optind != argc) { usage(argv); } printNoDialog(); /* initial setup */ verboseDisp(verbose, "deleting keychain"); unlink(KEYCHAIN_NAME); verboseDisp(verbose, "creating keychain"); SecKeychainRef kcRef = NULL; OSStatus ortn = SecKeychainCreate(KEYCHAIN_NAME, strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, false, NULL, &kcRef); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } /* * 1. Generate key pair with cleartext public key. * Ensure we can use the public key when keychain is locked with no * user interaction. */ /* generate key pair, cleartext public key */ verboseDisp(verbose, "creating key pair, cleartext public key"); SecKeyRef pubKeyRef = NULL; SecKeyRef privKeyRef = NULL; if(genKeyPair(false, kcRef, &pubKeyRef, &privKeyRef)) { exit(1); } /* Use generated cleartext public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); CFDataRef exportData = NULL; ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } CFRelease(exportData); verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } /* reset */ verboseDisp(verbose, "deleting keys"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); CFRelease(privKeyRef); /* * 2. Generate key pair with encrypted public key. * Ensure that user interaction is required when we use the public key * when keychain is locked. */ verboseDisp(verbose, "programmatically unlocking keychain"); ortn = SecKeychainUnlock(kcRef, strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, TRUE); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } /* generate key pair, encrypted public key */ verboseDisp(verbose, "creating key pair, encrypted public key"); if(genKeyPair(true, kcRef, &pubKeyRef, &privKeyRef)) { exit(1); } /* Use generated encrypted public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); printExpectDialog(); ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } /* we'll use that exported blob later to test import */ if(!didGetDialog()) { exit(1); } verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); printExpectDialog(); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } if(!didGetDialog()) { exit(1); } /* reset */ printNoDialog(); verboseDisp(verbose, "locking keychain"); SecKeychainLock(kcRef); verboseDisp(verbose, "deleting keys"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); CFRelease(privKeyRef); /* * 3. Import public key, storing in cleartext. Ensure that the import * doesn't require unlock, and ensure we can use the public key * when keychain is locked with no user interaction. */ printNoDialog(); verboseDisp(verbose, "locking keychain"); SecKeychainLock(kcRef); /* import public key - default is in the clear */ verboseDisp(verbose, "importing public key, store in the clear (default)"); CFArrayRef outArray = NULL; SecExternalFormat format = kSecFormatOpenSSL; SecExternalItemType type = kSecItemTypePublicKey; ortn = SecKeychainItemImport(exportData, NULL, &format, &type, 0, NULL, kcRef, &outArray); if(ortn) { cssmPerror("SecKeychainItemImport", ortn); exit(1); } CFRelease(exportData); if(CFArrayGetCount(outArray) != 1) { printf("***Unexpected outArray size (%ld) after import\n", (long)CFArrayGetCount(outArray)); exit(1); } pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { printf("***Unexpected item type after import\n"); exit(1); } /* Use imported cleartext public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); exportData = NULL; ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainItemExport", ortn); exit(1); } /* we'll use exportData again */ verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } /* reset */ verboseDisp(verbose, "deleting key"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); /* * Import public key, storing in encrypted form. * Ensure that user interaction is required when we use the public key * when keychain is locked. */ /* import public key, encrypted in the keychain */ SecKeyImportExportParameters impExpParams; memset(&impExpParams, 0, sizeof(impExpParams)); impExpParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; impExpParams.keyAttributes = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT; verboseDisp(verbose, "importing public key, store encrypted"); printExpectDialog(); outArray = NULL; format = kSecFormatOpenSSL; type = kSecItemTypePublicKey; ortn = SecKeychainItemImport(exportData, NULL, &format, &type, 0, &impExpParams, kcRef, &outArray); if(ortn) { cssmPerror("SecKeychainItemImport", ortn); exit(1); } if(!didGetDialog()) { exit(1); } CFRelease(exportData); if(CFArrayGetCount(outArray) != 1) { printf("***Unexpected outArray size (%ld) after import\n", (long)CFArrayGetCount(outArray)); exit(1); } pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { printf("***Unexpected item type after import\n"); exit(1); } /* Use imported encrypted public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); printExpectDialog(); ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainItemExport", ortn); exit(1); } if(!didGetDialog()) { exit(1); } CFRelease(exportData); verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); printExpectDialog(); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } if(!didGetDialog()) { exit(1); } SecKeychainDelete(kcRef); printf("...test succeeded.\n"); return 0; }
int main(int argc, char **argv) { OSStatus err; int arg; char fullFileBase[100]; SSLProtocol negVersion; SSLCipherSuite negCipher; Boolean sessionWasResumed; unsigned char sessionID[MAX_SESSION_ID_LENGTH]; size_t sessionIDLength; CFArrayRef peerCerts = NULL; char *argp; otSocket listenSock; CFArrayRef serverCerts = nil; // required CFArrayRef encryptCerts = nil; // optional SecKeychainRef serverKc = nil; SecKeychainRef encryptKc = nil; int loopNum; int errCount = 0; SSLClientCertificateState certState; // obtained from sslServe /* user-spec'd parameters */ unsigned short portNum = DEFAULT_PORT; bool allowExpired = false; bool allowAnyRoot = false; char *fileBase = NULL; bool displayCerts = false; char cipherRestrict = '\0'; SSLProtocol attemptProt = kTLSProtocol1; bool protXOnly = false; // kSSLProtocol3Only, // kTLSProtocol1Only char *acceptedProts = NULL; // "23t" ==> SSLSetProtocolVersionEnabled bool quiet = false; bool resumableEnable = true; bool pause = false; char *keyChainName = NULL; char *encryptKeyChainName = NULL; int loops = 1; SSLAuthenticate authenticate = kNeverAuthenticate; bool nonBlocking = false; bool allowExpiredRoot = false; bool disableCertVerify = false; char *anchorFile = NULL; bool replaceAnchors = false; bool vfyCertState = false; SSLClientCertificateState expectCertState = kSSLClientCertNone; char *password = NULL; char *dhParamsFile = NULL; unsigned char *dhParams = NULL; unsigned dhParamsLen = 0; bool doIdSearch = false; bool completeCertChain = false; uint32_t sessionCacheTimeout = 0; bool disableAnonCiphers = false; CFMutableArrayRef acceptableDNList = NULL; for(arg=1; arg<argc; arg++) { argp = argv[arg]; switch(argp[0]) { case 'P': portNum = atoi(&argp[2]); break; case 'k': keyChainName = &argp[2]; break; case 'y': encryptKeyChainName = &argp[2]; break; case 'e': allowExpired = true; break; case 'E': allowExpiredRoot = true; break; case 'x': disableCertVerify = true; break; case 'a': if(++arg == argc) { /* requires another arg */ usage(argv); } anchorFile = argv[arg]; break; case 'A': if(++arg == argc) { /* requires another arg */ usage(argv); } anchorFile = argv[arg]; replaceAnchors = true; break; case 'T': if(argp[1] != '=') { usage(argv); } vfyCertState = true; switch(argp[2]) { case 'n': expectCertState = kSSLClientCertNone; break; case 'r': expectCertState = kSSLClientCertRequested; break; case 's': expectCertState = kSSLClientCertSent; break; case 'j': expectCertState = kSSLClientCertRejected; break; default: usage(argv); } break; case 'r': allowAnyRoot = true; break; case 'd': break; case 'c': displayCerts = true; break; case 'f': fileBase = &argp[2]; break; case 'C': cipherRestrict = argp[2]; break; case '2': attemptProt = kSSLProtocol2; break; case '3': attemptProt = kSSLProtocol3; break; case 't': attemptProt = kTLSProtocol1; break; case 'o': protXOnly = true; break; case 'g': if(argp[1] != '=') { usage(argv); } acceptedProts = &argp[2]; break; case 'R': resumableEnable = false; break; case 'b': nonBlocking = true; break; case 'u': if(argp[1] != '=') { usage(argv); } switch(argp[2]) { case 'a': authenticate = kAlwaysAuthenticate; break; case 'n': authenticate = kNeverAuthenticate; break; case 't': authenticate = kTryAuthenticate; break; default: usage(argv); } break; case 'D': if(++arg == argc) { /* requires another arg */ usage(argv); } dhParamsFile = argv[arg]; break; case 'z': password = &argp[2]; break; case 'H': doIdSearch = true; break; case 'M': completeCertChain = true; break; case 'i': sessionCacheTimeout = atoi(&argp[2]); break; case '4': disableAnonCiphers = true; break; case 'p': pause = true; break; case 'q': quiet = true; break; #if 0 case 'U': if(++arg == argc) { /* requires another arg */ usage(argv); } if(cspReadFile(argv[arg], &caCert, &caCertLen)) { printf("***Error reading file %s. Aborting.\n", argv[arg]); exit(1); } if(acceptableDNList == NULL) { acceptableDNList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } certData.Data = caCert; certData.Length = caCertLen; ortn = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &secCert); if(ortn) { cssmPerror("SecCertificateCreateFromData", ortn); exit(1); } CFArrayAppendValue(acceptableDNList, secCert); CFRelease(secCert); break; #endif case 'l': if(argp[1] == '\0') { /* no loop count --> loop forever */ loops = 0; break; } else if(argp[1] != '=') { usage(argv); } loops = atoi(&argp[2]); break; default: usage(argv); } } #if NO_SERVER # if DEBUG securityd_init(NULL); # endif #endif /* get server cert and optional encryption cert as CFArrayRef */ if(keyChainName) { serverCerts = getSslCerts(keyChainName, false, completeCertChain, anchorFile, &serverKc); if(serverCerts == nil) { exit(1); } } else #if 0 if(doIdSearch) { OSStatus ortn = sslIdentityPicker(NULL, anchorFile, true, NULL, &serverCerts); if(ortn) { printf("***IdentitySearch failure; aborting.\n"); exit(1); } } if(password) { OSStatus ortn = SecKeychainUnlock(serverKc, strlen(password), password, true); if(ortn) { printf("SecKeychainUnlock returned %d\n", (int)ortn); /* oh well */ } } if(encryptKeyChainName) { encryptCerts = getSslCerts(encryptKeyChainName, true, completeCertChain, anchorFile, &encryptKc); if(encryptCerts == nil) { exit(1); } } #else (void) doIdSearch; (void) encryptKeyChainName; #endif if(protXOnly) { switch(attemptProt) { case kTLSProtocol1: attemptProt = kTLSProtocol1Only; break; case kSSLProtocol3: attemptProt = kSSLProtocol3Only; break; default: break; } } #if 0 if(dhParamsFile) { int r = cspReadFile(dhParamsFile, &dhParams, &dhParamsLen); if(r) { printf("***Error reading diffie-hellman params from %s; aborting\n", dhParamsFile); } } #else (void) dhParamsFile; #endif /* one-time only server port setup */ err = ListenForClients(portNum, nonBlocking, &listenSock); if(err) { printf("ListenForClients returned %d; aborting\n", (int)err); exit(1); } for(loopNum=1; ; loopNum++) { err = sslServe(listenSock, portNum, attemptProt, acceptedProts, serverCerts, password, encryptCerts, allowExpired, allowAnyRoot, allowExpiredRoot, disableCertVerify, anchorFile, replaceAnchors, cipherRestrict, authenticate, dhParams, dhParamsLen, acceptableDNList, resumableEnable, sessionCacheTimeout, disableAnonCiphers, quiet, pause, &negVersion, &negCipher, &certState, &sessionWasResumed, sessionID, &sessionIDLength, &peerCerts, argv); if(err) { errCount++; } if(!quiet) { SSLProtocol tryProt = attemptProt; showSSLResult(tryProt, acceptedProts, err, negVersion, negCipher, sessionWasResumed, sessionID, sessionIDLength, peerCerts, displayCerts, certState, fileBase ? fullFileBase : NULL); } errCount += verifyClientCertState(vfyCertState, expectCertState, certState); freePeerCerts(peerCerts); if(loops && (loopNum == loops)) { break; } }; endpointShutdown(listenSock); if(serverKc) { CFRelease(serverKc); } if(encryptKc) { CFRelease(encryptKc); } return errCount; }
/* * params->lock is held for us by runSession() - we use it as a semapahore by * unlocking it when we've created a port to listen on. * This is generally run from a thread via sslRunSession() and * sslServerThread() in sslAppUtils.cpp. */ OSStatus sslAppServe( SslAppTestParams *params) { otSocket listenSock = 0; otSocket acceptSock = 0; PeerSpec peerId; OSStatus ortn; SSLContextRef ctx = NULL; SecKeychainRef serverKc = nil; CFArrayRef serverCerts = nil; sslThrDebug("Server", "starting"); params->negVersion = kSSLProtocolUnknown; params->negCipher = SSL_NULL_WITH_NULL_NULL; params->ortn = noHardwareErr; /* set up a socket on which to listen */ for(unsigned retry=0; retry<BIND_RETRIES; retry++) { ortn = ListenForClients(params->port, params->nonBlocking, &listenSock); switch(ortn) { case errSecSuccess: break; case errSecOpWr: /* port already in use - try another */ params->port++; if(params->verbose || THREADING_DEBUG) { printf("...retrying ListenForClients at port %d\n", params->port); } break; default: break; } if(ortn != errSecOpWr) { break; } } /* let main thread know a socket is ready */ if(pthread_mutex_lock(¶ms->pthreadMutex)) { printf("***Error acquiring server lock; aborting.\n"); return -1; } params->serverReady = true; if(pthread_cond_broadcast(¶ms->pthreadCond)) { printf("***Error waking main thread; aborting.\n"); return -1; } if(pthread_mutex_unlock(¶ms->pthreadMutex)) { printf("***Error acquiring server lock; aborting.\n"); return -1; } if(ortn) { printf("ListenForClients returned %d; aborting\n", (int)ortn); return ortn; } /* wait for a connection */ if(params->verbose) { printf("Waiting for client connection..."); fflush(stdout); } ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); if(ortn) { printf("AcceptClientConnection returned %d; aborting\n", (int)ortn); return ortn; } /* * Set up a SecureTransport session. */ ortn = SSLNewContext(true, &ctx); if(ortn) { printSslErrStr("SSLNewContext", ortn); goto cleanup; } ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); if(ortn) { printSslErrStr("SSLSetIOFuncs", ortn); goto cleanup; } ortn = SSLSetConnection(ctx, (SSLConnectionRef)acceptSock); if(ortn) { printSslErrStr("SSLSetConnection", ortn); goto cleanup; } if(params->anchorFile) { ortn = sslAddTrustedRoot(ctx, params->anchorFile, params->replaceAnchors); if(ortn) { goto cleanup; } } if(params->myCertKcName != NULL) { /* if not, better be trying anonymous diff-hellman... :-) */ serverCerts = getSslCerts(params->myCertKcName, false, false, NULL, &serverKc); if(serverCerts == nil) { exit(1); } if(params->password) { ortn = SecKeychainUnlock(serverKc, strlen(params->password), (void *)params->password, true); if(ortn) { printf("SecKeychainUnlock returned %d\n", (int)ortn); /* oh well */ } } if(params->idIsTrustedRoot) { /* assume this is a root we want to implicitly trust */ ortn = addIdentityAsTrustedRoot(ctx, serverCerts); if(ortn) { goto cleanup; } } ortn = SSLSetCertificate(ctx, serverCerts); if(ortn) { printSslErrStr("SSLSetCertificate", ortn); goto cleanup; } } if(params->disableCertVerify) { ortn = SSLSetEnableCertVerify(ctx, false); if(ortn) { printSslErrStr("SSLSetEnableCertVerify", ortn); goto cleanup; } } ortn = sslSetProtocols(ctx, params->acceptedProts, params->tryVersion); if(ortn) { goto cleanup; } if(params->resumeEnable) { ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); if(ortn) { printSslErrStr("SSLSetPeerID", ortn); goto cleanup; } } if(params->ciphers != NULL) { ortn = sslSetEnabledCiphers(ctx, params->ciphers); if(ortn) { goto cleanup; } } if(params->authenticate != kNeverAuthenticate) { ortn = SSLSetClientSideAuthenticate(ctx, params->authenticate); if(ortn) { printSslErrStr("SSLSetClientSideAuthenticate", ortn); goto cleanup; } } if(params->dhParams) { #if JAGUAR_BUILD printf("***Diffie-Hellman not supported in this config.\n"); #else ortn = SSLSetDiffieHellmanParams(ctx, params->dhParams, params->dhParamsLen); if(ortn) { printSslErrStr("SSLSetDiffieHellmanParams", ortn); goto cleanup; } #endif } /* Perform SSL/TLS handshake */ do { ortn = SSLHandshake(ctx); if((ortn == errSSLWouldBlock) && !params->silent) { /* keep UI responsive */ sslOutputDot(); } } while (ortn == errSSLWouldBlock); SSLGetClientCertificateState(ctx, ¶ms->certState); SSLGetNegotiatedCipher(ctx, ¶ms->negCipher); SSLGetNegotiatedProtocolVersion(ctx, ¶ms->negVersion); if(params->verbose) { printf("\n"); } if(ortn) { goto cleanup; } /* wait for one complete line */ char readBuf[READBUF_LEN]; size_t length; while(ortn == errSecSuccess) { length = READBUF_LEN; ortn = SSLRead(ctx, readBuf, length, &length); if (ortn == errSSLWouldBlock) { /* keep trying */ ortn = errSecSuccess; continue; } if(length == 0) { /* keep trying */ continue; } /* poor person's line completion scan */ for(unsigned i=0; i<length; i++) { if((readBuf[i] == '\n') || (readBuf[i] == '\r')) { goto serverResp; } } } serverResp: /* send out canned response */ ortn = SSLWrite(ctx, SERVER_MESSAGE, strlen(SERVER_MESSAGE), &length); if(ortn) { printSslErrStr("SSLWrite", ortn); } cleanup: /* * always do close, even on error - to flush outgoing write queue */ if(ctx) { OSStatus cerr = SSLClose(ctx); if(ortn == errSecSuccess) { ortn = cerr; } } if(acceptSock) { while(!params->clientDone && !params->serverAbort) { usleep(100); } endpointShutdown(acceptSock); } if(listenSock) { endpointShutdown(listenSock); } if(ctx) { SSLDisposeContext(ctx); } params->ortn = ortn; sslThrDebug("Server", "done"); return ortn; }
int main(int argc, char **argv) { RingBuffer serverToClientRing; RingBuffer clientToServerRing; unsigned numBufs = DEFAULT_NUM_BUFS; unsigned bufSize = DEFAULT_BUF_SIZE; unsigned chunkSize = DEFAULT_CHUNK; unsigned char clientBuf[DEFAULT_CHUNK]; unsigned char serverBuf[DEFAULT_CHUNK]; CFArrayRef idArray; /* for SSLSetCertificate */ CFArrayRef anchorArray; /* trusted roots */ SslRingBufferArgs clientArgs; SslRingBufferArgs serverArgs; SecKeychainRef kcRef = NULL; SecCertificateRef anchorCert = NULL; SecIdentityRef idRef = NULL; bool abortFlag = false; pthread_t client_thread = NULL; int result; bool diffieHellman = true; /* FIXME needs work */ OSStatus ortn; /* user-spec'd variables */ char *kcName = DEFAULT_KC; unsigned xferSize = DEFAULT_XFER; SSLCipherSuite cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA; SSLProtocol prot = kTLSProtocol1; char password[200]; bool clientAuthEnable = false; bool pauseOnError = false; bool runForever = false; bool mallocPause = false; password[0] = 0; extern int optind; extern char *optarg; int arg; optind = 1; while ((arg = getopt(argc, argv, "k:x:c:v:w:aBpm")) != -1) { switch (arg) { case 'k': kcName = optarg; break; case 'x': { unsigned xsize = atoi(optarg); if(xsize == 0) { runForever = true; /* and leave xferSize alone */ } else { xferSize = xsize; } break; } case 'c': switch(optarg[0]) { case 'a': cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA; break; case 'r': cipherSuite = SSL_RSA_WITH_RC4_128_SHA; break; case 'd': cipherSuite = SSL_RSA_WITH_DES_CBC_SHA; break; case 'D': cipherSuite = SSL_RSA_WITH_3DES_EDE_CBC_SHA; break; case 'h': cipherSuite = SSL_DH_anon_WITH_RC4_128_MD5; diffieHellman = true; break; case 'H': cipherSuite = SSL_DHE_DSS_WITH_DES_CBC_SHA; diffieHellman = true; break; case 'A': cipherSuite = TLS_RSA_WITH_AES_256_CBC_SHA; break; default: usage(argv); } break; case 'v': switch(optarg[0]) { case 't': prot = kTLSProtocol1; break; case '2': prot = kSSLProtocol2; break; case '3': prot = kSSLProtocol3; break; default: usage(argv); } break; case 'w': strcpy(password, optarg); break; case 'a': clientAuthEnable = true; break; case 'p': pauseOnError = true; break; case 'm': mallocPause = true; break; default: usage(argv); } } if(optind != argc) { usage(argv); } /* set up ring buffers */ ringBufSetup(&serverToClientRing, "serveToClient", numBufs, bufSize); ringBufSetup(&clientToServerRing, "clientToServe", numBufs, bufSize); /* get server SecIdentity */ idArray = getSslCerts(kcName, CSSM_FALSE, /* encryptOnly */ CSSM_FALSE, /* completeCertChain */ NULL, /* anchorFile */ &kcRef); if(idArray == NULL) { printf("***Can't get signing cert from %s\n", kcName); exit(1); } idRef = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, 0); ortn = SecIdentityCopyCertificate(idRef, &anchorCert); if(ortn) { cssmPerror("SecIdentityCopyCertificate", ortn); exit(1); } anchorArray = CFArrayCreate(NULL, (const void **)&anchorCert, 1, &kCFTypeArrayCallBacks); /* unlock keychain? */ if(password[0]) { ortn = SecKeychainUnlock(kcRef, strlen(password), password, true); if(ortn) { cssmPerror("SecKeychainUnlock", ortn); /* oh well */ } } CFRelease(kcRef); if(mallocPause) { fpurge(stdin); printf("Pausing for MallocDebug setup. CR to proceed: "); getchar(); } /* set up server side */ memset(&serverArgs, 0, sizeof(serverArgs)); serverArgs.idArray = idArray; serverArgs.trustedRoots = anchorArray; serverArgs.xferSize = xferSize; serverArgs.xferBuf = serverBuf; serverArgs.chunkSize = chunkSize; serverArgs.runForever = runForever; serverArgs.cipherSuite = cipherSuite; serverArgs.prot = prot; serverArgs.ringWrite = &serverToClientRing; serverArgs.ringRead = &clientToServerRing; serverArgs.goFlag = &clientArgs.iAmReady; serverArgs.abortFlag = &abortFlag; serverArgs.pauseOnError = pauseOnError; /* set up client side */ memset(&clientArgs, 0, sizeof(clientArgs)); clientArgs.idArray = NULL; /* until we do client auth */ clientArgs.trustedRoots = anchorArray; clientArgs.xferSize = xferSize; clientArgs.xferBuf = clientBuf; clientArgs.chunkSize = chunkSize; clientArgs.runForever = runForever; clientArgs.cipherSuite = cipherSuite; clientArgs.prot = prot; clientArgs.ringWrite = &clientToServerRing; clientArgs.ringRead = &serverToClientRing; clientArgs.goFlag = &serverArgs.iAmReady; clientArgs.abortFlag = &abortFlag; clientArgs.pauseOnError = pauseOnError; /* fire up client thread */ result = pthread_create(&client_thread, NULL, sslRbClientThread, &clientArgs); if(result) { printf("***pthread_create returned %d, aborting\n", result); exit(1); } /* * And the server pseudo thread. This returns when all data has been transferred. */ ortn = sslRbServerThread(&serverArgs); if(abortFlag) { printf("***Test aborted.\n"); exit(1); } printf("\n"); if(mallocPause) { fpurge(stdin); printf("End of test. Pausing for MallocDebug analysis. CR to proceed: "); getchar(); } printf("SSL Protocol Version : %s\n", sslGetProtocolVersionString(serverArgs.negotiatedProt)); printf("SSL Cipher : %s\n", sslGetCipherSuiteString(serverArgs.negotiatedCipher)); printf("SSL Handshake : %f s\n", serverArgs.startData - serverArgs.startHandshake); printf("Data Transfer : %u bytes in %f s\n", (unsigned)xferSize, serverArgs.endData - serverArgs.startHandshake); printf(" : %.1f Kbytes/s\n", xferSize / (serverArgs.endData - serverArgs.startHandshake) / 1024.0); return 0; }
int main(int argc, char **argv) { /* user-spec'd variables */ const char *kcName = DEFAULT_KC; unsigned xferSize = XFERSIZE_DEF; int port = PORT_DEF; const char *hostName = HOST_DEF; SSLCipherSuite cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA; SSLProtocol prot = kTLSProtocol1Only; char password[200]; bool clientAuthEnable = false; bool isServer = false; unsigned bufSize = BUFSIZE; bool diffieHellman = false; int nonBlocking = 0; if(argc < 2) { usage(argv); } password[0] = 0; switch(argv[1][0]) { case 's': isServer = true; break; case 'c': isServer = false; break; default: usage(argv); } extern int optind; extern char *optarg; int arg; optind = 2; while ((arg = getopt(argc, argv, "h:p:k:x:c:v:w:b:aB")) != -1) { switch (arg) { case 'h': hostName = optarg; break; case 'p': port = atoi(optarg); break; case 'k': kcName = optarg; break; case 'x': xferSize = atoi(optarg); break; case 'c': if(!isServer) { printf("***Specify cipherSuite on server side.\n"); exit(1); } switch(optarg[0]) { case 'r': cipherSuite = SSL_RSA_WITH_RC4_128_SHA; break; case 'd': cipherSuite = SSL_RSA_WITH_DES_CBC_SHA; break; case 'D': cipherSuite = SSL_RSA_WITH_3DES_EDE_CBC_SHA; break; case 'h': cipherSuite = SSL_DH_anon_WITH_RC4_128_MD5; diffieHellman = true; break; case 'H': cipherSuite = SSL_DHE_DSS_WITH_DES_CBC_SHA; diffieHellman = true; break; case 'A': cipherSuite = TLS_RSA_WITH_AES_256_CBC_SHA; break; default: usage(argv); } break; case 'v': if(!isServer) { printf("***Specify protocol on server side.\n"); exit(1); } switch(optarg[0]) { case 't': prot = kTLSProtocol1Only; break; case '2': prot = kSSLProtocol2; break; case '3': prot = kSSLProtocol3Only; break; default: usage(argv); } break; case 'w': strcpy(password, optarg); break; case 'b': bufSize = atoi(optarg); break; case 'a': clientAuthEnable = true; break; case 'B': nonBlocking = 1; break; default: usage(argv); } } /* per-transfer buffer - make it random for server */ char *buf = (char *)malloc(bufSize); if(isServer) { Security::DevRandomGenerator rng; rng.random(buf, bufSize); } /* gather Diffie-Hellman params from cwd */ unsigned char *dhParams = NULL; unsigned dhParamsLen = 0; if(diffieHellman && isServer) { if(readFile(DH_PARAM_FILE, &dhParams, &dhParamsLen)) { printf("***Error reading Diffie-Hellman Params. Prepare to " "wait for a minute during SSL handshake.\n"); } } /* * Open keychain; both sides use the same one. */ OSStatus ortn; SecKeychainRef certKc = NULL; CFAbsoluteTime kcOpenStart = CFAbsoluteTimeGetCurrent(); ortn = SecKeychainOpen(kcName, &certKc); if(ortn) { printf("Error opening keychain %s (%d); aborting.\n", kcName, (int)ortn); exit(1); } if(password[0]) { ortn = SecKeychainUnlock(certKc, strlen(password), password, true); if(ortn) { printf("SecKeychainUnlock returned %d\n", (int)ortn); /* oh well */ } } CFAbsoluteTime kcOpenEnd = CFAbsoluteTimeGetCurrent(); otSocket peerSock = 0; otSocket listenSock = 0; // for server only PeerSpec peerId; if(isServer) { printf("...listening for client connection on port %d\n", port); ortn = ListenForClients(port, nonBlocking, &listenSock); if(ortn) { printf("...error establishing a listen socket. Aborting.\n"); exit(1); } ortn = AcceptClientConnection(listenSock, &peerSock, &peerId); if(ortn) { printf("...error listening for connection. Aborting.\n"); exit(1); } } else { printf("...connecting to host %s at port %d\n", hostName, port); ortn = MakeServerConnection(hostName, port, nonBlocking, &peerSock, &peerId); if(ortn) { printf("...error connecting to server %s. Aborting.\n", hostName); exit(1); } } /* start timing SSL setup */ CFAbsoluteTime setupStart = CFAbsoluteTimeGetCurrent(); SSLContextRef ctx; ortn = SSLNewContext(isServer, &ctx); if(ortn) { printSslErrStr("SSLNewContext", ortn); exit(1); } ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); if(ortn) { printSslErrStr("SSLSetIOFuncs", ortn); exit(1); } ortn = SSLSetConnection(ctx, (SSLConnectionRef)peerSock); if(ortn) { printSslErrStr("SSLSetConnection", ortn); exit(1); } ortn = SSLSetPeerDomainName(ctx, hostName, strlen(hostName) + 1); if(ortn) { printSslErrStr("SSLSetPeerDomainName", ortn); exit(1); } /* * Server/client specific setup. * * Client uses the same keychain as server, but it uses it for * sslAddTrustedRoots() instead of getSslCerts() and * SSLSetCertificate(). */ CFArrayRef myCerts = NULL; if(clientAuthEnable || isServer) { myCerts = sslKcRefToCertArray(certKc, CSSM_FALSE, CSSM_FALSE, NULL, NULL); if(myCerts == NULL) { exit(1); } ortn = addIdentityAsTrustedRoot(ctx, myCerts); if(ortn) { exit(1); } ortn = SSLSetCertificate(ctx, myCerts); if(ortn) { printSslErrStr("SSLSetCertificate", ortn); exit(1); } } if(isServer) { SSLAuthenticate auth; if(clientAuthEnable) { auth = kAlwaysAuthenticate; } else { auth = kNeverAuthenticate; } ortn = SSLSetClientSideAuthenticate(ctx, auth); if(ortn) { printSslErrStr("SSLSetClientSideAuthenticate", ortn); exit(1); } ortn = SSLSetEnabledCiphers(ctx, &cipherSuite, 1); if(ortn) { printSslErrStr("SSLSetEnabledCiphers", ortn); exit(1); } ortn = SSLSetProtocolVersion(ctx, prot); if(ortn) { printSslErrStr("SSLSetProtocolVersion", ortn); exit(1); } if(dhParams != NULL) { ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen); if(ortn) { printSslErrStr("SSLSetDiffieHellmanParams", ortn); exit(1); } } } else { /* client setup */ if(!clientAuthEnable) { /* We're not presenting a cert; trust the server certs */ bool foundOne; ortn = sslAddTrustedRoots(ctx, certKc, &foundOne); if(ortn) { printSslErrStr("sslAddTrustedRoots", ortn); exit(1); } } } /* * Context setup complete. Start timing handshake. */ CFAbsoluteTime hshakeStart = CFAbsoluteTimeGetCurrent(); do { ortn = SSLHandshake(ctx); } while (ortn == errSSLWouldBlock); if(ortn) { printSslErrStr("SSLHandshake", ortn); exit(1); } CFAbsoluteTime hshakeEnd = CFAbsoluteTimeGetCurrent(); /* snag these before data xfer possibly shuts down connection */ SSLProtocol negVersion; SSLCipherSuite negCipher; SSLClientCertificateState certState; // RETURNED SSLGetNegotiatedCipher(ctx, &negCipher); SSLGetNegotiatedProtocolVersion(ctx, &negVersion); SSLGetClientCertificateState(ctx, &certState); /* server sends xferSize bytes to client and shuts down */ size_t bytesMoved; CFAbsoluteTime dataStart = CFAbsoluteTimeGetCurrent(); size_t totalMoved = 0; if(isServer) { size_t bytesToGo = xferSize; bool done = false; do { size_t thisMove = bufSize; if(thisMove > bytesToGo) { thisMove = bytesToGo; } ortn = SSLWrite(ctx, buf, thisMove, &bytesMoved); switch(ortn) { case noErr: case errSSLWouldBlock: break; default: done = true; break; } bytesToGo -= bytesMoved; totalMoved += bytesMoved; if(bytesToGo == 0) { done = true; } } while(!done); if(ortn != noErr) { printSslErrStr("SSLWrite", ortn); exit(1); } } else { /* client reads until error or errSSLClosedGraceful */ bool done = false; do { ortn = SSLRead(ctx, buf, bufSize, &bytesMoved); switch(ortn) { case errSSLClosedGraceful: done = true; break; case noErr: case errSSLWouldBlock: break; default: done = true; break; } totalMoved += bytesMoved; } while(!done); if(ortn != errSSLClosedGraceful) { printSslErrStr("SSLRead", ortn); exit(1); } } /* shut down channel */ ortn = SSLClose(ctx); if(ortn) { printSslErrStr("SSLCLose", ortn); exit(1); } CFAbsoluteTime dataEnd = CFAbsoluteTimeGetCurrent(); /* how'd we do? */ printf("SSL version : %s\n", sslGetProtocolVersionString(negVersion)); printf("CipherSuite : %s\n", sslGetCipherSuiteString(negCipher)); printf("Client Cert State : %s\n", sslGetClientCertStateString(certState)); if(password[0]) { printf("keychain open/unlock : "); } else { printf("keychain open : "); } printf("%f s\n", kcOpenEnd - kcOpenStart); printf("SSLContext setup : %f s\n", hshakeStart - setupStart); printf("SSL Handshake : %f s\n", hshakeEnd - hshakeStart); printf("Data Transfer : %u bytes in %f s\n", (unsigned)totalMoved, dataEnd - dataStart); printf(" : %.1f Kbytes/s\n", totalMoved / (dataEnd - dataStart) / 1024.0); return 0; }
int main(int argc, char * const argv[]) { int verbose = 0; int dryRun = 0; int version = 0; char *toKeychainPath = NULL; struct option longopts[] = { { "dry-run", no_argument, &dryRun, 1 }, { "to-keychain", required_argument, NULL, 'k' }, { "verbose", no_argument, &verbose, 1 }, { "version", no_argument, &version, 1 }, { NULL, 0, NULL, 0 } }; int ch; while ((ch = getopt_long(argc, argv, "dk:v", longopts, NULL)) != -1) { switch (ch) { case 'k': toKeychainPath = optarg; break; case 'd': dryRun = 1; break; case 'v': verbose = 1; break; case 0: // Handle long-only options break; default: SRPrintUsage(); exit(EX_USAGE); } } argc -= optind; argv += optind; if (version) { fprintf(stderr, "splitring 1.1\nCopyright (C) 2013 Phil Calvin\n"); exit(0); } if (!argc) { SRPrintUsage(); exit(EX_USAGE); } CFMutableArrayRef keychains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // Iterate the passed keychain paths, opening each one for (int i = 0; i < argc; i++) { char* path = realpath(argv[i], NULL); if (path) { SecKeychainRef keychain = SROpenKeychain(path); CFArrayAppendValue(keychains, keychain); CFRelease(keychain); free(path); } else { fprintf(stderr, "Unable to find keychain: %s\n", argv[i]); } } // Unlock each of the keychains for (int i = 0; i < CFArrayGetCount(keychains); i++) { SecKeychainRef keychain = (SecKeychainRef)CFArrayGetValueAtIndex(keychains, i); // Unlock it; might not need to do this if (verbose) { UInt32 bufferSize = 4096; char keychainPath[bufferSize]; SecKeychainGetPath(keychain, &bufferSize, keychainPath); fprintf(stderr, "Unlocking keychain at path: %s\n", keychainPath); } OSStatus status = SecKeychainUnlock(keychain, 0, NULL, FALSE); SRHandleError(status, true); } SecKeychainRef targetKeychain = NULL; if (toKeychainPath) { // Convert this to a canonical path char* canonicalPath = realpath(toKeychainPath, NULL); if (canonicalPath) { // Import to the specified keychain targetKeychain = SROpenKeychain(canonicalPath); free(canonicalPath); } else { fprintf(stderr, "Unable to find keychain: %s\n", toKeychainPath); exit(EX_IOERR); } } else { // Import to the default keychain if one wasn't specified OSStatus status = SecKeychainCopyDefault(&targetKeychain); SRHandleError(status, true); status = SecKeychainUnlock(targetKeychain, 0, NULL, FALSE); SRHandleError(status, true); } // Search for all items CFMutableArrayRef classes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFArrayAppendValue(classes, kSecClassGenericPassword); CFArrayAppendValue(classes, kSecClassInternetPassword); //CFArrayAppendValue(classes, kSecClassCertificate); //CFArrayAppendValue(classes, kSecClassIdentity); //CFArrayAppendValue(classes, kSecClassKey); CFArrayRef items = SRCopyItems(keychains, classes); if (verbose) { UInt32 bufferSize = 4096; char defaultKeychainPath[bufferSize]; SecKeychainGetPath(targetKeychain, &bufferSize, defaultKeychainPath); fprintf(stderr, "Importing %li items to keychain at path: %s\n", CFArrayGetCount(items), defaultKeychainPath); } SRCopyItemsToKeychain(items, targetKeychain, verbose, dryRun); CFRelease(items); CFRelease(targetKeychain); CFRelease(keychains); return 0; }
static void tests(void) { char *home = getenv("HOME"); char kcname1[256], kcname2[256]; SecKeychainStatus status1, status2; if (!home || strlen(home) > 200) plan_skip_all("home too big"); sprintf(kcname1, "%s/kctests/kc1/kc1", home); SecKeychainRef kc1 = NULL, kc2 = NULL; kc1 = createNewKeychainAt(kcname1, "test"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); ok_status(SecKeychainLock(kc1), "SecKeychainLock kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecReadPermStatus|kSecWritePermStatus, "status (locked) readable writable"); } /* Make keychain non writable. */ char kcdir1[256]; sprintf(kcdir1, "%s/kctests/kc1", home); ok_unix(chmod(kcdir1, 0555), "chmod kcdir1 0555"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); is(status1, kSecReadPermStatus, "status (locked) readable"); ok_status(SecKeychainUnlock(kc1, 4, "test", TRUE), "SecKeychainLock kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus, "status unlocked readable"); } /* Reopen the keychain. */ CFRelease(kc1); ok_status(SecKeychainOpen(kcname1, &kc1), "SecKeychainOpen kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus, "status unlocked readable"); } sprintf(kcname2, "%s/kctests/kc2/kc2", home); kc2 = createNewKeychainAt(kcname2, "test"); ok_unix(chmod(kcname2, 0444), "chmod kc2 0444"); ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); /* Reopen the keychain. */ CFRelease(kc2); ok_status(SecKeychainOpen(kcname2, &kc2), "SecKeychainOpen kc2"); ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); /* Restore dir to writable so cleanup code will work ok. */ ok_unix(chmod(kcdir1, 0755), "chmod kcdir1 0755"); ok_status(SecKeychainDelete(kc1), "%s: SecKeychainDelete", testName); CFRelease(kc1); ok_status(SecKeychainDelete(kc2), "%s: SecKeychainDelete", testName); CFRelease(kc2); bool testWithFreshlyCreatedKeychain = true; SecKeychainRef keychain = createNewKeychain("test", "test"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); do { SecKeychainStatus keychainStatus = 0; is_status(SecKeychainUnlock(keychain, 0, NULL, true), -25293, "SecKeychainUnlock with NULL password (incorrect)"); ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); is( (keychainStatus & kSecUnlockStateStatus), 0, "Check it's not unlocked"); keychainStatus = 0; ok_status(SecKeychainUnlock(keychain, strlen("test"), "test", true), "SecKeychainUnlock with correct password"); ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); is( (keychainStatus & kSecUnlockStateStatus), kSecUnlockStateStatus, "Check it's unlocked"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); if (testWithFreshlyCreatedKeychain) { CFRelease(keychain); testWithFreshlyCreatedKeychain = false; ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen"); } else { testWithFreshlyCreatedKeychain = true; ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); CFReleaseNull(keychain); } } while(!testWithFreshlyCreatedKeychain); }
/* relies on SSLSetProtocolVersionEnabled */ OSStatus sslAppClient( SslAppTestParams *params) { PeerSpec peerId; otSocket sock = 0; OSStatus ortn; SSLContextRef ctx = NULL; SecKeychainRef clientKc = nil; CFArrayRef clientCerts = nil; sslThrDebug("Client", "starting"); params->negVersion = kSSLProtocolUnknown; params->negCipher = SSL_NULL_WITH_NULL_NULL; params->ortn = noHardwareErr; /* first make sure requested server is there */ ortn = MakeServerConnection(params->hostName, params->port, params->nonBlocking, &sock, &peerId); if(ortn) { printf("MakeServerConnection returned %d; aborting\n", (int)ortn); return ortn; } /* * Set up a SecureTransport session. */ ortn = SSLNewContext(false, &ctx); if(ortn) { printSslErrStr("SSLNewContext", ortn); goto cleanup; } ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); if(ortn) { printSslErrStr("SSLSetIOFuncs", ortn); goto cleanup; } ortn = SSLSetConnection(ctx, (SSLConnectionRef)sock); if(ortn) { printSslErrStr("SSLSetConnection", ortn); goto cleanup; } if(!params->skipHostNameCheck) { ortn = SSLSetPeerDomainName(ctx, params->hostName, strlen(params->hostName)); if(ortn) { printSslErrStr("SSLSetPeerDomainName", ortn); goto cleanup; } } /* remainder of setup is optional */ if(params->anchorFile) { ortn = sslAddTrustedRoot(ctx, params->anchorFile, params->replaceAnchors); if(ortn) { goto cleanup; } } ortn = sslSetProtocols(ctx, params->acceptedProts, params->tryVersion); if(ortn) { goto cleanup; } if(params->resumeEnable) { ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); if(ortn) { printSslErrStr("SSLSetPeerID", ortn); goto cleanup; } } if(params->disableCertVerify) { ortn = SSLSetEnableCertVerify(ctx, false); if(ortn) { printSslErrStr("SSLSetEnableCertVerify", ortn); goto cleanup; } } if(params->ciphers != NULL) { ortn = sslSetEnabledCiphers(ctx, params->ciphers); if(ortn) { goto cleanup; } } if(params->myCertKcName) { clientCerts = getSslCerts(params->myCertKcName, false, false, NULL, &clientKc); if(clientCerts == nil) { exit(1); } if(params->password) { ortn = SecKeychainUnlock(clientKc, strlen(params->password), (void *)params->password, true); if(ortn) { printf("SecKeychainUnlock returned %d\n", (int)ortn); /* oh well */ } } if(params->idIsTrustedRoot) { /* assume this is a root we want to implicitly trust */ ortn = addIdentityAsTrustedRoot(ctx, clientCerts); if(ortn) { goto cleanup; } } ortn = SSLSetCertificate(ctx, clientCerts); if(ortn) { printSslErrStr("SSLSetCertificate", ortn); goto cleanup; } } do { ortn = SSLHandshake(ctx); if((ortn == errSSLWouldBlock) && !params->silent) { /* keep UI responsive */ sslOutputDot(); } } while (ortn == errSSLWouldBlock); SSLGetClientCertificateState(ctx, ¶ms->certState); SSLGetNegotiatedCipher(ctx, ¶ms->negCipher); SSLGetNegotiatedProtocolVersion(ctx, ¶ms->negVersion); if(ortn != errSecSuccess) { goto cleanup; } /* send a GET msg */ size_t actLen; ortn = SSLWrite(ctx, CLIENT_GETMSG, strlen(CLIENT_GETMSG), &actLen); if(ortn) { printSslErrStr("SSLWrite", ortn); goto cleanup; } #if KEEP_CONNECTED /* * Consume any server data and wait for server to disconnect */ char readBuf[READBUF_LEN]; do { ortn = SSLRead(ctx, readBuf, READBUF_LEN, &actLen); } while (ortn == errSSLWouldBlock); /* convert normal "shutdown" into zero err rtn */ if(ortn == errSSLClosedGraceful) { ortn = errSecSuccess; } #endif /* KEEP_CONNECTED */ cleanup: if(ctx) { OSStatus cerr = SSLClose(ctx); if(ortn == errSecSuccess) { ortn = cerr; } } if(sock) { endpointShutdown(sock); } if(ctx) { SSLDisposeContext(ctx); } params->ortn = ortn; sslThrDebug("Client", "done"); return ortn; }