int keychain_import(int argc, char * const *argv) { int ch; int verbose=0; const char *keybag=NULL; const char *password=NULL; while ((ch = getopt(argc, argv, "vk:p:")) != -1) { switch (ch) { case 'v': verbose++; break; case 'k': keybag=optarg; break; case 'p': password=optarg; break; default: return 2; /* Trigger usage message. */ } } argc -= optind; argv += optind; if(keybag==NULL) { sec_error("-k is required\n"); return 2; } if (argc != 1) { sec_error("<backup> is required\n"); return 2; /* Trigger usage message. */ } return do_keychain_import(argv[0], keybag, password); }
int keychain_import(int argc, char * const *argv) { int ch, result = 0; char *inFile = NULL; char *kcName = NULL; SecKeychainRef kcRef = NULL; SecExternalFormat externFormat = kSecFormatUnknown; SecExternalItemType itemType = kSecItemTypeUnknown; Boolean wrapped = FALSE; Boolean nonExtractable = FALSE; const char *passphrase = NULL; unsigned char *inFileData = NULL; unsigned inFileLen = 0; CFDataRef inData = NULL; unsigned numExtendedAttributes = 0; char **attrNames = NULL; char **attrValues = NULL; Boolean access_specified = FALSE; Boolean always_allow = FALSE; SecAccessRef access = NULL; CFMutableArrayRef trusted_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); if(argc < 2) { result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } inFile = argv[1]; if((argc == 2) && (inFile[0] == '-')) { result = 2; goto cleanup; } optind = 2; while ((ch = getopt(argc, argv, "k:t:f:P:wxa:hAT:")) != -1) { switch (ch) { case 'k': kcName = optarg; break; case 't': if(!strcmp("pub", optarg)) { itemType = kSecItemTypePublicKey; } else if(!strcmp("priv", optarg)) { itemType = kSecItemTypePrivateKey; } else if(!strcmp("session", optarg)) { itemType = kSecItemTypeSessionKey; } else if(!strcmp("cert", optarg)) { itemType = kSecItemTypeCertificate; } else if(!strcmp("agg", optarg)) { itemType = kSecItemTypeAggregate; } else { result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } break; case 'f': if(!strcmp("openssl", optarg)) { externFormat = kSecFormatOpenSSL; } else if(!strcmp("openssh1", optarg)) { externFormat = kSecFormatSSH; } else if(!strcmp("openssh2", optarg)) { externFormat = kSecFormatSSHv2; } else if(!strcmp("bsafe", optarg)) { externFormat = kSecFormatBSAFE; } else if(!strcmp("raw", optarg)) { externFormat = kSecFormatRawKey; } else if(!strcmp("pkcs7", optarg)) { externFormat = kSecFormatPKCS7; } else if(!strcmp("pkcs8", optarg)) { externFormat = kSecFormatWrappedPKCS8; } else if(!strcmp("pkcs12", optarg)) { externFormat = kSecFormatPKCS12; } else if(!strcmp("netscape", optarg)) { externFormat = kSecFormatNetscapeCertSequence; } else if(!strcmp("x509", optarg)) { externFormat = kSecFormatX509Cert; } else if(!strcmp("pemseq", optarg)) { externFormat = kSecFormatPEMSequence; } else { result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } break; case 'w': wrapped = TRUE; break; case 'x': nonExtractable = TRUE; break; case 'P': passphrase = optarg; break; case 'a': /* this takes an additional argument */ if(optind > (argc - 1)) { result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } attrNames = (char **)realloc(attrNames, numExtendedAttributes * sizeof(char *)); attrValues = (char **)realloc(attrValues, numExtendedAttributes * sizeof(char *)); attrNames[numExtendedAttributes] = optarg; attrValues[numExtendedAttributes] = argv[optind]; numExtendedAttributes++; optind++; break; case 'A': always_allow = TRUE; access_specified = TRUE; break; case 'T': if (optarg[0]) { SecTrustedApplicationRef app = NULL; OSStatus status = noErr; /* check whether the argument specifies an application group */ const char *groupPrefix = "group://"; size_t prefixLen = strlen(groupPrefix); if (strlen(optarg) > prefixLen && !memcmp(optarg, groupPrefix, prefixLen)) { const char *groupName = &optarg[prefixLen]; if ((status = SecTrustedApplicationCreateApplicationGroup(groupName, NULL, &app)) != noErr) { sec_error("SecTrustedApplicationCreateApplicationGroup %s: %s", optarg, sec_errstr(status)); } } else { if ((status = SecTrustedApplicationCreateFromPath(optarg, &app)) != noErr) { sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status)); } } if (status) { result = 1; goto cleanup; } CFArrayAppendValue(trusted_list, app); CFRelease(app); } access_specified = TRUE; break; case '?': default: result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } } if(wrapped) { switch(externFormat) { case kSecFormatOpenSSL: case kSecFormatUnknown: // i.e., use default externFormat = kSecFormatWrappedOpenSSL; break; case kSecFormatSSH: externFormat = kSecFormatWrappedSSH; break; case kSecFormatSSHv2: /* there is no wrappedSSHv2 */ externFormat = kSecFormatWrappedOpenSSL; break; case kSecFormatWrappedPKCS8: /* proceed */ break; default: fprintf(stderr, "Don't know how to wrap in specified format/type\n"); result = 2; /* @@@ Return 2 triggers usage message. */ goto cleanup; } } if(kcName) { kcRef = keychain_open(kcName); if(kcRef == NULL) { return 1; } } if(readFile(inFile, &inFileData, &inFileLen)) { sec_error("Error reading infile %s: %s", inFile, strerror(errno)); result = 1; goto cleanup; } inData = CFDataCreate(NULL, inFileData, inFileLen); if(inData == NULL) { result = 1; goto cleanup; } free(inFileData); if(access_specified) { char *accessName = NULL; CFStringRef fileStr = CFStringCreateWithCString(NULL, inFile, kCFStringEncodingUTF8); if (fileStr) { CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, fileStr, kCFURLPOSIXPathStyle, FALSE); if (fileURL) { CFStringRef nameStr = CFURLCopyLastPathComponent(fileURL); if (nameStr) { CFIndex nameLen = CFStringGetLength(nameStr); CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8); accessName = (char *)malloc(bufLen); if (!CFStringGetCString(nameStr, accessName, bufLen-1, kCFStringEncodingUTF8)) accessName[0]=0; nameLen = strlen(accessName); char *p = &accessName[nameLen]; // initially points to terminating null while (--nameLen > 0) { if (*p == '.') { // strip extension, if any *p = '\0'; break; } p--; } safe_CFRelease(&nameStr); } safe_CFRelease(&fileURL); } safe_CFRelease(&fileStr); } result = create_access(accessName, always_allow, trusted_list, &access); if (accessName) { free(accessName); } if (result != 0) { goto cleanup; } } result = do_keychain_import(kcRef, inData, externFormat, itemType, access, nonExtractable, passphrase, inFile, attrNames, attrValues, numExtendedAttributes); cleanup: safe_CFRelease(&trusted_list); safe_CFRelease(&access); safe_CFRelease(&kcRef); safe_CFRelease(&inData); return result; }