ハンドシェイク(通信有り)対応するサーバーはこちら今回のクライアントプログラムは、実際にサーバーと通信して認証を行います。事前に対応するサーバープログラムを起動しておいてください。TEXT("クレデンシャルハンドルの取得に失敗しました。TEXT("認証に失敗しました。TEXT("認証に成功しました。TEXT("ホスト情報からアドレスの取得に失敗しました。TEXT("サーバーがリッスンしていません。TEXT("サーバーが存在しません。TEXT("サーバーへの接続が失敗しました。soc;}このプログラムでは、通信に使用するネットワークAPIとしてWinsockを採用しています。戻り値はサーバーと接続されたソケットの記述子になります。第1引数は接続するサーバーの名前であり、第2引数はサーバーのポート番号です。サーバーと実際に通信することになります。データを送信する際に呼び出すSendDataは、次のようになっています。これを送信する前にデータのサイズを送信しておきます。これにより、受信側はデータのサイズを前もって知ることができます。グローバル変数として定義されています。データを受信するReceiveDataは、次のようになっています。1回目のrecvの呼び出しでは、データのサイズを取得することになります。2回目のrecvの呼び出しによって実際にデータを取得することになります。lpuSizeにサイズを代入しておきます。関数の戻り値は、取得したデータへのアドレスになります。第5引数にはSEC_WINNT_AUTH_IDENTITY構造体のアドレスを指定することができます。これを初期化することで、任意のユーザーとしてサーバーにログオンすることができるようになります。SEC_WINNT_AUTH_IDENTITY_UNICODE;各種メンバの意味は、メンバ名が示す通りとなっています。Flagsは、アプリケーションがUNICODEとして実行されている場合は、SEC_WINNT_AUTH_IDENTITY_UNICODEを指定します。クライアントがサーバーにログオンしたことになります。サーバー上にログオンタイプがNetworkであるログオンセッションが作成されます。認証が成功してもログオンセッションが作成されることはありません。それではクライアントサーバーを同じコンピュータ上で実行した場合はどうなるのでしょうか。答えは、ローカルコンピュータへのローカルログオンです。下記のようにLogonUserを呼び出すのとほぼ同じ意味を持ちます。SSPIによるローカルログオンを実行する必要はないように思えます。SE_TCB_NAME特権が別途必要となり、環境によっては呼び出せない場合があります。よって、これらの環境を想定する場合は、SSPIによるローカルログオンの方法を知っておくべきといえます。クライアントとサーバーのコードを実行するだけです。ClientHandshakeとServerHandshakeを交互に呼び出します。TEXT("クレデンシャルハンドルの取得に失敗しました。TEXT("クレデンシャルハンドルの取得に失敗しました。TEXT("認証に成功しました。TEXT("認証に失敗しました。SEC_E_OK;}WinMainでは、AcquireCredentialsHandleを2回呼び出しています。1つは、クライアント用の認証ハンドルの取得で、もう1つはサーバー用の認証ハンドルの取得です。特定のユーザーがログオンできるようにします。認証ハンドルを取得すれば、ClientHandshakeとServerHandshakeを交互に呼び出します。NTLMの場合は、これを2回実行すれば認証は終了することになります。SSPIによるログオンには若干の違いがあります。それは、次に示すレジストリキーのforceguestエントリが1である場合の動作です。HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsaforceguestが1である場合、SSPIによるログオンは必ずGuestアカウントとして行われます。ユーザー名やパスワードが正しくない場合でもGuestアカウントとしてログオンされます。ユーザー名やパスワードが正しくない場合はGuestアカウントとしてログオンされます。Guestアカウントにネットワークログオンが許可されていない場合は、失敗します。ユーザー名やパスワードが正しくない場合はログオン失敗となります。