static VALUE rb_keychain_path(VALUE self){ SecKeychainRef keychain=NULL; Data_Get_Struct(self, struct OpaqueSecKeychainRef, keychain); UInt32 pathLength = PATH_MAX; char path[PATH_MAX]; OSStatus result = SecKeychainGetPath(keychain, &pathLength, path); CheckOSStatusOrRaise(result); return rb_enc_str_new(path, pathLength, rb_utf8_encoding()); }
std::string getKeychainPath(const SecKeychainItemRef& item) { SecKeychainRef keychain = nullptr; std::string path; auto status = SecKeychainItemCopyKeychain(item, &keychain); if (keychain == nullptr || status != errSecSuccess) { // Unhandled error, cannot get the keychain reference from certificate. return path; } UInt32 path_size = 1024; char keychain_path[1024] = {0}; status = SecKeychainGetPath(keychain, &path_size, keychain_path); if (status != errSecSuccess || (path_size > 0 && keychain_path[0] != 0)) { path = std::string(keychain_path); } CFRelease(keychain); return path; }
int main(int argc, char * const argv[]) { int verbose = 0; int dryRun = 0; int version = 0; char *toKeychainPath = NULL; struct option longopts[] = { { "dry-run", no_argument, &dryRun, 1 }, { "to-keychain", required_argument, NULL, 'k' }, { "verbose", no_argument, &verbose, 1 }, { "version", no_argument, &version, 1 }, { NULL, 0, NULL, 0 } }; int ch; while ((ch = getopt_long(argc, argv, "dk:v", longopts, NULL)) != -1) { switch (ch) { case 'k': toKeychainPath = optarg; break; case 'd': dryRun = 1; break; case 'v': verbose = 1; break; case 0: // Handle long-only options break; default: SRPrintUsage(); exit(EX_USAGE); } } argc -= optind; argv += optind; if (version) { fprintf(stderr, "splitring 1.1\nCopyright (C) 2013 Phil Calvin\n"); exit(0); } if (!argc) { SRPrintUsage(); exit(EX_USAGE); } CFMutableArrayRef keychains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // Iterate the passed keychain paths, opening each one for (int i = 0; i < argc; i++) { char* path = realpath(argv[i], NULL); if (path) { SecKeychainRef keychain = SROpenKeychain(path); CFArrayAppendValue(keychains, keychain); CFRelease(keychain); free(path); } else { fprintf(stderr, "Unable to find keychain: %s\n", argv[i]); } } // Unlock each of the keychains for (int i = 0; i < CFArrayGetCount(keychains); i++) { SecKeychainRef keychain = (SecKeychainRef)CFArrayGetValueAtIndex(keychains, i); // Unlock it; might not need to do this if (verbose) { UInt32 bufferSize = 4096; char keychainPath[bufferSize]; SecKeychainGetPath(keychain, &bufferSize, keychainPath); fprintf(stderr, "Unlocking keychain at path: %s\n", keychainPath); } OSStatus status = SecKeychainUnlock(keychain, 0, NULL, FALSE); SRHandleError(status, true); } SecKeychainRef targetKeychain = NULL; if (toKeychainPath) { // Convert this to a canonical path char* canonicalPath = realpath(toKeychainPath, NULL); if (canonicalPath) { // Import to the specified keychain targetKeychain = SROpenKeychain(canonicalPath); free(canonicalPath); } else { fprintf(stderr, "Unable to find keychain: %s\n", toKeychainPath); exit(EX_IOERR); } } else { // Import to the default keychain if one wasn't specified OSStatus status = SecKeychainCopyDefault(&targetKeychain); SRHandleError(status, true); status = SecKeychainUnlock(targetKeychain, 0, NULL, FALSE); SRHandleError(status, true); } // Search for all items CFMutableArrayRef classes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFArrayAppendValue(classes, kSecClassGenericPassword); CFArrayAppendValue(classes, kSecClassInternetPassword); //CFArrayAppendValue(classes, kSecClassCertificate); //CFArrayAppendValue(classes, kSecClassIdentity); //CFArrayAppendValue(classes, kSecClassKey); CFArrayRef items = SRCopyItems(keychains, classes); if (verbose) { UInt32 bufferSize = 4096; char defaultKeychainPath[bufferSize]; SecKeychainGetPath(targetKeychain, &bufferSize, defaultKeychainPath); fprintf(stderr, "Importing %li items to keychain at path: %s\n", CFArrayGetCount(items), defaultKeychainPath); } SRCopyItemsToKeychain(items, targetKeychain, verbose, dryRun); CFRelease(items); CFRelease(targetKeychain); CFRelease(keychains); return 0; }