One of the key issues in security is verifying identities. After such verification, a guard at a gate or a computer server can check to see what resources that person is allowed access to. This process is called authentication, and Windows 2000 provides for some very flexible options, including plugging your own custom authentication scheme into a network. The key to this flexibility is the Security Support Provider Interface, or SSPI.
But before we delve into the details of how this all works, let’s take a look at how authentication works. Before a gatekeeper grants access to resources, there must be some way to verify identity. In many common situations some kind of authority figure is consulted. For example, when I go to a bank to cash a check, the bank generally relies on the State of Alaska to have properly verified my identity before granting me the driver’s license I present as proof of my identity. Similarly, when I submit to a retinal scan, the system compares what it sees in my eye to a database that it trusts to contain records only for people who have some kind of access to the protected resources. There are obviously other issues to consider here, such as the integrity of the database and the security of the lines of communication used, but the point is that some kind of authority is consulted.
The complexity of this authentication process depends on the importance and sensitivity of the resources it is protecting. Naturally, I want the bank to check drivers license, passport, fingerprints, and DNA when someone tries to access my account, but when I want to get at my money it needs to be as simple as possible. The design of authentication systems consists of a series of tradeoffs like these.
Authenticating a client for secure network communication follows a common pattern, although the precise steps depend on the way the parties have agreed to handle such matters. The transaction typically begins by the client and system exchanging bits back and forth, kind of an electronic introduction. The server consults a trusted authority to check out the user and whether the user has access rights. Once they have established a trusted relationship, the client and server can begin exchanging information, reasonably confident that they know who the other party is.
It sounds simple enough, but next we need to consider the communications medium being used, such as a TCP/IP network. Assuming that the communication is going over the public Internet, any number of routers and intermediate systems must handle the data packets, opening the communication to modification by malicious third parties. But the client and server can agree to encrypt the data, using any of the many encryption methods available today. But such systems depend on at least one of the keys used for encryption to be safe and secure from prying eyes, and then it becomes a complex problem making sure that the keys are not compromised. Another option is protecting communications using a Message Authentication Code, which doesn’t prevent the contents from prying eyes but does prevent its modification. The checksum must be encrypted, but this frequently is far more efficient than encrypting the contents of an entire message. You can easily see how a simple request for information from a server can grow into a very complex transaction.
The logistics and details of how all these steps are handled are determined by the security protocol in use on the network. Both parties to a communication must agree to the protocol used, otherwise no communication will happen. Usually, this means that the server mandates a protocol; if the client can’t comply, it won’t have access to the network resources.
There are many protocols available for this, but in Windows there are a few in common use. Windows NT primarily used the Windows NT LAN Manager (NTLM) challenge-response protocol, while the default protocol in Windows 2000 is Kerberos. Kerberos, named after the multi-headed dog that guards the gates of hell, is an Internet standard that Microsoft almost fully implemented. (The company used an undefined field, which keeps some Kerberos implementations from communicating with Windows.) There are many other protocols, such as the Secure Sockets Layer (SSL) commonly used for Web applications.
The authentication process is quite different between NTLM and Kerberos, taking one example, as shown in the figure. At a high level in NTLM, a communication takes place between the client and server, then the server checks with the authority to authenticate the client. But in Kerberos, the client first checks in with the authority, obtains a ticket, and uses that to prove identity. Kerberos supports caching tickets, so an entire communication could occur with but a single interaction with the authority. NTLM doesn’t support caching, so every request from the client results in another request to the authority. And the differences go on.
As you can probably imagine, supporting multiple protocols in a single application could be a nightmare, akin to providing database access to multiple engines before ODBC provided a uniform interface to any relational database engine with an ODBC driver. But, like ODBC, SSPI, the Security Support Provider Interface, provides a uniform interface for the use of compliant authentication protocols in Windows 2000. SSPI is the Microsoft version of the Generic Security Service API (GSSAPI) standard described in the Internet Engineering Task Forces RFC 1508 and 1509 specifications.
To avoid coding every available security option into an application, SSPI enables applications to access dynamic-link libraries containing common authentication and cryptographic data schemes. These DLLs are called Security Support Providers (SSPs), each of which implements a security protocol. So as long as someone takes the time to properly implement an SSP for a security protocol, that protocol can be used in Windows 2000, providing a layer of abstraction between an application and the protocol.
SSPs make one or more security packages available to applications. A security package maps various SSPI functions to the security protocols specified in the package, acting as the translator or interface between applications and the provider. An application implementing SSPI can use any security package available on a system without knowing details about the security protocols that the security package implements.
There are four broad categories of APIs in SSPI: package management, credential management, context management, and message support. Package management functions enumerate and query the attributes of the security packages of an SSP. They list the security packages available on a system and enable an application to select one to support its requirements. Package management includes these methods:
- EnumerateSecurityPackages-Lists available security packages and their capabilities.
- InitSecurityInterface-Retrieves a pointer to a SSP dispatch table.
- QuerySecurityPackageInfo-Queries an individual security package for its capabilities.
Credential management functions enable applications to gain access to the credentials of a principal. A principal is an entity recognized by the security system, such as human users and autonomous processes. A credential is data used by a principal to establish the identity of the principal, such as a password or user name. The credential management methods of SSPI include:
- AcquireCredentialsHandle-Acquires a handle to the reference credentials.
- ExportSecurityContext-Exports a security context into a context buffer.
- FreeCredentialsHandle-Releases a credential handle and associated resources.
- ImportSecurityContext-Imports a security context exported by using ExportSecurityContext into the current process.
- QueryCredentialAttributes-Allows queries on various credential attributes such as associated name and domain name.
Context management functions enable applications to create and use security contexts. A security context is the security data relevant to a connection, and contains such data as a session key and the session duration. Both client and server must cooperate to create a security context. The client and the server can then use the security context with message support functions to ensure message integrity and privacy during the connection. This is the largest section of the SSPI, and includes methods for manipulating and maintaining security contexts, along with encryption and decryption:
- AcceptSecurityContext-Used by a server to creates a security context based on an opaque message received from a client.
- ApplyControlToken-Applies a supplemental security message to an existing security context.
- CompleteAuthToken-Completes an authentication token, used by protocols that need to revise the security information after the transport application has updated some message parameters.
- DeleteSecurityContext-Frees a security context and associated resources.
- FreeContextBuffer-Frees a memory buffer allocated by a security package.
- ImpersonateSecurityContext-Impersonates the security context to appear as the client to the system.
- InitializeSecurityContext-Used by a client to initiates a security context by generating an opaque message to be passed to a server, which can neither interpret or change the message.
- QueryContextAttributes-Queries the attributes of a security context.
- QuerySecurityContextToken-Obtains the impersonation token for a security context for direct manipulation.
- RevertSecurityContext-Ceases impersonating a security context.
Message support functions transmit messages that cannot be tampered with. The functions work with one or more buffers that contain a message and an associated security context created by the context management functions. Message support methods include:
- DecryptMessage-Decrypts an encrypted message using the session key from a security context.
- EncryptMessage-Encrypts a message using the session key from a security context.
- MakeSignature-Generates a secure signature, based on a message and a security context.
- VerifySignature-Verifies that the signature matches a received message.
Impersonation is an important topic in Windows 2000 security, key to security hierarchies. Impersonation occurs when Windows allows one process to take on the security attributes of another. The primary reason for impersonation is to cause access checks to be performed against the client’s identity, which can cause access to be either restricted or expanded, depending on what the client has permission to do.
In essence, impersonation means that the client has agreed to some extent to let the server “be” the client; the extent to which the client assigns authority to the server is the impersonation level. These levels indicate how much authority the client gives to the server when it is impersonating the client. Windows 2000 supports four impersonation levels: anonymous, identify, impersonate, and delegate.
At the anonymous level, the client is anonymous to the server. The server process can impersonate the client but the impersonation token does not contain any information about the client. At the identify level, the system default, the server can obtain the client’s identity. At the impersonate level, the server can impersonate the client’s security context while acting on behalf of the client. At the delegate level, the most powerful of the four, the server can impersonate the client’s security context while acting on behalf of the client. During impersonation, the client’s credentials can be passed to any number of machines.
SSPI supports impersonation through the ImpersonateSecurityContext, QuerySecurityContextToken, and RevertSecurityContext methods. Problems can be indicated with the SSPI status codes SEC_E_NO_TOKEN when the context does not possess an impersonation token, and SEC_E_NO_IMPERSONATION when no impersonation is allowed for the context.
There are four primary steps involved in using SSPI in an application:
- Initializing SSPI
- Establishing an authentic connection
- Ensuring communication integrity during message exchange
- Calling the Windows NT LAN Manager Security Support Provider
Using SSPI still requires that the client and server agree to a protocol to use and that both have access to that protocol’s SSP DLLs.
The client and server take the same steps to initialize the security provider and select the appropriate security package: loading the security provider DLL, getting a pointer to the provider initialization function, using the initialization function to get a reference to the provider’s security function table, and getting specific information about the security package. The security function table contains the SSPI entry points for the security package, used to invoke the calls implemented by the security package.
Establishing an authentic connection involves the exchange of one or more security tokens between the security providers for the client and server. These tokens are sent as opaque messages by the two sides along with any other application protocol specific information. The application level protocol strips the security token out of the received message and passes on to the security package on their side to figure out if authentication is complete or if further exchange of tokens is required. This process could continue forever, but usually requires only a few round trips.
To ensure the integrity of communication, SSPI provides message APIs. Message privacy APIs, such as data encryption, are not exposed directly but a particular provider may expose them and document them separately. After an authenticated connection has been established, the SSPs on each side establish a common session key that is used to sign messages on the sending side and to verify messages on the receiving side. The algorithms used in message signatures are private to the security package.
Application Development with SSPI
There are two broad options for application development with custom security and SSPI. One, of course, is to use SSPI directly with an appropriate SSP, getting down and dirty with the details. This method uses request/response messages to implement the application protocol that carries security-related data.
But the other option is to approach security from a higher level, using the various system services available that use SSPI. There are several such system services with SSPI built-in, including distributed COM (DCOM) via remote procedure calls, COM+, Winsock 2.0, and WinInet through SSL.
Building secure applications with DCOM and COM+ doesn’t require any security specific coding or design in either the client or the server. These programming models hide the security requirements of a component, requiring that the component handle security for the client application. In DCOM this was a bit klunky, but these services are built into COM+ and make it far easier than before to use the services. Similarly, any RPC application can use its RPC APIs.
With Winsock the SSP is integrated into the network stack and provides both security and transport services through a common interface, exposing security features built into the SSP. For example, an application could use TCP/IP and SSL as the SSP, requiring simple steps to activate security:
- Enumerate the available transport providers
- Create a socket in which to use the transport
- Initialize the necessary callback functions
- Initialize the SSL security provider options using WSAIoctl calls
- Connect to the server
The important concept of SSPI is that it doesn’t matter what security protocol the application uses as long as the protocol defines security requirements for connection authentication, message integrity, message privacy, and security quality of service. By meeting these requirements, SSPI can be used as the common abstraction layer to obtain these services, and give Windows 2000 its flexible security infrastructure.
About the author: Don Kiely writes software in Fairbanks, Alaska for Third Sector Technologies, working with non-profits and government agencies. He writes articles about technology, speaks at software conferences, trains for AppDev, and consults on technology.