/ SecurityTool / macOS / keychain_recode.c
keychain_recode.c
  1  /*
  2   * Copyright (c) 2003-2005,2009,2012,2014 Apple 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_cssm.h"
 30  #include "security_tool.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  
 44  static int
 45  do_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  
 93  loser:
 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  
108  int
109  keychain_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 SHOW_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 SHOW_USAGE_MESSAGE;
145  
146  	result = do_recode(keychainName1, keychainName2);
147  
148  loser:
149  
150  	return result;
151  }