OSStatus sslSetProtocols( SSLContextRef ctx, const char *acceptedProts, SSLProtocol tryVersion) // only used if acceptedProts NULL { OSStatus ortn; if(acceptedProts) { #if JAGUAR_BUILD printf("***SSLSetProtocolVersionEnabled not supported in this config.\n"); exit(1); #endif ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); if(ortn) { printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn); return ortn; } for(const char *cp = acceptedProts; *cp; cp++) { SSLProtocol prot; switch(*cp) { case '2': prot = kSSLProtocol2; break; case '3': prot = kSSLProtocol3; break; case 't': prot = kTLSProtocol1; break; default: printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts); exit(1); } ortn = SSLSetProtocolVersionEnabled(ctx, prot, true); if(ortn) { printSslErrStr("SSLSetProtocolVersionEnabled", ortn); return ortn; } } } else { ortn = SSLSetProtocolVersion(ctx, tryVersion); if(ortn) { printSslErrStr("SSLSetProtocolVersion", ortn); return ortn; } } return errSecSuccess; }
BOOL schan_imp_create_session(schan_imp_session *session, BOOL is_server, schan_imp_certificate_credentials cred) { struct mac_session *s; OSStatus status; TRACE("(%p, %d)\n", session, is_server); s = HeapAlloc(GetProcessHeap(), 0, sizeof(*s)); if (!s) return FALSE; status = SSLNewContext(is_server, &s->context); if (status != noErr) { ERR("Failed to create session context: %ld\n", (long)status); goto fail; } status = SSLSetConnection(s->context, s); if (status != noErr) { ERR("Failed to set session connection: %ld\n", (long)status); goto fail; } status = SSLSetEnableCertVerify(s->context, FALSE); if (status != noErr) { ERR("Failed to disable certificate verification: %ld\n", (long)status); goto fail; } status = SSLSetProtocolVersionEnabled(s->context, kSSLProtocol2, FALSE); if (status != noErr) { ERR("Failed to disable SSL version 2: %ld\n", (long)status); goto fail; } status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter); if (status != noErr) { ERR("Failed to set session I/O funcs: %ld\n", (long)status); goto fail; } TRACE(" -> %p/%p\n", s, s->context); *session = (schan_imp_session)s; return TRUE; fail: HeapFree(GetProcessHeap(), 0, s); return FALSE; }
static CURLcode darwinssl_connect_step1(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; bool sni = true; #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif /*SSLConnectionRef ssl_connection;*/ OSStatus err = noErr; #if defined(__MAC_10_8) || defined(__IPHONE_5_0) if(SSLCreateContext != NULL) { /* use the newer API if avaialble */ if(connssl->ssl_ctx) CFRelease(connssl->ssl_ctx); connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); if(!connssl->ssl_ctx) { failf(data, "SSL: couldn't create a context!"); return CURLE_OUT_OF_MEMORY; } } else { #elif TARGET_OS_EMBEDDED == 0 if(connssl->ssl_ctx) (void)SSLDisposeContext(connssl->ssl_ctx); err = SSLNewContext(false, &(connssl->ssl_ctx)); if(err != noErr) { failf(data, "SSL: couldn't create a context: OSStatus %d", err); return CURLE_OUT_OF_MEMORY; } #endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */ #if defined(__MAC_10_8) || defined(__IPHONE_5_0) } #endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */ /* check to see if we've been told to use an explicit SSL/TLS version */ #if defined(__MAC_10_8) || defined(__IPHONE_5_0) if(SSLSetProtocolVersionMax != NULL) { switch(data->set.ssl.version) { case CURL_SSLVERSION_DEFAULT: default: (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); break; case CURL_SSLVERSION_TLSv1: (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); break; case CURL_SSLVERSION_SSLv3: (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); break; case CURL_SSLVERSION_SSLv2: (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2); (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2); } } else { #if TARGET_OS_EMBEDDED == 0 (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); switch (data->set.ssl.version) { case CURL_SSLVERSION_DEFAULT: default: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocol3, true); (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol1, true); (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol11, true); (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol12, true); break; case CURL_SSLVERSION_TLSv1: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol1, true); (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol11, true); (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol12, true); break; case CURL_SSLVERSION_SSLv3: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocol3, true); break; case CURL_SSLVERSION_SSLv2: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocol2, true); break; } #endif /* TARGET_OS_EMBEDDED == 0 */ } #else (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); switch(data->set.ssl.version) { default: case CURL_SSLVERSION_DEFAULT: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocol3, true); (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol1, true); break; case CURL_SSLVERSION_TLSv1: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol1, true); break; case CURL_SSLVERSION_SSLv2: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocol2, true); break; case CURL_SSLVERSION_SSLv3: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocol3, true); break; } #endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */ /* No need to load certificates here. SecureTransport uses the Keychain * (which is also part of the Security framework) to evaluate trust. */ /* SSL always tries to verify the peer, this only says whether it should * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ #if defined(__MAC_10_6) || defined(__IPHONE_5_0) if(SSLSetSessionOption != NULL) { err = SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionBreakOnServerAuth, data->set.ssl.verifypeer?false:true); if(err != noErr) { failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; } } else { #elif TARGET_OS_EMBEDDED == 0 err = SSLSetEnableCertVerify(connssl->ssl_ctx, data->set.ssl.verifypeer?true:false); if(err != noErr) { failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; } #endif /* defined(__MAC_10_6) || defined(__IPHONE_5_0) */ #if defined(__MAC_10_6) || defined(__IPHONE_5_0) } #endif /* defined(__MAC_10_6) || defined(__IPHONE_5_0) */ /* If this is a domain name and not an IP address, then configure SNI: */ if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && #ifdef ENABLE_IPV6 (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && #endif sni) { err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name, strlen(conn->host.name)); if(err != noErr) { infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d", err); } } err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite); if(err != noErr) { failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; } /* pass the raw socket into the SSL layers */ /* We need to store the FD in a constant memory address, because * SSLSetConnection() will not copy that address. I've found that * conn->sock[sockindex] may change on its own. */ connssl->ssl_sockfd = sockfd; /*ssl_connection = &(connssl->ssl_sockfd); err = SSLSetConnection(connssl->ssl_ctx, ssl_connection);*/ err = SSLSetConnection(connssl->ssl_ctx, connssl); if(err != noErr) { failf(data, "SSL: SSLSetConnection() failed: %d", err); return CURLE_SSL_CONNECT_ERROR; } connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred) { struct mac_session *s; unsigned i; int status; TRACE("(%p)\n", session); s = heap_alloc(sizeof(*s)); if (!s) return FALSE; InitializeCriticalSection(&s->cs); s->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": mac_session.cs"); status = SSLNewContext(cred->credential_use == SECPKG_CRED_INBOUND, &s->context); if (status != noErr) { ERR("Failed to create session context: %d\n", status); goto fail; } /* We don't handle all the signature algorithms that OS X supports so it is important * to limit the enabled ciphers before the handshake happens. That will ensure we * only get certificates we can handle (assuming the server has alternate chains to offer). */ status = SSLSetEnabledCiphers(s->context, enabled_cipher_suites, sizeof(enabled_cipher_suites) / sizeof(SSLCipherSuite)); if (status != noErr) { ERR("Failed to set enabled ciphers: %d\n", status); goto fail; } status = SSLSetConnection(s->context, s); if (status != noErr) { ERR("Failed to set session connection: %d\n", status); goto fail; } status = SSLSetEnableCertVerify(s->context, FALSE); if (status != noErr) { ERR("Failed to disable certificate verification: %d\n", status); goto fail; } for(i=0; i < sizeof(protocol_priority_flags)/sizeof(*protocol_priority_flags); i++) { if(!(protocol_priority_flags[i].enable_flag & supported_protocols)) continue; status = SSLSetProtocolVersionEnabled(s->context, protocol_priority_flags[i].mac_version, (cred->enabled_protocols & protocol_priority_flags[i].enable_flag) != 0); if (status != noErr) { ERR("Failed to set SSL version %d: %d\n", protocol_priority_flags[i].mac_version, status); goto fail; } } status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter); if (status != noErr) { ERR("Failed to set session I/O funcs: %d\n", status); goto fail; } TRACE(" -> %p/%p\n", s, s->context); *session = (schan_imp_session)s; return TRUE; fail: heap_free(s); return FALSE; }
static void ssl_cdsa_create_context(gpointer data) { PurpleSslConnection *gsc = (PurpleSslConnection *)data; PurpleAccount *account = gsc->account; PurpleSslCDSAData *cdsa_data; OSStatus err; bool requireFS = purple_account_get_bool(account, "require_forward_secrecy", FALSE); /* * allocate some memory to store variables for the cdsa connection. * the memory comes zero'd from g_new0 so we don't need to null the * pointers held in this struct. */ cdsa_data = g_new0(PurpleSslCDSAData, 1); gsc->private_data = cdsa_data; connections = g_list_append(connections, gsc); /* * allocate a new SSLContextRef object */ err = SSLNewContext(false, &cdsa_data->ssl_ctx); if (err != noErr) { purple_debug_error("cdsa", "SSLNewContext failed\n"); if (gsc->error_cb != NULL) gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); purple_ssl_close(gsc); return; } /* * Set up our callbacks for reading/writing the file descriptor */ err = SSLSetIOFuncs(cdsa_data->ssl_ctx, SocketRead, SocketWrite); if (err != noErr) { purple_debug_error("cdsa", "SSLSetIOFuncs failed\n"); if (gsc->error_cb != NULL) gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); purple_ssl_close(gsc); return; } /* * Pass the connection information to the connection to be used by our callbacks */ err = SSLSetConnection(cdsa_data->ssl_ctx, (SSLConnectionRef)(intptr_t)gsc->fd); if (err != noErr) { purple_debug_error("cdsa", "SSLSetConnection failed: %d\n", err); if (gsc->error_cb != NULL) gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); purple_ssl_close(gsc); return; } size_t numCiphers = 0; err = SSLGetNumberEnabledCiphers(cdsa_data->ssl_ctx, &numCiphers); if (err != noErr) { purple_debug_error("cdsa", "SSLGetNumberEnabledCiphers failed: %d\n", err); if (gsc->error_cb != NULL) gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); purple_ssl_close(gsc); return; } SSLCipherSuite ciphers[numCiphers]; err = SSLGetEnabledCiphers(cdsa_data->ssl_ctx, ciphers, &numCiphers); if (err != noErr) { purple_debug_error("cdsa", "SSLGetSupportedCiphers failed: %d\n", err); if (gsc->error_cb != NULL) gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); purple_ssl_close(gsc); return; } SSLCipherSuite enabledCiphers[numCiphers]; size_t numEnabledCiphers = 0; int i; for (i = 0; i < numCiphers; i++) { if (ssl_cdsa_use_cipher(ciphers[i], requireFS)) { enabledCiphers[numEnabledCiphers] = ciphers[i]; numEnabledCiphers++; } } err = SSLSetEnabledCiphers(cdsa_data->ssl_ctx, enabledCiphers, numEnabledCiphers); if (err != noErr) { purple_debug_error("cdsa", "SSLSetEnabledCiphers failed: %d\n", err); if (gsc->error_cb != NULL) gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); purple_ssl_close(gsc); return; } if (purple_account_get_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, false)) { purple_debug_info("cdsa", "Explicitly disabling TLS 1.1 and above to try and work around buggy TLS stacks\n"); OSStatus protoErr; protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kSSLProtocolAll, false); if (protoErr != noErr) { purple_debug_error("cdsa", "SSLSetProtocolVersionEnabled failed to disable protocols\n"); if (gsc->error_cb != NULL) gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); purple_ssl_close(gsc); return; } protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kSSLProtocol3, true); protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kTLSProtocol1, true); } if(gsc->host) { /* * Set the peer's domain name so CDSA can check the certificate's CN */ err = SSLSetPeerDomainName(cdsa_data->ssl_ctx, gsc->host, strlen(gsc->host)); if (err != noErr) { purple_debug_error("cdsa", "SSLSetPeerDomainName failed\n"); if (gsc->error_cb != NULL) gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); purple_ssl_close(gsc); return; } } /* * Disable verifying the certificate chain. * We have to do that manually later on! This is the only way to be able to continue with a connection, even though the user * had to manually accept the certificate. */ err = SSLSetEnableCertVerify(cdsa_data->ssl_ctx, false); if (err != noErr) { purple_debug_error("cdsa", "SSLSetEnableCertVerify failed\n"); /* error is not fatal */ } cdsa_data->handshake_handler = purple_input_add(gsc->fd, PURPLE_INPUT_READ, ssl_cdsa_handshake_cb, gsc); }
static OSStatus sslServe( otSocket listenSock, unsigned short portNum, SSLProtocol tryVersion, // only used if acceptedProts NULL const char *acceptedProts, CFArrayRef serverCerts, // required char *password, // optional CFArrayRef encryptServerCerts, // optional bool allowExpired, bool allowAnyRoot, bool allowExpiredRoot, bool disableCertVerify, char *anchorFile, bool replaceAnchors, char cipherRestrict, // '2', 'd'. etc...'\0' for no // restriction SSLAuthenticate authenticate, unsigned char *dhParams, // optional D-H parameters unsigned dhParamsLen, CFArrayRef acceptableDNList, // optional bool resumableEnable, uint32_t sessionCacheTimeout,// optional bool disableAnonCiphers, bool silent, // no stdout bool pause, SSLProtocol *negVersion, // RETURNED SSLCipherSuite *negCipher, // RETURNED SSLClientCertificateState *certState, // RETURNED Boolean *sessionWasResumed, // RETURNED unsigned char *sessionID, // mallocd by caller, RETURNED size_t *sessionIDLength, // RETURNED CFArrayRef *peerCerts, // mallocd & RETURNED char **argv) { otSocket acceptSock; PeerSpec peerId; OSStatus ortn; SSLContextRef ctx = NULL; size_t length; uint8_t rcvBuf[RCV_BUF_SIZE]; const char *outMsg = SERVER_MESSAGE; *negVersion = kSSLProtocolUnknown; *negCipher = SSL_NULL_WITH_NULL_NULL; *peerCerts = NULL; #if IGNORE_SIGPIPE signal(SIGPIPE, sigpipe); #endif /* first wait for a connection */ if(!silent) { printf("Waiting for client connection on port %u...", portNum); fflush(stdout); } ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); if(ortn) { printf("AcceptClientConnection returned %d; aborting\n", (int)ortn); return ortn; } /* * Set up a SecureTransport session. * First the standard calls. */ 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)(intptr_t)acceptSock); if(ortn) { printSslErrStr("SSLSetConnection", ortn); goto cleanup; } /* have to do these options befor setting server certs */ if(allowExpired) { ortn = SSLSetAllowsExpiredCerts(ctx, true); if(ortn) { printSslErrStr("SSLSetAllowExpiredCerts", ortn); goto cleanup; } } if(allowAnyRoot) { ortn = SSLSetAllowsAnyRoot(ctx, true); if(ortn) { printSslErrStr("SSLSetAllowAnyRoot", ortn); goto cleanup; } } if(anchorFile) { ortn = sslAddTrustedRoot(ctx, anchorFile, replaceAnchors); if(ortn) { printf("***Error obtaining anchor file %s\n", anchorFile); goto cleanup; } } if(serverCerts != NULL) { if(anchorFile == NULL) { /* no specific anchors, so assume we want to trust this one */ ortn = addIdentityAsTrustedRoot(ctx, serverCerts); if(ortn) { goto cleanup; } } ortn = SSLSetCertificate(ctx, serverCerts); if(ortn) { printSslErrStr("SSLSetCertificate", ortn); goto cleanup; } } if(encryptServerCerts) { ortn = SSLSetEncryptionCertificate(ctx, encryptServerCerts); if(ortn) { printSslErrStr("SSLSetEncryptionCertificate", ortn); goto cleanup; } } if(allowExpiredRoot) { ortn = SSLSetAllowsExpiredRoots(ctx, true); if(ortn) { printSslErrStr("SSLSetAllowsExpiredRoots", ortn); goto cleanup; } } if(disableCertVerify) { ortn = SSLSetEnableCertVerify(ctx, false); if(ortn) { printSslErrStr("SSLSetEnableCertVerify", ortn); goto cleanup; } } /* * SecureTransport options. */ if(acceptedProts) { ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); if(ortn) { printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn); goto cleanup; } for(const char *cp = acceptedProts; *cp; cp++) { SSLProtocol prot = kSSLProtocolUnknown; switch(*cp) { case '2': prot = kSSLProtocol2; break; case '3': prot = kSSLProtocol3; break; case 't': prot = kTLSProtocol1; break; default: usage(argv); } ortn = SSLSetProtocolVersionEnabled(ctx, prot, true); if(ortn) { printSslErrStr("SSLSetProtocolVersionEnabled", ortn); goto cleanup; } } } else { ortn = SSLSetProtocolVersion(ctx, tryVersion); if(ortn) { printSslErrStr("SSLSetProtocolVersion", ortn); goto cleanup; } } if(resumableEnable) { ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); if(ortn) { printSslErrStr("SSLSetPeerID", ortn); goto cleanup; } } if(cipherRestrict != '\0') { ortn = sslSetCipherRestrictions(ctx, cipherRestrict); if(ortn) { goto cleanup; } } if(authenticate != kNeverAuthenticate) { ortn = SSLSetClientSideAuthenticate(ctx, authenticate); if(ortn) { printSslErrStr("SSLSetClientSideAuthenticate", ortn); goto cleanup; } } if(dhParams) { ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen); if(ortn) { printSslErrStr("SSLSetDiffieHellmanParams", ortn); goto cleanup; } } if(sessionCacheTimeout) { ortn = SSLSetSessionCacheTimeout(ctx, sessionCacheTimeout); if(ortn) { printSslErrStr("SSLSetSessionCacheTimeout", ortn); goto cleanup; } } if(disableAnonCiphers) { ortn = SSLSetAllowAnonymousCiphers(ctx, false); if(ortn) { printSslErrStr("SSLSetAllowAnonymousCiphers", ortn); goto cleanup; } /* quickie test of the getter */ Boolean e; ortn = SSLGetAllowAnonymousCiphers(ctx, &e); if(ortn) { printSslErrStr("SSLGetAllowAnonymousCiphers", ortn); goto cleanup; } if(e) { printf("***SSLGetAllowAnonymousCiphers() returned true; expected false\n"); ortn = errSecIO; goto cleanup; } } /* XXX/cs if(acceptableDNList) { ortn = SSLSetCertificateAuthorities(ctx, acceptableDNList, TRUE); if(ortn) { printSslErrStr("SSLSetCertificateAuthorities", ortn); goto cleanup; } } */ /* end options */ if(pause) { doPause("SSLContext initialized"); } /* Perform SSL/TLS handshake */ do { ortn = SSLHandshake(ctx); if((ortn == errSSLWouldBlock) && !silent) { /* keep UI responsive */ sslOutputDot(); } } while (ortn == errSSLWouldBlock); /* this works even if handshake failed due to cert chain invalid */ copyPeerCerts(ctx, peerCerts); SSLGetClientCertificateState(ctx, certState); SSLGetNegotiatedCipher(ctx, negCipher); SSLGetNegotiatedProtocolVersion(ctx, negVersion); *sessionIDLength = MAX_SESSION_ID_LENGTH; SSLGetResumableSessionInfo(ctx, sessionWasResumed, sessionID, sessionIDLength); if(!silent) { printf("\n"); } if(ortn) { goto cleanup; } if(pause) { doPause("SSLContext handshake complete"); } /* wait for one complete line or user says they've had enough */ while(ortn == errSecSuccess) { length = sizeof(rcvBuf); ortn = SSLRead(ctx, rcvBuf, length, &length); if(length == 0) { /* keep UI responsive */ sslOutputDot(); } else { /* print what we have */ printf("client request: "); dumpAscii(rcvBuf, length); } if(pause) { /* allow user to bail */ char resp; fpurge(stdin); printf("\nMore client request (y/anything): "); resp = getchar(); if(resp != 'y') { break; } } /* poor person's line completion scan */ for(unsigned i=0; i<length; i++) { if((rcvBuf[i] == '\n') || (rcvBuf[i] == '\r')) { /* a labelled break would be nice here.... */ goto serverResp; } } if (ortn == errSSLWouldBlock) { ortn = errSecSuccess; } } serverResp: if(pause) { doPause("Client GET msg received"); } /* send out canned response */ length = strlen(outMsg); ortn = SSLWrite(ctx, outMsg, length, &length); if(ortn) { printSslErrStr("SSLWrite", ortn); } if(pause) { doPause("Server response sent"); } cleanup: /* * always do close, even on error - to flush outgoing write queue */ OSStatus cerr = SSLClose(ctx); if(ortn == errSecSuccess) { ortn = cerr; } if(acceptSock) { endpointShutdown(acceptSock); } if(ctx) { SSLDisposeContext(ctx); } /* FIXME - dispose of serverCerts */ return ortn; }
BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred) { struct mac_session *s; unsigned i; int status; TRACE("(%p)\n", session); s = HeapAlloc(GetProcessHeap(), 0, sizeof(*s)); if (!s) return FALSE; status = SSLNewContext(cred->credential_use == SECPKG_CRED_INBOUND, &s->context); if (status != noErr) { ERR("Failed to create session context: %d\n", status); goto fail; } status = SSLSetConnection(s->context, s); if (status != noErr) { ERR("Failed to set session connection: %d\n", status); goto fail; } status = SSLSetEnableCertVerify(s->context, FALSE); if (status != noErr) { ERR("Failed to disable certificate verification: %d\n", status); goto fail; } for(i=0; i < sizeof(protocol_priority_flags)/sizeof(*protocol_priority_flags); i++) { if(!(protocol_priority_flags[i].enable_flag & supported_protocols)) continue; status = SSLSetProtocolVersionEnabled(s->context, protocol_priority_flags[i].mac_version, (cred->enabled_protocols & protocol_priority_flags[i].enable_flag) != 0); if (status != noErr) { ERR("Failed to set SSL version %d: %d\n", protocol_priority_flags[i].mac_version, status); goto fail; } } status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter); if (status != noErr) { ERR("Failed to set session I/O funcs: %d\n", status); goto fail; } TRACE(" -> %p/%p\n", s, s->context); *session = (schan_imp_session)s; return TRUE; fail: HeapFree(GetProcessHeap(), 0, s); return FALSE; }
Connection::Connection(Context& ctx, std::ios& ios, OpenMode omode) : _ctx(&ctx) , _context(0) , _ios(&ios) , _iocount(0) , _connected(false) , _wantRead(false) , _isReading(false) , _isWriting(false) , _receivedShutdown(false) , _sentShutdown(false) { Boolean isServer = (omode == Accept); SSLNewContext(isServer, &_context); SSLSetConnection(_context, (SSLConnectionRef) this); SSLSetIOFuncs(_context, &Connection::sslReadCallback, &Connection::sslWriteCallback); SSLSetProtocolVersionEnabled(_context, kSSLProtocolAll, false); switch(_ctx->protocol()) { case SSLv2: SSLSetProtocolVersionEnabled(_context, kSSLProtocol2, true); break; case SSLv3or2: SSLSetProtocolVersionEnabled(_context, kSSLProtocol2, true); SSLSetProtocolVersionEnabled(_context, kSSLProtocol3, true); break; default: case SSLv3: SSLSetProtocolVersionEnabled(_context, kSSLProtocol3, true); break; case TLSv1: SSLSetProtocolVersionEnabled(_context, kTLSProtocol1, true); break; } if(isServer) { #ifdef PT_IOS SSLSetEnableCertVerify(_context, false); SSLSetSessionOption(_context, kSSLSessionOptionBreakOnClientAuth, true); #else if(_ctx->verifyMode() == NoVerify) { SSLSetClientSideAuthenticate(_context, kNeverAuthenticate); } else if(_ctx->verifyMode() == TryVerify) { SSLSetClientSideAuthenticate(_context, kTryAuthenticate); } else if(_ctx->verifyMode() == AlwaysVerify) { SSLSetClientSideAuthenticate(_context, kAlwaysAuthenticate); } CFArrayRef caArr = _ctx->impl()->caCertificates(); SSLSetCertificateAuthorities(_context, caArr, true); SSLSetTrustedRoots(_context, caArr, true); #endif } else { SSLSetEnableCertVerify(_context, false); SSLSetSessionOption(_context, kSSLSessionOptionBreakOnServerAuth, true); } // certificates to present to peer CFArrayRef certs = _ctx->impl()->certificates(); if(certs) { log_debug("using " << CFArrayGetCount(certs) << " certificates"); SSLSetCertificate(_context, certs); } }