1/* 2 * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 * 23 * keychain_recode.c 24 */ 25 26#include "keychain_recode.h" 27 28#include "keychain_utilities.h" 29#include "readline.h" 30#include "security.h" 31 32#include <pwd.h> 33#include <stdio.h> 34#include <stdlib.h> 35#include <string.h> 36#include <unistd.h> 37#include <CoreFoundation/CoreFoundation.h> 38#include <Security/SecKeychain.h> 39 40// SecKeychainCopyBlob, SecKeychainRecodeKeychain 41#include <Security/SecKeychainPriv.h> 42 43 44static int 45do_recode(const char *keychainName1, const char *keychainName2) 46{ 47 SecKeychainRef keychain1 = NULL, keychain2 = NULL; 48 CFMutableArrayRef dbBlobArray = NULL; 49 CFDataRef dbBlob = NULL, extraData = NULL; 50 OSStatus result; 51 52 if (keychainName1) 53 { 54 keychain1 = keychain_open(keychainName1); 55 if (!keychain1) 56 { 57 result = 1; 58 goto loser; 59 } 60 } 61 62 keychain2 = keychain_open(keychainName2); 63 if (!keychain2) 64 { 65 result = 1; 66 goto loser; 67 } 68 69 result = SecKeychainCopyBlob(keychain2, &dbBlob); 70 if (result) 71 { 72 sec_error("SecKeychainCopyBlob %s: %s", keychainName2, 73 sec_errstr(result)); 74 goto loser; 75 } 76 77 extraData = CFDataCreate(NULL, NULL, 0); 78 79 dbBlobArray = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); 80 if (dbBlobArray) { 81 CFArrayAppendValue(dbBlobArray, dbBlob); 82 } 83 84#if !defined MAC_OS_X_VERSION_10_6 || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 85 result = SecKeychainRecodeKeychain(keychain1, dbBlob, extraData); 86#else 87 result = SecKeychainRecodeKeychain(keychain1, dbBlobArray, extraData); 88#endif 89 if (result) 90 sec_error("SecKeychainRecodeKeychain %s, %s: %s", keychainName1, 91 keychainName2, sec_errstr(result)); 92 93loser: 94 if (dbBlobArray) 95 CFRelease(dbBlobArray); 96 if (dbBlob) 97 CFRelease(dbBlob); 98 if (extraData) 99 CFRelease(extraData); 100 if (keychain1) 101 CFRelease(keychain1); 102 if (keychain2) 103 CFRelease(keychain2); 104 105 return result; 106} 107 108int 109keychain_recode(int argc, char * const *argv) 110{ 111 char *keychainName1 = NULL, *keychainName2 = NULL; 112 int ch, result = 0; 113 114 while ((ch = getopt(argc, argv, "h")) != -1) 115 { 116 switch (ch) 117 { 118 case '?': 119 default: 120 return 2; /* @@@ Return 2 triggers usage message. */ 121 } 122 } 123 argc -= optind; 124 argv += optind; 125 126 if (argc == 2) 127 { 128 keychainName1 = argv[0]; 129 if (*keychainName1 == '\0') 130 { 131 result = 2; 132 goto loser; 133 } 134 135 keychainName2 = argv[1]; 136 if (*keychainName2 == '\0') 137 { 138 result = 2; 139 goto loser; 140 } 141 142 } 143 else 144 return 2; 145 146 result = do_recode(keychainName1, keychainName2); 147 148loser: 149 150 return result; 151} 152