Client Initialization

This section describes how the client of a transport application connects to a Windows-based desktop platform server, using Windows NT LMSSP authentication.

To initialize, the application client calls the InitSecurityInterface function. If the client is binding directly to Secur32.dll, it can discard the returned function table; otherwise, it must use the function table to make subsequent calls to the security provider functions. The client must also call the QuerySecurityPackageInfo function to get the maximum security buffer size.

To make the connection, the application calls the AcquireCredentialsHandle function, using the SEC_WINNT_AUTH_IDENTITY structure to specify the credentials. The application must save the credential handle for use when calling the InitializeSecurityContext function, but it can discard the other parameters after the call to AcquireCredentialsHandle. The following code example shows how to make a connection.

SEC_WINNT_AUTH_IDENTITY AdditionalCredentials;
SECURITY_STATUS status;
CredHandle hCredential;
TimeStamp tsExpiry;
BOOL bSupplyCredentials;

// If there are additional credentials stored in lpszUserName, 
// lpszDomainName, and lpszPassword, fill them in here.
AdditionalCredentials.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

if (lpszUserName != NULL) 
{
  AdditionalCredentials.User = lpszUserName;
  AdditionalCredentials.UserLength = wcslen (lpszUserName);
}

if (lpszDomainName != NULL) 
{
  AdditionalCredentials.User = lpszDomainName;
  AdditionalCredentials.UserLength = wcslen (lpszDomainName);
}

if (lpszPassword != NULL) 
{
  AdditionalCredentials.User = lpszPassword;
  AdditionalCredentials.UserLength = wcslen (lpszPassword);
}

status = AcquireCredentialsHandle (
              NULL,                   // No principal name
              TEXT("NTLM"),           // Package name
              SECPKG_CRED_OUTBOUND,   // Credential use flag
              NULL,                   // No logon identifier
              bSupplyCredentials ?  &AdditionalCredentials : NULL,
                                      // Package-specific data     
              NULL,                   // No GetKey function
              NULL,                   // No GetKey function argument
              &hCredential,           // Receives the new credential
              &tsExpiry);             // Receives the expiration 
                                      // time of the credential

The credential handle does not expire, so the client can ignore the expiration time for this security package.

Next, the application calls InitializeSecurityContext to start setting up the security context. The following code example shows how to start up the security context.

SecBufferDesc OutputBufferDescriptor;
SecBuffer OutputSecurityToken;
ULONG ulContextRequirements,
      ulContextAttributes;
SECURITY_STATUS status;
CredHandle hCredential;
CtxtHandle hNewContext;
TimeStamp tsExpiry;

// Build the output buffer descriptor.
OutputBufferDescriptor.cBuffers = 1;
OutputBufferDescriptor.pBuffers = &OutputSecurityToken;
OutputBufferDescriptor.ulVersion = SECBUFFER_VERSION;

OutputSecurityToken.BufferType = SECBUFFER_TOKEN;
OutputSecurityToken.cbBuffer = pPackageInfo->cbMaxToken;
OutputSecurityToken.pvBuffer = 
                        LocalAlloc (0, OutputSecurityToken.cbBuffer);

// Insert code here to check for memory allocation failure.
// ...

// Compute context requirements. For message integrity, request 
// replay or sequence detection. For message encryption, 
// request confidentiality.
ulContextRequirements = ISC_REQ_REPLAY_DETECT;

// Assume that szTargetName is the name of the target server, or NULL.
// Call the InitializeSecurityContext function.
status = InitializeSecurityContext (
              &hCredential,
              NULL,                   // No context handle
              szTargetName,           // Target name, if available
              ulContextRequirements,
              0,                      // Reserved parameter
              SECURITY_NATIVE_DREP,   // Target data representation
              NULL,                   // No input buffer
              0,                      // Reserved parameter
              &hNewContext,           // Receives new context handle
              &OutputBufferDescriptor,// Receives output security token
              &ulContextAttributes,   // Receives context attributes
              &tsExpiry);             // Receives context expiration 
                                      // time

InitializeSecurityContext returns SEC_I_CONTINUE_NEEDED on success, or an error code on failure. If the function is successful, the application passes the token buffer to the server. The token buffer is stored in the pvBuffer member of the OUTPUTSECURITYTOKEN structure. The cbBuffer member of the structure specifies the buffer length. The token buffer is then sent to the server. The server sends the output back to the client. The client then calls InitializeSecurityContext again.