Security Function Table

The Security Function Table is an array of function pointers which are defined in the include file, SSPI.H. The function names correspond to the interface specification for SSPI.

The definition of the Security Function Table is shown below:


typedef struct _SECURITY_FUNCTION_TABLE_W {
 unsigned long      dwVersion;
 ENUMERATE_SECURITY_PACKAGES_FN_W EnumerateSecurityPackagesW;
 void SEC_FAR *      Reserved1;
// QUERY_CREDENTIALS_ATTRIBUTES_FN_W QueryCredentialsAttributesW;
 ACQUIRE_CREDENTIALS_HANDLE_FN_W  AcquireCredentialsHandleW;
 FREE_CREDENTIALS_HANDLE_FN   FreeCredentialHandle;
 void SEC_FAR *      Reserved2;
 INITIALIZE_SECURITY_CONTEXT_FN_W InitializeSecurityContextW;
 ACCEPT_SECURITY_CONTEXT_FN   AcceptSecurityContext;
 COMPLETE_AUTH_TOKEN_FN    CompleteAuthToken;
 DELETE_SECURITY_CONTEXT_FN   DeleteSecurityContext;
 APPLY_CONTROL_TOKEN_FN    ApplyControlToken;
 QUERY_CONTEXT_ATTRIBUTES_FN_W  QueryContextAttributesW;
 IMPERSONATE_SECURITY_CONTEXT_FN  ImpersonateSecurityContext;
 REVERT_SECURITY_CONTEXT_FN   RevertSecurityContext;
 MAKE_SIGNATURE_FN     MakeSignature;
 VERIFY_SIGNATURE_FN     VerifySignature;
 FREE_CONTEXT_BUFFER_FN    FreeContextBuffer;
 QUERY_SECURITY_PACKAGE_INFO_FN_W QuerySecurityPackageInfoW;
 void SEC_FAR *      Reserved3;
 void SEC_FAR *      Reserved4;
 QUERY_SECURITY_CONTEXT_TOKEN_FN  QuerySecurityContextToken;
} SecurityFunctionTableW, SEC_FAR * PSecurityFunctionTableW;

Note that Windows NT 4.0 does not support the QueryCredentialsAttributes function and therefore is commented out of the function table. This function will be supported in a future release of Windows NT.

Also note that SSPI in Windows NT 4.0 does not provide encryption/decryption interfaces because of legal restrictions on such interfaces. Microsoft is planning to extend the interface to provide encryption interfaces in a future release of Windows NT.

Memory Use, Security Buffers, and Descriptor

Most of the SSPI functions have variable length arguments for the caller (application) to provide message data to the security package and for the security package to return security data to the caller. SSPI APIs use a parameter type, BufferDescriptor, to define the size and location of the variable length data. Security buffers are used by the caller, for example, to pass message data to the security package, or to receive an output security token.

Security buffers can be passed in as an array of buffers. The security buffer descriptor identifies the number of buffers and starting address of the buffer array. Each security buffer also has a buffer type field to identify the contents of the buffer.

The definition of security buffers, buffer descriptors, and buffer data types from SSPI.H are shown below:


//
// SecBuffer
//
// Generic memory descriptors for buffers passed in to the security
// API
//

typedef struct _SecBuffer {
 unsigned long cbBuffer;    // Size of the buffer, in bytes
 unsigned long BufferType;   // Type of the buffer (below)
 void SEC_FAR * pvBuffer;   // Pointer to the buffer
} SecBuffer, SEC_FAR * PSecBuffer;

typedef struct _SecBufferDesc {
 unsigned long ulVersion;   // Version number
 unsigned long cBuffers;    // Number of buffers
#ifdef MIDL_PASS
 [size_is(cBuffers)]
#endif
 PSecBuffer pBuffers;    // Pointer to array of buffers
} SecBufferDesc, SEC_FAR * PSecBufferDesc;

#define SECBUFFER_VERSION   0

#define SECBUFFER_EMPTY    0 // Undefined, replaced by provider
#define SECBUFFER_DATA    1 // Packet data
#define SECBUFFER_TOKEN    2 // Security token
#define SECBUFFER_PKG_PARAMS  3 // Package specific parameters
#define SECBUFFER_MISSING   4 // Missing Data indicator
#define SECBUFFER_EXTRA    5 // Extra data
#define SECBUFFER_STREAM_TRAILER 6 // Security Trailer
#define SECBUFFER_STREAM_HEADER  7 // Security Header

#define SECBUFFER_ATTRMASK   0xF0000000
#define SECBUFFER_READONLY   0x80000000 // Buffer is read-only

Each time a security API is called that takes a SecBufferDesc parameter, it should be setup with one or more SecBuffers. For example, there can be two security buffers, one that contains input message data and the other for the output opaque security token returned by the security package. The order of security buffers in the security buffer descriptor is not important but they should be tagged with appropriate type. Also, an input buffer that can not be modified by the security package should additionally be tagged as read only.

The size of the output buffer that is expected to contain the security token is important. An application can find the maximum token size for a security package during initial setup. The call to EnumerateSecurityPackages returns an array of pointers to security package information. The security package information structure contains maximum token size value. In the example code, the information is in SecPkgInfo.cbMaxToken. It can also be obtained later on using QuerySecurityPackageInfo.

The application initializes the buffer pointers and sizes in the buffer description to indicate where message data and other information may be found.

The example below shows how to initialize an array of security buffers. This particular case shows how input security buffers are initialized by the server-side of a connection in a call to AcceptSecurityContext. Note that the last buffer contains the opaque security token received by the client and the SECBUFFER_READONLY flag is also set.


SecBuffer  Buffers[3];
SecBufferDesc BufferDesc;
...
BufferDesc.ulVersion = SECBUFFER_VERSION;
BufferDesc.cBuffers = 3;
BufferDesc.pBuffers = &Buffers; Buffers[0].cbBuffer = sizeof(Protocol_Header);
Buffers[0].BufferType = SECBUFFER_READONLY | SECBUFFER_DATA;
Buffers[0].pvBuffer = pHeader;

Buffers[1].cbBuffer = pHeader->MessageSize;
Buffers[1].BufferType = SECBUFFER_DATA;
Buffers[1].pvBuffer = pMessage;

Buffers[2].cbBuffer = pHeader->TrailerSize;
Buffers[2].BufferType = SECBUFFER_READONLY | SECBUFFER_TOKEN;
Buffers[2].pvBuffer = pSecurityTrailer;