X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/b04fe171f0375ecd5d8a24747ca1dff85720a0ca..6b200bc335dc93c5516ccb52f14bd896d8c7fad7:/SecurityTests/clxutils/krbtool/identPicker.cpp diff --git a/SecurityTests/clxutils/krbtool/identPicker.cpp b/SecurityTests/clxutils/krbtool/identPicker.cpp deleted file mode 100644 index f7509755..00000000 --- a/SecurityTests/clxutils/krbtool/identPicker.cpp +++ /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 -#include -#include -#include - -/* - * 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; dexcount != 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= 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); -} -