X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/sslViewer/sslClient.cpp diff --git a/sslViewer/sslClient.cpp b/sslViewer/sslClient.cpp new file mode 100644 index 00000000..24edd7bf --- /dev/null +++ b/sslViewer/sslClient.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2006-2008,2010-2011,2013 Apple Inc. All Rights Reserved. + * + * sslClient.cpp : perform one SSL client side sesssion + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +/* when true, keep listening until server disconnects */ +#define KEEP_CONNECTED 1 + +#define CLIENT_GETMSG "GET / HTTP/1.0\r\n\r\n" + +#define READBUF_LEN 256 + +/* 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; +}