Esempio n. 1
0
static void showPeerCerts(
	CFArrayRef			peerCerts,
	CSSM_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", ortn);
			continue;
		}
		printf("\n================== Peer Cert %d ===================\n\n", i);
		printCert(certData.Data, certData.Length, verbose);
		printf("\n=============== End of Peer Cert %d ===============\n", i);
	}
}
int p12ParseTop(
	CSSM_DATA		&rawBlob,
	CSSM_CSP_HANDLE cspHand,
	CFStringRef 	pwd,
	bool 			verbose)
{
	SecNssCoder coder;
	OidParser parser;
	P12Parsed parsed(coder);
	P12ParseInfo pinfo(coder,
		cspHand, 
		parser,
		pwd,
		NULL,			// no separate pwd
		parsed);

	printf("PKCS12 PFX:\n");
	int rtn = p12Parse(rawBlob, pinfo, 3);
	
	/* find anything? */
	if(verbose) {
		P12KnownBlobs &certs = pinfo.mParsed.mCerts;
		if(certs.mNumBlobs) {
			printf("\n\n");
			for(unsigned dex=0; dex<certs.mNumBlobs; dex++) {
				printf("Cert %u:\n", dex);
				printCert(certs.mBlobs[dex].Data, 
					certs.mBlobs[dex].Length, CSSM_FALSE);
				printf("\n");
			}
		}
		P12KnownBlobs &crls = pinfo.mParsed.mCrls;
		if(crls.mNumBlobs) {
			printf("\n\n");
			for(unsigned dex=0; dex<crls.mNumBlobs; dex++) {
				printf("CRL %u:\n", dex);
				printCrl(crls.mBlobs[dex].Data, 
					crls.mBlobs[dex].Length, CSSM_FALSE);
			}
		}
	}
	return rtn;
}
/*
 * Search DB for all records of type CRL or cert, calling appropriate
 * parse/print routine for each record. 
 */ 
