static VALUE rb_keychain_item_delete(VALUE self){ SecKeychainItemRef keychainItem=NULL; Data_Get_Struct(self, struct OpaqueSecKeychainItemRef, keychainItem); OSStatus result = SecKeychainItemDelete(keychainItem); CheckOSStatusOrRaise(result); return self; }
static int do_keychain_delete_internet_password(CFTypeRef keychainOrArray, FourCharCode itemCreator, FourCharCode itemType, const char *kind, const char *comment, const char *label, const char *serverName, const char *securityDomain, const char *accountName, const char *path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType) { OSStatus result = noErr; SecKeychainItemRef itemRef = NULL; void *passwordData = NULL; itemRef = find_first_internet_password(keychainOrArray, itemCreator, itemType, kind, comment, label, serverName, securityDomain, accountName, path, port, protocol, authenticationType); if (!itemRef) { result = errSecItemNotFound; sec_perror("SecKeychainSearchCopyNext", result); goto cleanup; } print_keychain_item_attributes(stdout, itemRef, FALSE, FALSE, FALSE, FALSE); result = SecKeychainItemDelete(itemRef); fputs("password has been deleted.\n", stderr); cleanup: if (passwordData) SecKeychainItemFreeContent(NULL, passwordData); if (itemRef) CFRelease(itemRef); return result; }
void keychain_clear_password(const char *server, const char *username) { if (!strlen(server) || !strlen(username)) return; BADGE_HOSTNAME(server); SecKeychainItemRef keychainItem = get_password_details(server, username, NULL, 0); if (keychainItem) SecKeychainItemDelete(keychainItem); free((void*)server); }
static OSStatus callbackFunction(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void *context) { assert(keychainEvent == kSecAddEvent && context != NULL); assert(info != NULL); assert(info->item != NULL); checkContent(info->item); *((UInt32 *)context) = 1; ok_status(SecKeychainItemDelete(info->item), "delete item"); return 0; }
char *keychain_remove(char *service, char *account) { SecKeychainItemRef item; OSStatus status = SecKeychainFindGenericPassword( NULL, strlen(service), service, strlen(account), account, NULL, NULL, &item ); if (status) return get_error(status); status = SecKeychainItemDelete(item); if (status) return get_error(status); return NULL; }
static void delete_internet_password(void) { SecKeychainItemRef item; /* * Require at least a protocol and host for removal, which is what git * will give us; if you want to do something more fancy, use the * Keychain manager. */ if (!protocol || !host) return; if (SecKeychainFindInternetPassword(KEYCHAIN_ARGS, 0, NULL, &item)) return; SecKeychainItemDelete(item); }
/* Implementation of OSXKeychain.deleteGenericPassword(). See the Java docs for * explanations of the parameters. */ JNIEXPORT void JNICALL Java_com_mcdermottroe_apple_OSXKeychain__1deleteGenericPassword(JNIEnv* env, jobject obj, jstring serviceName, jstring accountName) { OSStatus status; jstring_unpacked service_name; jstring_unpacked account_name; SecKeychainItemRef itemToDelete; /* Query the keychain. */ status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainUser); if (status != errSecSuccess) { throw_osxkeychainexception(env, status); return; } /* Unpack the params. */ jstring_unpack(env, serviceName, &service_name); jstring_unpack(env, accountName, &account_name); if (service_name.str == NULL || account_name.str == NULL) { jstring_unpacked_free(env, serviceName, &service_name); jstring_unpacked_free(env, accountName, &account_name); return; } status = SecKeychainFindGenericPassword( NULL, service_name.len, service_name.str, account_name.len, account_name.str, NULL, NULL, &itemToDelete ); if (status != errSecSuccess) { throw_osxkeychainexception(env, status); } else { status = SecKeychainItemDelete(itemToDelete); if (status != errSecSuccess) { throw_osxkeychainexception(env, status); } } /* Clean up. */ jstring_unpacked_free(env, serviceName, &service_name); jstring_unpacked_free(env, accountName, &account_name); }
static int do_keychain_delete_generic_password(CFTypeRef keychainOrArray, FourCharCode itemCreator, FourCharCode itemType, const char *kind, const char *value, const char *comment, const char *label, const char *serviceName, const char *accountName) { OSStatus result = noErr; SecKeychainItemRef itemRef = NULL; void *passwordData = NULL; itemRef = find_first_generic_password(keychainOrArray, itemCreator, itemType, kind, value, comment, label, serviceName, accountName); if (!itemRef) { result = errSecItemNotFound; sec_perror("SecKeychainSearchCopyNext", result); goto cleanup; } print_keychain_item_attributes(stdout, itemRef, FALSE, FALSE, FALSE, FALSE); result = SecKeychainItemDelete(itemRef); fputs("password has been deleted.\n", stderr); cleanup: if (passwordData) SecKeychainItemFreeContent(NULL, passwordData); if (itemRef) CFRelease(itemRef); return result; }
int main(int argc, char **argv) { if ((argc < 3) || (argc > 4)) { printf("Usage: %s <service> <account> [<password>]\n", argv[0]); return 1; } const char *service = argv[1]; const char *login = argv[2]; const char *password = argc == 4 ? argv[3] : NULL; void *buf; UInt32 len; SecKeychainItemRef item; if (password != NULL) { if (key_exists_p(service, login, &item) == 0) { SecKeychainItemDelete(item); } OSStatus create_key = SecKeychainAddGenericPassword( NULL, strlen(service), service, strlen(login), login, strlen(password), password, &item ); if (create_key != 0) { fprintf(stderr, "Boxen Keychain Helper: Encountered error code: %d\n", create_key); return 1; } } else { OSStatus find_key = SecKeychainFindGenericPassword( NULL, strlen(service), service, strlen(login), login, &len, &buf, &item); if (find_key != 0) { fprintf(stderr, "Boxen Keychain Helper: Encountered error code: %d\n", find_key); return 1; } fwrite(buf, 1, len, stdout); } return 0; }
bool OsxWallet::deleteCredentials(const QString &realm, const QString &user) { const QByteArray realm_data = realm.toUtf8(); const QByteArray user_data = user.toUtf8(); SecKeychainItemRef itemRef = NULL; /* check whether the entry exists */ int rc = SecKeychainFindInternetPassword(keychain, realm_data.size(), realm_data.constData(), 0, NULL, user_data.size(), user_data.constData(), 0, NULL, 0, kSecProtocolTypeAny, kSecAuthenticationTypeAny, 0, NULL, &itemRef); if (rc != errSecSuccess) return false; rc = SecKeychainItemDelete(itemRef); CFRelease(itemRef); return (rc == errSecSuccess); }
OSStatus SecIdentityDeletePreferenceItemWithNameAndKeyUsage( CFTypeRef keychainOrArray, CFStringRef name, int32_t keyUsage) { // when a specific key usage is passed, we'll only match & delete that pref; // when a key usage of 0 is passed, all matching prefs should be deleted. // maxUsages represents the most matches there could theoretically be, so // cut things off at that point if we're still finding items (if they can't // be deleted for some reason, we'd never break out of the loop.) OSStatus status; SecKeychainItemRef item = NULL; int count = 0, maxUsages = 12; while (++count <= maxUsages && (status = SecIdentityFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) { status = SecKeychainItemDelete(item); CFRelease(item); item = NULL; } // it's not an error if the item isn't found return (status == errSecItemNotFound) ? errSecSuccess : status; }
OSStatus OTMacKeychain::ItemDelete(SecKeychainItemRef itemRef) const { return SecKeychainItemDelete(itemRef); }
static krb5_error_code get_new_tickets(krb5_context context, krb5_principal principal, krb5_ccache ccache, krb5_deltat ticket_life, int interactive) { krb5_error_code ret; krb5_get_init_creds_opt *opt; krb5_creds cred; char passwd[256]; krb5_deltat start_time = 0; krb5_deltat renew = 0; const char *renewstr = NULL; krb5_enctype *enctype = NULL; krb5_ccache tempccache; krb5_init_creds_context icc; krb5_keytab kt = NULL; int will_use_keytab = (use_keytab || keytab_str); krb5_prompter_fct prompter = NULL; int need_prompt; passwd[0] = '\0'; if (password_file) { FILE *f; if (strcasecmp("STDIN", password_file) == 0) f = stdin; else f = fopen(password_file, "r"); if (f == NULL) krb5_errx(context, 1, "Failed to open the password file %s", password_file); if (fgets(passwd, sizeof(passwd), f) == NULL) krb5_errx(context, 1, N_("Failed to read password from file %s", ""), password_file); if (f != stdin) fclose(f); passwd[strcspn(passwd, "\n")] = '\0'; } #if defined(__APPLE__) && !defined(__APPLE_TARGET_EMBEDDED__) if (passwd[0] == '\0' && !will_use_keytab && home_directory_flag) { const char *realm; OSStatus osret; UInt32 length; void *buffer; char *name; realm = krb5_principal_get_realm(context, principal); ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); if (ret) goto nopassword; osret = SecKeychainFindGenericPassword(NULL, (UInt32)strlen(realm), realm, (UInt32)strlen(name), name, &length, &buffer, &passwordItem); free(name); if (osret != noErr) goto nopassword; if (length < sizeof(passwd) - 1) { memcpy(passwd, buffer, length); passwd[length] = '\0'; } SecKeychainItemFreeContent(NULL, buffer); nopassword: do { } while(0); } #endif need_prompt = !(pk_user_id || ent_user_id || anonymous_flag || will_use_keytab || passwd[0] != '\0') && interactive; if (need_prompt) prompter = krb5_prompter_posix; else prompter = krb5_prompter_print_only; memset(&cred, 0, sizeof(cred)); ret = krb5_get_init_creds_opt_alloc (context, &opt); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); krb5_get_init_creds_opt_set_default_flags(context, "kinit", krb5_principal_get_realm(context, principal), opt); if(forwardable_flag != -1) krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag); if(proxiable_flag != -1) krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag); if(anonymous_flag) krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag); if (pac_flag != -1) krb5_get_init_creds_opt_set_pac_request(context, opt, pac_flag ? TRUE : FALSE); if (canonicalize_flag) krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE); if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag) krb5_get_init_creds_opt_set_win2k(context, opt, TRUE); if (pk_user_id || ent_user_id || anonymous_flag) { ret = krb5_get_init_creds_opt_set_pkinit(context, opt, principal, pk_user_id, pk_x509_anchors, NULL, NULL, pk_use_enckey ? 2 : 0 | anonymous_flag ? 4 : 0, interactive ? krb5_prompter_posix : krb5_prompter_print_only, NULL, passwd); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit"); if (ent_user_id) krb5_get_init_creds_opt_set_pkinit_user_cert(context, opt, ent_user_id); } if (addrs_flag != -1) krb5_get_init_creds_opt_set_addressless(context, opt, addrs_flag ? FALSE : TRUE); if (renew_life == NULL && renewable_flag) renewstr = "1 month"; if (renew_life) renewstr = renew_life; if (renewstr) { renew = parse_time (renewstr, "s"); if (renew < 0) errx (1, "unparsable time: %s", renewstr); krb5_get_init_creds_opt_set_renew_life (opt, renew); } if(ticket_life != 0) krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life); if(start_str) { int tmp = parse_time (start_str, "s"); if (tmp < 0) errx (1, N_("unparsable time: %s", ""), start_str); start_time = tmp; } if(etype_str.num_strings) { int i; enctype = malloc(etype_str.num_strings * sizeof(*enctype)); if(enctype == NULL) errx(1, "out of memory"); for(i = 0; i < etype_str.num_strings; i++) { ret = krb5_string_to_enctype(context, etype_str.strings[i], &enctype[i]); if(ret) krb5_err(context, 1, ret, "unrecognized enctype: %s", etype_str.strings[i]); } krb5_get_init_creds_opt_set_etype_list(opt, enctype, etype_str.num_strings); } ret = krb5_init_creds_init(context, principal, prompter, NULL, start_time, opt, &icc); if (ret) krb5_err (context, 1, ret, "krb5_init_creds_init"); if (server_str) { ret = krb5_init_creds_set_service(context, icc, server_str); if (ret) krb5_err (context, 1, ret, "krb5_init_creds_set_service"); } if (kdc_hostname) krb5_init_creds_set_kdc_hostname(context, icc, kdc_hostname); if (fast_armor_cache_string) { krb5_ccache fastid; ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid); if (ret) krb5_err(context, 1, ret, "krb5_cc_resolve(FAST cache)"); ret = krb5_init_creds_set_fast_ccache(context, icc, fastid); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_set_fast_ccache"); } if(will_use_keytab) { if(keytab_str) ret = krb5_kt_resolve(context, keytab_str, &kt); else ret = krb5_kt_default(context, &kt); if (ret) krb5_err (context, 1, ret, "resolving keytab"); ret = krb5_init_creds_set_keytab(context, icc, kt); if (ret) krb5_err (context, 1, ret, "krb5_init_creds_set_keytab"); } if (passwd[0] == '\0' && need_prompt) { char *p, *prompt; krb5_unparse_name(context, principal, &p); asprintf (&prompt, N_("%s's Password: "******""), p); free(p); if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){ memset(passwd, 0, sizeof(passwd)); errx(1, "failed to read password"); } free (prompt); } if (passwd[0]) { ret = krb5_init_creds_set_password(context, icc, passwd); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_set_password"); } ret = krb5_init_creds_get(context, icc); #ifdef __APPLE__ /* * Save password in Keychain */ if (ret == 0 && keychain_flag && passwordItem == NULL) { krb5_error_code ret2; const char *realm; char *name; realm = krb5_principal_get_realm(context, principal); ret2 = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); if (ret2 == 0) { (void)SecKeychainAddGenericPassword(NULL, (UInt32)strlen(realm), realm, (UInt32)strlen(name), name, (UInt32)strlen(passwd), passwd, NULL); free(name); } } #endif memset(passwd, 0, sizeof(passwd)); switch(ret){ case 0: break; case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */ exit(1); case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_MODIFIED: case KRB5KDC_ERR_PREAUTH_FAILED: case KRB5_GET_IN_TKT_LOOP: #ifdef __APPLE__ if (passwordItem) SecKeychainItemDelete(passwordItem); #endif krb5_errx(context, 1, N_("Password incorrect", "")); case KRB5KRB_AP_ERR_V4_REPLY: krb5_errx(context, 1, N_("Looks like a Kerberos 4 reply", "")); case KRB5KDC_ERR_KEY_EXPIRED: krb5_errx(context, 1, N_("Password expired", "")); default: krb5_err(context, 1, ret, "krb5_get_init_creds"); } ret = krb5_init_creds_get_creds(context, icc, &cred); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_get_creds"); krb5_process_last_request(context, opt, icc); ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache), NULL, &tempccache); if (ret) krb5_err (context, 1, ret, "krb5_cc_new_unique"); ret = krb5_init_creds_store(context, icc, tempccache); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_store"); ret = krb5_init_creds_store_config(context, icc, tempccache); if (ret) krb5_warn(context, ret, "krb5_init_creds_store_config"); ret = krb5_init_creds_warn_user(context, icc); if (ret) krb5_warn(context, ret, "krb5_init_creds_warn_user"); #ifdef __APPLE__ /* * Set for this case, default to * so that all processes can use * this cache. */ { heim_array_t bundleacl = heim_array_create(); heim_string_t ace; if (bundle_acl_strings.num_strings > 0) { int i; for (i = 0; i < bundle_acl_strings.num_strings; i++) { ace = heim_string_create(bundle_acl_strings.strings[i]); heim_array_append_value(bundleacl, ace); heim_release(ace); } } else { ace = heim_string_create("*"); heim_array_append_value(bundleacl, ace); heim_release(ace); } krb5_cc_set_acl(context, tempccache, "kHEIMAttrBundleIdentifierACL", bundleacl); heim_release(bundleacl); } #endif ret = krb5_cc_move(context, tempccache, ccache); if (ret) { (void)krb5_cc_destroy(context, tempccache); krb5_err (context, 1, ret, "krb5_cc_move"); } if (switch_cache_flags) krb5_cc_switch(context, ccache); if (ok_as_delegate_flag || windows_flag || use_referrals_flag) { unsigned char d = 0; krb5_data data; if (ok_as_delegate_flag || windows_flag) d |= 1; if (use_referrals_flag || windows_flag) d |= 2; data.length = 1; data.data = &d; krb5_cc_set_config(context, ccache, NULL, "realm-config", &data); } if (enctype) free(enctype); krb5_init_creds_free(context, icc); krb5_get_init_creds_opt_free(context, opt); if (kt) krb5_kt_close(context, kt); #ifdef __APPLE__ if (passwordItem) CFRelease(passwordItem); #endif return 0; }
SEXP find_password(SEXP svc, SEXP usr, SEXP new_pwd, SEXP quiet, SEXP del) { SEXP res; OSStatus status; SecKeychainRef kc = NULL; /* default */ SecKeychainItemRef kci; const char *un, *sn; char *svc_name; void *pwd; UInt32 pwd_len = 0; int l; int silent = Rf_asInteger(quiet) == 1; int do_rm = Rf_asInteger(del) == 1; int modify = 0; if (TYPEOF(svc) != STRSXP || LENGTH(svc) != 1) Rf_error("Invalid service name"); if (new_pwd != R_NilValue && (TYPEOF(new_pwd) != STRSXP || LENGTH(new_pwd) != 1)) Rf_error("Invalid password"); if (new_pwd != R_NilValue || do_rm) modify = 1; if (usr == R_NilValue) { un = getlogin(); if (!un) Rf_error("Unable to get current user name via getlogin()"); } else { if (TYPEOF(usr) != STRSXP || LENGTH(usr) != 1) Rf_error("Invalid user name (must be a character vector of length one)"); un = Rf_translateCharUTF8(STRING_ELT(usr, 0)); } sn = Rf_translateCharUTF8(STRING_ELT(svc, 0)); l = strlen(sn); if (l > sizeof(buf) - 16) { svc_name = (char*) malloc(l + 16); if (!svc_name) Rf_error("Cannot allocate memory for service name"); } else svc_name = buf; /* we are enforcing R.keychain. prefix to avoid abuse to access other system keys */ strcpy(svc_name, SEC_PREFIX); strcat(svc_name, sn); status = SecKeychainFindGenericPassword(kc, strlen(svc_name), svc_name, strlen(un), un, &pwd_len, &pwd, modify ? &kci : NULL); if (svc_name != buf) free(svc_name); if (silent && status == errSecItemNotFound) return R_NilValue; chk_status(status, "find"); res = PROTECT(Rf_ScalarString(Rf_mkCharLenCE(pwd, pwd_len, CE_UTF8))); /* FIXME: we'll leak if the above fails in R */ SecKeychainItemFreeContent(NULL, pwd); if (do_rm) { status = SecKeychainItemDelete(kci); chk_status(status, "delete"); } else if (new_pwd != R_NilValue) { /* set a new one */ const char *np = Rf_translateCharUTF8(STRING_ELT(new_pwd, 0)); status = SecKeychainItemModifyContent(kci, NULL, strlen(np), np); chk_status(status, "modify"); } UNPROTECT(1); return res; }
static int testExtractable( SecKeychainRef keychain, Boolean extractable, Boolean explicit) { OSStatus status; SecKeyRef publicKeyRef = NULL; SecKeyRef privateKeyRef = NULL; CFStringRef label = (extractable) ? CFSTR("test-extractable-YES") : CFSTR("test-extractable-NO"); Boolean *extractablePtr = (explicit) ? &extractable : NULL; status = GenerateRSAKeyPair(keychain, label, 1024, // size extractablePtr, &publicKeyRef, &privateKeyRef); if (status != noErr) { //errx(EXIT_FAILURE, "Unable to get key pair (err = %d)", status); return status; } // check that the attributes of the generated private key are what we think they are const CSSM_KEY *cssmPrivKey; status = SecKeyGetCSSMKey(privateKeyRef, &cssmPrivKey); ok_status(status, "%s: SecKeyGetCSSMKey", testName); if (status != noErr) { //errx(EXIT_FAILURE, "Unable to get CSSM reference key (err = %d)", status); return status; } if (extractable) { ok(cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE, "%s: check private key marked as extractable (as requested)", testName); if (!(cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE)) { //errx(EXIT_FAILURE, "Oops! the private key was not marked as extractable!"); return 1; } } else { ok(!(cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE), "%s: check private key marked as non-extractable (as requested)", testName); if (cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE) { //errx(EXIT_FAILURE, "Oops! the private key was marked as extractable!"); return 1; } } SecKeyImportExportParameters keyParams; memset(&keyParams, 0, sizeof(keyParams)); keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; keyParams.passphrase = CFSTR("borken"); CFDataRef exportedData = NULL; status = SecKeychainItemExport(privateKeyRef, kSecFormatWrappedPKCS8, 0, &keyParams, &exportedData); if(extractable) { ok_status(status, "%s: SecKeychainItemExport (PKCS8) (and we expected it to succeed)", testName); } else { is(status, errSecDataNotAvailable, "%s: SecKeychainItemExport (PKCS8) (and we expected this to fail with errSecDataNotAvailable)", testName); } status = SecKeychainItemExport(privateKeyRef, kSecFormatPKCS12, 0, &keyParams, &exportedData); if(extractable) { ok_status(status, "%s: SecKeychainItemExport(and we expected it to succeed)", testName); } else { is(status, errSecDataNotAvailable, "%s: SecKeychainItemExport (PKCS12) (and we expected this to fail with errSecDataNotAvailable)", testName); } if (status != noErr) { if (extractable) { //errx(EXIT_FAILURE, "Unable to export extractable key! (err = %d)", status); return 1; } else { status = 0; // wasn't extractable, so this is the expected result } } else if (status == noErr && !extractable) { //errx(EXIT_FAILURE, "Was able to export non-extractable key! (err = %d)", status); return 1; } status = SecKeychainItemDelete((SecKeychainItemRef)publicKeyRef); ok_status(status, "%s: SecKeychainItemDelete", testName); if (status != noErr) { warnx("Unable to delete created public key from keychain (err = %d)", (int)status); } status = SecKeychainItemDelete((SecKeychainItemRef)privateKeyRef); ok_status(status, "%s: SecKeychainItemDelete", testName); if (status != noErr) { warnx("Unable to delete created private key from keychain (err = %d)", (int)status); } CFRelease(publicKeyRef); CFRelease(privateKeyRef); return 0; }
int main(int argc, char **argv) { bool verbose = false; int arg; while ((arg = getopt(argc, argv, "vh")) != -1) { switch (arg) { case 'v': verbose = true; break; case 'h': usage(argv); } } if(optind != argc) { usage(argv); } printNoDialog(); /* initial setup */ verboseDisp(verbose, "deleting keychain"); unlink(KEYCHAIN_NAME); verboseDisp(verbose, "creating keychain"); SecKeychainRef kcRef = NULL; OSStatus ortn = SecKeychainCreate(KEYCHAIN_NAME, strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, false, NULL, &kcRef); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } /* * 1. Generate key pair with cleartext public key. * Ensure we can use the public key when keychain is locked with no * user interaction. */ /* generate key pair, cleartext public key */ verboseDisp(verbose, "creating key pair, cleartext public key"); SecKeyRef pubKeyRef = NULL; SecKeyRef privKeyRef = NULL; if(genKeyPair(false, kcRef, &pubKeyRef, &privKeyRef)) { exit(1); } /* Use generated cleartext public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); CFDataRef exportData = NULL; ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } CFRelease(exportData); verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } /* reset */ verboseDisp(verbose, "deleting keys"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); CFRelease(privKeyRef); /* * 2. Generate key pair with encrypted public key. * Ensure that user interaction is required when we use the public key * when keychain is locked. */ verboseDisp(verbose, "programmatically unlocking keychain"); ortn = SecKeychainUnlock(kcRef, strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, TRUE); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } /* generate key pair, encrypted public key */ verboseDisp(verbose, "creating key pair, encrypted public key"); if(genKeyPair(true, kcRef, &pubKeyRef, &privKeyRef)) { exit(1); } /* Use generated encrypted public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); printExpectDialog(); ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } /* we'll use that exported blob later to test import */ if(!didGetDialog()) { exit(1); } verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); printExpectDialog(); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } if(!didGetDialog()) { exit(1); } /* reset */ printNoDialog(); verboseDisp(verbose, "locking keychain"); SecKeychainLock(kcRef); verboseDisp(verbose, "deleting keys"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); CFRelease(privKeyRef); /* * 3. Import public key, storing in cleartext. Ensure that the import * doesn't require unlock, and ensure we can use the public key * when keychain is locked with no user interaction. */ printNoDialog(); verboseDisp(verbose, "locking keychain"); SecKeychainLock(kcRef); /* import public key - default is in the clear */ verboseDisp(verbose, "importing public key, store in the clear (default)"); CFArrayRef outArray = NULL; SecExternalFormat format = kSecFormatOpenSSL; SecExternalItemType type = kSecItemTypePublicKey; ortn = SecKeychainItemImport(exportData, NULL, &format, &type, 0, NULL, kcRef, &outArray); if(ortn) { cssmPerror("SecKeychainItemImport", ortn); exit(1); } CFRelease(exportData); if(CFArrayGetCount(outArray) != 1) { printf("***Unexpected outArray size (%ld) after import\n", (long)CFArrayGetCount(outArray)); exit(1); } pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { printf("***Unexpected item type after import\n"); exit(1); } /* Use imported cleartext public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); exportData = NULL; ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainItemExport", ortn); exit(1); } /* we'll use exportData again */ verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } /* reset */ verboseDisp(verbose, "deleting key"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); /* * Import public key, storing in encrypted form. * Ensure that user interaction is required when we use the public key * when keychain is locked. */ /* import public key, encrypted in the keychain */ SecKeyImportExportParameters impExpParams; memset(&impExpParams, 0, sizeof(impExpParams)); impExpParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; impExpParams.keyAttributes = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT; verboseDisp(verbose, "importing public key, store encrypted"); printExpectDialog(); outArray = NULL; format = kSecFormatOpenSSL; type = kSecItemTypePublicKey; ortn = SecKeychainItemImport(exportData, NULL, &format, &type, 0, &impExpParams, kcRef, &outArray); if(ortn) { cssmPerror("SecKeychainItemImport", ortn); exit(1); } if(!didGetDialog()) { exit(1); } CFRelease(exportData); if(CFArrayGetCount(outArray) != 1) { printf("***Unexpected outArray size (%ld) after import\n", (long)CFArrayGetCount(outArray)); exit(1); } pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { printf("***Unexpected item type after import\n"); exit(1); } /* Use imported encrypted public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); printExpectDialog(); ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainItemExport", ortn); exit(1); } if(!didGetDialog()) { exit(1); } CFRelease(exportData); verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); printExpectDialog(); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } if(!didGetDialog()) { exit(1); } SecKeychainDelete(kcRef); printf("...test succeeded.\n"); return 0; }
VALUE destroy_internet_password_for(VALUE self, VALUE data) { CHECK_FETCH_HASH_KEY(account) CHECK_FETCH_HASH_KEY(protocol) CHECK_FETCH_HASH_KEY(server) VALUE sym_auth = rb_eval_string(":auth"); VALUE auth; if (!rb_funcall(data, rb_intern("has_key?"), 1, sym_auth)) { auth = 0; } else { auth = rb_funcall(rb_funcall(data, rb_intern("fetch"), 1, sym_auth), rb_intern("to_s"), 0); auth = String2FourChar(StringValuePtr(auth)); } VALUE sym_port = rb_eval_string(":port"); VALUE port; if (!rb_funcall(data, rb_intern("has_key?"), 1, sym_port)) { port = 0; } else { port = rb_funcall(rb_funcall(data, rb_intern("fetch"), 1, sym_port), rb_intern("to_i"), 0); port = NUM2INT(port); } VALUE sym_path = rb_eval_string(":path"); VALUE path; if (!rb_funcall(data, rb_intern("has_key?"), 1, sym_path)) { path = rb_str_new2(""); } else { path = rb_funcall(rb_funcall(data, rb_intern("fetch"), 1, sym_path), rb_intern("to_s"), 0); } SecKeychainItemRef itemRef = nil; OSStatus status = SecKeychainFindInternetPassword ( NULL, // default keychain strlen(StringValuePtr(server)), // length of serverName StringValuePtr(server), // serverName 0, // length of domain NULL, // no domain strlen(StringValuePtr(account)), // length of account name StringValuePtr(account), // account name strlen(StringValuePtr(path)), // length of path StringValuePtr(path), // path port, // ignore port String2FourChar(StringValuePtr(protocol)), // protocol auth, nil, nil, &itemRef ); if (status != noErr || !itemRef) return Qfalse; status = SecKeychainItemDelete(itemRef); return status == noErr ? Qtrue : Qfalse; }