Ejemplo n.º 1
0
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;

}