]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/clxutils/krbtool/identPicker.cpp
Security-57740.51.3.tar.gz
[apple/security.git] / SecurityTests / clxutils / krbtool / identPicker.cpp
diff --git a/SecurityTests/clxutils/krbtool/identPicker.cpp b/SecurityTests/clxutils/krbtool/identPicker.cpp
deleted file mode 100644 (file)
index f750975..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
- * 
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * identPicker.cpp - Given a keychain, select from possible multiple
- *                  SecIdentityRefs via stdio UI, and cook up a 
- *                  CFArray containing that identity and all certs needed
- *                  for cert verification by an SSL peer. The resulting
- *                  CFArrayRef is suitable for passing to SSLSetCertificate().
- */
-#include "identPicker.h"
-#include <sys/param.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-
-/* 
- * Safe gets().
- * -- guaranteed no buffer overflow
- * -- guaranteed NULL-terminated string
- * -- handles empty string (i.e., response is just CR) properly
- */
-static void getString(
-       char *buf,
-       unsigned bufSize)
-{
-    unsigned dex;
-    char c;
-    char *cp = buf;
-    
-    for(dex=0; dex<bufSize-1; dex++) {
-       c = getchar();
-       if(!isprint(c)) {
-           break;
-       }
-       switch(c) {
-           case '\n':
-           case '\r':
-               goto done;
-           default:
-               *cp++ = c;
-       }
-    }
-done:
-    *cp = '\0';
-}
-
-/*
- * Obtain the printable name of a SecKeychainItemRef as a C string.
- * Caller must free() the result.
- */
-static char *kcItemPrintableName(
-    SecKeychainItemRef certRef)
-{
-    char *crtn = NULL;
-
-    /* just search for the one attr we want */
-    UInt32 tag = kSecLabelItemAttr;
-    SecKeychainAttributeInfo attrInfo;
-    attrInfo.count = 1;
-    attrInfo.tag = &tag;
-    attrInfo.format = NULL;
-    SecKeychainAttributeList *attrList = NULL;
-    SecKeychainAttribute *attr = NULL;
-    
-    OSStatus ortn = SecKeychainItemCopyAttributesAndData(
-       (SecKeychainItemRef)certRef, 
-       &attrInfo,
-       NULL,                   // itemClass
-       &attrList, 
-       NULL,                   // length - don't need the data
-       NULL);                  // outData
-    if(ortn) {
-       cssmPerror("SecKeychainItemCopyAttributesAndData", ortn);
-       /* may want to be a bit more robust here, but this should
-        * never happen */
-       return strdup("Unnamed KeychainItem");
-    }
-    /* subsequent errors to errOut: */
-    
-    if((attrList == NULL) || (attrList->count != 1)) {
-       printf("***Unexpected result fetching label attr\n");
-       crtn = strdup("Unnamed KeychainItem");
-       goto errOut;
-    }
-    /* We're assuming 8-bit ASCII attribute data here... */
-    attr = attrList->attr;
-    crtn = (char *)malloc(attr->length + 1);
-    memmove(crtn, attr->data, attr->length);
-    crtn[attr->length] = '\0';
-    
-errOut:
-    SecKeychainItemFreeAttributesAndData(attrList, NULL);
-    return crtn;
-}
-
-/*
- * Get the final term of a keychain's path as a C string. Caller must free() 
- * the result.
- */
-static char *kcFileName(
-       SecKeychainRef kcRef)
-{
-    char fullPath[MAXPATHLEN + 1];
-    OSStatus ortn;
-    UInt32 pathLen = MAXPATHLEN;
-    
-    ortn = SecKeychainGetPath(kcRef,  &pathLen, fullPath);
-    if(ortn) {
-       cssmPerror("SecKeychainGetPath", ortn);
-       return strdup("orphan keychain");
-    }
-    
-    /* NULL terminate the path string and search for final '/' */
-    fullPath[pathLen] = '\0';
-    char *lastSlash = NULL;
-    char *thisSlash = fullPath;
-    do {
-       thisSlash = strchr(thisSlash, '/');
-       if(thisSlash == NULL) {
-           /* done */
-           break;
-       }
-       thisSlash++;
-       lastSlash = thisSlash;
-    } while(thisSlash != NULL);
-    if(lastSlash == NULL) {
-       /* no slashes, odd, but handle it */
-       return strdup(fullPath);
-    }
-    else {
-       return strdup(lastSlash);
-    }
-}
-
-/*
- * Determine if specified SecCertificateRef is a self-signed cert.
- * We do this by comparing the subject and issuerr names; no cryptographic
- * verification is performed.
- *
- * Returns true if the cert appears to be a root. 
- */
-static bool isCertRefRoot(
-       SecCertificateRef certRef)
-{
-    /* just search for the two attrs we want */
-    UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr};
-    SecKeychainAttributeInfo attrInfo;
-    attrInfo.count = 2;
-    attrInfo.tag = tags;
-    attrInfo.format = NULL;
-    SecKeychainAttributeList *attrList = NULL;
-    SecKeychainAttribute *attr1 = NULL;
-    SecKeychainAttribute *attr2 = NULL;
-    bool brtn = false;
-    
-    OSStatus ortn = SecKeychainItemCopyAttributesAndData(
-       (SecKeychainItemRef)certRef, 
-       &attrInfo,
-       NULL,                   // itemClass
-       &attrList, 
-       NULL,                   // length - don't need the data
-       NULL);                  // outData
-    if(ortn) {
-       cssmPerror("SecKeychainItemCopyAttributesAndData", ortn);
-       /* may want to be a bit more robust here, but this should
-        * never happen */
-       return false;
-    }
-    /* subsequent errors to errOut: */
-    
-    if((attrList == NULL) || (attrList->count != 2)) {
-       printf("***Unexpected result fetching label attr\n");
-       goto errOut;
-    }
-    
-    /* rootness is just byte-for-byte compare of the two names */ 
-    attr1 = &attrList->attr[0];
-    attr2 = &attrList->attr[1];
-    if(attr1->length == attr2->length) {
-       if(memcmp(attr1->data, attr2->data, attr1->length) == 0) {
-           brtn = true;
-       }
-    }
-errOut:
-    SecKeychainItemFreeAttributesAndData(attrList, NULL);
-    return brtn;
-}
-
-
-/*
- * Given a SecIdentityRef, do our best to construct a complete, ordered, and 
- * verified cert chain, returning the result in a CFArrayRef. The result is 
- * suitable for use when calling SSLSetCertificate().
- */
-static OSStatus completeCertChain(
-       SecIdentityRef          identity, 
-       SecCertificateRef       trustedAnchor,  // optional additional trusted anchor
-       bool                    includeRoot,    // include the root in outArray
-       CFArrayRef              *outArray)      // created and RETURNED
-{
-    CFMutableArrayRef                  certArray;
-    SecTrustRef                                        secTrust = NULL;
-    SecPolicyRef                               policy = NULL;
-    SecPolicySearchRef                 policySearch = NULL;
-    SecTrustResultType                 secTrustResult;
-    CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv;                      // not used
-    CFArrayRef                                 certChain = NULL;   // constructed chain
-    CFIndex                                    numResCerts;
-    
-    certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    CFArrayAppendValue(certArray, identity);
-    
-    /*
-     * Case 1: identity is a root; we're done. Note that this case
-     * overrides the includeRoot argument.
-     */
-    SecCertificateRef certRef;
-    OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef);
-    if(ortn) {
-       /* should never happen */
-       cssmPerror("SecIdentityCopyCertificate", ortn);
-       return ortn;
-    }
-    bool isRoot = isCertRefRoot(certRef);
-    if(isRoot) {
-       *outArray = certArray;
-       CFRelease(certRef);
-       return noErr;
-    }
-    
-    /* 
-     * Now use SecTrust to get a complete cert chain, using all of the 
-     * user's keychains to look for intermediate certs.
-     * NOTE this does NOT handle root certs which are not in the system
-     * root cert DB. (The above case, where the identity is a root cert, does.)
-     */
-    CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
-    CFArraySetValueAtIndex(subjCerts, 0, certRef);
-                   
-    /* the array owns the subject cert ref now */
-    CFRelease(certRef);
-    
-    /* Get a SecPolicyRef for generic X509 cert chain verification */
-    ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
-           &CSSMOID_APPLE_X509_BASIC,
-           NULL,                               // value
-           &policySearch);
-    if(ortn) {
-       cssmPerror("SecPolicySearchCreate", ortn);
-       goto errOut;
-    }
-    ortn = SecPolicySearchCopyNext(policySearch, &policy);
-    if(ortn) {
-       cssmPerror("SecPolicySearchCopyNext", ortn);
-       goto errOut;
-    }
-
-    /* build a SecTrustRef for specified policy and certs */
-    ortn = SecTrustCreateWithCertificates(subjCerts,
-           policy, &secTrust);
-    if(ortn) {
-       cssmPerror("SecTrustCreateWithCertificates", ortn);
-       goto errOut;
-    }
-    
-    if(trustedAnchor) {
-       /* 
-        * Tell SecTrust to trust this one in addition to the current
-        * trusted system-wide anchors.
-        */
-       CFMutableArrayRef newAnchors;
-       CFArrayRef currAnchors;
-       
-       ortn = SecTrustCopyAnchorCertificates(&currAnchors);
-       if(ortn) {
-           /* should never happen */
-           cssmPerror("SecTrustCopyAnchorCertificates", ortn);
-           goto errOut;
-       }
-       newAnchors = CFArrayCreateMutableCopy(NULL,
-           CFArrayGetCount(currAnchors) + 1,
-           currAnchors);
-       CFRelease(currAnchors);
-       CFArrayAppendValue(newAnchors, trustedAnchor);
-       ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
-       CFRelease(newAnchors);
-       if(ortn) {
-           cssmPerror("SecTrustSetAnchorCertificates", ortn);
-           goto errOut;
-       }
-    }
-    /* evaluate: GO */
-    ortn = SecTrustEvaluate(secTrust, &secTrustResult);
-    if(ortn) {
-       cssmPerror("SecTrustEvaluate", ortn);
-       goto errOut;
-    }
-    switch(secTrustResult) {
-       case kSecTrustResultUnspecified:
-           /* cert chain valid, no special UserTrust assignments */
-       case kSecTrustResultProceed:
-           /* cert chain valid AND user explicitly trusts this */
-           break;
-       default:
-           /*
-            * Cert chain construction failed. 
-            * Just go with the single subject cert we were given.
-            */
-           printf("***Warning: could not construct completed cert chain\n");
-           ortn = noErr;
-           goto errOut;
-    }
-
-    /* get resulting constructed cert chain */
-    ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
-    if(ortn) {
-       cssmPerror("SecTrustEvaluate", ortn);
-       goto errOut;
-    }
-    
-    /*
-     * Copy certs from constructed chain to our result array, skipping 
-     * the leaf (which is already there, as a SecIdentityRef) and possibly
-     * a root.
-     */
-    numResCerts = CFArrayGetCount(certChain);
-    if(numResCerts < 2) {
-       /*
-        * Can't happen: if subject was a root, we'd already have returned. 
-        * If chain doesn't verify to a root, we'd have bailed after
-        * SecTrustEvaluate().
-        */
-       printf("***sslCompleteCertChain screwup: numResCerts %d\n", 
-               (int)numResCerts);
-       ortn = noErr;
-       goto errOut;
-    }
-    if(!includeRoot) {
-       /* skip the last (root) cert) */
-       numResCerts--;
-    }
-    for(CFIndex dex=1; dex<numResCerts; dex++) {
-       certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
-       CFArrayAppendValue(certArray, certRef);
-    }
-errOut:
-    /* clean up */
-    if(secTrust) {
-       CFRelease(secTrust);
-    }
-    if(subjCerts) {
-       CFRelease(subjCerts);
-    }
-    if(policy) {
-       CFRelease(policy);
-    }
-    if(policySearch) {
-       CFRelease(policySearch);
-    }
-    *outArray = certArray;
-    return ortn;
-}
-
-
-/*
- * Given an array of SecIdentityRefs:
- *  -- display a printable name of each identity's cert;
- *  -- prompt user to select which one to use;
- *
- * Returns CFIndex of desired identity. A return of <0 indicates
- * "none - abort".
- */
-static CFIndex pickIdent(
-       CFArrayRef idArray)
-{
-    CFIndex count = CFArrayGetCount(idArray);
-    CFIndex dex;
-    OSStatus ortn;
-    
-    if(count == 0) {
-           printf("***sslIdentPicker screwup: no identities found\n");
-           return -1;
-    }
-    for(dex=0; dex<count; dex++) {
-       SecIdentityRef idRef = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, dex);
-       SecCertificateRef certRef;
-       ortn = SecIdentityCopyCertificate(idRef, &certRef);
-       if(ortn) {
-           /* should never happen */
-           cssmPerror("SecIdentityCopyCertificate", ortn);
-           return -1;
-       }
-       
-       /* get printable name of cert and the keychain it's in */
-       char *certLabel = kcItemPrintableName((SecKeychainItemRef)certRef);
-       SecKeychainRef kcRef;
-       char *kcLabel;
-       ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)certRef, &kcRef);
-       if(ortn) {
-           cssmPerror("SecKeychainItemCopyKeychain", ortn);
-           kcLabel = "Unnamed keychain";
-       }
-       else {
-           kcLabel = kcFileName(kcRef);
-       }
-       printf("[%d] keychain : %s\n", (int)dex, kcLabel);
-       printf("    cert     : %s\n", certLabel);
-       free(certLabel);
-       if(ortn == noErr) {
-           free(kcLabel);
-       }
-       CFRelease(certRef);
-    }
-    
-    while(1) {
-       fpurge(stdin);
-       printf("\nEnter Certificate number or CR to quit : ");
-       fflush(stdout);
-       char resp[64];
-       getString(resp, sizeof(resp));
-       if(resp[0] == '\0') {
-           return -1;
-       }
-       int ires = atoi(resp);
-       if((ires >= 0) && (ires < count)) {
-           return (CFIndex)ires;
-       }
-       printf("***Invalid entry. Type a number between 0 and %d\n", 
-           (int)(count-1));
-    }
-    return -1;
-}
-
-OSStatus simpleIdentPicker(
-    SecKeychainRef     kcRef,                  // NULL means use default list
-    SecIdentityRef     *ident)                 // RETURNED
-{
-    OSStatus           ortn;
-    CFMutableArrayRef  idArray = NULL;         // holds all SecIdentityRefs found
-    
-    /* Search for all identities */
-    *ident = NULL;
-    SecIdentitySearchRef srchRef = nil;
-    ortn = SecIdentitySearchCreate(kcRef, 
-       0,                              // keyUsage - any
-       &srchRef);
-    if(ortn) {
-       cssmPerror("SecIdentitySearchCreate", (CSSM_RETURN)ortn);
-       printf("Cannot find signing key in keychain.\n");
-       return ortn;
-    }
-    
-    /* get all identities, stuff them into idArray */
-    SecIdentityRef identity = nil;
-    idArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    do {
-       ortn = SecIdentitySearchCopyNext(srchRef, &identity);
-       if(ortn != noErr) {
-           break;
-       }
-       CFArrayAppendValue(idArray, identity);
-       
-       /* the array has the retain count we need */
-       CFRelease(identity);
-    } while(ortn == noErr);
-    
-    switch(ortn) {
-       case errSecItemNotFound:
-           if(CFArrayGetCount(idArray) == 0) {
-               printf("No signing keys found in keychain.\n");
-               return errSecItemNotFound;
-           }
-           else {
-               /* found at least one; proceed */
-               break;
-           }
-       default:
-           cssmPerror("SecIdentitySearchCopyNext", (CSSM_RETURN)ortn);
-           printf("Cannot find signing key in keychain.\n");
-           return ortn;
-    }
-    
-    /*
-     * If there is just one, use it without asking 
-     */
-    CFIndex whichId;
-    if(CFArrayGetCount(idArray) == 1) {
-       whichId = 0;
-    }
-    else {
-       whichId = pickIdent(idArray);
-       if(whichId < 0) {
-           return CSSMERR_CSSM_USER_CANCELED;
-       }
-    }
-    
-    /* keep this one, free the rest */
-    identity = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, whichId);
-    CFRetain(identity);
-    CFRelease(idArray);
-    *ident = identity;
-    return noErr;
-}
-
-OSStatus identPicker(
-    SecKeychainRef     kcRef,          // NULL means use default list
-    SecCertificateRef  trustedAnchor,  // optional additional trusted anchor
-    bool               includeRoot,    // true --> root is appended to outArray
-                                       // false --> root not included
-    CFArrayRef         *outArray)      // created and RETURNED
-{
-    OSStatus                   ortn;
-    SecIdentityRef             identity;
-    
-    ortn = simpleIdentPicker(kcRef, &identity);
-    if(ortn) {
-       return ortn;
-    }
-    return completeCertChain(identity, trustedAnchor, includeRoot, outArray);
-}
-