CSSM_RETURN cuDumpCrlsCerts(
	CSSM_DL_DB_HANDLE	dlDbHand,
	CSSM_CL_HANDLE		clHand,
	CSSM_BOOL			isCert,
	unsigned			&numItems,		// returned
	CSSM_BOOL			verbose)
{
	CSSM_QUERY					query;
	CSSM_DB_UNIQUE_RECORD_PTR	record = NULL;
	CSSM_HANDLE					resultHand;
	CSSM_RETURN					crtn;
	CSSM_DATA					certCrl;
	const char					*itemStr;
	
	numItems = 0;
	itemStr = isCert ? "Certificate" : "CRL";
	
	/* just search by recordType, no predicates, no attributes */
	if(isCert) {
		query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE;
	}
	else {
		query.RecordType = CSSM_DL_DB_RECORD_X509_CRL;
	}
	query.Conjunctive = CSSM_DB_NONE;
	query.NumSelectionPredicates = 0;
	query.SelectionPredicate = NULL;
	query.QueryLimits.TimeLimit = 0;			// FIXME - meaningful?
	query.QueryLimits.SizeLimit = 1;			// FIXME - meaningful?
	query.QueryFlags = 0;		// CSSM_QUERY_RETURN_DATA...FIXME - used?

	certCrl.Data = NULL;
	certCrl.Length = 0;
	crtn = CSSM_DL_DataGetFirst(dlDbHand,
		&query,
		&resultHand,
		NULL,			// no attrs 
		&certCrl,
		&record);
	switch(crtn) {
		case CSSM_OK:
			break;		// proceed
		case CSSMERR_DL_ENDOFDATA:
			/* no data, otherwise OK */
			return CSSM_OK;
		case CSSMERR_DL_INVALID_RECORDTYPE:
			/* invalid record type just means "this hasn't been set up
			* for certs yet". */
			return crtn;
		default:
			cuPrintError("DataGetFirst", crtn);
			return crtn;
	}

	/* got one; print it */
	dprintf("%s %u:\n", itemStr, numItems);
	if(isCert) {
		printCert(certCrl.Data, (unsigned)certCrl.Length, verbose);
	}
	else {
		printCrl(certCrl.Data, (unsigned)certCrl.Length, verbose);
	}
	CSSM_DL_FreeUniqueRecord(dlDbHand, record);
	APP_FREE(certCrl.Data);
	certCrl.Data = NULL;
	certCrl.Length = 0;
	numItems++;
	
	/* get the rest */
	for(;;) {
		crtn = CSSM_DL_DataGetNext(dlDbHand,
			resultHand, 
			NULL,
			&certCrl,
			&record);
		switch(crtn) {
			case CSSM_OK:
				dprintf("%s %u:\n", itemStr, numItems);
				if(isCert) {
					printCert(certCrl.Data, (unsigned)certCrl.Length, verbose);
				}
				else {
					printCrl(certCrl.Data, (unsigned)certCrl.Length, verbose);
				}
				CSSM_DL_FreeUniqueRecord(dlDbHand, record);
				APP_FREE(certCrl.Data);
				certCrl.Data = NULL;
				certCrl.Length = 0;
				numItems++;
				break;		// and go again 
			case CSSMERR_DL_ENDOFDATA:
				/* normal termination */
				return CSSM_OK;
			default:
				cuPrintError("DataGetNext", crtn);
				return crtn;
		}
	}
	/* NOT REACHED */
}
static int parseOcspResp(
	CSSM_CL_HANDLE clHand, 
	unsigned char *inFile, 
	unsigned inFileLen,
	bool verbose)
{
	SecAsn1OCSPResponse topResp;
	SecAsn1CoderRef coder;
	OSStatus ortn;
	int indent = 0;
	const char *str;
	SecAsn1OCSPBasicResponse basicResp;
	unsigned numCerts = 0;
	
	SecAsn1CoderCreate(&coder);	
	memset(&topResp, 0, sizeof(topResp));
	ortn = SecAsn1Decode(coder, inFile, inFileLen, kSecAsn1OCSPResponseTemplate,
		&topResp);
	if(ortn) {
		printf("***Error decoding SecAsn1OCSPResponse\n");
		goto errOut;
	}
	printf("OCSPResponse:\n");
	indent += 2;
	doIndent(indent);
	printf("responseStatus: ");
	if(topResp.responseStatus.Length == 0) {
		printf("**MALFORMED**\n");
	}
	else {
		switch(topResp.responseStatus.Data[0]) {
			case RS_Success: str = "RS_Success"; break;
			case RS_MalformedRequest: str = "RS_MalformedRequest"; break;
			case RS_InternalError: str = "RS_InternalError"; break;
			case RS_TryLater: str = "RS_TryLater"; break;
			case RS_Unused: str = "RS_Unused"; break;
			case RS_SigRequired: str = "RS_SigRequired"; break;
			case RS_Unauthorized: str = "RS_Unauthorized"; break;
			default: str = "MALFORMED (unknown enum)\n"; break;
		}
		printf("%s (%u(d))\n", str, topResp.responseStatus.Data[0]);
	}
	doIndent(indent);
	printf("ResponseBytes: ");
	if(topResp.responseBytes == NULL) {
		printf("empty\n");
		goto errOut;
	}
	printf("\n");
	indent += 2;
	doIndent(indent);
	printf("responseType: ");
	if(appCompareCssmData(&topResp.responseBytes->responseType,
			&CSSMOID_PKIX_OCSP_BASIC)) {
		str = "ocsp-basic";
	}
	else {
		str = "Unknown type\n";
	}
	printf("%s\n", str);
		
	/* decode the BasicOCSPResponse */
	memset(&basicResp, 0, sizeof(basicResp));
	ortn = SecAsn1DecodeData(coder, &topResp.responseBytes->response,
		kSecAsn1OCSPBasicResponseTemplate, &basicResp);
	if(ortn) {
		printf("***Error decoding BasicOCSPResponse\n");
		goto errOut;
	}
	
	doIndent(indent);
	printf("BasicOCSPResponse:\n");
	indent += 2;
	doIndent(indent);
	printf("ResponseData:\n");
	parseResponseData(coder, indent + 2, basicResp.tbsResponseData);
	doIndent(indent);
	printf("sig: ");
	printDataAsHex(&basicResp.sig, 8);
	numCerts = ocspdArraySize((const void **)basicResp.certs);
	doIndent(indent);
	printf("Num Certs: %u\n", numCerts);
	
	if(verbose) {
		for(unsigned dex=0; dex<numCerts; dex++) {
			printf("+++++++++++++++++++++++++ Cert %u +++++++++++++++++++++++++\n", dex);
			printCert(basicResp.certs[dex]->Data, basicResp.certs[dex]->Length, 
				CSSM_FALSE);
			printf("+++++++++++++++++++++++ End Cert %u +++++++++++++++++++++++\n", dex);
		}
	}
	indent -= 2;		// end of BasicOCSPResponse
	indent -= 2;		// end of ResponseBytes
	indent -= 2;		// end of OCSPResponse
errOut:
	SecAsn1CoderRelease(coder);
	return ortn;
}
int main(int argc, char **argv)
{
	if(argc < 2) {
		usage(argv);
	}
	
	bool print_cert = false;
	bool allCerts = false;
	const char *emailAddress = NULL;
	bool addToKC = false;
	
	extern int optind;
	optind = 1;

	if(argv[1][0] != '-') {
		/* normal case, email address specified */
		emailAddress = argv[1];
		optind++;
	}
	
	extern char *optarg;
	int arg;
	while ((arg = getopt(argc, argv, "aphA")) != -1) {
		switch (arg) {
			case 'p':
				print_cert = true;
				break;
			case 'a':
				allCerts = true;
				break;
			case 'A':
				addToKC = true;
				break;
			case 'h':
			default:
				usage(argv);
		}
	}
	if(optind != argc) {
		usage(argv);
	}
	if(!allCerts && (emailAddress == NULL)) {
		printf("***You must specify either an email address or the -a option.\n");
		exit(1);
	}
	
	OSStatus					ortn;
	SecKeychainSearchRef		srch;
	SecKeychainAttributeList	attrList;
	SecKeychainAttribute		attr;
	unsigned					numCerts = 0;
	
	if(emailAddress) {
		attr.tag = kSecAlias;			// i.e., email address
		attr.length = strlen(emailAddress);
		attr.data = (void *)emailAddress;
		attrList.count = 1;
		attrList.attr = &attr;
	}
	else {
		attrList.count = 0;
		attrList.attr = NULL;
	}
	ortn = SecKeychainSearchCreateFromAttributes(NULL,	// default search list
		kSecCertificateItemClass,
		&attrList,
		&srch);
	if(ortn) {
		cssmPerror("SecKeychainSearchCreateFromAttributes", ortn);
		exit(1);
	}
	
	do {
		SecCertificateRef certRef = NULL;
		CSSM_DATA certData;
		
		ortn = SecKeychainSearchCopyNext(srch, (SecKeychainItemRef *)&certRef);
		if(ortn) {
			break;
		}
		ortn = SecCertificateGetData(certRef, &certData);
		if(ortn) {
			cssmPerror("SecCertificateGetData", ortn);
			continue;
		}
		
		printf("=== Cert %u ===\n", numCerts);
		printCertName(certData.Data, certData.Length, NameBoth);
		if(print_cert) {
			printCert(certData.Data, certData.Length, CSSM_FALSE);
		}
		if(addToKC) {
			/* 
			 * Can't call SecCertificateAddToKeychain directly since this 
			 * cert already has a keychain. 
			 */
			SecCertificateRef newCertRef = NULL;
			ortn = SecCertificateCreateFromData(&certData,	
				CSSM_CERT_X_509v3,	CSSM_CERT_ENCODING_DER, 
				&newCertRef);
			if(ortn) {
				cssmPerror("SecCertificateCreateFromData", ortn);
				printf("***Error adding this cert to default keychain.\n");
			}
			else {
				ortn = SecCertificateAddToKeychain(newCertRef, NULL);
				if(ortn) {
					cssmPerror("SecCertificateAddToKeychain", ortn);
					printf("***Error adding this cert to default keychain.\n");
				}
				else {
					printf("...cert added to default keychain.\n");
				}
				CFRelease(newCertRef);
			}
		}
		CFRelease(certRef);
		numCerts++;
	} while(ortn == noErr);
	printf("...%u certs found matching email address \'%s\'\n", numCerts, 
		emailAddress ? emailAddress : "<any>");
	CFRelease(srch);
	return 0;
}