void TCPStream_CFNetwork::secure() { if (state != Stream::State::Open) { return; } state = Stream::State::OpenAndSecuring; OSStatus status = noErr; secureLayerContext = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType); status = SSLSetConnection(secureLayerContext, reinterpret_cast<SSLConnectionRef>(this)); if (status != noErr) { handleSecuringFailedEvent(); return; } status = SSLSetIOFuncs(secureLayerContext, TCPStream_CFNetwork::secureTransportReadCallback, TCPStream_CFNetwork::secureTransportWriteCallback); if (status != noErr) { handleSecuringFailedEvent(); return; } status = SSLSetPeerDomainName(secureLayerContext, domainName.c_str(), domainName.size()); if (status != noErr) { handleSecuringFailedEvent(); return; } do { status = SSLHandshake(secureLayerContext); } while (status == errSSLWouldBlock); switch (status) { default: //TODO: Log this! handleSecuringFailedEvent(); return; case errSSLFatalAlert: handleSecuringFailedEvent(); return; case errSSLUnknownRootCert: case errSSLNoRootCert: case errSSLCertExpired: case errSSLXCertChainInvalid: //TODO: The UI (if any) should probably ask what to do instead of simply failing. handleSecuringFailedEvent(); return; case errSSLClientCertRequested: //TODO: The App should supply this. Add an event handler. handleSecuringFailedEvent(); return; case noErr: state = Stream::State::OpenAndSecured; handleSecuredEvent(); return; } }
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; }
int git_stransport_stream_new(git_stream **out, const char *host, const char *port) { stransport_stream *st; int error; OSStatus ret; assert(out && host); st = git__calloc(1, sizeof(stransport_stream)); GITERR_CHECK_ALLOC(st); #ifdef GIT_CURL error = git_curl_stream_new(&st->io, host, port); #else error = git_socket_stream_new(&st->io, host, port); #endif if (error < 0){ git__free(st); return error; } st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); if (!st->ctx) { giterr_set(GITERR_NET, "failed to create SSL context"); git__free(st); return -1; } if ((ret = SSLSetIOFuncs(st->ctx, read_cb, write_cb)) != noErr || (ret = SSLSetConnection(st->ctx, st->io)) != noErr || (ret = SSLSetSessionOption(st->ctx, kSSLSessionOptionBreakOnServerAuth, true)) != noErr || (ret = SSLSetProtocolVersionMin(st->ctx, kTLSProtocol1)) != noErr || (ret = SSLSetProtocolVersionMax(st->ctx, kTLSProtocol12)) != noErr || (ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) { CFRelease(st->ctx); git__free(st); return stransport_error(ret); } st->parent.version = GIT_STREAM_VERSION; st->parent.encrypted = 1; st->parent.proxy_support = git_stream_supports_proxy(st->io); st->parent.connect = stransport_connect; st->parent.certificate = stransport_certificate; st->parent.set_proxy = stransport_set_proxy; st->parent.read = stransport_read; st->parent.write = stransport_write; st->parent.close = stransport_close; st->parent.free = stransport_free; *out = (git_stream *) st; return 0; }
static SSLContextRef make_ssl_ref(bool server, int sock, CFArrayRef certs) { SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType); require(ctx, out); require_noerr(SSLSetIOFuncs(ctx, (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out); require_noerr(SSLSetCertificate(ctx, certs), out); return ctx; out: if (ctx) CFRelease(ctx); return NULL; }
static SSLContextRef make_ssl_ref(int sock, SSLProtocol maxprot, Boolean false_start) { SSLContextRef ctx = NULL; require_noerr(SSLNewContext(false, &ctx), out); require_noerr(SSLSetIOFuncs(ctx, (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out); require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnServerAuth, true), out); require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionFalseStart, false_start), out); require_noerr(SSLSetProtocolVersionMax(ctx, maxprot), out); return ctx; out: if (ctx) SSLDisposeContext(ctx); return NULL; }
static int test_GetEnabledCiphers(SSLContextRef ssl) { size_t max_ciphers = 0; int fail=1; SSLCipherSuite *ciphers = NULL; OSStatus err; err=SSLSetIOFuncs(ssl, &SocketRead, &SocketWrite); err=SSLSetConnection(ssl, NULL); err=SSLHandshake(ssl); require_noerr(SSLGetNumberEnabledCiphers(ssl, &max_ciphers), out); size_t size = max_ciphers * sizeof (SSLCipherSuite); ciphers = (SSLCipherSuite *) malloc(size); require_string(ciphers, out, "out of memory"); memset(ciphers, 0xff, size); size_t num_ciphers = max_ciphers; require_noerr(SSLGetEnabledCiphers(ssl, ciphers, &num_ciphers), out); for (size_t i = 0; i < num_ciphers; i++) { char csname[256]; snprintf(csname, 256, "(%04x) %s", ciphers[i], ciphersuite_name(ciphers[i])); /* Uncomment the next line if you want to list the default enabled ciphers */ //printf("%s\n", csname); require_string(allowed_default_ciphers(ciphers[i]), out, csname); } /* Success! */ fail=0; out: if(ciphers) free(ciphers); return fail; }
/** * Initializes a client-side TLS session. */ static int st_ClientSessionOpen (vlc_tls_creds_t *crd, vlc_tls_t *session, int fd, const char *hostname) { msg_Dbg(session, "open TLS session for %s", hostname); vlc_tls_sys_t *sys = malloc (sizeof (*session->sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; sys->p_cred = crd->sys; sys->i_fd = fd; sys->b_handshaked = false; sys->b_blocking_send = false; sys->i_send_buffered_bytes = 0; session->sys = sys; session->sock.p_sys = session; session->sock.pf_send = st_Send; session->sock.pf_recv = st_Recv; session->handshake = st_Handshake; SSLContextRef p_context = NULL; #if TARGET_OS_IPHONE p_context = SSLCreateContext (NULL, kSSLClientSide, kSSLStreamType); if(p_context == NULL) { msg_Err(session, "cannot create ssl context"); goto error; } #else if (SSLNewContext (false, &p_context) != noErr) { msg_Err(session, "error calling SSLNewContext"); goto error; } #endif sys->p_context = p_context; OSStatus ret = SSLSetIOFuncs (p_context, st_SocketReadFunc, st_SocketWriteFunc); if(ret != noErr) { msg_Err(session, "cannot set io functions"); goto error; } ret = SSLSetConnection (p_context, session); if(ret != noErr) { msg_Err(session, "cannot set connection"); goto error; } ret = SSLSetPeerDomainName (p_context, hostname, strlen(hostname)); if(ret != noErr) { msg_Err(session, "cannot set peer domain name"); goto error; } /* disable automatic validation. We do so manually to also handle invalid certificates */ /* this has effect only on iOS 5 and OSX 10.8 or later ... */ SSLSetSessionOption (sys->p_context, kSSLSessionOptionBreakOnServerAuth, true); #if !TARGET_OS_IPHONE /* ... thus calling this for earlier osx versions, which is not available on iOS in turn */ SSLSetEnableCertVerify (sys->p_context, false); #endif return VLC_SUCCESS; error: st_ClientSessionClose(crd, session); return VLC_EGENERIC; }
static OSStatus sslServe( otSocket listenSock, SSLProtocol tryVersion, const char *hostName, // e.g., "www.amazon.com" CFArrayRef serverCerts, // required CFArrayRef encryptServerCerts, // optional CSSM_BOOL allowExpired, CSSM_BOOL allowAnyRoot, char cipherRestrict, // '2', 'd'. etc...'\0' for no // restriction SSLAuthenticate authenticate, CSSM_BOOL resumableEnable, CSSM_BOOL silent, // no stdout CSSM_BOOL pause, SSLProtocol *negVersion, // RETURNED SSLCipherSuite *negCipher, // RETURNED CFArrayRef *peerCerts) // mallocd & RETURNED { otSocket acceptSock; PeerSpec peerId; OSStatus ortn; SSLContextRef ctx = NULL; UInt32 length; uint8 rcvBuf[RCV_BUF_SIZE]; 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..."); fflush(stdout); } ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); if(ortn) { printf("AcceptClientConnection returned %d; aborting\n", 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 = SSLSetProtocolVersion(ctx, tryVersion); if(ortn) { printSslErrStr("SSLSetProtocolVersion", ortn); goto cleanup; } ortn = SSLSetConnection(ctx, acceptSock); if(ortn) { printSslErrStr("SSLSetConnection", ortn); goto cleanup; } ortn = SSLSetPeerDomainName(ctx, hostName, strlen(hostName) + 1); if(ortn) { printSslErrStr("SSLSetPeerDomainName", 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; } } ortn = SSLSetCertificate(ctx, serverCerts); if(ortn) { printSslErrStr("SSLSetCertificate", ortn); goto cleanup; } if(encryptServerCerts) { ortn = SSLSetEncryptionCertificate(ctx, encryptServerCerts); if(ortn) { printSslErrStr("SSLSetEncryptionCertificate", ortn); goto cleanup; } } /* * SecureTransport options. */ if(resumableEnable) { ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); if(ortn) { printSslErrStr("SSLSetPeerID", ortn); goto cleanup; } } if(cipherRestrict != '\0') { ortn = setCipherRestrictions(ctx, cipherRestrict); if(ortn) { goto cleanup; } } #if AUTHENTICATE_ENABLE if(authenticate != kNeverAuthenticate) { ortn = SSLSetClientSideAuthenticate(ctx, authenticate); if(ortn) { printSslErrStr("SSLSetClientSideAuthenticate", ortn); goto cleanup; } } #endif if(pause) { doPause("SSLContext initialized"); } /* Perform SSL/TLS handshake */ do { ortn = SSLHandshake(ctx); if((ortn == errSSLWouldBlock) && !silent) { /* keep UI responsive */ outputDot(); } } while (ortn == errSSLWouldBlock); /* this works even if handshake failed due to cert chain invalid */ copyPeerCerts(ctx, peerCerts); SSLGetNegotiatedCipher(ctx, negCipher); SSLGetNegotiatedProtocolVersion(ctx, negVersion); 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 == noErr) { length = sizeof(rcvBuf); ortn = SSLRead(ctx, rcvBuf, length, &length); if(length == 0) { /* keep UI responsive */ outputDot(); } 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 = noErr; } } 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"); } if (ortn == noErr) { ortn = SSLClose(ctx); } cleanup: if(acceptSock) { endpointShutdown(acceptSock); } if(ctx) { SSLDisposeContext(ctx); } /* FIXME - dispose of serverCerts */ return ortn; }
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; }
/* * 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; }
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; }
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); } }
mongoc_stream_t * mongoc_stream_tls_secure_transport_new (mongoc_stream_t *base_stream, const char *host, mongoc_ssl_opt_t *opt, int client) { mongoc_stream_tls_t *tls; mongoc_stream_tls_secure_transport_t *secure_transport; ENTRY; BSON_ASSERT (base_stream); BSON_ASSERT (opt); if (opt->ca_dir) { MONGOC_ERROR ("Setting mongoc_ssl_opt_t.ca_dir has no effect when built " "against Secure Transport"); RETURN (NULL); } if (opt->crl_file) { MONGOC_ERROR ( "Setting mongoc_ssl_opt_t.crl_file has no effect when built " "against Secure Transport"); RETURN (NULL); } secure_transport = (mongoc_stream_tls_secure_transport_t *) bson_malloc0 ( sizeof *secure_transport); tls = (mongoc_stream_tls_t *) bson_malloc0 (sizeof *tls); tls->parent.type = MONGOC_STREAM_TLS; tls->parent.destroy = _mongoc_stream_tls_secure_transport_destroy; tls->parent.failed = _mongoc_stream_tls_secure_transport_failed; tls->parent.close = _mongoc_stream_tls_secure_transport_close; tls->parent.flush = _mongoc_stream_tls_secure_transport_flush; tls->parent.writev = _mongoc_stream_tls_secure_transport_writev; tls->parent.readv = _mongoc_stream_tls_secure_transport_readv; tls->parent.setsockopt = _mongoc_stream_tls_secure_transport_setsockopt; tls->parent.get_base_stream = _mongoc_stream_tls_secure_transport_get_base_stream; tls->parent.check_closed = _mongoc_stream_tls_secure_transport_check_closed; tls->parent.timed_out = _mongoc_stream_tls_secure_channel_timed_out; memcpy (&tls->ssl_opts, opt, sizeof tls->ssl_opts); tls->handshake = mongoc_stream_tls_secure_transport_handshake; tls->ctx = (void *) secure_transport; tls->timeout_msec = -1; secure_transport->ssl_ctx_ref = SSLCreateContext (kCFAllocatorDefault, client ? kSSLClientSide : kSSLServerSide, kSSLStreamType); SSLSetIOFuncs (secure_transport->ssl_ctx_ref, mongoc_secure_transport_read, mongoc_secure_transport_write); SSLSetProtocolVersionMin (secure_transport->ssl_ctx_ref, kTLSProtocol1); if (opt->pem_file && !mongoc_secure_transport_setup_certificate (secure_transport, opt)) { mongoc_stream_destroy ((mongoc_stream_t *) tls); RETURN (NULL); } if (opt->ca_file && !mongoc_secure_transport_setup_ca (secure_transport, opt)) { mongoc_stream_destroy ((mongoc_stream_t *) tls); RETURN (NULL); } /* don't link base_stream to tls until we're sure we won't destroy tls */ tls->base_stream = base_stream; if (client) { SSLSetSessionOption (secure_transport->ssl_ctx_ref, kSSLSessionOptionBreakOnServerAuth, opt->weak_cert_validation); } else if (!opt->allow_invalid_hostname) { /* used only in mock_server_t tests */ SSLSetClientSideAuthenticate (secure_transport->ssl_ctx_ref, kAlwaysAuthenticate); } if (!opt->allow_invalid_hostname) { SSLSetPeerDomainName (secure_transport->ssl_ctx_ref, host, strlen (host)); } SSLSetConnection (secure_transport->ssl_ctx_ref, tls); mongoc_counter_streams_active_inc (); RETURN ((mongoc_stream_t *) tls); }
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 /* O - 1 on success, 0 on error */ cupsdStartTLS(cupsd_client_t *con) /* I - Client connection */ { OSStatus error = 0; /* Error code */ SecTrustRef peerTrust; /* Peer certificates */ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.", con->number); con->http->encryption = HTTP_ENCRYPTION_ALWAYS; con->http->tls_credentials = copy_cdsa_certificate(con); if (!con->http->tls_credentials) { /* * No keychain (yet), make a self-signed certificate... */ if (make_certificate(con)) con->http->tls_credentials = copy_cdsa_certificate(con); } if (!con->http->tls_credentials) { cupsdLogMessage(CUPSD_LOG_ERROR, "Could not find signing key in keychain \"%s\"", ServerCertificate); error = errSSLBadConfiguration; } if (!error) con->http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType); if (!error) error = SSLSetIOFuncs(con->http->tls, _httpReadCDSA, _httpWriteCDSA); if (!error) error = SSLSetConnection(con->http->tls, HTTP(con)); if (!error) error = SSLSetCertificate(con->http->tls, con->http->tls_credentials); if (!error) { /* * Perform SSL/TLS handshake */ while ((error = SSLHandshake(con->http->tls)) == errSSLWouldBlock) usleep(1000); } if (error) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to encrypt connection from %s - %s (%d)", con->http->hostname, cssmErrorString(error), (int)error); con->http->error = error; con->http->status = HTTP_ERROR; if (con->http->tls) { CFRelease(con->http->tls); con->http->tls = NULL; } if (con->http->tls_credentials) { CFRelease(con->http->tls_credentials); con->http->tls_credentials = NULL; } return (0); } cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", con->http->hostname); if (!SSLCopyPeerTrust(con->http->tls, &peerTrust) && peerTrust) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates.", (int)SecTrustGetCertificateCount(peerTrust)); CFRelease(peerTrust); } else cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates."); return (1); }
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); }
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; }
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; }
/* 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; }