X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/sslViewer/sslServe.cpp?ds=sidebyside diff --git a/sslViewer/sslServe.cpp b/sslViewer/sslServe.cpp new file mode 100644 index 00000000..349d618f --- /dev/null +++ b/sslViewer/sslServe.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2006-2008,2010,2013 Apple Inc. All Rights Reserved. + * + * sslServe.cpp : perform one server side sesssion + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define BIND_RETRIES 10 + +#define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012\015\012" \ + "SecureTransport Test Server" \ + "

Secure connection established.

" \ + "Message from the 'sslServe' test library.\015\012" \ + "\015\012" + +#define READBUF_LEN 256 + +/* relies on SSLSetProtocolVersionEnabled */ + +/* + * 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; retryport, 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; iclientDone && !params->serverAbort) { + usleep(100); + } + endpointShutdown(acceptSock); + } + if(listenSock) { + endpointShutdown(listenSock); + } + if(ctx) { + SSLDisposeContext(ctx); + } + params->ortn = ortn; + sslThrDebug("Server", "done"); + return ortn; +}