JNIEXPORT void JNICALL Java_com_mcdermottroe_apple_OSXKeychain__1modifyGenericPassword(JNIEnv *env, jobject obj, jstring serviceName, jstring accountName, jstring password) {
	OSStatus status;
	jstring_unpacked service_name;
	jstring_unpacked account_name;
	jstring_unpacked service_password;
	SecKeychainItemRef existingItem;

	/* Unpack the params */
	jstring_unpack(env, serviceName, &service_name);
	jstring_unpack(env, accountName, &account_name);
	jstring_unpack(env, password, &service_password);
	/* check for allocation failures */
	if (service_name.str == NULL || 
	    account_name.str == NULL || 
		service_password.str == NULL) {
		jstring_unpacked_free(env, serviceName, &service_name);
		jstring_unpacked_free(env, accountName, &account_name);
		jstring_unpacked_free(env, password, &service_password);
		return;
	}

	status = SecKeychainFindGenericPassword(
		NULL,
		service_name.len,
		service_name.str,
		account_name.len,
		account_name.str,
		NULL,
		NULL,
		&existingItem
	);
	if (status != errSecSuccess) {
		throw_osxkeychainexception(env, status);
	}
	else {
		/* Update the details in the keychain. */
		status = SecKeychainItemModifyContent(
			existingItem,
			NULL,
			service_password.len,
			service_password.str
		);
		if (status != errSecSuccess) {
			throw_osxkeychainexception(env, status);
		}
	}

	/* Clean up. */
	jstring_unpacked_free(env, serviceName, &service_name);
	jstring_unpacked_free(env, accountName, &account_name);
	jstring_unpacked_free(env, password, &service_password);
}
コード例 #2
0
ファイル: mac.c プロジェクト: hirenj/keychain
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;
}