+#include <Security/Security.h>
+#include "printCertName.h"
+#include <clAppUtils/clutils.h>
+#include <utilLib/common.h>
+
+static CSSM_CL_HANDLE gClHand = 0;
+
+static CSSM_CL_HANDLE getClHand()
+{
+ if(gClHand) {
+ return gClHand;
+ }
+ gClHand = clStartup();
+ return gClHand;
+}
+
+static void printString(
+ const CSSM_DATA *str)
+{
+ unsigned i;
+ char *cp = (char *)str->Data;
+ for(i=0; i<str->Length; i++) {
+ printf("%c", *cp++);
+ }
+ printf("\n");
+}
+
+static void printData(
+ const CSSM_DATA *cd)
+{
+ for(unsigned dex=0; dex<cd->Length; dex++) {
+ printf("%02X", cd->Data[dex]);
+ if((dex % 4) == 3) {
+ printf(" ");
+ }
+ }
+ printf("\n");
+}
+
+/*
+ * Print an CSSM_X509_TYPE_VALUE_PAIR
+ */
+static void printAtv(
+ const CSSM_X509_TYPE_VALUE_PAIR_PTR atv)
+{
+ const CSSM_OID *oid = &atv->type;
+ const char *fieldName = "Other";
+ if(appCompareCssmData(oid, &CSSMOID_CountryName)) {
+ fieldName = "Country ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_OrganizationName)) {
+ fieldName = "Org ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_LocalityName)) {
+ fieldName = "Locality ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_OrganizationalUnitName)) {
+ fieldName = "OrgUnit ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_CommonName)) {
+ fieldName = "Common Name ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_Surname)) {
+ fieldName = "Surname ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_Title)) {
+ fieldName = "Title ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_Surname)) {
+ fieldName = "Surname ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_StateProvinceName)) {
+ fieldName = "State ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_CollectiveStateProvinceName)) {
+ fieldName = "Coll. State ";
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_EmailAddress)) {
+ /* deprecated, used by Thawte */
+ fieldName = "Email addrs ";
+ }
+ else {
+ fieldName = "Other name ";
+ }
+ printf(" %s : ", fieldName);
+ switch(atv->valueType) {
+ case BER_TAG_PRINTABLE_STRING:
+ case BER_TAG_IA5_STRING:
+ case BER_TAG_T61_STRING: // mostly printable....
+ case BER_TAG_PKIX_UTF8_STRING: // ditto
+ printString(&atv->value);
+ break;
+ default:
+ printData(&atv->value);
+ break;
+ }
+}
+
+/*
+ * Print contents of a CSSM_X509_NAME.
+ */
+static void printName(
+ const char *title,
+ const CSSM_X509_NAME *name)
+{
+ printf(" %s:\n", title);
+ unsigned numRdns = name->numberOfRDNs;
+ for(unsigned rdnDex=0; rdnDex<numRdns; rdnDex++) {
+ const CSSM_X509_RDN *rdn = &name->RelativeDistinguishedName[rdnDex];
+ unsigned numAtvs = rdn->numberOfPairs;
+ for(unsigned atvDex=0; atvDex<numAtvs; atvDex++) {
+ printAtv(&rdn->AttributeTypeAndValue[atvDex]);
+ }
+ }
+}
+
+static void printOneCertName(
+ CSSM_CL_HANDLE clHand,
+ CSSM_HANDLE cacheHand,
+ const char *title,
+ const CSSM_OID *oid)
+{
+ CSSM_HANDLE resultHand = 0;
+ CSSM_DATA_PTR field = NULL;
+ uint32 numFields;
+ CSSM_RETURN crtn;
+
+ crtn = CSSM_CL_CertGetFirstCachedFieldValue(clHand, cacheHand,
+ oid, &resultHand, &numFields, &field);
+ if(crtn) {
+ printf("***Error parsing cert\n");
+ cssmPerror("CSSM_CL_CertGetFirstCachedFieldValue", crtn);
+ return;
+ }
+ printName(title, (CSSM_X509_NAME_PTR)field->Data);
+ CSSM_CL_FreeFieldValue(clHand, oid, field);
+ CSSM_CL_CertAbortQuery(clHand, resultHand);
+}
+
+/*
+ * Print subject and/or issuer of a cert.
+ */
+void printCertName(
+ const unsigned char *cert,
+ unsigned certLen,
+ WhichName whichName)
+{
+ CSSM_CL_HANDLE clHand = getClHand();
+ CSSM_HANDLE cacheHand;
+ CSSM_DATA certData = {certLen, (uint8 *)cert};
+ CSSM_RETURN crtn;
+ bool printSubj = false;
+ bool printIssuer = false;
+
+ switch(whichName) {
+ case NameBoth:
+ printSubj = true;
+ printIssuer = true;
+ break;
+ case NameSubject:
+ printSubj = true;
+ break;
+ case NameIssuer:
+ printIssuer = true;
+ break;
+ default:
+ printf("***BRRZAP! Illegal whichName argument\n");
+ return;
+ }
+
+ crtn = CSSM_CL_CertCache(clHand, &certData, &cacheHand);
+ if(crtn) {
+ printf("***Error parsing cert\n");
+ cssmPerror("CSSM_CL_CertCache", crtn);
+ return;
+ }
+
+ if(printSubj) {
+ printOneCertName(clHand, cacheHand, "Subject", &CSSMOID_X509V1SubjectNameCStruct);
+ }
+ if(printIssuer) {
+ printOneCertName(clHand, cacheHand, "Issuer", &CSSMOID_X509V1IssuerNameCStruct);
+ }
+ CSSM_CL_CertAbortCache(clHand, cacheHand);
+ return;
+}