0

私のプロジェクトの1つとして、Java用の完全なPAM実装を実装したいと思います(アプリケーション側とモジュール側も)。

現在、私はアプリケーション側にいます。私はjpamをベースとして使用しましたが、問題に遭遇しました。数時間検索しても、問題の解決策が見つかりません:/

これは現在のコードです:

JNIEXPORT jint JNICALL Java_org_eel_kitchen_pam_PamHandle_authenticate(
    JNIEnv *pEnv, jobject pObj, jstring pServiceName, jstring pUsername,
    jstring pPassword, jboolean debug)
{
    pam_handle_t *pamh = NULL;
    int retval;

    /*
     * TODO: unclear, see what's what
     *
     * With my first tests, it appears that GetStringUTFChars() makes the JVM
     * crash if memory cannot be allocated... But an array copy was made. See
     * what happens if the JVM decides NOT to make a copy. Right now it is
     * assumed that allocations succeed. And the JNI spec says
     * GetStringUTFChars() does NOT throw an OOM on failure.
     */
    service_name = (*pEnv)->GetStringUTFChars(pEnv, pServiceName, NULL);
    username = (*pEnv)->GetStringUTFChars(pEnv, pUsername, NULL);
    password = (*pEnv)->GetStringUTFChars(pEnv, pPassword, NULL);

    /* Get a handle to a PAM instance */
    retval = pam_start(service_name, username, &PAM_converse, &pamh);

    if (retval != PAM_SUCCESS) {
        pr_debug("pam_start failed for service %s: %s\n", service_name,
            pam_strerror(NULL, retval));
        goto out_nohandle;
    }

    pam_set_item(pamh, PAM_AUTHTOK, password);
    retval = pam_authenticate(pamh, 0);

    /* Is user permitted access? */
    if (retval != PAM_SUCCESS) {
        pr_debug("failed to authenticate user %s: %s\n", username,
            pam_strerror(NULL, retval));
        goto out_free;
    }

    retval = pam_acct_mgmt(pamh, 0);

    if (retval != PAM_SUCCESS)
        pr_debug("failed to setup account for user %s: %s\n", username,
            pam_strerror(NULL, retval));

out_free:
    /* Clean up our handles and variables */
    if (pam_end(pamh, retval) != PAM_SUCCESS) {
        pamh = NULL;
        pr_debug("Fuchs! Failed to release PAM handle\n");
    }

out_nohandle:
    (*pEnv)->ReleaseStringUTFChars(pEnv, pServiceName, service_name);
    (*pEnv)->ReleaseStringUTFChars(pEnv, pUsername, username);
    (*pEnv)->ReleaseStringUTFChars(pEnv, pPassword, password);

    return retval;
}

ここで必要なのは、pamhのすべてのインスタンスの参照を保持することですPamHandle。これはどのように行われますか?

編集:OK、私はこれに対する答えを持っています、そして今クリーンアップの部分があります:finalize()それからネイティブのクリーンアップメソッドを呼び出すために使用しますsuper.finalize();か、それとも私が実装できる/しなければならないGCによってトリガーされるJNI関数がありますか?

4

2 に答える 2

3

longを使用して、pam_handle_tへのポインタを格納します。

Java側は次のようになります

long handle = Pam.create();
Pam.DoSomething(handle,arg1,arg2);

もちろん、これをクラス内にカプセル化できるので、インターフェースを持つことができます。

PamHandle p = new PamHandle();
p.DoSomething(arg1,arg2);

C側は次のようになります。

JNIEXPORT jlong JNICALL Java_org_Create(
    JNIEnv *pEnv)
{
    pam_handle_t *pamh = createNew pam_handle somehow
    jlong result = (jlong) pamh;
    return result;
}

JNIEXPORT jint JNICALL Java_org_Blah_Blah_blah(
    JNIEnv *pEnv, jlong handle, jstring arg1,jstring arg2)
{
    pam_handle_t *pamh = (pam_handle_t*)handle;
 // ... Do rest of stuff
}

これにより、インスタンスごとに1つのpam_handle_tを持つことができます。また、オブジェクトを渡してからオブジェクトのフィールドにアクセスするよりも、毎回手動で整数を渡す方がはるかにパフォーマンスが高くなります。

編集

また、jlong​​がポインタを正しく保持できないことが心配な場合は、jlong​​が64ビットであることが保証されます。したがって、jlong​​は、128ビット整数の取得を開始するまで(はるか遠く)、この場合はずっと機能します。

于 2011-12-17T13:11:11.897 に答える
1

ここには2つのケースがあります。
現在、ポインタは関数に対してローカルであり、関数のスコープを超えて使用することはできません。新しく作成したすべての関数が、現在宣言している関数を介して呼び出される関数を介して呼び出される場合はpamh、関数パラメーターとしてポインターを渡し続けることができることに注意してください。

ただし、ケースが上記のとおりでない場合はpamh、プログラムの存続期間を通じて有効であり続けるようにglbalを作成する必要があります。そうすれば、さまざまな機能で使用できます。

宣言する必要があります、

pam_handle_t *pamh = NULL; 

グローバルとして。

グローバルにするということは、プログラムがマルチスレッドの場合にアクセスが同期されるようにすることを意味することに注意してください。

于 2011-12-17T13:04:03.560 に答える