+++ /dev/null
-/*
- * Copyright (c) 2008-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/*
- * Trivial SSL server example, using SecureTransport / OS X version.
- *
- */
-
-#include <Security/SecureTransport.h>
-#include <Security/SecureTransportPriv.h>
-#include "sslAppUtils.h"
-#include "ioSock.h"
-#include "fileIo.h"
-
-#include <Security/SecBase.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/param.h>
-
-#include <Security/Security.h>
-#include <Security/SecCertificatePriv.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include "printCert.h"
-
-#if NO_SERVER
-#include <securityd/spi.h>
-#endif
-
-/* Set true when PR-3074739 is merged to TOT */
-#define SET_DH_PARAMS_ENABLE 1
-
-/* true when using SSLCopyPeerCertificates() per Radar 3311892 */
-#define USE_COPY_PEER_CERTS 1
-
-/*
- * Defaults, overridable by user.
- */
-#define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012Content-Type: text/html\015\012\015\012" \
- "<HTML><HEAD><TITLE>SecureTransport Test Server</TITLE></HEAD>" \
- "<BODY><H2>Secure connection established.</H2>" \
- "Message from the 'sslServer' sample application.\015\012</BODY>" \
- "</HTML>\015\012"
-
-/* For ease of debugging, pick a non-privileged port */
-#define DEFAULT_PORT 1200
-// #define DEFAULT_PORT 443
-
-#define DEFAULT_HOST "localhost"
-
-#define DEFAULT_KC "certkc"
-
-static void usage(char **argv)
-{
- printf("Usage: %s [option ...]\n", argv[0]);
- printf("Options:\n");
- printf(" P=port Port to listen on; default is %d\n", DEFAULT_PORT);
- printf(" k=keychain Contains server cert and keys.\n");
- printf(" y=keychain Encryption-only cert and keys.\n");
- printf(" e Allow Expired Certs\n");
- printf(" r Allow any root cert\n");
- printf(" E Allow Expired Roots\n");
- printf(" x Disable Cert Verification\n");
- printf(" f=fileBase Write Peer Certs to fileBase*\n");
- printf(" c Display peer certs\n");
- printf(" d Display received data\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\n");
- printf(" 2 SSLv2 only (default is best fit)\n");
- printf(" 3 SSLv3 only (default is best fit)\n");
- printf(" t TLSv1 only (default is best fit)\n");
- printf(" o TLSv1, SSLv3 use kSSLProtocol__X__Only\n");
- printf(" g={prot...} Specify legal protocols; prot = any combo of [23t]\n");
- printf(" T=[nrsj] Verify client cert state = "
- "none/requested/sent/rejected\n");
- printf(" R Disable resumable session support\n");
- printf(" i=timeout Session cache timeout\n");
- printf(" u=[nat] Authentication: n=never; a=always; t=try\n");
- printf(" b Non-blocking I/O\n");
- printf(" a fileNmae Add fileName to list of trusted roots\n");
- printf(" A fileName fileName is ONLY trusted root\n");
- printf(" U filename Add filename to acceptable DNList (multiple times OK)\n");
- printf(" D filename Diffie-Hellman parameters from filename\n");
- printf(" z=password Unlock server keychain with password.\n");
- printf(" H Do SecIdentityRef search instead of specific keychain\n");
- printf(" M Complete cert chain (default assumes that our identity is root)\n");
- printf(" 4 Disable anonymous ciphers\n");
- printf(" p Pause after each phase\n");
- printf(" l[=loops] Loop, performing multiple transactions\n");
- printf(" q Quiet/diagnostic mode (site names and errors only)\n");
- printf(" h Help\n");
- exit(1);
-}
-
-/* snag a copy of current connection's peer certs so we can
- * examine them later after the connection is closed */
-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() */
-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
-}
-
-/* print reply received from server */
-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");
-}
-
-static void doPause(const char *prompt) {
- if(prompt) {
- printf("%s. ", prompt);
- }
- fpurge(stdin);
- printf("Continue (n/anything)? ");
- char c = getchar();
- if(c == 'n') {
- exit(0);
- }
-}
-
-/*
- * Perform one SSL diagnostic server-side session. Returns nonzero on error.
- * Normally no output to stdout except initial "waiting for connection" 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 sslServe(
- otSocket listenSock,
- unsigned short portNum,
- SSLProtocol tryVersion, // only used if acceptedProts NULL
- const char *acceptedProts,
- CFArrayRef serverCerts, // required
- char *password, // optional
- CFArrayRef encryptServerCerts, // optional
- bool allowExpired,
- bool allowAnyRoot,
- bool allowExpiredRoot,
- bool disableCertVerify,
- char *anchorFile,
- bool replaceAnchors,
- char cipherRestrict, // '2', 'd'. etc...'\0' for no
- // restriction
- SSLAuthenticate authenticate,
- unsigned char *dhParams, // optional D-H parameters
- unsigned dhParamsLen,
- CFArrayRef acceptableDNList, // optional
- bool resumableEnable,
- uint32_t sessionCacheTimeout,// optional
- bool disableAnonCiphers,
- bool silent, // no stdout
- bool pause,
- SSLProtocol *negVersion, // RETURNED
- SSLCipherSuite *negCipher, // RETURNED
- SSLClientCertificateState *certState, // RETURNED
- Boolean *sessionWasResumed, // RETURNED
- unsigned char *sessionID, // mallocd by caller, RETURNED
- size_t *sessionIDLength, // RETURNED
- CFArrayRef *peerCerts, // mallocd & RETURNED
- char **argv)
-{
- otSocket acceptSock;
- PeerSpec peerId;
- OSStatus ortn;
- SSLContextRef ctx = NULL;
- size_t length;
- uint8_t rcvBuf[RCV_BUF_SIZE];
- const char *outMsg = SERVER_MESSAGE;
-
- *negVersion = kSSLProtocolUnknown;
- *negCipher = SSL_NULL_WITH_NULL_NULL;
- *peerCerts = NULL;
-
- #if IGNORE_SIGPIPE
- signal(SIGPIPE, sigpipe);
- #endif
-
- /* first wait for a connection */
- if(!silent) {
- printf("Waiting for client connection on port %u...", portNum);
- fflush(stdout);
- }
- ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId);
- if(ortn) {
- printf("AcceptClientConnection returned %d; aborting\n", (int)ortn);
- return ortn;
- }
-
- /*
- * Set up a SecureTransport session.
- * First the standard calls.
- */
- ortn = SSLNewContext(true, &ctx);
- if(ortn) {
- printSslErrStr("SSLNewContext", ortn);
- goto cleanup;
- }
- ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite);
- if(ortn) {
- printSslErrStr("SSLSetIOFuncs", ortn);
- goto cleanup;
- }
- ortn = SSLSetConnection(ctx, (SSLConnectionRef)acceptSock);
- if(ortn) {
- printSslErrStr("SSLSetConnection", ortn);
- goto cleanup;
- }
-
- /* have to do these options befor setting server certs */
- if(allowExpired) {
- ortn = SSLSetAllowsExpiredCerts(ctx, true);
- if(ortn) {
- printSslErrStr("SSLSetAllowExpiredCerts", ortn);
- goto cleanup;
- }
- }
- if(allowAnyRoot) {
- ortn = SSLSetAllowsAnyRoot(ctx, true);
- if(ortn) {
- printSslErrStr("SSLSetAllowAnyRoot", ortn);
- goto cleanup;
- }
- }
-
- if(anchorFile) {
- ortn = sslAddTrustedRoot(ctx, anchorFile, replaceAnchors);
- if(ortn) {
- printf("***Error obtaining anchor file %s\n", anchorFile);
- goto cleanup;
- }
- }
- if(serverCerts != NULL) {
- if(anchorFile == NULL) {
- /* no specific anchors, so assume we want to trust this one */
- ortn = addIdentityAsTrustedRoot(ctx, serverCerts);
- if(ortn) {
- goto cleanup;
- }
- }
- ortn = SSLSetCertificate(ctx, serverCerts);
- if(ortn) {
- printSslErrStr("SSLSetCertificate", ortn);
- goto cleanup;
- }
- }
- if(encryptServerCerts) {
- ortn = SSLSetEncryptionCertificate(ctx, encryptServerCerts);
- if(ortn) {
- printSslErrStr("SSLSetEncryptionCertificate", ortn);
- goto cleanup;
- }
- }
- if(allowExpiredRoot) {
- ortn = SSLSetAllowsExpiredRoots(ctx, true);
- if(ortn) {
- printSslErrStr("SSLSetAllowsExpiredRoots", ortn);
- goto cleanup;
- }
- }
- if(disableCertVerify) {
- ortn = SSLSetEnableCertVerify(ctx, false);
- if(ortn) {
- printSslErrStr("SSLSetEnableCertVerify", ortn);
- goto cleanup;
- }
- }
-
- /*
- * SecureTransport options.
- */
- if(acceptedProts) {
- ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false);
- if(ortn) {
- printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn);
- goto cleanup;
- }
- for(const char *cp = acceptedProts; *cp; cp++) {
- SSLProtocol prot = kSSLProtocolUnknown;
- switch(*cp) {
- case '2':
- prot = kSSLProtocol2;
- break;
- case '3':
- prot = kSSLProtocol3;
- break;
- case 't':
- prot = kTLSProtocol1;
- break;
- default:
- usage(argv);
- }
- ortn = SSLSetProtocolVersionEnabled(ctx, prot, true);
- if(ortn) {
- printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
- goto cleanup;
- }
- }
- }
- else {
- ortn = SSLSetProtocolVersion(ctx, tryVersion);
- if(ortn) {
- printSslErrStr("SSLSetProtocolVersion", ortn);
- goto cleanup;
- }
- }
- if(resumableEnable) {
- ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec));
- if(ortn) {
- printSslErrStr("SSLSetPeerID", ortn);
- goto cleanup;
- }
- }
- if(cipherRestrict != '\0') {
- ortn = sslSetCipherRestrictions(ctx, cipherRestrict);
- if(ortn) {
- goto cleanup;
- }
- }
- if(authenticate != kNeverAuthenticate) {
- ortn = SSLSetClientSideAuthenticate(ctx, authenticate);
- if(ortn) {
- printSslErrStr("SSLSetClientSideAuthenticate", ortn);
- goto cleanup;
- }
- }
- if(dhParams) {
- ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen);
- if(ortn) {
- printSslErrStr("SSLSetDiffieHellmanParams", ortn);
- goto cleanup;
- }
- }
- if(sessionCacheTimeout) {
- ortn = SSLSetSessionCacheTimeout(ctx, sessionCacheTimeout);
- if(ortn) {
- printSslErrStr("SSLSetSessionCacheTimeout", ortn);
- goto cleanup;
- }
- }
- if(disableAnonCiphers) {
- ortn = SSLSetAllowAnonymousCiphers(ctx, false);
- if(ortn) {
- printSslErrStr("SSLSetAllowAnonymousCiphers", ortn);
- goto cleanup;
- }
- /* quickie test of the getter */
- Boolean e;
- ortn = SSLGetAllowAnonymousCiphers(ctx, &e);
- if(ortn) {
- printSslErrStr("SSLGetAllowAnonymousCiphers", ortn);
- goto cleanup;
- }
- if(e) {
- printf("***SSLGetAllowAnonymousCiphers() returned true; expected false\n");
- ortn = errSecIO;
- goto cleanup;
- }
- }
-/* XXX/cs
- if(acceptableDNList) {
- ortn = SSLSetCertificateAuthorities(ctx, acceptableDNList, TRUE);
- if(ortn) {
- printSslErrStr("SSLSetCertificateAuthorities", ortn);
- goto cleanup;
- }
- }
-*/
- /* end options */
-
- if(pause) {
- doPause("SSLContext initialized");
- }
-
- /* Perform SSL/TLS handshake */
- do
- { ortn = SSLHandshake(ctx);
- if((ortn == errSSLWouldBlock) && !silent) {
- /* keep UI responsive */
- sslOutputDot();
- }
- } while (ortn == errSSLWouldBlock);
-
- /* this works even if handshake failed due to cert chain invalid */
- copyPeerCerts(ctx, peerCerts);
-
- SSLGetClientCertificateState(ctx, certState);
- SSLGetNegotiatedCipher(ctx, negCipher);
- SSLGetNegotiatedProtocolVersion(ctx, negVersion);
- *sessionIDLength = MAX_SESSION_ID_LENGTH;
- SSLGetResumableSessionInfo(ctx, sessionWasResumed, sessionID,
- sessionIDLength);
-
- if(!silent) {
- printf("\n");
- }
- if(ortn) {
- goto cleanup;
- }
- if(pause) {
- doPause("SSLContext handshake complete");
- }
-
- /* wait for one complete line or user says they've had enough */
- while(ortn == errSecSuccess) {
- length = sizeof(rcvBuf);
- ortn = SSLRead(ctx, rcvBuf, length, &length);
- if(length == 0) {
- /* keep UI responsive */
- sslOutputDot();
- }
- else {
- /* print what we have */
- printf("client request: ");
- dumpAscii(rcvBuf, length);
- }
- if(pause) {
- /* allow user to bail */
- char resp;
-
- fpurge(stdin);
- printf("\nMore client request (y/anything): ");
- resp = getchar();
- if(resp != 'y') {
- break;
- }
- }
-
- /* poor person's line completion scan */
- for(unsigned i=0; i<length; i++) {
- if((rcvBuf[i] == '\n') || (rcvBuf[i] == '\r')) {
- /* a labelled break would be nice here.... */
- goto serverResp;
- }
- }
- if (ortn == errSSLWouldBlock) {
- ortn = errSecSuccess;
- }
- }
-
-serverResp:
- if(pause) {
- doPause("Client GET msg received");
- }
-
- /* send out canned response */
- length = strlen(outMsg);
- ortn = SSLWrite(ctx, outMsg, length, &length);
- if(ortn) {
- printSslErrStr("SSLWrite", ortn);
- }
- if(pause) {
- doPause("Server response sent");
- }
-cleanup:
- /*
- * always do close, even on error - to flush outgoing write queue
- */
- OSStatus cerr = SSLClose(ctx);
- if(ortn == errSecSuccess) {
- ortn = cerr;
- }
- if(acceptSock) {
- endpointShutdown(acceptSock);
- }
- if(ctx) {
- SSLDisposeContext(ctx);
- }
- /* FIXME - dispose of serverCerts */
- return ortn;
-}
-
-static void showPeerCerts(
- CFArrayRef peerCerts,
- bool verbose)
-{
- CFIndex numCerts;
- SecCertificateRef certRef;
- CFIndex i;
-
- if(peerCerts == NULL) {
- return;
- }
- numCerts = CFArrayGetCount(peerCerts);
- for(i=0; i<numCerts; i++) {
- certRef = (SecCertificateRef)CFArrayGetValueAtIndex(peerCerts, i);
- printf("\n================== Server Cert %lu ===================\n\n", i);
- print_cert(certRef, verbose);
- printf("\n=============== End of Server Cert %lu ===============\n", i);
- }
-}
-
-static void writePeerCerts(
- CFArrayRef peerCerts,
- const char *fileBase)
-{
- CFIndex numCerts;
- SecCertificateRef certRef;
- 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);
- writeFile(fileName, SecCertificateGetBytePtr(certRef),
- SecCertificateGetLength(certRef));
- }
- printf("...wrote %lu certs to fileBase %s\n", numCerts, fileBase);
-}
-
-static void showSSLResult(
- SSLProtocol tryVersion,
- char *acceptedProts,
- OSStatus err,
- SSLProtocol negVersion,
- SSLCipherSuite negCipher,
- Boolean sessionWasResumed,
- unsigned char *sessionID,
- size_t sessionIDLength,
- CFArrayRef peerCerts,
- bool displayPeerCerts,
- SSLClientCertificateState certState,
- char *fileBase) // non-NULL: write certs to file
-{
- CFIndex numPeerCerts;
-
- printf("\n");
- if(acceptedProts) {
- printf(" Allowed SSL versions : %s\n", acceptedProts);
- }
- else {
- printf(" Attempted SSL version : %s\n",
- sslGetProtocolVersionString(tryVersion));
- }
- printf(" Result : %s\n", sslGetSSLErrString(err));
- printf(" Negotiated SSL version : %s\n",
- sslGetProtocolVersionString(negVersion));
- printf(" Negotiated CipherSuite : %s\n",
- sslGetCipherSuiteString(negCipher));
- if(certState != kSSLClientCertNone) {
- printf(" Client Cert State : %s\n",
- sslGetClientCertStateString(certState));
- }
- printf(" Resumed Session : ");
- if(sessionWasResumed) {
- for(unsigned dex=0; dex<sessionIDLength; dex++) {
- printf("%02X ", sessionID[dex]);
- if(((dex % 8) == 7) && (dex != (sessionIDLength - 1))) {
- printf("\n ");
- }
- }
- printf("\n");
- }
- else {
- printf("NOT RESUMED\n");
- }
- if(peerCerts == NULL) {
- numPeerCerts = 0;
- }
- else {
- numPeerCerts = CFArrayGetCount(peerCerts);
- }
- printf(" Number of peer certs : %lu\n", numPeerCerts);
- if(numPeerCerts != 0) {
- if(displayPeerCerts) {
- showPeerCerts(peerCerts, false);
- }
- if(fileBase != NULL) {
- writePeerCerts(peerCerts, fileBase);
- }
- }
- printf("\n");
-}
-
-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;
-}
-
-int main(int argc, char **argv)
-{
- OSStatus err;
- int arg;
- char fullFileBase[100];
- SSLProtocol negVersion;
- SSLCipherSuite negCipher;
- Boolean sessionWasResumed;
- unsigned char sessionID[MAX_SESSION_ID_LENGTH];
- size_t sessionIDLength;
- CFArrayRef peerCerts = NULL;
- char *argp;
- otSocket listenSock;
- CFArrayRef serverCerts = nil; // required
- CFArrayRef encryptCerts = nil; // optional
- SecKeychainRef serverKc = nil;
- SecKeychainRef encryptKc = nil;
- int loopNum;
- int errCount = 0;
- SSLClientCertificateState certState; // obtained from sslServe
-
- /* user-spec'd parameters */
- unsigned short portNum = DEFAULT_PORT;
- bool allowExpired = false;
- bool allowAnyRoot = false;
- char *fileBase = NULL;
- bool displayRxData = false;
- bool displayCerts = false;
- char cipherRestrict = '\0';
- SSLProtocol attemptProt = kTLSProtocol1;
- bool protXOnly = false; // kSSLProtocol3Only,
- // kTLSProtocol1Only
- char *acceptedProts = NULL; // "23t" ==> SSLSetProtocolVersionEnabled
- bool quiet = false;
- bool resumableEnable = true;
- bool pause = false;
- char *keyChainName = NULL;
- char *encryptKeyChainName = NULL;
- int loops = 1;
- SSLAuthenticate authenticate = kNeverAuthenticate;
- bool nonBlocking = false;
- bool allowExpiredRoot = false;
- bool disableCertVerify = false;
- char *anchorFile = NULL;
- bool replaceAnchors = false;
- bool vfyCertState = false;
- SSLClientCertificateState expectCertState = kSSLClientCertNone;
- char *password = NULL;
- char *dhParamsFile = NULL;
- unsigned char *dhParams = NULL;
- unsigned dhParamsLen = 0;
- bool doIdSearch = false;
- bool completeCertChain = false;
- uint32_t sessionCacheTimeout = 0;
- bool disableAnonCiphers = false;
- CFMutableArrayRef acceptableDNList = NULL;
-
- for(arg=1; arg<argc; arg++) {
- argp = argv[arg];
- switch(argp[0]) {
- case 'P':
- portNum = atoi(&argp[2]);
- break;
- case 'k':
- keyChainName = &argp[2];
- break;
- case 'y':
- encryptKeyChainName = &argp[2];
- break;
- case 'e':
- allowExpired = true;
- break;
- case 'E':
- allowExpiredRoot = true;
- break;
- case 'x':
- disableCertVerify = true;
- break;
- case 'a':
- if(++arg == argc) {
- /* requires another arg */
- usage(argv);
- }
- anchorFile = argv[arg];
- break;
- case 'A':
- if(++arg == argc) {
- /* requires another arg */
- usage(argv);
- }
- anchorFile = argv[arg];
- replaceAnchors = true;
- 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 'r':
- allowAnyRoot = true;
- break;
- case 'd':
- displayRxData = true;
- break;
- case 'c':
- displayCerts = true;
- break;
- case 'f':
- fileBase = &argp[2];
- break;
- case 'C':
- cipherRestrict = argp[2];
- break;
- case '2':
- attemptProt = kSSLProtocol2;
- break;
- case '3':
- attemptProt = kSSLProtocol3;
- break;
- case 't':
- attemptProt = kTLSProtocol1;
- break;
- case 'o':
- protXOnly = true;
- break;
- case 'g':
- if(argp[1] != '=') {
- usage(argv);
- }
- acceptedProts = &argp[2];
- break;
- case 'R':
- resumableEnable = false;
- break;
- case 'b':
- nonBlocking = true;
- break;
- case 'u':
- if(argp[1] != '=') {
- usage(argv);
- }
- switch(argp[2]) {
- case 'a': authenticate = kAlwaysAuthenticate; break;
- case 'n': authenticate = kNeverAuthenticate; break;
- case 't': authenticate = kTryAuthenticate; break;
- default: usage(argv);
- }
- break;
- case 'D':
- if(++arg == argc) {
- /* requires another arg */
- usage(argv);
- }
- dhParamsFile = argv[arg];
- break;
- case 'z':
- password = &argp[2];
- break;
- case 'H':
- doIdSearch = true;
- break;
- case 'M':
- completeCertChain = true;
- break;
- case 'i':
- sessionCacheTimeout = atoi(&argp[2]);
- break;
- case '4':
- disableAnonCiphers = true;
- break;
- case 'p':
- pause = true;
- break;
- case 'q':
- quiet = true;
- break;
-#if 0
- case 'U':
- if(++arg == argc) {
- /* requires another arg */
- usage(argv);
- }
- if(cspReadFile(argv[arg], &caCert, &caCertLen)) {
- printf("***Error reading file %s. Aborting.\n", argv[arg]);
- exit(1);
- }
- if(acceptableDNList == NULL) {
- acceptableDNList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- }
- certData.Data = caCert;
- certData.Length = caCertLen;
- ortn = SecCertificateCreateFromData(&certData,
- CSSM_CERT_X_509v3,
- CSSM_CERT_ENCODING_DER,
- &secCert);
- if(ortn) {
- cssmPerror("SecCertificateCreateFromData", ortn);
- exit(1);
- }
- CFArrayAppendValue(acceptableDNList, secCert);
- CFRelease(secCert);
- break;
-#endif
- case 'l':
- if(argp[1] == '\0') {
- /* no loop count --> loop forever */
- loops = 0;
- break;
- }
- else if(argp[1] != '=') {
- usage(argv);
- }
- loops = atoi(&argp[2]);
- break;
- default:
- usage(argv);
- }
- }
-
-#if NO_SERVER
-# if DEBUG
- securityd_init();
-# endif
-#endif
-
- /* get server cert and optional encryption cert as CFArrayRef */
- if(keyChainName) {
- serverCerts = getSslCerts(keyChainName, false, completeCertChain,
- anchorFile, &serverKc);
- if(serverCerts == nil) {
- exit(1);
- }
- }
- else
-#if 0
- if(doIdSearch) {
- OSStatus ortn = sslIdentityPicker(NULL, anchorFile, true, NULL, &serverCerts);
- if(ortn) {
- printf("***IdentitySearch failure; aborting.\n");
- exit(1);
- }
- }
- if(password) {
- OSStatus ortn = SecKeychainUnlock(serverKc, strlen(password), password, true);
- if(ortn) {
- printf("SecKeychainUnlock returned %d\n", (int)ortn);
- /* oh well */
- }
- }
- if(encryptKeyChainName) {
- encryptCerts = getSslCerts(encryptKeyChainName, true, completeCertChain,
- anchorFile, &encryptKc);
- if(encryptCerts == nil) {
- exit(1);
- }
- }
-#endif
- if(protXOnly) {
- switch(attemptProt) {
- case kTLSProtocol1:
- attemptProt = kTLSProtocol1Only;
- break;
- case kSSLProtocol3:
- attemptProt = kSSLProtocol3Only;
- break;
- default:
- break;
- }
- }
-#if 0
- if(dhParamsFile) {
- int r = cspReadFile(dhParamsFile, &dhParams, &dhParamsLen);
- if(r) {
- printf("***Error reading diffie-hellman params from %s; aborting\n",
- dhParamsFile);
- }
- }
-#endif
-
- /* one-time only server port setup */
- err = ListenForClients(portNum, nonBlocking, &listenSock);
- if(err) {
- printf("ListenForClients returned %d; aborting\n", (int)err);
- exit(1);
- }
-
- for(loopNum=1; ; loopNum++) {
- err = sslServe(listenSock,
- portNum,
- attemptProt,
- acceptedProts,
- serverCerts,
- password,
- encryptCerts,
- allowExpired,
- allowAnyRoot,
- allowExpiredRoot,
- disableCertVerify,
- anchorFile,
- replaceAnchors,
- cipherRestrict,
- authenticate,
- dhParams,
- dhParamsLen,
- acceptableDNList,
- resumableEnable,
- sessionCacheTimeout,
- disableAnonCiphers,
- quiet,
- pause,
- &negVersion,
- &negCipher,
- &certState,
- &sessionWasResumed,
- sessionID,
- &sessionIDLength,
- &peerCerts,
- argv);
- if(err) {
- errCount++;
- }
- if(!quiet) {
- SSLProtocol tryProt = attemptProt;
- showSSLResult(tryProt,
- acceptedProts,
- err,
- negVersion,
- negCipher,
- sessionWasResumed,
- sessionID,
- sessionIDLength,
- peerCerts,
- displayCerts,
- certState,
- fileBase ? fullFileBase : NULL);
- }
- errCount += verifyClientCertState(vfyCertState, expectCertState,
- certState);
- freePeerCerts(peerCerts);
- if(loops && (loopNum == loops)) {
- break;
- }
- };
-
- endpointShutdown(listenSock);
-
- if(serverKc) {
- CFRelease(serverKc);
- }
- if(encryptKc) {
- CFRelease(encryptKc);
- }
- return errCount;
-
-}
-
-