EternalWindows
SSPI / クレデンシャルハンドル

SSPIを使用して認証や暗号化を行うためには、 まずはそれらを実装するSSPを選択しなければなりません。 これには、AcquireCredentialsHandleを呼び出します。

SECURITY_STATUS SEC_Entry AcquireCredentialsHandle(
  SEC_CHAR *pszPrincipal,
  SEC_CHAR *pszPackage,
  ULONG fCredentialUse,
  PLUID pvLogonID,
  PVOID pAuthData,
  SEC_GET_KEY_FN pGetKeyFn,
  PVOID pvGetKeyArgument,
  PCredHandle phCredential,
  PTimeStamp ptsExpiry
);

pszPrincipalは、セキュリティプリンシパルを設定します。 プリンシパルは、セキュリティシステムにおいて認識されるエンティティのことです。 pszPackageは、認証に使用するSSPの名前を指定します。 fCredentialUseは、認証情報をどのように使用するかを表す定数を指定します。 pvLogonIDは、ユーザーを識別するLUIDを指定します。 通常は、NULLを指定します。 pAuthDataは、認証情報を格納した構造体のアドレスを指定します。 使用するSSPによっては、NULLを指定することができます。 pGetKeyFnは、NULLを指定します。 pvGetKeyArgumentは、NULLを指定します。 phCredentialは、クレデンシャルハンドルを受け取るCredHandle構造体のアドレスを指定します。 ptsExpiryは、ローカル時刻を受け取るTimeStamp構造体のアドレスを指定します。

AcquireCredentialsHandleの第2引数には、次のような定数を指定することができます。

定数 使用するSSP
MICROSOFT_KERBEROS_NAME Kerberos
NTLMSP_NAME NTLM
NEGOSSP_NAME Negotiate
UNISP_NAME SChannel
WDIGEST_SP_NAME wDigest

たとえば、NTLMを使用する場合、NTLMSP_NAMEという定義を使用しても構いませんし、 TEXT("NTLM")のように指定しても構いません。 定義を使用すると、NTLMSP_NAME_WのようにUNICODE文字列として解釈されます。

AcquireCredentialsHandleの第3引数には、次のような定数を指定することができます。

定義 意味
SECPKG_CRED_INBOUND 送られてきたンテキストの妥当性を確認する。サーバーの一般的な値。
SECPKG_CRED_OUTBOUND 通信相手に認証を要求する。クライアントの一般的な値。
SECPKG_CRED_BOTH クレデンシャルハンドルを両方の目的で使用する。相互認証をサポートするサーバーの一般的な値。

SECPKG_CRED_BOTHは、NTLMとKerberos及びNegotiateでのみ指定することができます。

AcquireCredentialsHandleが返すクレデンシャルハンドルには、 認証に使用するプロトコルやユーザー名、暗号化アルゴリズムのIDなどが含まれています。 こうした情報を取得したい場合は、QueryCredentialsAttributesを呼び出します。

SECURITY_STATUS SEC_Entry QueryCredentialsAttributes(
  PCredHandle phCredential,
  ULONG ulAttribute,
  PVOID pBuffer
);

phCredentialは、CredHandle構造体のアドレスを指定します。 ulAttributeは、取得する情報の種類を表す定数を指定します。 pBufferは、情報を受け取るバッファを指定します。

不要になったクレデンシャルハンドルは、FreeCredentialsHandleで開放することになります。

SECURITY_STATUS SEC_Entry FreeCredentialsHandle(
  PCredHandle phCredential
);

phCredentialは、開放したいクレデンシャルハンドルを指定します。

今回のプログラムは、AcquireCredentialsHandleを呼び出す例を示しています。

#define  SECURITY_WIN32
#include <windows.h>
#include <security.h>

#pragma comment (lib, "secur32.lib")

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	LPTSTR          lpszName;
	TimeStamp       ts;
	CredHandle      hCredential;
	SECURITY_STATUS ss;

	ss = AcquireCredentialsHandle(NULL, TEXT("NTLM"), SECPKG_CRED_BOTH, NULL, NULL, NULL, NULL, &hCredential, &ts);
	if (ss != SEC_E_OK) {
		MessageBox(NULL, TEXT("クレデンシャルハンドルの取得に失敗しました。"), NULL, MB_ICONWARNING);
		return 0;
	}
	
	QueryCredentialsAttributes(&hCredential, SECPKG_CRED_ATTR_NAMES, &lpszName);
	MessageBox(NULL, lpszName, TEXT("OK"), MB_OK);
	
	FreeContextBuffer(lpszName);
	FreeCredentialsHandle(&hCredential);
	
	return 0;
}

AcquireCredentialsHandleの第2引数にNTLMを指定していることから、 このアプリケーションがNTLM SSPを使用したいことが分かります。 第1引数にNULLを指定していますが、NTLMの場合ではこれは問題ありません。 この場合は、現在のスレッドあるいはプロセスのトークンからプリンしパル名が参照されます。 第3引数は、NTLMの場合はSECPKG_CRED_BOTHを指定することができます。 第5引数は、NTLMの場合はSEC_WINNT_AUTH_IDENTITY構造体を指定することができますが、 NULLでも問題ありません。 この場合は、現在のスレッドあるいはプロセスのトークンから認証情報が参照されます。 NTLMではなく他のSSPを使用する場合は、 引数の指定が大きく変わる場合があるので注意してください。

QueryCredentialsAttributesの第2引数にSECPKG_CRED_ATTR_NAMESを指定した場合、 クレデンシャルハンドルに関連するユーザー名を取得することができます。 このバッファは、SSPIによって確保されたものであるため、 不要になった場合はFreeContextBufferで開放することになります。 また、クレデンシャルハンドルも不要になった場合は、 FreeCredentialsHandleで開放することになります。


戻る