--- /dev/null
+/*
+ * Find all certs in keychain search list matching specified email address.
+ */
+#include <Security/Security.h>
+#include <Security/SecKeychainItemPriv.h>
+#include <unistd.h>
+#include <security_cdsa_utils/cuPrintCert.h>
+#include "asnUtils.h"
+
+static void usage(char **argv)
+{
+ printf("Usage: %s [emailaddrs] [option...]\n", argv[0]);
+ printf("Options:\n");
+ printf(" -p -- print cert contents\n");
+ printf(" -a -- show all certs, no email match\n");
+ printf(" -A -- add to default keychain\n");
+ exit(1);
+}
+
+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;
+}
+