Using a Security Context

Both the client and the server side of a transport application can use the MakeSignature function to generate a signed message to send to the other side. The receiving side then uses the VerifySignature function to verify that a signature matches the received message. If the application wants to generate signed messages, the client must have specified the ISC_REQ_REPLAY_DETECT or ISC_REQ_SEQUENCE_DETECT flag in its first call to the InitializeSecurityContext function.

When the client calls MakeSignature or VerifySignature, it uses the ClientContext handle that it obtained from its first call to InitializeSecurityContext.

The following code example shows how the client side generates a signed message to send to the server. Before calling MakeSignature, the client calls the QueryContextAttributes function with a SECPKGCONTEXT_SIZES structure to determine the length of the buffer needed to hold the message signature. If the cbMaxSignature parameter is zero, the security package does not support signing messages; otherwise, this parameter indicates the size of the buffer to allocate to receive the signature.

SecPkgContext_Sizes ContextSizes;

status = QueryContextAttributes (&hContext,
                                 SECPKG_ATTR_SIZES,
                                 &ContextSizes);

// Assume the message is in the variable MessageBuffer, and 
// its length is in MessageBufferSize. Build up the buffer descriptors
// to pass to the MakeSignature call.
SecBufferDesc InputBufferDescriptor;
SecBuffer InputSecurityToken[2];

// Build the input buffer descriptor.
InputBufferDescriptor.cBuffers = 2;
InputBufferDescriptor.pBuffers = InputSecurityToken;
InputBufferDescriptor.ulVersion = SECBUFFER_VERSION;

// Build a security buffer for the message. If the SECBUFFER_READONLY
// attribute is added, this buffer would not get signed.
InputSecurityToken[0].BufferType = SECBUFFER_DATA;
InputSecurityToken[0].cbBuffer = MessageBufferSize;
InputSecurityToken[0].pvBuffer = MessageBuffer;

// Allocate and build a security buffer for the message signature.
InputSecurityToken[1].BufferType = SECBUFFER_TOKEN;
InputSecurityToken[1].cbBuffer = ContextSizes.cbMaxSignature;
InputSecurityToken[1].pvBuffer = 
                          LocalAlloc (0, ContextSizes.cbMaxSignature);

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

// Call MakeSignature now. Specify the sequence number; 
// Windows NTLM provides one. The quality of service is ignored.
status = MakeSignature (
              &hContext,
              0,                      // No quality of service
              &InputBufferDescriptor, // Input message descriptor
              0);                     // No sequence number

MakeSignature returns successfully if the context was set up to enable signing messages and the input buffer descriptor is correctly formatted. If the function is successful, the application sends the message buffer and its size, along with the signature buffer and its size, to the server.

To delete the security contexts after the client and server have finished communicating, both sides can call the DeleteSecurityContext function with their respective context handles. The client should also call the FreeCredentialsHandle function when it has finished communicating with any server or has finished using the additional credentials passed to the AcquireCredentialsHandle function. For more information on writing the server side of the Windows NT LMSSP transport application, see the Microsoft Platform SDK.