Platform SDK: Logon Authentication |
To establish a secure connection, the client acquires an outbound credentials handle before sending an authentication request to the server. The server creates a security context for the client from the authentication request. There are two client-side SSPI functions involved in authentication setup:
Code for this process can be seen in the GenClientContext function in Using SSPI with a Windows Sockets Client.
If a client program needs to use credentials in addition to its own logon credentials, such as a different user name, domain name, and password, it provides them in the AcquireCredentialsHandle call with a SEC_WINNT_AUTH_IDENTITY structure specifying the additional credentials. For more information on credentials functions, see Credential Management.
Note For the SEC_WINNT_AUTH_IDENTITY structure, the Flags member is set to SEC_WINNT_AUTH_IDENTITY_ANSI only when strings in the structure are OEM. If strings are ANSI, they must first be converted to Unicode using the MultByteToWideChar function, and the Flags member of the SEC_WINNT_AUTH_IDENTITY structure must be set to SEC_WINNT_AUTH_IDENTITY_UNICODE.
The following code uses the GenClientContext function to acquire alternate credentials. This example uses the Negotiate package that is the preferred package for use with Windows 2000; however, note that the Negotiate package is not supported on any earlier platform.
//-------------------------------------------------------------------- // This code fills in any additional credentials. The string // UserName holds the name of the user for whom the additional // credentials are being acquired. DomainName and Password are strings // with the domain name and the password associated with the user. SEC_WINNT_AUTH_IDENTITY AdditionalCredentials; CredHand ClientCredentials; TimeStamp Expiration; AdditionalCredentials.User = UserName; AdditionalCredentials.UserLength = strlen(UserName); AdditionalCredentials.Domain = DomainName; AdditionalCredentials.DomainLength=strlen(DomainName); AdditionalCredentials.Password = Password; AdditionalCredentials.PasswordLength = strlen(Password); #ifdef UNICODE AdditionalCredentials.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE #else AdditionalCredentials.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI #endif SecStatus = AcquireCredentialsHandle( NULL, // no principal name "negotiate", // package name SECPKG_CRED_OUTBOUND, // credential use flag NULL, // no logon identifier &AdditionalCredentials // the address of the // data structure containing // the alternative credentials. NULL, // no GetKey function NULL, // no GetKey function argument &ClientCredential, // receives the new credential &Expiration);
To initiate the first leg of the authentication, the client calls InitializeSecurityContext to obtain an initial security token to be sent in a connection request message to the server.
The client uses the security token information received in the output buffer descriptor to generate a message to send to the server. The construction of the message, in terms of placement of various buffers and so forth, is part of the application protocol and must be understood by both parties.
The client checks the return status from InitializeSecurityContext to see if authentication will complete in a single call. A return status of SEC_I_CONTINUE_NEEDED indicates that the security protocol requires multiple authentication messages. For more information on context functions, see Context Management.