QA@IT

CredentialProviderでのログオン手順について

4979 PV

ICカードを使ってパソコンにログオンするアプリを作成しています。
マイクロソフトのサンプルアプリをベースにICカードを読み取るロジックの実装まで行うことができましたが、
ログオンを行う部分の実装で躓いています。

カードを検知し内容を読み取った後、カードに紐づくユーザIDでログオンを行いたいのですが、
以下のロジック(MyLogonUser())で返り値正常となるもののログオン画面からデスクトップ画面に遷移できない状況です。
※カードとユーザIDは事前に紐づけ情報をパソコンに保存しています

いろいろググってはいるものの、CredentialProvider自体の情報が乏しく、
サンプルアプリ自体の理解度も進んでいない状態です。
勉強になりそうなサイトがございましたら、教えていただきたく思います。

■質問事項
・「LsaLogonUser」ではログオン(デスクトップ画面に遷移)することができないのでしょうか?
・「LsaLogonUser」を実行した後、ログオンするための別の処理が必要なのでしょうか?

■開発環境
・Windows8.1Pro 64Bit
・Visual Studio 2017 C++
・「test」というユーザが1つ存在している状態

■実装ロジック
ログオン部分の実装になります。その他のロジックはどこを提示して良いかの判断がつきませんでした。
ご指摘いただきましたら、その都度掲載するようにいたします。

○クラス
・CCredentialProvider
 GetCredentialCount()でCCredentialProviderCredentialを呼び出ししています
・CCredentialProviderCredential
 カードの受付開始/停止(SmartCard)及び読み取った内容の表示を行っています
・SmartCard
 カード検知、内容の読み出しとログオン処理を行っています

○ログオン部分

#カード内容の読取後に実行している処理
#※ユーザID/パスワードは固定にしています
NTSTATUS st;
HANDLE lsa;
HANDLE hToken;
LSA_STRING lsaString;
ULONG uPackageId;

st = LsaConnectUntrusted(&lsa);
if (st != 0)
{
    DebugPrint(L"LsaConnectUntrusted failed");
} 
else 
{
    DebugPrint(L"LsaConnectUntrusted ok");
    InitString(&lsaString, MSV1_0_PACKAGE_NAME);
    st = LsaLookupAuthenticationPackage(lsa, &lsaString, &uPackageId);
    if (st != 0)
    {
        DebugPrint(L"LsaLookupAuthenticationPackage failed");
        LsaDeregisterLogonProcess(lsa);
    }
    else
    {
        DebugPrint(L"LsaLookupAuthenticationPackage ok");
        if (!MyLogonUser(lsa, uPackageId, L"test", L"12345678", L"", &hToken)) {
            DebugPrint(L"MyLogonUser failed ");
            LsaDeregisterLogonProcess(lsa);
        }
        else {
            DebugPrint(L"MyLogonUser ok");
            CloseHandle(hToken);
            LsaDeregisterLogonProcess(lsa);
        }
    }
}

extern "C" BOOL MyLogonUser(HANDLE hLsa, ULONG uPackageId, LPWSTR lpszUserName, LPWSTR lpszPassword, LPWSTR lpszDomainName, HANDLE *phToken)
{
    LUID                        luid;
    ULONG                       uBufferLength;
    ULONG                       uProfileLength;
    LPBYTE                      lp;
    NTSTATUS                    ns;
    NTSTATUS                    nsSub;
    LSA_STRING                  lsaOriginal;
    QUOTA_LIMITS                limits;
    TOKEN_SOURCE                tokenSource;
    MSV1_0_INTERACTIVE_LOGON    msvLogon;
    PMSV1_0_INTERACTIVE_LOGON   pmsvLogon;
    PMSV1_0_INTERACTIVE_PROFILE pmsvProfile;

    InitString(&lsaOriginal, "origial");

    uBufferLength = sizeof(MSV1_0_INTERACTIVE_LOGON);
    uBufferLength += InitUnicodeString(&msvLogon.UserName, lpszUserName);
    uBufferLength += InitUnicodeString(&msvLogon.Password, lpszPassword);
    uBufferLength += InitUnicodeString(&msvLogon.LogonDomainName, lpszDomainName);
    msvLogon.MessageType = MsV1_0InteractiveLogon;

    lp = (LPBYTE)LocalAlloc(LPTR, uBufferLength);
    CopyMemory(lp, (PVOID)&msvLogon, sizeof(MSV1_0_INTERACTIVE_LOGON));
    pmsvLogon = (PMSV1_0_INTERACTIVE_LOGON)lp;

    lp += sizeof(MSV1_0_INTERACTIVE_LOGON);
    FormatBuffer(&lp, &pmsvLogon->UserName);

    lp += pmsvLogon->UserName.Length;
    FormatBuffer(&lp, &pmsvLogon->Password);

    lp += pmsvLogon->Password.Length;
    FormatBuffer(&lp, &pmsvLogon->LogonDomainName);

    lstrcpyA(tokenSource.SourceName, "LsaLogonUser");
    AllocateLocallyUniqueId(&tokenSource.SourceIdentifier);

    ns = LsaLogonUser(hLsa, &lsaOriginal, Interactive, uPackageId,
        (PVOID)pmsvLogon, uBufferLength, 0, &tokenSource, (PVOID *)&pmsvProfile,
        &uProfileLength, &luid, phToken, &limits, &nsSub);

    if (LsaNtStatusToWinError(ns) != ERROR_SUCCESS) {
        LocalFree(pmsvLogon);
        return FALSE;
    }

    LsaFreeReturnBuffer(pmsvProfile);
    LocalFree(pmsvLogon);

    return TRUE;
}

extern "C" ULONG InitString(PLSA_STRING plsaString, LPSTR lpszString)
{
    if (lpszString == NULL) {
        plsaString->Length = 0;
        plsaString->MaximumLength = 0;
        plsaString->Buffer = NULL;
    }
    else {
        plsaString->Length = (USHORT)(lstrlenA(lpszString) * sizeof(CHAR));
        plsaString->MaximumLength = plsaString->Length + sizeof(CHAR);
        plsaString->Buffer = lpszString;
    }

    return plsaString->Length;
}

extern "C" ULONG InitUnicodeString(PLSA_UNICODE_STRING plsaString, LPWSTR lpszString)
{
    if (lpszString == NULL) {
        plsaString->Length = 0;
        plsaString->MaximumLength = 0;
        plsaString->Buffer = NULL;
    }
    else {
        plsaString->Length = (USHORT)(lstrlen(lpszString) * sizeof(WCHAR));
        plsaString->MaximumLength = plsaString->Length + sizeof(WCHAR);
        plsaString->Buffer = lpszString;
    }

    return plsaString->Length;
}

extern "C" void FormatBuffer(LPBYTE *lp, PUNICODE_STRING pString)
{
    if (pString->Buffer != NULL) {
        CopyMemory(*lp, pString->Buffer, pString->Length);
        pString->Buffer = (LPWSTR)*lp;
    }
}

回答

回答なしの状態が継続しているため、
本件クローズといたします。

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。