int main(int argc, char **argv) { OSStatus err; int arg; char fullFileBase[100]; SSLProtocol negVersion; SSLCipherSuite negCipher; CFArrayRef peerCerts = NULL; char *argp; otSocket listenSock; CFArrayRef serverCerts = nil; // required CFArrayRef encryptCerts = nil; // optional SecKeychainRef serverKc = nil; SecKeychainRef encryptKc = nil; /* user-spec'd parameters */ char *hostName = DEFAULT_HOST; unsigned short portNum = DEFAULT_PORT; CSSM_BOOL allowExpired = CSSM_FALSE; CSSM_BOOL allowAnyRoot = CSSM_FALSE; char *fileBase = NULL; CSSM_BOOL displayRxData = CSSM_FALSE; CSSM_BOOL displayCerts = CSSM_FALSE; char cipherRestrict = '\0'; SSLProtocol attemptProt = kTLSProtocol1; CSSM_BOOL protXOnly = CSSM_FALSE; // kSSLProtocol3Only, // kTLSProtocol1Only CSSM_BOOL quiet = CSSM_FALSE; CSSM_BOOL resumableEnable = CSSM_TRUE; CSSM_BOOL pause = CSSM_FALSE; char *keyChainName = NULL; char *encryptKeyChainName = NULL; CSSM_BOOL loop = CSSM_FALSE; SSLAuthenticate authenticate = kNeverAuthenticate; for(arg=1; arg<argc; arg++) { argp = argv[arg]; switch(argp[0]) { case 'H': hostName = &argp[2]; break; case 'P': portNum = atoi(&argp[2]); break; case 'k': keyChainName = &argp[2]; break; case 'E': encryptKeyChainName = &argp[2]; break; case 'e': allowExpired = CSSM_TRUE; break; case 'r': allowAnyRoot = CSSM_TRUE; break; case 'd': displayRxData = CSSM_TRUE; break; case 'c': displayCerts = CSSM_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 = CSSM_TRUE; break; case 'R': resumableEnable = CSSM_FALSE; break; case 'a': 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 'p': pause = CSSM_TRUE; break; case 'q': quiet = CSSM_TRUE; break; case 'l': loop = CSSM_TRUE; break; default: usage(argv); } } /* get server cert and optional encryption cert as CFArrayRef */ serverCerts = getSslCerts(keyChainName, CSSM_FALSE, &serverKc); if(serverCerts == nil) { exit(1); } if(encryptKeyChainName) { encryptCerts = getSslCerts(encryptKeyChainName, CSSM_TRUE, &encryptKc); if(encryptCerts == nil) { exit(1); } } /* one-time only server port setup */ err = ListenForClients(portNum, &listenSock); if(err) { printf("ListenForClients returned %d; aborting\n", err); exit(1); } do { err = sslServe(listenSock, attemptProt, hostName, serverCerts, encryptCerts, allowExpired, allowAnyRoot, cipherRestrict, authenticate, resumableEnable, quiet, pause, &negVersion, &negCipher, &peerCerts); if(!quiet) { showSSLResult(attemptProt, err, negVersion, negCipher, peerCerts, displayCerts, fileBase ? fullFileBase : NULL); } freePeerCerts(peerCerts); } while(loop); endpointShutdown(listenSock); parseCertShutdown(); if(serverKc) { CFRelease(serverKc); } if(encryptKc) { CFRelease(encryptKc); } return 0; }
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 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': 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(NULL); # 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); } } #else (void) doIdSearch; (void) encryptKeyChainName; #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); } } #else (void) 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; }