2  * Copyright (c) 2008-2013 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25  * Trivial SSL server example, using SecureTransport / OS X version. 
  27  * Written by Doug Mitchell.  
  29 #include <Security/SecureTransport.h> 
  30 #include <Security/SecureTransportPriv.h> 
  31 #include "sslAppUtils.h" 
  33 #include "utilities/fileIo.h" 
  35 #include <Security/SecBase.h> 
  42 #include <sys/param.h> 
  44 #include <Security/Security.h> 
  45 #include <Security/SecCertificatePriv.h> 
  47 #include <CoreFoundation/CoreFoundation.h> 
  48 #include "SecurityTool/print_cert.h" 
  51 #include <securityd/spi.h> 
  54 /* Set true when PR-3074739 is merged to TOT */ 
  55 #define SET_DH_PARAMS_ENABLE            1 
  57 /* true when using SSLCopyPeerCertificates() per Radar 3311892 */ 
  58 #define USE_COPY_PEER_CERTS             1 
  61  * Defaults, overridable by user.  
  63 #define SERVER_MESSAGE  "HTTP/1.0 200 OK\015\012Content-Type: text/html\015\012\015\012" \ 
  64         "<HTML><HEAD><TITLE>SecureTransport Test Server</TITLE></HEAD>" \ 
  65         "<BODY><H2>Secure connection established.</H2>" \ 
  66         "Message from the 'sslServer' sample application.\015\012</BODY>" \ 
  69 /* For ease of debugging, pick a non-privileged port */ 
  70 #define DEFAULT_PORT     1200 
  71 // #define DEFAULT_PORT     443 
  73 #define DEFAULT_HOST    "localhost" 
  75 #define DEFAULT_KC              "certkc" 
  77 static void usage(char **argv
) 
  79     printf("Usage: %s [option ...]\n", argv
[0]); 
  81         printf("   P=port      Port to listen on; default is %d\n", DEFAULT_PORT
); 
  82         printf("   k=keychain  Contains server cert and keys.\n"); 
  83         printf("   y=keychain  Encryption-only cert and keys.\n"); 
  84     printf("   e           Allow Expired Certs\n"); 
  85     printf("   r           Allow any root cert\n"); 
  86     printf("   E           Allow Expired Roots\n"); 
  87         printf("   x           Disable Cert Verification\n"); 
  88         printf("   f=fileBase  Write Peer Certs to fileBase*\n"); 
  89         printf("   c           Display peer certs\n"); 
  90         printf("   d           Display received data\n"); 
  91         printf("   C=cipherSuite (e=40-bit d=DES D=40-bit DES 3=3DES 4=RC4 $=40-bit RC4\n" 
  92                    "                  2=RC2 a=AES128 A=AES256 h=DH H=Anon DH r=DHE/RSA s=DH/DSS\n" 
  94         printf("   2           SSLv2 only (default is best fit)\n"); 
  95         printf("   3           SSLv3 only (default is best fit)\n"); 
  96         printf("   t           TLSv1 only (default is best fit)\n"); 
  97         printf("   o           TLSv1, SSLv3 use kSSLProtocol__X__Only\n"); 
  98         printf("   g={prot...} Specify legal protocols; prot = any combo of [23t]\n"); 
  99         printf("   T=[nrsj]    Verify client cert state = " 
 100                                                         "none/requested/sent/rejected\n"); 
 101         printf("   R           Disable resumable session support\n"); 
 102         printf("   i=timeout   Session cache timeout\n"); 
 103         printf("   u=[nat]     Authentication: n=never; a=always; t=try\n"); 
 104         printf("   b           Non-blocking I/O\n"); 
 105         printf("   a fileNmae  Add fileName to list of trusted roots\n"); 
 106         printf("   A fileName  fileName is ONLY trusted root\n"); 
 107         printf("   U filename  Add filename to acceptable DNList (multiple times OK)\n"); 
 108         printf("   D filename  Diffie-Hellman parameters from filename\n"); 
 109         printf("   z=password  Unlock server keychain with password.\n"); 
 110         printf("   H           Do SecIndentityRef search instead of specific keychain\n"); 
 111         printf("   M           Complete cert chain (default assumes that our identity is root)\n"); 
 112         printf("   4           Disable anonymous ciphers\n"); 
 113         printf("   p           Pause after each phase\n"); 
 114         printf("   l[=loops]   Loop, performing multiple transactions\n"); 
 115         printf("   q           Quiet/diagnostic mode (site names and errors only)\n"); 
 120 /* snag a copy of current connection's peer certs so we can  
 121  * examine them later after the connection is closed */ 
 122 static OSStatus 
copyPeerCerts( 
 124         CFArrayRef      
*peerCerts
)             // mallocd & RETURNED 
 126         #if USE_COPY_PEER_CERTS 
 127         OSStatus ortn 
= SSLCopyPeerCertificates(ctx
, peerCerts
); 
 129         OSStatus ortn 
= SSLGetPeerCertificates(ctx
, peerCerts
); 
 132                 printf("***Error obtaining peer certs: %s\n", 
 133                         sslGetSSLErrString(ortn
)); 
 138 /* free the cert array obtained via SSLGetPeerCertificates() */ 
 139 static void     freePeerCerts( 
 140         CFArrayRef                      peerCerts
) 
 142         if(peerCerts 
== NULL
) { 
 146         #if USE_COPY_PEER_CERTS 
 148         /* Voila! Problem fixed. */ 
 149         CFRelease(peerCerts
); 
 155         SecCertificateRef certData
; 
 158         numCerts 
= CFArrayGetCount(peerCerts
); 
 159         for(i
=0; i
<numCerts
; i
++) { 
 160                 certData 
= (SecCertificateRef
)CFArrayGetValueAtIndex(peerCerts
, i
); 
 163         CFRelease(peerCerts
); 
 167 /* print reply received from server */ 
 168 static void dumpAscii( 
 172         char *cp 
= (char *)rcvBuf
; 
 176         for(i
=0; i
<len
; i
++) { 
 189                                 if(isprint(c
) && (c 
!= '\n')) { 
 193                                         printf("<%02X>", ((unsigned)c
) & 0xff); 
 202 static void doPause(const char *prompt
) {        
 204                 printf("%s. ", prompt
); 
 207         printf("Continue (n/anything)? "); 
 215  * Perform one SSL diagnostic server-side session. Returns nonzero on error.  
 216  * Normally no output to stdout except initial "waiting for connection" message,  
 217  * unless there is a really screwed up error (i.e., something not directly related  
 218  * to the SSL connection).  
 220 #define RCV_BUF_SIZE            256 
 222 static OSStatus 
sslServe( 
 224         unsigned short                  portNum
, 
 225         SSLProtocol                             tryVersion
,                     // only used if acceptedProts NULL 
 226         const char                              *acceptedProts
, 
 227         CFArrayRef                              serverCerts
,            // required 
 228         char                                    *password
,                      // optional 
 231         bool                            allowExpiredRoot
, 
 232         bool                            disableCertVerify
, 
 235         char                                    cipherRestrict
,         // '2', 'd'. etc...'\0' for no 
 237         SSLAuthenticate                 authenticate
, 
 238         unsigned char                   *dhParams
,                      // optional D-H parameters       
 239         unsigned                                dhParamsLen
, 
 240         CFArrayRef                              acceptableDNList
,       // optional  
 241         bool                            resumableEnable
, 
 242         uint32_t                                        sessionCacheTimeout
,// optional 
 243         bool                            disableAnonCiphers
, 
 244         bool                            silent
,                         // no stdout 
 246         SSLProtocol                             
*negVersion
,            // RETURNED 
 247         SSLCipherSuite                  
*negCipher
,                     // RETURNED 
 248         SSLClientCertificateState 
*certState
,           // RETURNED 
 249         Boolean                                 
*sessionWasResumed
,     // RETURNED 
 250         unsigned char                   *sessionID
,                     // mallocd by caller, RETURNED 
 251         size_t                                  *sessionIDLength
,       // RETURNED 
 252         CFArrayRef                              
*peerCerts
,                     // mallocd & RETURNED 
 258     SSLContextRef       ctx 
= NULL
; 
 260     uint8_t             rcvBuf
[RCV_BUF_SIZE
]; 
 261         const char *outMsg 
= SERVER_MESSAGE
; 
 263     *negVersion 
= kSSLProtocolUnknown
; 
 264     *negCipher 
= SSL_NULL_WITH_NULL_NULL
; 
 268         signal(SIGPIPE
, sigpipe
); 
 271         /* first wait for a connection */ 
 273                 printf("Waiting for client connection on port %u...", portNum
); 
 276         ortn 
= AcceptClientConnection(listenSock
, &acceptSock
, &peerId
); 
 278         printf("AcceptClientConnection returned %d; aborting\n", (int)ortn
); 
 283          * Set up a SecureTransport session. 
 284          * First the standard calls. 
 286         ortn 
= SSLNewContext(true, &ctx
); 
 288                 printSslErrStr("SSLNewContext", ortn
); 
 291         ortn 
= SSLSetIOFuncs(ctx
, SocketRead
, SocketWrite
); 
 293                 printSslErrStr("SSLSetIOFuncs", ortn
); 
 296         ortn 
= SSLSetConnection(ctx
, (SSLConnectionRef
)(intptr_t)acceptSock
); 
 298                 printSslErrStr("SSLSetConnection", ortn
); 
 302         /* have to do these options befor setting server certs */ 
 304                 ortn 
= SSLSetAllowsExpiredCerts(ctx
, true); 
 306                         printSslErrStr("SSLSetAllowExpiredCerts", ortn
); 
 311                 ortn 
= SSLSetAllowsAnyRoot(ctx
, true); 
 313                         printSslErrStr("SSLSetAllowAnyRoot", ortn
); 
 319                 ortn 
= sslAddTrustedRoot(ctx
, anchorFile
, replaceAnchors
); 
 321                         printf("***Error obtaining anchor file %s\n", anchorFile
); 
 325         if(serverCerts 
!= NULL
) { 
 326                 if(anchorFile 
== NULL
) { 
 327                         /* no specific anchors, so assume we want to trust this one */ 
 328                         ortn 
= addIdentityAsTrustedRoot(ctx
, serverCerts
); 
 333                 ortn 
= SSLSetCertificate(ctx
, serverCerts
); 
 335                         printSslErrStr("SSLSetCertificate", ortn
); 
 339         if(allowExpiredRoot
) { 
 340                 ortn 
= SSLSetAllowsExpiredRoots(ctx
, true); 
 342                         printSslErrStr("SSLSetAllowsExpiredRoots", ortn
); 
 346         if(disableCertVerify
) { 
 347                 ortn 
= SSLSetEnableCertVerify(ctx
, false); 
 349                         printSslErrStr("SSLSetEnableCertVerify", ortn
); 
 355          * SecureTransport options. 
 358                 ortn 
= SSLSetProtocolVersionEnabled(ctx
, kSSLProtocolAll
, false); 
 360                         printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn
); 
 363                 for(const char *cp 
= acceptedProts
; *cp
; cp
++) { 
 364                         SSLProtocol prot 
= kSSLProtocolUnknown
; 
 367                                         prot 
= kSSLProtocol2
; 
 370                                         prot 
= kSSLProtocol3
; 
 373                                         prot 
= kTLSProtocol1
; 
 378                         ortn 
= SSLSetProtocolVersionEnabled(ctx
, prot
, true); 
 380                                 printSslErrStr("SSLSetProtocolVersionEnabled", ortn
); 
 386                 ortn 
= SSLSetProtocolVersion(ctx
, tryVersion
); 
 388                         printSslErrStr("SSLSetProtocolVersion", ortn
); 
 392         if(resumableEnable
) { 
 393                 ortn 
= SSLSetPeerID(ctx
, &peerId
, sizeof(PeerSpec
)); 
 395                         printSslErrStr("SSLSetPeerID", ortn
); 
 399         if(cipherRestrict 
!= '\0') { 
 400                 ortn 
= sslSetCipherRestrictions(ctx
, cipherRestrict
); 
 405         if(authenticate 
!= kNeverAuthenticate
) { 
 406                 ortn 
= SSLSetClientSideAuthenticate(ctx
, authenticate
); 
 408                         printSslErrStr("SSLSetClientSideAuthenticate", ortn
); 
 413                 ortn 
= SSLSetDiffieHellmanParams(ctx
, dhParams
, dhParamsLen
); 
 415                         printSslErrStr("SSLSetDiffieHellmanParams", ortn
); 
 419         if(sessionCacheTimeout
) { 
 420                 ortn 
= SSLSetSessionCacheTimeout(ctx
, sessionCacheTimeout
); 
 422                         printSslErrStr("SSLSetSessionCacheTimeout", ortn
); 
 426         if(disableAnonCiphers
) { 
 427                 ortn 
= SSLSetAllowAnonymousCiphers(ctx
, false); 
 429                         printSslErrStr("SSLSetAllowAnonymousCiphers", ortn
); 
 432                 /* quickie test of the getter */ 
 434                 ortn 
= SSLGetAllowAnonymousCiphers(ctx
, &e
); 
 436                         printSslErrStr("SSLGetAllowAnonymousCiphers", ortn
); 
 440                         printf("***SSLGetAllowAnonymousCiphers() returned true; expected false\n"); 
 446         if(acceptableDNList) { 
 447                 ortn = SSLSetCertificateAuthorities(ctx, acceptableDNList, TRUE); 
 449                         printSslErrStr("SSLSetCertificateAuthorities", ortn); 
 457                 doPause("SSLContext initialized"); 
 460         /* Perform SSL/TLS handshake */ 
 462     {   ortn 
= SSLHandshake(ctx
); 
 463             if((ortn 
== errSSLWouldBlock
) && !silent
) { 
 464                 /* keep UI responsive */  
 467     } while (ortn 
== errSSLWouldBlock
); 
 469         /* this works even if handshake failed due to cert chain invalid */ 
 470         copyPeerCerts(ctx
, peerCerts
); 
 472         SSLGetClientCertificateState(ctx
, certState
); 
 473         SSLGetNegotiatedCipher(ctx
, negCipher
); 
 474         SSLGetNegotiatedProtocolVersion(ctx
, negVersion
); 
 475         *sessionIDLength 
= MAX_SESSION_ID_LENGTH
; 
 476         SSLGetResumableSessionInfo(ctx
, sessionWasResumed
, sessionID
, 
 486                 doPause("SSLContext handshake complete"); 
 489         /* wait for one complete line or user says they've had enough */ 
 490         while(ortn 
== errSecSuccess
) { 
 491             length 
= sizeof(rcvBuf
); 
 492             ortn 
= SSLRead(ctx
, rcvBuf
, length
, &length
); 
 494                 /* keep UI responsive */  
 498                 /* print what we have */ 
 499                 printf("client request: "); 
 500                 dumpAscii(rcvBuf
, length
); 
 503                 /* allow user to bail */ 
 507                 printf("\nMore client request (y/anything): "); 
 514             /* poor person's line completion scan */ 
 515             for(unsigned i
=0; i
<length
; i
++) { 
 516                 if((rcvBuf
[i
] == '\n') || (rcvBuf
[i
] == '\r')) { 
 517                         /* a labelled break would be nice here.... */ 
 521             if (ortn 
== errSSLWouldBlock
) { 
 522                 ortn 
= errSecSuccess
; 
 528                 doPause("Client GET msg received"); 
 531         /* send out canned response */ 
 532         length 
= strlen(outMsg
); 
 533         ortn 
= SSLWrite(ctx
, outMsg
, length
, &length
); 
 535                 printSslErrStr("SSLWrite", ortn
); 
 538                 doPause("Server response sent"); 
 542          * always do close, even on error - to flush outgoing write queue  
 544         OSStatus cerr 
= SSLClose(ctx
); 
 545         if(ortn 
== errSecSuccess
) { 
 549                 endpointShutdown(acceptSock
); 
 552             SSLDisposeContext(ctx
);   
 554         /* FIXME - dispose of serverCerts */ 
 558 static void showPeerCerts( 
 559         CFArrayRef                      peerCerts
, 
 563         SecCertificateRef certRef
; 
 566         if(peerCerts 
== NULL
) { 
 569         numCerts 
= CFArrayGetCount(peerCerts
); 
 570         for(i
=0; i
<numCerts
; i
++) { 
 571                 certRef 
= (SecCertificateRef
)CFArrayGetValueAtIndex(peerCerts
, i
); 
 572                 printf("\n================== Server Cert %lu ===================\n\n", i
); 
 573         print_cert(certRef
, verbose
); 
 574                 printf("\n=============== End of Server Cert %lu ===============\n", i
); 
 578 static void writePeerCerts( 
 579         CFArrayRef                      peerCerts
, 
 580         const char                      *fileBase
) 
 583         SecCertificateRef certRef
; 
 587         if(peerCerts 
== NULL
) { 
 590         numCerts 
= CFArrayGetCount(peerCerts
); 
 591         for(i
=0; i
<numCerts
; i
++) { 
 592                 sprintf(fileName
, "%s%02d.cer", fileBase
, (int)i
); 
 593                 certRef 
= (SecCertificateRef
)CFArrayGetValueAtIndex(peerCerts
, i
); 
 594                 writeFileSizet(fileName
, SecCertificateGetBytePtr(certRef
), 
 595                         SecCertificateGetLength(certRef
)); 
 597         printf("...wrote %lu certs to fileBase %s\n", numCerts
, fileBase
); 
 600 static void showSSLResult( 
 601         SSLProtocol                     tryVersion
, 
 604         SSLProtocol                     negVersion
, 
 605         SSLCipherSuite          negCipher
, 
 606         Boolean                         sessionWasResumed
,       
 607         unsigned char           *sessionID
,                      
 608         size_t                          sessionIDLength
,         
 609         CFArrayRef                      peerCerts
, 
 610         bool                    displayPeerCerts
, 
 611         SSLClientCertificateState       certState
, 
 612         char                            *fileBase
)              // non-NULL: write certs to file 
 614         CFIndex numPeerCerts
; 
 618                 printf("   Allowed SSL versions   : %s\n", acceptedProts
); 
 621                 printf("   Attempted  SSL version : %s\n",  
 622                         sslGetProtocolVersionString(tryVersion
)); 
 624         printf("   Result                 : %s\n", sslGetSSLErrString(err
)); 
 625         printf("   Negotiated SSL version : %s\n",  
 626                 sslGetProtocolVersionString(negVersion
)); 
 627         printf("   Negotiated CipherSuite : %s\n", 
 628                 sslGetCipherSuiteString(negCipher
)); 
 629         if(certState 
!= kSSLClientCertNone
) { 
 630                 printf("   Client Cert State      : %s\n", 
 631                         sslGetClientCertStateString(certState
)); 
 633         printf("   Resumed Session        : "); 
 634         if(sessionWasResumed
) { 
 635                 for(unsigned dex
=0; dex
<sessionIDLength
; dex
++) { 
 636                         printf("%02X ", sessionID
[dex
]); 
 637                         if(((dex 
% 8) == 7) && (dex 
!= (sessionIDLength 
- 1))) { 
 644                 printf("NOT RESUMED\n"); 
 646         if(peerCerts 
== NULL
) { 
 650                 numPeerCerts 
= CFArrayGetCount(peerCerts
); 
 652         printf("   Number of peer certs : %lu\n", numPeerCerts
); 
 653         if(numPeerCerts 
!= 0) { 
 654                 if(displayPeerCerts
) { 
 655                         showPeerCerts(peerCerts
, false); 
 657                 if(fileBase 
!= NULL
) { 
 658                         writePeerCerts(peerCerts
, fileBase
); 
 664 static int verifyClientCertState( 
 665         bool                                    verifyCertState
, 
 666         SSLClientCertificateState       expectState
, 
 667         SSLClientCertificateState       gotState
) 
 669         if(!verifyCertState
) { 
 672         if(expectState 
== gotState
) { 
 675         printf("***Expected clientCertState %s; got %s\n", 
 676                 sslGetClientCertStateString(expectState
), 
 677                 sslGetClientCertStateString(gotState
)); 
 681 int main(int argc
, char **argv
) 
 685         char                            fullFileBase
[100]; 
 686         SSLProtocol                     negVersion
; 
 687         SSLCipherSuite          negCipher
; 
 688         Boolean                         sessionWasResumed
; 
 689         unsigned char           sessionID
[MAX_SESSION_ID_LENGTH
]; 
 690         size_t                          sessionIDLength
; 
 691         CFArrayRef                      peerCerts 
= NULL
;                
 694         CFArrayRef                      serverCerts 
= nil
;              // required 
 695         SecKeychainRef          serverKc 
= nil
; 
 698         SSLClientCertificateState certState
;            // obtained from sslServe 
 700         /* user-spec'd parameters */ 
 701         unsigned short          portNum 
= DEFAULT_PORT
; 
 702         bool                    allowExpired 
= false; 
 703         bool                    allowAnyRoot 
= false; 
 704         char                            *fileBase 
= NULL
; 
 705         bool                    displayCerts 
= false; 
 706         char                            cipherRestrict 
= '\0'; 
 707         SSLProtocol                     attemptProt 
= kTLSProtocol1
; 
 708         bool                    protXOnly 
= false;      // kSSLProtocol3Only,  
 710         char                            *acceptedProts 
= NULL
;  // "23t" ==> SSLSetProtocolVersionEnabled 
 712         bool                    resumableEnable 
= true; 
 714         char                            *keyChainName 
= NULL
; 
 716         SSLAuthenticate         authenticate 
= kNeverAuthenticate
; 
 717         bool                    nonBlocking 
= false; 
 718         bool                    allowExpiredRoot 
= false; 
 719         bool                    disableCertVerify 
= false; 
 720         char                            *anchorFile 
= NULL
; 
 721         bool                    replaceAnchors 
= false; 
 722         bool                    vfyCertState 
= false; 
 723         SSLClientCertificateState expectCertState 
= kSSLClientCertNone
; 
 724         char                            *password 
= NULL
; 
 725         char                            *dhParamsFile 
= NULL
; 
 726         unsigned char           *dhParams 
= NULL
; 
 727         unsigned                        dhParamsLen 
= 0; 
 728         bool                    doIdSearch 
= false; 
 729         bool                    completeCertChain 
= false; 
 730         uint32_t                                sessionCacheTimeout 
= 0; 
 731         bool                    disableAnonCiphers 
= false; 
 732         CFMutableArrayRef       acceptableDNList 
= NULL
; 
 734         for(arg
=1; arg
<argc
; arg
++) { 
 738                                 portNum 
= atoi(&argp
[2]); 
 741                                 keyChainName 
= &argp
[2]; 
 747                                 allowExpiredRoot 
= true; 
 750                                 disableCertVerify 
= true; 
 754                                         /* requires another arg */ 
 757                                 anchorFile 
= argv
[arg
]; 
 761                                         /* requires another arg */ 
 764                                 anchorFile 
= argv
[arg
]; 
 765                                 replaceAnchors 
= true; 
 774                                                 expectCertState 
= kSSLClientCertNone
; 
 777                                                 expectCertState 
= kSSLClientCertRequested
; 
 780                                                 expectCertState 
= kSSLClientCertSent
; 
 783                                                 expectCertState 
= kSSLClientCertRejected
; 
 801                                 cipherRestrict 
= argp
[2]; 
 804                                 attemptProt 
= kSSLProtocol2
; 
 807                                 attemptProt 
= kSSLProtocol3
; 
 810                                 attemptProt 
= kTLSProtocol1
; 
 819                                 acceptedProts 
= &argp
[2]; 
 822                                 resumableEnable 
= false; 
 832                                         case 'a': authenticate 
= kAlwaysAuthenticate
; break; 
 833                                         case 'n': authenticate 
= kNeverAuthenticate
; break; 
 834                                         case 't': authenticate 
= kTryAuthenticate
; break; 
 835                                         default: usage(argv
); 
 840                                         /* requires another arg */ 
 843                                 dhParamsFile 
= argv
[arg
]; 
 852                                 completeCertChain 
= true; 
 855                                 sessionCacheTimeout 
= atoi(&argp
[2]); 
 858                                 disableAnonCiphers 
= true; 
 869                                         /* requires another arg */ 
 872                                 if(cspReadFile(argv
[arg
], &caCert
, &caCertLen
)) { 
 873                                         printf("***Error reading file %s. Aborting.\n", argv
[arg
]); 
 876                                 if(acceptableDNList 
== NULL
) { 
 877                                         acceptableDNList 
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
); 
 879                                 certData
.Data 
= caCert
; 
 880                                 certData
.Length 
= caCertLen
; 
 881                                 ortn 
= SecCertificateCreateFromData(&certData
, 
 883                                                                                                         CSSM_CERT_ENCODING_DER
, 
 886                                         cssmPerror("SecCertificateCreateFromData", ortn
); 
 889                                 CFArrayAppendValue(acceptableDNList
, secCert
); 
 894                                 if(argp
[1] == '\0') { 
 895                                         /* no loop count --> loop forever */ 
 899                                 else if(argp
[1] != '=') { 
 902                                 loops 
= atoi(&argp
[2]); 
 911     securityd_init(NULL
); 
 915         /* get server cert and optional encryption cert as CFArrayRef */ 
 917                 serverCerts 
= getSslCerts(keyChainName
, false, completeCertChain
,  
 918                         anchorFile
, &serverKc
); 
 919                 if(serverCerts 
== nil
) { 
 926                 OSStatus ortn 
= sslIdentityPicker(NULL
, anchorFile
, true, NULL
, &serverCerts
); 
 928                         printf("***IdentitySearch failure; aborting.\n"); 
 933                 OSStatus ortn 
= SecKeychainUnlock(serverKc
, strlen(password
), password
, true); 
 935                         printf("SecKeychainUnlock returned %d\n", (int)ortn
); 
 943                 switch(attemptProt
) { 
 945                                 attemptProt 
= kTLSProtocol1Only
; 
 948                                 attemptProt 
= kSSLProtocol3Only
; 
 956                 int r 
= cspReadFile(dhParamsFile
, &dhParams
, &dhParamsLen
); 
 958                         printf("***Error reading diffie-hellman params from %s; aborting\n", 
 966         /* one-time only server port setup */ 
 967         err 
= ListenForClients(portNum
, nonBlocking
, &listenSock
); 
 969         printf("ListenForClients returned %d; aborting\n", (int)err
); 
 973         for(loopNum
=1; ; loopNum
++) { 
 974                 err 
= sslServe(listenSock
, 
1008                         SSLProtocol tryProt 
= attemptProt
; 
1009                         showSSLResult(tryProt
, 
1020                                 fileBase 
? fullFileBase 
: NULL
); 
1022                 errCount 
+= verifyClientCertState(vfyCertState
, expectCertState
,  
1024                 freePeerCerts(peerCerts
); 
1025                 if(loops 
&& (loopNum 
== loops
)) { 
1030         endpointShutdown(listenSock
); 
1033                 CFRelease(serverKc
);