]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/clxutils/sslViewer/SSLViewer.cpp
Security-57740.51.3.tar.gz
[apple/security.git] / SecurityTests / clxutils / sslViewer / SSLViewer.cpp
diff --git a/SecurityTests/clxutils/sslViewer/SSLViewer.cpp b/SecurityTests/clxutils/sslViewer/SSLViewer.cpp
deleted file mode 100644 (file)
index 19a9418..0000000
+++ /dev/null
@@ -1,1799 +0,0 @@
-/*
- * Copyright (c) 2003-2010 Apple Inc. All Rights Reserved.
- *
- * SSL viewer tool, SecureTransport / OS X version.
- */
-
-#include <Security/SecureTransport.h>
-#include <Security/SecureTransportPriv.h>      // for SSLGetPeerSecTrust
-#include <Security/SecCertificate.h>
-#include <clAppUtils/sslAppUtils.h>
-#include <clAppUtils/ioSock.h>
-#include <security_cdsa_utils/cuPrintCert.h>
-#include <utilLib/fileIo.h>
-
-#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-#define DEFAULT_GETMSG         "GET"
-#define DEFAULT_PATH           "/"
-#define DEFAULT_GET_SUFFIX     "HTTP/1.0\r\n\r\n"
-
-#define DEFAULT_HOST                   "www.amazon.com"
-#define DEFAULT_PORT           443
-
-#define CFRELEASE(cf)  if (cf) { CFRelease(cf); cf = NULL; }
-
-/* true when using SSLCopyPeerCertificates() per Radar 3311892 */
-#define USE_COPY_PEER_CERTS            1
-
-static void usageNorm(char **argv)
-{
-    printf("Usage: %s [hostname|-] [path] [option ...]\n", argv[0]);
-    printf("       %s hostname [path] [option ...]\n", argv[0]);
-       printf("Specifying '-' for hostname, or no args, uses default of %s.\n",
-               DEFAULT_HOST);
-       printf("Optional path argument must start with leading '/'.\n");
-    printf("Options:\n");
-    printf("   e           Allow Expired Certs\n");
-    printf("   E           Allow Expired Roots\n");
-    printf("   r           Allow any root cert\n");
-       printf("   c           Display peer certs\n");
-       printf("   d           Display received data\n");
-       printf("   S           Display enabled cipher suites\n");
-       printf("   2           SSLv2 only (default is TLSv1)\n");
-       printf("   3           SSLv3 only w/SSLv2 enabled (default is TLSv1)\n");
-       printf("   t           TLSv1 only w/SSLv2,SSLv3 enabled (this is the default)\n");
-       printf("   L           all - TLSv1, SSLv3, SSLv2 (default = TLSv1)\n");
-       printf("   o           TLSv1, SSLv3 use kSSLProtocol__X__Only\n");
-       printf("   g={prot...} Specify legal protocols; prot = any combo of"
-                                                       " [23t]\n");
-       printf("   k=keychain  Contains (client|server) cert and keys. Optional.\n");
-       printf("   l=loopCount Perform loopCount ops (default = 1)\n");
-       printf("   P=port      Default = %d\n", DEFAULT_PORT); 
-       printf("   p           Pause after each loop\n");
-       printf("   q           Quiet/diagnostic mode (site names and errors"
-                                                               " only)\n");
-       printf("   a fileName  Add fileName to list of trusted roots\n");
-       printf("   A fileName  fileName is ONLY trusted root\n");
-    printf("   Z fileName  fileName is a trusted leaf cert\n");
-       printf("   x           Disable Cert Verification\n");
-       printf("   z=password  Unlock client keychain with password.\n");
-       printf("   8           Complete cert chains (default is out cert is a root)\n");
-       printf("   s           Silent\n");
-       printf("   V           Verbose\n");
-       printf("   h           Help\n");
-       printf("   hv          More, verbose help\n");
-}
-
-static void usageVerbose(char **argv)
-{
-    usageNorm(argv);
-       printf("Obscure Usage:\n");
-       printf("   u           kSSLProtocolUnknown only (TLSv1)\n");
-       printf("   M           Manual cert verification via "
-                                                       "SecTrustEvaluate\n");
-       printf("   f fileBase  Write Peer Certs to fileBase*\n");
-       printf("   D fileBase  Write DNList to fileBase*\n");
-       printf("   C=cipherSuite (e=40-bit d=DES D=40-bit DES 3=3DES 4=RC4"
-                                                               "$=40-bit RC4\n"
-                  "                  2=RC2 a=AES128 A=AES256 h=DH H=Anon DH r=DHE/RSA s=DH/DSS\n"
-                  "                  n=RSA/NULL E=ECDHE F=ECDH\n");
-       printf("   y=keychain  Encryption-only cert and keys. Optional.\n");
-       printf("   K           Keep connected until server disconnects\n");
-       printf("   n           Require closure notify message in TLSv1, "
-                                                               "SSLv3 mode (implies K)\n");
-       printf("   R           Disable resumable session support\n");
-       printf("   i=timeout   Session cache timeout\n");
-       printf("   b           Non-blocking I/O\n");
-       printf("   v           Verify negotiated protocol equals attempted\n");
-       printf("   m=[23t]     Max protocol supported as specified; implies "
-                                                               "v\n");
-       printf("   T=[nrsj]    Verify client cert state = "
-                                                               "none/requested/sent/rejected\n");
-       printf("   H           allow hostname spoofing\n");
-       printf("   F=vfyHost   Verify certs with specified host name\n");
-       printf("   G=getMsg    Specify entire GET, POST, etc.\n");
-       printf("   I           Interactive client authentication\n");
-       printf("   N           Log handshake timing\n");
-       printf("   4           Disable anonymous ciphers\n");
-       printf("   7           Pause only after first loop\n");
-       exit(1);
-}
-
-static void usage(char **argv)
-{
-    usageNorm(argv);
-       exit(1);
-}
-
-/* 
- * Arguments to top-level sslPing()
- */
-typedef struct {
-       SSLProtocol                             tryVersion;                     // only used if acceptedProts NULL
-                                                                                               // uses SSLSetProtocolVersion
-       char                                    *acceptedProts;         // optional, any combo of {2,3,t}
-                                                                                               // uses SSLSetProtocolVersionEnabled
-       const char                              *hostName;                      // e.g., "www.amazon.com"
-       const char                              *vfyHostName;           // use this for cert vfy if non-NULL,
-                                                                                               //   else use hostName
-       unsigned short                  port;
-       const char                              *getMsg;                        // e.g., 
-                                                                                               //   "GET / HTTP/1.0\r\n\r\n" 
-       bool                                    allowExpired;
-       bool                                    allowAnyRoot;
-       bool                                    allowExpiredRoot;
-       bool                                    disableCertVerify;
-       bool                                    manualCertVerify;
-       bool                                    dumpRxData;                     // display server data
-       char                                    cipherRestrict;         // '2', 'd'. etc...; '\0' for 
-                                                                                               //   no restriction
-       bool                                    keepConnected;
-       bool                                    requireNotify;          // require closure notify 
-                                                                                               //   in V3 mode
-       bool                                    resumableEnable;
-       bool                                    allowHostnameSpoof;
-       bool                                    nonBlocking;
-       char                                    *anchorFile;
-    char                                       *trustedLeafFile;
-       bool                                    replaceAnchors;
-       bool                                    interactiveAuth;
-       CFArrayRef                              clientCerts;            // optional
-       CFArrayRef                              encryptClientCerts;     // optional
-       uint32                                  sessionCacheTimeout;// optional
-       bool                                    disableAnonCiphers;
-       bool                                    showCipherSuites;
-       bool                                    quiet;                          // minimal stdout
-       bool                                    silent;                         // no stdout
-       bool                                    verbose;
-       SSLProtocol                             negVersion;                     // RETURNED
-       SSLCipherSuite                  negCipher;                      // RETURNED
-       CFArrayRef                              peerCerts;                      // mallocd & RETURNED
-       SecTrustRef                             peerTrust;                      // RETURNED
-       SSLClientCertificateState certState;            // RETURNED
-       SSLClientAuthenticationType authType;           // RETURNED
-       CFArrayRef                              dnList;                         // RETURNED
-       char                                    *password;                      // optional to open clientCerts
-       char                                    **argv;
-       Boolean                                 sessionWasResumed;
-       unsigned char                   sessionID[MAX_SESSION_ID_LENGTH];
-       size_t                                  sessionIDLength;
-       CFAbsoluteTime                  handshakeTimeOp;                // time for this op
-       CFAbsoluteTime                  handshakeTimeFirst;             // time for FIRST op, not averaged
-       CFAbsoluteTime                  handshakeTimeTotal;             // time for all ops except first
-       unsigned                                numHandshakes;          
-
-} sslPingArgs;
-
-#include <signal.h>
-static void sigpipe(int sig) 
-{ 
-       fflush(stdin);
-       printf("***SIGPIPE***\n");
-}
-
-/* 
- * Start up a CFRunLoop. This is needed to field keychain event callbacks, used
- * to maintain root cert cache coherency. 
- */
-/* first we need something to register so we *have* a run loop */
-static OSStatus kcCacheCallback (
-   SecKeychainEvent keychainEvent,
-   SecKeychainCallbackInfo *info,
-   void *context)
-{
-       return noErr;
-}
-
-/* main thread has to wait for this to be set to know a run loop has been set up */
-static int runLoopInitialized = 0;
-
-/* this is the thread which actually runs the CFRunLoop */
-void *cfRunLoopThread(void *arg)
-{
-       OSStatus ortn = SecKeychainAddCallback(kcCacheCallback, 
-               kSecTrustSettingsChangedEventMask, NULL);
-       if(ortn) {
-               printf("registerCacheCallbacks: SecKeychainAddCallback returned %d", (int32_t)ortn);
-               /* Not sure how this could ever happen - maybe if there is no run loop active? */
-               return NULL;
-       }
-       runLoopInitialized = 1;
-       CFRunLoopRun();
-       /* should not be reached */
-       printf("\n*** Hey! CFRunLoopRun() exited!***\n");
-       return NULL;
-}
-
-static int startCFRunLoop()
-{
-       pthread_t runLoopThread;
-       
-       int result = pthread_create(&runLoopThread, NULL, cfRunLoopThread, NULL);
-       if(result) {
-               printf("***pthread_create returned %d, aborting\n", result);
-               return -1;
-       }
-       return 0;
-}
-
-/* 
- * Snag a copy of current connection's peer certs so we can 
- * examine them later after the connection is closed.
- * SecureTransport actually does the create and retain for us. 
- */
-static OSStatus copyPeerCerts(
-       SSLContext      *ctx,
-       CFArrayRef      *peerCerts)             // mallocd & RETURNED
-{
-       #if USE_COPY_PEER_CERTS
-       OSStatus ortn = SSLCopyPeerCertificates(ctx, peerCerts);
-       #else
-       OSStatus ortn = SSLGetPeerCertificates(ctx, peerCerts);
-       #endif
-       if(ortn) {
-               printf("***Error obtaining peer certs: %s\n",
-                       sslGetSSLErrString(ortn));
-       }
-       return ortn;
-}
-
-/* free the cert array obtained via SSLGetPeerCertificates() */
-/* necessary due to a buggy SSLGetPeerCertificates which really should
- * release its certs after they get added to this array */
-static void    freePeerCerts(
-       CFArrayRef                      peerCerts)
-{
-       if(peerCerts == NULL) {
-               return;
-       }
-
-       #if USE_COPY_PEER_CERTS
-       
-       /* Voila! Problem fixed. */
-       CFRelease(peerCerts);
-       return;
-       
-       #else 
-       CFIndex numCerts;
-       SecCertificateRef certData;
-       CFIndex i;
-       
-       numCerts = CFArrayGetCount(peerCerts);
-       for(i=0; i<numCerts; i++) {
-               certData = (SecCertificateRef)CFArrayGetValueAtIndex(peerCerts, i);
-               CFRelease(certData);
-       }
-       CFRelease(peerCerts);
-       #endif  /* USE_COPY_PEER_CERTS */
-}      
-
-/*
- * Manually evaluate session's SecTrustRef.
- */
-#define SSL_SEC_TRUST  1
-
-static OSStatus sslEvaluateTrust(
-       SSLContext      *ctx,
-       bool            verbose, 
-       bool            silent,
-       CFArrayRef      *peerCerts)             // fetched and retained
-{
-       OSStatus ortn;
-       SecTrustRef secTrust = NULL;
-
-       #if     SSL_SEC_TRUST
-       ortn = SSLGetPeerSecTrust(ctx, &secTrust);
-       #else
-       ortn = unimpErr;
-       #endif
-       if(ortn) {
-               printf("\n***Error obtaining peer SecTrustRef: %s\n",
-                       sslGetSSLErrString(ortn));
-               return ortn;
-       }
-       if(secTrust == NULL) {
-               /* this is the normal case for resumed sessions, in which 
-                * no cert evaluation is performed */
-               if(!silent) {
-                       printf("...No SecTrust available - this is a resumed session, right?\n");
-               }
-               return noErr;
-       }
-       SecTrustResultType      secTrustResult;
-       ortn = SecTrustEvaluate(secTrust, &secTrustResult);
-       if(ortn) {
-               printf("\n***Error on SecTrustEvaluate: %d\n", (int)ortn);
-               return ortn;
-       }
-       if(verbose) {
-               const char *res = NULL;
-               switch(secTrustResult) {
-                       case kSecTrustResultInvalid: 
-                               res = "kSecTrustResultInvalid"; break;
-                       case kSecTrustResultProceed: 
-                               res = "kSecTrustResultProceed"; break;
-                       case kSecTrustResultConfirm: 
-                               res = "kSecTrustResultConfirm"; break;
-                       case kSecTrustResultDeny: 
-                               res = "kSecTrustResultDeny"; break;
-                       case kSecTrustResultUnspecified: 
-                               res = "kSecTrustResultUnspecified"; break;
-                       case kSecTrustResultRecoverableTrustFailure: 
-                               res = "kSecTrustResultRecoverableTrustFailure"; break;
-                       case kSecTrustResultFatalTrustFailure: 
-                               res = "kSecTrustResultFatalTrustFailure"; break;
-                       case kSecTrustResultOtherError: 
-                               res = "kSecTrustResultOtherError"; break;
-                       default:
-                               res = "UNKNOWN"; break;
-               }
-               printf("\nSecTrustEvaluate(): secTrustResult %s\n", res);
-       }
-       
-       switch(secTrustResult) {
-               case kSecTrustResultUnspecified:
-                       /* cert chain valid, no special UserTrust assignments */
-               case kSecTrustResultProceed:
-                       /* cert chain valid AND user explicitly trusts this */
-                       break;
-               default:
-                       printf("\n***SecTrustEvaluate reported secTrustResult %d\n", 
-                               (int)secTrustResult);
-                       ortn = errSSLXCertChainInvalid;
-                       break;
-       }
-       
-       *peerCerts = NULL;
-
-       /* one more thing - get peer certs in the form of an evidence chain */
-       CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv;
-       OSStatus thisRtn = SecTrustGetResult(secTrust, &secTrustResult,
-               peerCerts, &dummyEv);
-       if(thisRtn) {
-               printSslErrStr("SecTrustGetResult", thisRtn);
-       }
-       #if             !USE_COPY_PEER_CERTS
-       else {
-               /* workaround for the fact that SSLGetPeerCertificates()
-                * leaves a retain count on each element in the returned array,
-                * requiring us to do a release on each cert.
-                */
-               CFIndex numCerts = CFArrayGetCount(*peerCerts);
-               for(CFIndex dex=0; dex<numCerts; dex++) {
-                       CFRetain(CFArrayGetValueAtIndex(*peerCerts, dex));
-               }
-       }
-       #endif  /* !USE_COPY_PEER_CERTS */
-       return ortn;
-}
-
-static void sslShowEnabledCipherSuites(
-       SSLContextRef ctx)
-{
-       OSStatus status;
-       SSLCipherSuite *ciphers;
-       size_t numCiphers, totalCiphers;
-       const char *c;
-       unsigned int i;
-       
-       status = SSLGetNumberSupportedCiphers(ctx, &totalCiphers);
-       status = SSLGetNumberEnabledCiphers(ctx, &numCiphers);
-       ciphers = (SSLCipherSuite *)malloc(sizeof(SSLCipherSuite) * numCiphers);
-       status = SSLGetEnabledCiphers(ctx, ciphers, &numCiphers);
-
-       printf("   Total enabled ciphers  : %ld of %ld\n", numCiphers, totalCiphers);
-       
-       for(i=0; i<numCiphers; i++) {
-               switch(ciphers[i]) {
-                       case SSL_NULL_WITH_NULL_NULL:                           c="SSL_NULL_WITH_NULL_NULL"; break;
-                       case SSL_RSA_WITH_NULL_MD5:                                     c="SSL_RSA_WITH_NULL_MD5"; break;
-                       case SSL_RSA_WITH_NULL_SHA:                                     c="SSL_RSA_WITH_NULL_SHA"; break;
-                       case SSL_RSA_EXPORT_WITH_RC4_40_MD5:            c="SSL_RSA_EXPORT_WITH_RC4_40_MD5"; break;
-                       case SSL_RSA_WITH_RC4_128_MD5:                          c="SSL_RSA_WITH_RC4_128_MD5"; break;
-                       case SSL_RSA_WITH_RC4_128_SHA:                          c="SSL_RSA_WITH_RC4_128_SHA"; break;
-                       case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:        c="SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; break;
-                       case SSL_RSA_WITH_IDEA_CBC_SHA:                         c="SSL_RSA_WITH_IDEA_CBC_SHA"; break;
-                       case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:         c="SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; break;
-                       case SSL_RSA_WITH_DES_CBC_SHA:                          c="SSL_RSA_WITH_DES_CBC_SHA"; break;
-                       case SSL_RSA_WITH_3DES_EDE_CBC_SHA:                     c="SSL_RSA_WITH_3DES_EDE_CBC_SHA"; break;
-                       case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:      c="SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; break;
-                       case SSL_DH_DSS_WITH_DES_CBC_SHA:                       c="SSL_DH_DSS_WITH_DES_CBC_SHA"; break;
-                       case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:          c="SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; break;
-                       case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:      c="SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; break;
-                       case SSL_DH_RSA_WITH_DES_CBC_SHA:                       c="SSL_DH_RSA_WITH_DES_CBC_SHA"; break;
-                       case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:          c="SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; break;
-                       case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:     c="SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; break;
-                       case SSL_DHE_DSS_WITH_DES_CBC_SHA:                      c="SSL_DHE_DSS_WITH_DES_CBC_SHA"; break;
-                       case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:         c="SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; break;
-                       case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:     c="SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; break;
-                       case SSL_DHE_RSA_WITH_DES_CBC_SHA:                      c="SSL_DHE_RSA_WITH_DES_CBC_SHA"; break;
-                       case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:         c="SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; break;
-                       case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:        c="SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; break;
-                       case SSL_DH_anon_WITH_RC4_128_MD5:                      c="SSL_DH_anon_WITH_RC4_128_MD5"; break;
-                       case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:     c="SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; break;
-                       case SSL_DH_anon_WITH_DES_CBC_SHA:                      c="SSL_DH_anon_WITH_DES_CBC_SHA"; break;
-                       case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:         c="SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; break;
-                       case SSL_FORTEZZA_DMS_WITH_NULL_SHA:            c="SSL_FORTEZZA_DMS_WITH_NULL_SHA"; break;
-                       case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:c="SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; break;
-       
-                       /* TLS addenda using AES, per RFC 3268 */
-                       case TLS_RSA_WITH_AES_128_CBC_SHA:                      c="TLS_RSA_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_DH_DSS_WITH_AES_128_CBC_SHA:           c="TLS_DH_DSS_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_DH_RSA_WITH_AES_128_CBC_SHA:           c="TLS_DH_RSA_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:          c="TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:          c="TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_DH_anon_WITH_AES_128_CBC_SHA:          c="TLS_DH_anon_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_RSA_WITH_AES_256_CBC_SHA:                      c="TLS_RSA_WITH_AES_256_CBC_SHA"; break;
-                       case TLS_DH_DSS_WITH_AES_256_CBC_SHA:           c="TLS_DH_DSS_WITH_AES_256_CBC_SHA"; break;
-                       case TLS_DH_RSA_WITH_AES_256_CBC_SHA:           c="TLS_DH_RSA_WITH_AES_256_CBC_SHA"; break;
-                       case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:          c="TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; break;
-                       case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:          c="TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; break;
-                       case TLS_DH_anon_WITH_AES_256_CBC_SHA:          c="TLS_DH_anon_WITH_AES_256_CBC_SHA"; break;
-       
-                       /* ECDSA addenda, RFC 4492 */
-                       case TLS_ECDH_ECDSA_WITH_NULL_SHA:                      c="TLS_ECDH_ECDSA_WITH_NULL_SHA"; break;
-                       case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:           c="TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; break;
-                       case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:      c="TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; break;
-                       case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:       c="TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:       c="TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; break;
-                       case TLS_ECDHE_ECDSA_WITH_NULL_SHA:                     c="TLS_ECDHE_ECDSA_WITH_NULL_SHA"; break;
-                       case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:          c="TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; break;
-                       case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:     c="TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; break;
-                       case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:      c="TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:      c="TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; break;
-                       case TLS_ECDH_RSA_WITH_NULL_SHA:                        c="TLS_ECDH_RSA_WITH_NULL_SHA"; break;
-                       case TLS_ECDH_RSA_WITH_RC4_128_SHA:                     c="TLS_ECDH_RSA_WITH_RC4_128_SHA"; break;
-                       case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:        c="TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; break;
-                       case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:         c="TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:         c="TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; break;
-                       case TLS_ECDHE_RSA_WITH_NULL_SHA:                       c="TLS_ECDHE_RSA_WITH_NULL_SHA"; break;
-                       case TLS_ECDHE_RSA_WITH_RC4_128_SHA:            c="TLS_ECDHE_RSA_WITH_RC4_128_SHA"; break;
-                       case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:       c="TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; break;
-                       case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:        c="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:        c="TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; break;
-                       case TLS_ECDH_anon_WITH_NULL_SHA:                       c="TLS_ECDH_anon_WITH_NULL_SHA"; break;
-                       case TLS_ECDH_anon_WITH_RC4_128_SHA:            c="TLS_ECDH_anon_WITH_RC4_128_SHA"; break;
-                       case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:       c="TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; break;
-                       case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:        c="TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; break;
-                       case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:        c="TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; break;
-       
-                       /*
-                        * Tags for SSL 2 cipher kinds which are not specified 
-                        * for SSL 3. 
-                        */
-                       case SSL_RSA_WITH_RC2_CBC_MD5:                          c="SSL_RSA_WITH_RC2_CBC_MD5"; break;
-                       case SSL_RSA_WITH_IDEA_CBC_MD5:                         c="SSL_RSA_WITH_IDEA_CBC_MD5"; break;
-                       case SSL_RSA_WITH_DES_CBC_MD5:                          c="SSL_RSA_WITH_DES_CBC_MD5"; break;
-                       case SSL_RSA_WITH_3DES_EDE_CBC_MD5:                     c="SSL_RSA_WITH_3DES_EDE_CBC_MD5"; break;
-                       case SSL_NO_SUCH_CIPHERSUITE:
-                       default:
-                                                                                                               c="SSL_NO_SUCH_CIPHERSUITE"; break;
-               }
-               printf("   %s\n", c);
-               fflush(stdout);
-       }
-       free(ciphers);
-}
-
-/* print reply received from server, safely */
-static void dumpAscii(
-       uint8_t *rcvBuf, 
-       uint32_t len)
-{
-       char *cp = (char *)rcvBuf;
-       uint32_t i;
-       char c;
-       
-       for(i=0; i<len; i++) {
-               c = *cp++;
-               if(c == '\0') {
-                       break;
-               }
-               switch(c) {
-                       case '\n':
-                               printf("\\n");
-                               break;
-                       case '\r':
-                               printf("\\r");
-                               break;
-                       default:
-                               if(isprint(c) && (c != '\n')) {
-                                       printf("%c", c);
-                               }
-                               else {
-                                       printf("<%02X>", ((unsigned)c) & 0xff);
-                               }
-                       break;
-               }
-
-       }
-       printf("\n");
-}
-
-/*
- * Perform one SSL diagnostic session. Returns nonzero on error. Normally no
- * output to stdout except initial "connecting to" message, unless there 
- * is a really screwed up error (i.e., something not directly related 
- * to the SSL connection). 
- */
-#define RCV_BUF_SIZE           256
-
-static OSStatus sslPing(
-       sslPingArgs *pargs)
-{
-    PeerSpec            peerId;
-       otSocket                        sock = 0;
-    OSStatus            ortn;
-    SSLContextRef       ctx = NULL;
-    size_t              length;
-       size_t                          actLen;
-    uint8_t             rcvBuf[RCV_BUF_SIZE];
-       CFAbsoluteTime          startHandshake;
-       CFAbsoluteTime          endHandshake;
-       
-    pargs->negVersion = kSSLProtocolUnknown;
-    pargs->negCipher = SSL_NULL_WITH_NULL_NULL;
-    pargs->peerCerts = NULL;
-    
-       /* first make sure requested server is there */
-       ortn = MakeServerConnection(pargs->hostName, pargs->port, pargs->nonBlocking,
-               &sock, &peerId);
-    if(ortn) {
-       printf("MakeServerConnection returned %d; aborting\n", (int)ortn);
-       return ortn;
-    }
-       if(pargs->verbose) {
-               printf("...connected to server; starting SecureTransport\n");
-       }
-       
-       /* 
-        * Set up a SecureTransport session.
-        * First the standard calls.
-        */
-       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;
-       }
-       SSLConnectionRef getConn;
-       ortn = SSLGetConnection(ctx, &getConn);
-       if(ortn) {
-               printSslErrStr("SSLGetConnection", ortn);
-               goto cleanup;
-       }
-       if(getConn != (SSLConnectionRef)sock) {
-               printf("***SSLGetConnection error\n");
-               ortn = paramErr;
-               goto cleanup; 
-       }
-       if(!pargs->allowHostnameSpoof) {
-               /* if this isn't set, it isn't checked by AppleX509TP */
-               const char *vfyHost = pargs->hostName;
-               if(pargs->vfyHostName) {
-                       /* generally means we're expecting an error */
-                       vfyHost = pargs->vfyHostName;
-               }
-               ortn = SSLSetPeerDomainName(ctx, vfyHost, strlen(vfyHost));
-               if(ortn) {
-                       printSslErrStr("SSLSetPeerDomainName", ortn);
-                       goto cleanup;
-               }
-       }
-       
-       /* 
-        * SecureTransport options.
-        */ 
-       if(pargs->acceptedProts) {
-               ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false);
-               if(ortn) {
-                       printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn);
-                       goto cleanup;
-               }
-               for(const char *cp = pargs->acceptedProts; *cp; cp++) {
-                       SSLProtocol prot;
-                       switch(*cp) {
-                               case '2':
-                                       prot = kSSLProtocol2;
-                                       break;
-                               case '3':
-                                       prot = kSSLProtocol3;
-                                       break;
-                               case 't':
-                                       prot = kTLSProtocol1;
-                                       break;
-                               default:
-                                       usage(pargs->argv);
-                       }
-                       ortn = SSLSetProtocolVersionEnabled(ctx, prot, true);
-                       if(ortn) {
-                               printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
-                               goto cleanup;
-                       }
-               }
-       }
-       else {
-               ortn = SSLSetProtocolVersion(ctx, pargs->tryVersion);
-               if(ortn) {
-                       printSslErrStr("SSLSetProtocolVersion", ortn);
-                       goto cleanup;
-               } 
-               SSLProtocol getVers;
-               ortn = SSLGetProtocolVersion(ctx, &getVers);
-               if(ortn) {
-                       printSslErrStr("SSLSetProtocolVersion", ortn);
-                       goto cleanup;
-               }
-               if(getVers != pargs->tryVersion) {
-                       printf("***SSLGetProtocolVersion screwup: try %s  get %s\n",
-                               sslGetProtocolVersionString(pargs->tryVersion),
-                               sslGetProtocolVersionString(getVers));
-                       ortn = paramErr;
-                       goto cleanup;
-               }
-       }
-       if(pargs->resumableEnable) {
-               const void *rtnId = NULL;
-               size_t rtnIdLen = 0;
-               
-               ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec));
-               if(ortn) {
-                       printSslErrStr("SSLSetPeerID", ortn);
-                       goto cleanup;
-               }
-               /* quick test of the get fcn */
-               ortn = SSLGetPeerID(ctx, &rtnId, &rtnIdLen);
-               if(ortn) {
-                       printSslErrStr("SSLGetPeerID", ortn);
-                       goto cleanup;
-               }
-               if((rtnId == NULL) || (rtnIdLen != sizeof(PeerSpec))) {
-                       printf("***SSLGetPeerID screwup\n");
-               }
-               else if(memcmp(&peerId, rtnId, rtnIdLen) != 0) {
-                       printf("***SSLGetPeerID data mismatch\n");
-               }
-       }
-       if(pargs->allowExpired) {
-               ortn = SSLSetAllowsExpiredCerts(ctx, true);
-               if(ortn) {
-                       printSslErrStr("SSLSetAllowExpiredCerts", ortn);
-                       goto cleanup;
-               }
-       }
-       if(pargs->allowExpiredRoot) {
-               ortn = SSLSetAllowsExpiredRoots(ctx, true);
-               if(ortn) {
-                       printSslErrStr("SSLSetAllowsExpiredRoots", ortn);
-                       goto cleanup;
-               }
-       }
-       if(pargs->disableCertVerify) {
-               ortn = SSLSetEnableCertVerify(ctx, false);
-               if(ortn) {
-                       printSslErrStr("SSLSetEnableCertVerify", ortn);
-                       goto cleanup;
-               }
-       }
-       if(pargs->allowAnyRoot) {
-               ortn = SSLSetAllowsAnyRoot(ctx, true);
-               if(ortn) {
-                       printSslErrStr("SSLSetAllowAnyRoot", ortn);
-                       goto cleanup;
-               }
-       }
-       if(pargs->cipherRestrict != '\0') {
-               ortn = sslSetCipherRestrictions(ctx, pargs->cipherRestrict);
-               if(ortn) {
-                       goto cleanup;
-               }
-       }
-       if(pargs->anchorFile) {
-               ortn = sslAddTrustedRoot(ctx, pargs->anchorFile, pargs->replaceAnchors);
-               if(ortn) {
-                       printf("***Error obtaining anchor file %s\n", pargs->anchorFile);
-                       goto cleanup;
-               }
-       }
-    if(pargs->trustedLeafFile) {
-        SecCertificateRef leafCertRef = NULL;
-        CFMutableArrayRef leafCerts = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-        /* sslReadAnchor is a misnomer; it just creates a SecCertificateRef from a file */
-        ortn = sslReadAnchor(pargs->trustedLeafFile, &leafCertRef);
-        if (!ortn) {
-            CFArrayAppendValue(leafCerts, leafCertRef);
-            CFRelease(leafCertRef);
-            ortn = SSLSetTrustedLeafCertificates(ctx, leafCerts);
-            CFRelease(leafCerts);
-        }
-        if(ortn) {
-            goto cleanup;
-        }
-    }
-       if(pargs->interactiveAuth) {
-               /* we want to get errSSLServerAuthCompleted from SSLHandshake on server auth completion */
-               SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnServerAuth, true);
-               /* we want to get errSSLClientCertRequested from SSLHandshake on client auth request */
-               SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnCertRequested, true);
-       }       
-       else if(pargs->clientCerts) {
-               CFArrayRef dummy;
-               if(pargs->anchorFile == NULL) {
-                       /* assume this is a root we want to implicitly trust */
-                       ortn = addIdentityAsTrustedRoot(ctx, pargs->clientCerts);
-                       if(ortn) {
-                               goto cleanup;
-                       }
-               }
-               ortn = SSLSetCertificate(ctx, pargs->clientCerts);
-               if(ortn) {
-                       printSslErrStr("SSLSetCertificate", ortn);
-                       goto cleanup;
-               }
-               /* quickie test for this new function */
-               ortn = SSLGetCertificate(ctx, &dummy);
-               if(ortn) {
-                       printSslErrStr("SSLGetCertificate", ortn);
-                       goto cleanup;
-               }
-               if(dummy != pargs->clientCerts) {
-                       printf("***SSLGetCertificate error\n");
-                       ortn = ioErr;
-                       goto cleanup;
-               }
-       }
-       if(pargs->encryptClientCerts) {
-               if(pargs->anchorFile == NULL) {
-                       ortn = addIdentityAsTrustedRoot(ctx, pargs->encryptClientCerts);
-                       if(ortn) {
-                               goto cleanup;
-                       }
-               }
-               ortn = SSLSetEncryptionCertificate(ctx, pargs->encryptClientCerts);
-               if(ortn) {
-                       printSslErrStr("SSLSetEncryptionCertificate", ortn);
-                       goto cleanup;
-               }
-       }
-       if(pargs->sessionCacheTimeout) {
-               ortn = SSLSetSessionCacheTimeout(ctx, pargs->sessionCacheTimeout);
-               if(ortn) {
-                       printSslErrStr("SSLSetSessionCacheTimeout", ortn);
-                       goto cleanup;
-               }
-       }
-       if(pargs->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 = ioErr;
-                       goto cleanup;
-               }
-       }
-       if(pargs->showCipherSuites) {
-               sslShowEnabledCipherSuites(ctx);
-       }
-       /*** end options ***/
-       
-       if(pargs->verbose) {
-               printf("...starting SSL handshake\n");
-       }
-       startHandshake = CFAbsoluteTimeGetCurrent();
-       
-    do
-    {   ortn = SSLHandshake(ctx);
-           if((ortn == errSSLWouldBlock) && !pargs->silent) {
-               /* keep UI responsive */ 
-               sslOutputDot();
-           }
-               else if(ortn == errSSLServerAuthCompleted) {
-                       if(pargs->verbose) {
-                               printf("...server authentication completed\n");
-                       }
-               }
-               else if(ortn == errSSLClientCertRequested) {
-                       if(pargs->verbose) {
-                               printf("...received client cert request\n");
-                       }
-                       /* %%% could prompt interactively here for client cert to use;
-                        * for now, just use the client cert passed on the command line
-                        */
-                       if(pargs->clientCerts) {
-                               CFArrayRef dummy;
-                               if(pargs->anchorFile == NULL) {
-                                       /* assume this is a root we want to implicitly trust */
-                                       ortn = addIdentityAsTrustedRoot(ctx, pargs->clientCerts);
-                                       if(ortn) {
-                                               goto cleanup;
-                                       }
-                               }
-                               if(pargs->verbose) {
-                                       printf("...setting client certificate\n");
-                               }
-                               ortn = SSLSetCertificate(ctx, pargs->clientCerts);
-                               if(ortn) {
-                                       printSslErrStr("SSLSetCertificate", ortn);
-                                       goto cleanup;
-                               }
-                               /* quickie test for this new function */
-                               ortn = SSLGetCertificate(ctx, &dummy);
-                               if(ortn) {
-                                       printSslErrStr("SSLGetCertificate", ortn);
-                                       goto cleanup;
-                               }
-                               if(dummy != pargs->clientCerts) {
-                                       printf("***SSLGetCertificate error\n");
-                                       ortn = ioErr;
-                                       goto cleanup;
-                               }
-                       }
-                       else {
-                               printf("***no client certificate specified!\n");
-                       }
-               }
-    } while (ortn == errSSLWouldBlock ||
-                        ortn == errSSLServerAuthCompleted ||
-                        ortn == errSSLClientCertRequested);
-
-       endHandshake = CFAbsoluteTimeGetCurrent();
-       pargs->handshakeTimeOp = endHandshake - startHandshake;
-       if(pargs->numHandshakes == 0) {
-               /* special case, this one is always way longer */
-               pargs->handshakeTimeFirst = pargs->handshakeTimeOp;
-       }
-       else {
-               /* normal running total */
-               pargs->handshakeTimeTotal += pargs->handshakeTimeOp;
-       }
-       pargs->numHandshakes++;
-       
-       /* this works even if handshake failed due to cert chain invalid */
-       CFRELEASE(pargs->peerCerts);
-       if(!pargs->manualCertVerify) {
-               copyPeerCerts(ctx, &pargs->peerCerts);
-       }
-       else {
-               /* else fetched via SecTrust later */
-               pargs->peerCerts = NULL;
-       }
-       
-    ortn = SSLCopyPeerTrust(ctx, &pargs->peerTrust);
-    if(ortn) {
-        printf("***SSLCopyPeerTrust error %d\n", (int)ortn);
-        pargs->peerTrust = NULL;
-    }
-
-       /* ditto */
-       SSLGetClientCertificateState(ctx, &pargs->certState);
-       SSLGetNegotiatedClientAuthType(ctx, &pargs->authType);
-       SSLGetNegotiatedCipher(ctx, &pargs->negCipher);
-       SSLGetNegotiatedProtocolVersion(ctx, &pargs->negVersion);
-       CFRELEASE(pargs->dnList);
-       SSLCopyDistinguishedNames(ctx, &pargs->dnList);
-       pargs->sessionIDLength = MAX_SESSION_ID_LENGTH;
-       SSLGetResumableSessionInfo(ctx, &pargs->sessionWasResumed, pargs->sessionID,
-               &pargs->sessionIDLength);
-       if(pargs->manualCertVerify) {
-               OSStatus certRtn = sslEvaluateTrust(ctx, pargs->verbose, pargs->silent,
-                       &pargs->peerCerts);
-               if(certRtn && !ortn ) {
-                       ortn = certRtn;
-               }
-       }
-       
-    if(ortn) {
-               if(!pargs->silent) {
-                       printf("\n");
-               }
-       goto cleanup;
-    }
-
-       if(pargs->verbose) {
-               printf("...SSL handshake complete\n");
-       }
-
-       /* Write our GET request */
-       length = strlen(pargs->getMsg);
-       ortn = SSLWrite(ctx, pargs->getMsg, length, &actLen);
-       if(ortn) {
-               printf("***SSLWrite error: %d\n", (int)ortn);
-       } else if((actLen > 0) && pargs->dumpRxData) {
-               dumpAscii((uint8_t*)pargs->getMsg, actLen);
-       }
-       
-       /* 
-        * Try to snag RCV_BUF_SIZE bytes. Exit if (!keepConnected and we get any data
-        * at all), or (keepConnected and err != (none, wouldBlock)).
-        */
-    while (ortn == noErr) {   
-               actLen = 0;
-               if(pargs->dumpRxData) {
-                       size_t avail = 0;
-                       
-                       ortn = SSLGetBufferedReadSize(ctx, &avail);
-                       if(ortn) {
-                               printf("***SSLGetBufferedReadSize error\n");
-                               break;
-                       }
-                       if(avail != 0) {
-                               printf("\n%d bytes available: ", (int)avail);
-                       }
-               }
-        ortn = SSLRead(ctx, rcvBuf, RCV_BUF_SIZE, &actLen);
-        if((actLen == 0) && !pargs->silent) {
-               sslOutputDot();
-        }
-        if((actLen == 0) && (ortn == noErr)) {
-                       printf("***Radar 2984932 confirmed***\n");
-               }
-        if (ortn == errSSLWouldBlock) {
-                       /* for this loop, these are identical */
-            ortn = noErr;
-        }
-               if(ortn == errSSLServerAuthCompleted ||
-                  ortn == errSSLClientCertRequested) {
-                       /* should never get these once the handshake is complete */
-                       printf("***SSLRead returned unexpected handshake error!\n");
-               }
-               
-               if((actLen > 0) && pargs->dumpRxData) {
-                       dumpAscii(rcvBuf, actLen);
-               }
-               if(ortn != noErr) {
-                       /* connection closed by server or by error */
-                       break;
-               }
-               if(!pargs->keepConnected && (actLen > 0)) {
-               /* good enough, we connected */
-               break;
-        }
-    }
-       if(!pargs->silent) {
-               printf("\n");
-       }
-
-       /* snag these again in case of renegotiate */
-       SSLGetClientCertificateState(ctx, &pargs->certState);
-       SSLGetNegotiatedCipher(ctx, &pargs->negCipher);
-       SSLGetNegotiatedProtocolVersion(ctx, &pargs->negVersion);
-       CFRELEASE(pargs->dnList);
-       SSLCopyDistinguishedNames(ctx, &pargs->dnList);
-       
-    /* convert normal "shutdown" into zero err rtn */
-       if(ortn == errSSLClosedGraceful) {
-               ortn = noErr;
-       }
-       if((ortn == errSSLClosedNoNotify) && !pargs->requireNotify) {
-               /* relaxed disconnect rules */
-               ortn = noErr;
-       }
-cleanup:
-       /*
-        * always do close, even on error - to flush outgoing write queue 
-        */
-       OSStatus cerr = SSLClose(ctx);
-       if(ortn == noErr) {
-               ortn = cerr;
-       }
-       if(sock) {
-               endpointShutdown(sock);
-       }
-       if(ctx) {
-           SSLDisposeContext(ctx);  
-       }    
-       return ortn;
-}
-
-static void showPeerCerts(
-       CFArrayRef                      peerCerts,
-       bool                            verbose)
-{
-       CFIndex numCerts;
-       SecCertificateRef certRef;
-       OSStatus ortn;
-       CSSM_DATA certData;
-       CFIndex i;
-       
-       if(peerCerts == NULL) {
-               return;
-       }
-       numCerts = CFArrayGetCount(peerCerts);
-       for(i=0; i<numCerts; i++) {
-               certRef = (SecCertificateRef)CFArrayGetValueAtIndex(peerCerts, i);
-               ortn = SecCertificateGetData(certRef, &certData);
-               if(ortn) {
-                       printf("***SecCertificateGetData returned %d\n", (int)ortn);
-                       continue;
-               }
-               printf("\n================== Server Cert %lu ===================\n\n", i);
-               printCert(certData.Data, certData.Length, verbose);
-               printf("\n=============== End of Server Cert %lu ===============\n", i);
-       }
-}
-
-static void writePeerCerts(
-       CFArrayRef                      peerCerts,
-       const char                      *fileBase)
-{
-       CFIndex numCerts;
-       SecCertificateRef certRef;
-       OSStatus ortn;
-       CSSM_DATA certData;
-       CFIndex i;
-       char fileName[100];
-       
-       if(peerCerts == NULL) {
-               return;
-       }
-       numCerts = CFArrayGetCount(peerCerts);
-       for(i=0; i<numCerts; i++) {
-               sprintf(fileName, "%s%02d.cer", fileBase, (int)i);
-               certRef = (SecCertificateRef)CFArrayGetValueAtIndex(peerCerts, i);
-               ortn = SecCertificateGetData(certRef, &certData);
-               if(ortn) {
-                       printf("***SecCertificateGetData returned %d\n", (int)ortn);
-                       continue;
-               }
-               cspWriteFile(fileName, certData.Data, certData.Length);
-       }
-       printf("...wrote %lu certs to fileBase %s\n", numCerts, fileBase);
-}
-
-static void writeDnList(
-       CFArrayRef                      dnList,
-       const char                      *fileBase)
-{
-       CFIndex numDns;
-       CFDataRef cfDn;
-       CFIndex i;
-       char fileName[100];
-       
-       if(dnList == NULL) {
-               return;
-       }
-       numDns = CFArrayGetCount(dnList);
-       for(i=0; i<numDns; i++) {
-               sprintf(fileName, "%s%02d.der", fileBase, (int)i);
-               cfDn = (CFDataRef)CFArrayGetValueAtIndex(dnList, i);
-               cspWriteFile(fileName, CFDataGetBytePtr(cfDn), CFDataGetLength(cfDn));
-       }
-       printf("...wrote %lu RDNs to fileBase %s\n", numDns, fileBase);
-}
-
-/*
- * Show result of an sslPing().
- * Assumes the following from sslPingArgs:
- *
- *             verbose
- *             tryVersion
- *             acceptedProts
- *             negVersion
- *             negCipher
- *             peerCerts
- *             certState
- *             authType
- *             sessionWasResumed
- *             sessionID
- *             sessionIDLength
- *             handshakeTime
- */
-static void showSSLResult(
-       const sslPingArgs       &pargs,
-       OSStatus                        err,
-       bool                            displayPeerCerts,
-       const char                      *fileBase,              // non-NULL: write certs to file
-       const char                      *dnFileBase)    // non-NULL: write DNList to file
-{
-       CFIndex numPeerCerts;
-       
-       printf("\n");
-       
-       if(pargs.acceptedProts) {
-               printf("   Allowed SSL versions   : %s\n", pargs.acceptedProts);
-       }
-       else {
-               printf("   Attempted  SSL version : %s\n", 
-                       sslGetProtocolVersionString(pargs.tryVersion));
-       }
-       
-       printf("   Result                 : %s\n", sslGetSSLErrString(err));
-       printf("   Negotiated SSL version : %s\n", 
-               sslGetProtocolVersionString(pargs.negVersion));
-       printf("   Negotiated CipherSuite : %s\n",
-               sslGetCipherSuiteString(pargs.negCipher));
-       if(pargs.certState != kSSLClientCertNone) {
-               printf("   Client Cert State      : %s\n",
-                       sslGetClientCertStateString(pargs.certState));
-               printf("   Client Auth Type       : %s\n",
-                       sslGetClientAuthTypeString(pargs.authType));
-       }
-       if(pargs.verbose) {
-               printf("   Resumed Session        : ");
-               if(pargs.sessionWasResumed) {
-                       for(unsigned dex=0; dex<pargs.sessionIDLength; dex++) {
-                               printf("%02X ", pargs.sessionID[dex]);
-                               if(((dex % 8) == 7) && (dex != (pargs.sessionIDLength - 1))) {
-                                       printf("\n                            ");
-                               }
-                       }
-                       printf("\n");
-               }
-               else {
-                       printf("NOT RESUMED\n");
-               }
-               printf("   Handshake time         : %f seconds\n", pargs.handshakeTimeOp);
-       }
-       if(pargs.peerCerts == NULL) {
-               numPeerCerts = 0;
-       }
-       else {
-               numPeerCerts = CFArrayGetCount(pargs.peerCerts);
-       }
-       printf("   Number of server certs : %lu\n", numPeerCerts);
-       if(numPeerCerts != 0) {
-               if(displayPeerCerts) {
-                       showPeerCerts(pargs.peerCerts, false);
-               }
-               if(fileBase != NULL) {
-                       writePeerCerts(pargs.peerCerts, fileBase);
-               }
-       }
-       if(dnFileBase != NULL) {
-               writeDnList(pargs.dnList, dnFileBase);
-       }
-       
-       printf("\n");
-}
-
-static int verifyProtocol(
-       bool            verifyProt,
-       SSLProtocol     maxProtocol,
-       SSLProtocol     reqProtocol,
-       SSLProtocol negProtocol)
-{
-       if(!verifyProt) {
-               return 0;
-       }
-       if(reqProtocol > maxProtocol) {
-               /* known not to support this attempt, relax */
-               reqProtocol = maxProtocol;
-       }
-       if(reqProtocol != negProtocol) {
-               printf("***Expected protocol %s; negotiated %s\n",
-                       sslGetProtocolVersionString(reqProtocol),
-                       sslGetProtocolVersionString(negProtocol));
-               return 1;
-       }
-       else {
-               return 0;
-       }
-}
-
-static int verifyClientCertState(
-       bool                                            verifyCertState,
-       SSLClientCertificateState       expectState,
-       SSLClientCertificateState       gotState)
-{
-       if(!verifyCertState) {
-               return 0;
-       }
-       if(expectState == gotState) {
-               return 0;
-       }
-       printf("***Expected clientCertState %s; got %s\n",
-               sslGetClientCertStateString(expectState),
-               sslGetClientCertStateString(gotState));
-       return 1;
-}
-
-/*
- * Free everything allocated by sslPing in an sslPingArgs. 
- * Mainly for looping and malloc debugging.
- */
-static void freePingArgs(
-                                                sslPingArgs *pargs)
-{
-       freePeerCerts(pargs->peerCerts);
-       pargs->peerCerts = NULL;
-       CFRELEASE(pargs->peerTrust);
-       CFRELEASE(pargs->dnList);
-       /* more, later, for client retry/identity fetch */
-}
-
-static SSLProtocol charToProt(
-       char c,                 // 2, 3, t
-       char **argv)
-{
-       switch(c) {
-               case '2':
-                       return kSSLProtocol2;
-               case '3':
-                       return kSSLProtocol3;
-               case 't':
-                       return kTLSProtocol1;
-               default:
-                       usage(argv);
-       }
-       /* NOT REACHED */
-       return kSSLProtocolUnknown;
-}
-
-int main(int argc, char **argv)
-{   
-    OSStatus            err;
-       int                                     arg;
-       char                            *argp;
-       char                            getMsg[300];
-       char                            fullFileBase[100];
-       int                                     ourRtn = 0;                     // exit status - sum of all errors
-       unsigned                        loop;
-       SecKeychainRef          serverKc = nil;
-       SecKeychainRef          encryptKc = nil;
-       sslPingArgs                     pargs;
-       
-       /* user-spec'd parameters */
-       char                            *getPath = (char *)DEFAULT_PATH;
-       char                            *fileBase = NULL;
-       bool                            displayCerts = false;
-       bool                            doSslV2 = false;
-       bool                            doSslV3 = false;
-       bool                            doTlsV1 = true;
-       bool                            protXOnly = false;      // kSSLProtocol3Only, kTLSProtocol1Only
-       bool                            doProtUnknown = false;
-       unsigned                        loopCount = 1;
-       bool                            doPause = false;
-       bool                            pauseFirstLoop = false;
-       bool                            verifyProt = false;
-       SSLProtocol                     maxProtocol = kTLSProtocol1;    // for verifying negotiated 
-                                                                                                               // protocol
-       char                            *acceptedProts = NULL;
-       char                            *keyChainName = NULL;
-       char                            *encryptKeyChainName = NULL;
-       char                            *getMsgSpec = NULL;
-       bool                            vfyCertState = false;
-       SSLClientCertificateState expectCertState;
-       bool                            displayHandshakeTimes = false;
-       bool                            completeCertChain = false;
-       char                            *dnFileBase = NULL;
-
-       /* special case - one arg of "h" or "-h" or "hv" */
-       if(argc == 2) {
-           if((strcmp(argv[1], "h") == 0) || (strcmp(argv[1], "-h") == 0)) {
-                       usage(argv);
-               }
-               if(strcmp(argv[1], "hv") == 0) {
-                       usageVerbose(argv);
-               }
-       }
-       
-       /* set up defaults */
-       memset(&pargs, 0, sizeof(sslPingArgs));
-       pargs.hostName = DEFAULT_HOST;
-       pargs.port = DEFAULT_PORT;
-       pargs.resumableEnable = true;
-       pargs.argv = argv;
-       
-       for(arg=1; arg<argc; arg++) {
-               argp = argv[arg];
-               if(arg == 1) {
-                       /* first arg, is always hostname; '-' means default */
-                       if(argp[0] != '-') {
-                               pargs.hostName = argp;
-                       }
-                       continue;
-               }
-               if(argp[0] == '/') {
-                       /* path always starts with leading slash */
-                       getPath = argp;
-                       continue;
-               }
-               /* options */
-               switch(argp[0]) {
-                       case 'e':
-                               pargs.allowExpired = true;
-                               break;
-                       case 'E':
-                               pargs.allowExpiredRoot = true;
-                               break;
-                       case 'x':
-                               pargs.disableCertVerify = true;
-                               break;
-                       case 'M':
-                               pargs.disableCertVerify = true; // implied
-                               pargs.manualCertVerify = true;
-                               break;
-                       case 'I':
-                               pargs.interactiveAuth = true;
-                               break;
-                       case 'a':
-                               if(++arg == argc)  {
-                                       /* requires another arg */
-                                       usage(argv);
-                               }
-                               pargs.anchorFile = argv[arg];
-                               break;
-                       case 'A':
-                               if(++arg == argc)  {
-                                       /* requires another arg */
-                                       usage(argv);
-                               }
-                               pargs.anchorFile = argv[arg];
-                               pargs.replaceAnchors = true;
-                               break;
-                       case 'Z':
-                               if(++arg == argc)  {
-                                       /* requires another arg */
-                                       usage(argv);
-                               }
-                               pargs.trustedLeafFile = argv[arg];
-                               break;
-                       case 'r':
-                               pargs.allowAnyRoot = true;
-                               break;
-                       case 'd':
-                               pargs.dumpRxData = true;
-                               break;
-                       case 'c':
-                               displayCerts = true;
-                               break;
-                       case 'f':
-                               if(++arg == argc)  {
-                                       /* requires another arg */
-                                       usage(argv);
-                               }
-                               fileBase = argv[arg];
-                               break;
-                       case 'C':
-                               pargs.cipherRestrict = argp[2];
-                               break;
-                       case 'S':
-                               pargs.showCipherSuites = true;
-                               break;
-                       case '2':
-                               doSslV3 = doTlsV1 = false;
-                               doSslV2 = true;
-                               break;
-                       case '3':
-                               doSslV2 = doTlsV1 = false;
-                               doSslV3 = true;
-                               break;
-                       case 't':
-                               /* currently the default... */
-                               doSslV2 = doSslV3 = false;
-                               doTlsV1 = true;
-                               break;
-                       case 'L':
-                               doSslV2 = doSslV3 = doTlsV1 = true;
-                               break;
-                       case 'o':
-                               protXOnly = true;
-                               break;
-                       case 'u':
-                               doSslV2 = doSslV3 = doTlsV1 = false;
-                               doProtUnknown = true;
-                               break;
-                       case 'K':
-                               pargs.keepConnected = true;
-                               break;
-                       case 'n':
-                               pargs.requireNotify = true;
-                               pargs.keepConnected = true;
-                               break;
-                       case 'R':
-                               pargs.resumableEnable = false;
-                               break;
-                       case 'b':
-                               pargs.nonBlocking = true;
-                               break;
-                       case 'v':
-                               verifyProt = true;
-                               break;
-                       case 'm':
-                               if(argp[1] != '=') {
-                                       usage(argv);
-                               }
-                               verifyProt = true;              // implied
-                               maxProtocol = charToProt(argp[2], argv);
-                               break;
-                       case 'g':
-                               if(argp[1] != '=') {
-                                       usage(argv);
-                               }
-                               acceptedProts = &argp[2];
-                               doSslV3 = doSslV2 = doTlsV1 = false;
-                               break;
-                       case 'l':
-                               loopCount = atoi(&argp[2]);
-                               if(loopCount == 0) {
-                                       printf("***bad loopCount\n");
-                                       usage(argv);
-                               }
-                               break;
-                       case 'P':
-                               pargs.port = atoi(&argp[2]);
-                               break;
-                       case 'H':
-                               pargs.allowHostnameSpoof = true;
-                               break;
-                       case 'F':
-                               pargs.vfyHostName = &argp[2];
-                               break;
-                       case 'k':
-                               keyChainName = &argp[2];
-                               break;
-                       case 'y':
-                               encryptKeyChainName = &argp[2];
-                               break;
-                       case 'G':
-                               getMsgSpec = &argp[2];
-                               break;
-                       case 'T':
-                               if(argp[1] != '=') {
-                                       usage(argv);
-                               }
-                               vfyCertState = true;
-                               switch(argp[2]) {
-                                       case 'n':
-                                               expectCertState = kSSLClientCertNone;
-                                               break;
-                                       case 'r':
-                                               expectCertState = kSSLClientCertRequested;
-                                               break;
-                                       case 's':
-                                               expectCertState = kSSLClientCertSent;
-                                               break;
-                                       case 'j':
-                                               expectCertState = kSSLClientCertRejected;
-                                               break;
-                                       default:
-                                               usage(argv);
-                               }
-                               break;
-                       case 'z':
-                               pargs.password = &argp[2];
-                               break;
-                       case 'p':
-                               doPause = true;
-                               break;
-                       case '7':
-                               pauseFirstLoop = true;
-                               break;
-                       case 'q':
-                               pargs.quiet = true;
-                               break;
-                       case 'V':
-                               pargs.verbose = true;
-                               break;
-                       case 's':
-                               pargs.silent = pargs.quiet = true;
-                               break;
-                       case 'N':
-                               displayHandshakeTimes = true;
-                               break;
-                       case '8':
-                               completeCertChain = true;
-                               break;
-                       case 'i':
-                               pargs.sessionCacheTimeout = atoi(&argp[2]);
-                               break;
-                       case '4':
-                               pargs.disableAnonCiphers = true;
-                               break;
-                       case 'D':
-                               if(++arg == argc)  {
-                                       /* requires another arg */
-                                       usage(argv);
-                               }
-                               dnFileBase = argv[arg];
-                               break;
-                       case 'h':
-                               if(pargs.verbose || (argp[1] == 'v')) {
-                                       usageVerbose(argv);
-                               }
-                               else {
-                                       usage(argv);
-                               }
-                       default:
-                               usage(argv);
-               }
-       }
-       if(getMsgSpec) {
-               pargs.getMsg = getMsgSpec;
-       }
-       else {
-               sprintf(getMsg, "%s %s %s", 
-                       DEFAULT_GETMSG, getPath, DEFAULT_GET_SUFFIX);
-               pargs.getMsg = getMsg;
-       }
-                       
-       /* get client cert and optional encryption cert as CFArrayRef */
-       if(keyChainName) {
-               pargs.clientCerts = getSslCerts(keyChainName, false, completeCertChain,
-                       pargs.anchorFile, &serverKc);
-               if(pargs.clientCerts == nil) {
-                       exit(1);
-               }
-               if(pargs.password) {
-                       OSStatus ortn = SecKeychainUnlock(serverKc, 
-                               strlen(pargs.password), pargs.password, true);
-                       if(ortn) {
-                               printf("SecKeychainUnlock returned %d\n", (int)ortn);
-                               /* oh well */
-                       }
-               }
-       }
-       if(encryptKeyChainName) {
-               pargs.encryptClientCerts = getSslCerts(encryptKeyChainName, true, 
-                               completeCertChain, pargs.anchorFile, &encryptKc);
-               if(pargs.encryptClientCerts == nil) {
-                       exit(1);
-               }
-       }
-       signal(SIGPIPE, sigpipe);
-
-       if(loopCount != 0) {
-               /* prepare to handle KC callbacks for root cert cache invalidation */
-               if(startCFRunLoop()) {
-                       exit(1);
-               }
-
-               /* give that thread a chance right now */
-               while(!runLoopInitialized) {
-                       usleep(1000);
-               };
-       }
-
-       if(doPause) {
-               char resp;
-               fpurge(stdin);
-               printf("Before main loop. Hit a to abort, c to continue: ");
-               resp = getchar();
-               if(resp == 'a') {
-                       exit(1);
-               }
-       }
-
-       for(loop=0; loop<loopCount; loop++) {
-               /* 
-                * One pass for each protocol version, skipping any explicit version if
-                * an attempt at a higher version and succeeded in doing so successfully fell
-                * back.
-                */
-               if(doTlsV1) {
-                       pargs.tryVersion = 
-                               protXOnly ? kTLSProtocol1Only : kTLSProtocol1;
-                       pargs.acceptedProts = NULL;
-                       if(!pargs.silent) {
-                               printf("Connecting to host %s with TLS V1...\n", pargs.hostName); 
-                       }
-                       fflush(stdout);
-                       err = sslPing(&pargs);
-                       if(err) {
-                               ourRtn++;
-                       }
-                       if(!pargs.quiet) {
-                               if(fileBase) {
-                                       sprintf(fullFileBase, "%s_v3.1", fileBase);
-                               }
-                               showSSLResult(pargs,
-                                       err, 
-                                       displayCerts,
-                                       fileBase ? fullFileBase : NULL,
-                                       dnFileBase);
-                       }
-                       freePingArgs(&pargs);
-                       if(!err) {
-                               /* deal with fallbacks, skipping redundant tests */
-                               switch(pargs.negVersion) {
-                                       case kSSLProtocol3:
-                                               doSslV3 = false;
-                                               break;
-                                       case kSSLProtocol2:
-                                               doSslV3 = false;
-                                               doSslV2 = false;
-                                               break;
-                                       default:
-                                               break;
-                               }
-                               ourRtn += verifyProtocol(verifyProt, maxProtocol, kTLSProtocol1,
-                                       pargs.negVersion);
-                       }
-                       /* note we do this regardless since the client state might be
-                        * the cause of a failure */
-                       ourRtn += verifyClientCertState(vfyCertState, expectCertState,
-                               pargs.certState);
-               }
-               if(doSslV3) {
-                       pargs.tryVersion = protXOnly ? kSSLProtocol3Only : kSSLProtocol3;
-                       pargs.acceptedProts = NULL;
-                       if(!pargs.silent) {
-                               printf("Connecting to host %s with SSL V3...\n", pargs.hostName); 
-                       }
-                       fflush(stdout);
-                       err = sslPing(&pargs);
-                       if(err) {
-                               ourRtn++;
-                       }
-                       if(!pargs.quiet) {
-                               if(fileBase) {
-                                       sprintf(fullFileBase, "%s_v3.0", fileBase);
-                               }
-                               showSSLResult(pargs,
-                                       err, 
-                                       displayCerts,
-                                       fileBase ? fullFileBase : NULL,
-                                       dnFileBase);
-                       }
-                       freePingArgs(&pargs);
-                       if(!err) {
-                               /* deal with fallbacks, skipping redundant tests */
-                               switch(pargs.negVersion) {
-                                       case kSSLProtocol2:
-                                               doSslV2 = false;
-                                               break;
-                                       default:
-                                               break;
-                               }
-                               ourRtn += verifyProtocol(verifyProt, maxProtocol, kSSLProtocol3,
-                                       pargs.negVersion);
-                       }
-                       /* note we do this regardless since the client state might be
-                        * the cause of a failure */
-                       ourRtn += verifyClientCertState(vfyCertState, expectCertState,
-                               pargs.certState);
-               }
-               
-               if(doSslV2) {
-                       if(fileBase) {
-                               sprintf(fullFileBase, "%s_v2", fileBase);
-                       }
-                       if(!pargs.silent) {
-                               printf("Connecting to host %s with SSL V2...\n", pargs.hostName);
-                       }
-                       fflush(stdout);
-                       pargs.tryVersion = kSSLProtocol2;
-                       pargs.acceptedProts = NULL;
-                       err = sslPing(&pargs);
-                       if(err) {
-                               ourRtn++;
-                       }
-                       if(!pargs.quiet) {
-                               if(fileBase) {
-                                       sprintf(fullFileBase, "%s_v2", fileBase);
-                               }
-                               showSSLResult(pargs,
-                                       err, 
-                                       displayCerts,
-                                       fileBase ? fullFileBase : NULL,
-                                       dnFileBase);
-                       }
-                       freePingArgs(&pargs);   
-                       if(!err) {
-                               ourRtn += verifyProtocol(verifyProt, maxProtocol, kSSLProtocol2,
-                                       pargs.negVersion);
-                       }
-                       /* note we do this regardless since the client state might be
-                        * the cause of a failure */
-                       ourRtn += verifyClientCertState(vfyCertState, expectCertState,
-                               pargs.certState);
-               }
-               if(doProtUnknown) {
-                       if(!pargs.silent) {
-                               printf("Connecting to host %s with kSSLProtocolUnknown...\n", 
-                                       pargs.hostName); 
-                       }
-                       fflush(stdout);
-                       pargs.tryVersion = kSSLProtocolUnknown;
-                       pargs.acceptedProts = NULL;
-                       err = sslPing(&pargs);
-                       if(err) {
-                               ourRtn++;
-                       }
-                       if(!pargs.quiet) {
-                               if(fileBase) {
-                                       sprintf(fullFileBase, "%s_def", fileBase);
-                               }
-                               showSSLResult(pargs,
-                                       err, 
-                                       displayCerts,
-                                       fileBase ? fullFileBase : NULL,
-                                       dnFileBase);
-                       }
-                       freePingArgs(&pargs);
-               }
-               if(acceptedProts != NULL) {
-                       pargs.acceptedProts = acceptedProts;
-                       pargs.tryVersion = kSSLProtocolUnknown; // not used
-                       if(!pargs.silent) {
-                               printf("Connecting to host %s with acceptedProts %s...\n", 
-                                       pargs.hostName, pargs.acceptedProts); 
-                       }
-                       fflush(stdout);
-                       err = sslPing(&pargs);
-                       if(err) {
-                               ourRtn++;
-                       }
-                       if(!pargs.quiet) {
-                               if(fileBase) {
-                                       sprintf(fullFileBase, "%s_def", fileBase);
-                               }
-                               showSSLResult(pargs,
-                                       err, 
-                                       displayCerts,
-                                       fileBase ? fullFileBase : NULL,
-                                       dnFileBase);
-                       }
-                       freePingArgs(&pargs);
-               }
-               if(doPause || 
-                     (pauseFirstLoop && 
-                                /* pause after first, before last to grab trace */
-                        ((loop == 0) || (loop == loopCount - 1))
-                         )
-                  ) {
-                       char resp;
-                       fpurge(stdin);
-                       printf("a to abort, c to continue: ");
-                       resp = getchar();
-                       if(resp == 'a') {
-                               break;
-                       }
-               }
-    }  /* main loop */
-       if(displayHandshakeTimes) {
-               CFAbsoluteTime totalTime;
-               unsigned numHandshakes;
-               if(pargs.numHandshakes == 1) {
-                       /* just display the first one */
-                       totalTime = pargs.handshakeTimeFirst;
-                       numHandshakes = 1;
-               }
-               else {
-                       /* skip the first one */
-                       totalTime = pargs.handshakeTimeTotal;
-                       numHandshakes = pargs.numHandshakes - 1;
-               }
-               if(numHandshakes != 0) {
-                       printf("   %u handshakes in %f seconds; %f seconds per handshake\n",
-                               numHandshakes, totalTime,
-                               (totalTime / numHandshakes));
-               }
-       }
-       printCertShutdown();
-       if(ourRtn) {
-               printf("===%s exiting with %d %s for host %s\n", argv[0], ourRtn, 
-                       (ourRtn > 1) ? "errors" : "error", pargs.hostName);
-       }
-    return ourRtn;
-
-}
-
-