+++ /dev/null
-/*
- * Copyright (c) 2003-2010,2012,2014 Apple 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@
- *
- * identity_prefs.c
- */
-
-#include "identity_prefs.h"
-#include "identity_find.h"
-#include "keychain_utilities.h"
-#include "security_tool.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <Security/cssmtype.h>
-#include <Security/SecCertificate.h>
-#include <Security/SecIdentity.h>
-#include <Security/SecIdentitySearch.h>
-#include <Security/SecItem.h>
-
-// SecCertificateInferLabel, SecDigestGetData
-#include <Security/SecCertificatePriv.h>
-
-
-static int
-do_set_identity_preference(CFTypeRef keychainOrArray,
- const char *identity,
- const char *service,
- CSSM_KEYUSE keyUsage,
- const char *hash)
-{
- int result = 0;
- CFStringRef serviceRef = NULL;
- SecIdentityRef identityRef = NULL;
-
- // must have a service name
- if (!service) {
- return SHOW_USAGE_MESSAGE;
- }
-
- // find identity (if specified by name or hash)
- if (identity || hash) {
- identityRef = CopyMatchingIdentity(keychainOrArray, identity, hash, keyUsage);
- if (!identityRef) {
- sec_error("No matching identity found for \"%s\"", (hash) ? hash : identity);
- result = 1;
- goto cleanup;
- }
- }
-
- // set the identity preference
- serviceRef = CFStringCreateWithCString(NULL, service, kCFStringEncodingUTF8);
- result = SecIdentitySetPreference(identityRef, serviceRef, keyUsage);
-
-cleanup:
- if (identityRef)
- CFRelease(identityRef);
- if (serviceRef)
- CFRelease(serviceRef);
-
- return result;
-}
-
-typedef struct {
- int i;
- const char *name;
-} ctk_print_context;
-
-OSStatus ctk_dump_item(CFTypeRef item, ctk_print_context *ctx);
-
-static int
-do_get_identity_preference(const char *service,
- CSSM_KEYUSE keyUsage,
- Boolean printName,
- Boolean printHash,
- Boolean pemFormat)
-{
- int result = 0;
- if (!service) {
- return SHOW_USAGE_MESSAGE;
- }
- CFStringRef serviceRef = CFStringCreateWithCString(NULL, service, kCFStringEncodingUTF8);
- SecCertificateRef certRef = NULL;
- SecIdentityRef identityRef = NULL;
- CSSM_DATA certData = { 0, NULL };
-
- result = SecIdentityCopyPreference(serviceRef, keyUsage, NULL, &identityRef);
- if (result) {
- sec_perror("SecIdentityCopyPreference", result);
- goto cleanup;
- }
- result = SecIdentityCopyCertificate(identityRef, &certRef);
- if (result) {
- sec_perror("SecIdentityCopyCertificate", result);
- goto cleanup;
- }
- result = SecCertificateGetData(certRef, &certData);
- if (result) {
- sec_perror("SecCertificateGetData", result);
- goto cleanup;
- }
-
- if (printName) {
- char *nameBuf = NULL;
- CFStringRef nameRef = NULL;
- (void)SecCertificateCopyCommonName(certRef, &nameRef);
- CFIndex nameLen = (nameRef) ? CFStringGetLength(nameRef) : 0;
- if (nameLen > 0) {
- CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8);
- nameBuf = (char *)malloc(bufLen);
- if (!CFStringGetCString(nameRef, nameBuf, bufLen-1, kCFStringEncodingUTF8))
- nameBuf[0]=0;
- }
- fprintf(stdout, "common name: \"%s\"\n", (nameBuf && nameBuf[0] != 0) ? nameBuf : "<NULL>");
- if (nameBuf)
- free(nameBuf);
- safe_CFRelease(&nameRef);
- }
-
- if (printHash) {
- uint8 sha1_hash[20];
- CSSM_DATA digest;
- digest.Length = sizeof(sha1_hash);
- digest.Data = sha1_hash;
- if (SecDigestGetData(CSSM_ALGID_SHA1, &digest, &certData) == CSSM_OK) {
- unsigned int i;
- size_t len = digest.Length;
- uint8 *cp = digest.Data;
- fprintf(stdout, "SHA-1 hash: ");
- for(i=0; i<len; i++) {
- fprintf(stdout, "%02X", ((unsigned char *)cp)[i]);
- }
- fprintf(stdout, "\n");
- }
- }
-
- if (pemFormat)
- {
- CSSM_DATA certData = { 0, NULL };
- result = SecCertificateGetData(certRef, &certData);
- if (result) {
- sec_perror("SecCertificateGetData", result);
- goto cleanup;
- }
-
- print_buffer_pem(stdout, "CERTIFICATE", certData.Length, certData.Data);
- }
- else
- {
- CFTypeRef keys[] = { kSecValueRef, kSecReturnAttributes };
- CFTypeRef values[] = { certRef, kCFBooleanTrue };
- CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys) / sizeof(CFTypeRef), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- CFDictionaryRef attributes = NULL;
- if (SecItemCopyMatching(query, (void *)&attributes) == errSecSuccess && CFDictionaryContainsKey(attributes, kSecAttrTokenID)) {
- ctk_print_context ctx = { 1, "certificate" };
- ctk_dump_item(attributes, &ctx);
- } else
- print_keychain_item_attributes(stdout, (SecKeychainItemRef)certRef, FALSE, FALSE, FALSE, FALSE);
-
- CFRelease(query);
- if(attributes)
- CFRelease(attributes);
- }
-
-cleanup:
- safe_CFRelease(&serviceRef);
- safe_CFRelease(&certRef);
- safe_CFRelease(&identityRef);
-
- return result;
-}
-
-int
-set_identity_preference(int argc, char * const *argv)
-{
- int ch, result = 0;
- char *identity = NULL, *service = NULL, *hash = NULL;
- CSSM_KEYUSE keyUsage = 0;
- CFTypeRef keychainOrArray = NULL;
-
- /*
- * " -n Specify no identity (clears existing preference for service)\n"
- * " -c Specify identity by common name of the certificate\n"
- * " -s Specify service (URI, email address, DNS host, or other name)\n"
- * " for which this identity is to be preferred\n"
- * " -u Specify key usage (optional)\n"
- * " -Z Specify identity by SHA-1 hash of certificate (optional)\n"
- */
-
- while ((ch = getopt(argc, argv, "hnc:s:u:Z:")) != -1)
- {
- switch (ch)
- {
- case 'n':
- identity = NULL;
- break;
- case 'c':
- identity = optarg;
- break;
- case 's':
- service = optarg;
- break;
- case 'u':
- keyUsage = atoi(optarg);
- break;
- case 'Z':
- hash = optarg;
- break;
- case '?':
- default:
- result = SHOW_USAGE_MESSAGE;
- goto cleanup;
- }
- }
-
- argc -= optind;
- argv += optind;
-
- keychainOrArray = keychain_create_array(argc, argv);
-
- result = do_set_identity_preference(keychainOrArray, identity, service, keyUsage, hash);
-
-cleanup:
- safe_CFRelease(&keychainOrArray);
-
- return result;
-}
-
-int
-get_identity_preference(int argc, char * const *argv)
-{
- int ch, result = 0;
- char *service = NULL;
- Boolean printName = FALSE, printHash = FALSE, pemFormat = FALSE;
- CSSM_KEYUSE keyUsage = 0;
-
- /*
- * " -s Specify service (URI, email address, DNS host, or other name)\n"
- * " -u Specify key usage (optional)\n"
- * " -p Output identity certificate in pem format\n"
- * " -c Print common name of the preferred identity certificate (optional)\n"
- * " -Z Print SHA-1 hash of the preferred identity certificate (optional)\n"
- */
-
- while ((ch = getopt(argc, argv, "hs:u:pcZ")) != -1)
- {
- switch (ch)
- {
- case 'c':
- printName = TRUE;
- break;
- case 'p':
- pemFormat = TRUE;
- break;
- case 's':
- service = optarg;
- break;
- case 'u':
- keyUsage = atoi(optarg);
- break;
- case 'Z':
- printHash = TRUE;
- break;
- case '?':
- default:
- result = 2; /* @@@ Return 2 triggers usage message. */
- goto cleanup;
- }
- }
-
- result = do_get_identity_preference(service, keyUsage, printName, printHash, pemFormat);
-
-cleanup:
-
- return result;
-}
-