WinSock 2.0 extends the Windows Socket interface to allow the underlying transport provider to expose security features that may be built into the provider. It is conceivable that a TCP/IP provider could use SSPI to encapsulate security functionality such that it can be invoked by a WinSock application. This will be very similar to how RPC encapsulates this functionality and all the application needs to do is to request it! Note that such a provider does not currently exist for Windows NT 4.0. Microsoft is implementing a WinSock 2.0 provider for SSL 3.0 which will be available soon. A general purpose SSPI-TCP/IP transport provider is not currently implemented, but Microsoft will make one available in a future release.
Using the TCP/IP and SSL security provider as an example, all that an application needs to do to use SSPI services is the following:
The following example is taken from the Microsoft Internet Security Schannel examples. The example below shows how to use SSL 3.0 and a TCP/IP provider from WinSock 2.0.
// // Initialize the WinSock 2 subsystem. // err = WSAStartup(MAKEWORD(2,2), &WsaData); if(err != 0) { printf("**** Error initializing WinSock!\n"); return; } // // Choose a WinSock 2 provider that supports both TCP/IP and the // chosen security scheme. // cProtocols = WSAEnumProtocols(NULL, NULL, &cbProtocolBuffer); if(cProtocols == SOCKET_ERROR && WSAGetLastError() != WSAENOBUFS) { printf("**** Error %d during WSAEnumProtocols\n", WSAGetLastError()); return; } // Allocate memory pProtocolBuffer = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cbProtocolBuffer); if(pProtocolBuffer == NULL) return FALSE; // Read array of WSAPROTOCOL_INFO structures. cProtocols = WSAEnumProtocols(NULL, pProtocolBuffer, &cbProtocolBuffer); if(cProtocols == SOCKET_ERROR) { LocalFree(pProtocolBuffer); return; } // Search for SSL protocol for(i = 0, fFound = FALSE ; i < cProtocols ; i++) { if(pProtocolBuffer[i].iProtocol == IPPROTO_TCP && pProtocolBuffer[i].iSecurityScheme == SECURITY_PROTOCOL_SSL) { *pProtocolInfo = pProtocolBuffer[i]; fFound = TRUE; break; } } if(!fFound) { LocalFree(pProtocolBuffer); return; } // Free memory LocalFree(pProtocolBuffer);
Once we have selected the WinSock provider of choice, we can go ahead and create a socket and initialize security on it.
// // Create socket // Socket = WSASocket(FROM_PROTOCOL_INFO, // address family FROM_PROTOCOL_INFO, // type FROM_PROTOCOL_INFO, // protocol pProtocolInfo, // protocol info 0, // group 0); // flags if(Socket == INVALID_SOCKET) { printf("**** Error creating socket!\n"); return FALSE; } else { *pSocket = Socket; } // // Set the socket's SSL flags. // { DWORD dwFlags; dwFlags = SSL_FLAG_ENABLE; err = WSAIoctl(Socket, SO_SSL_SET_FLAGS, (LPVOID)&dwFlags, sizeof(dwFlags), NULL, // output buffer 0, // output buffer size NULL, // # bytes returned NULL, // overlapped structure NULL); // completion routine if(err == SOCKET_ERROR) { printf("**** Error setting SSL flags!\n"); return FALSE; } } // // Set the socket's SSL client parameters. // { SSLCLIENTOPTS SslClientOpts; DWORD cbBytesRead; // Read the default client parameters. err = WSAIoctl(Socket, // socket SO_SSL_GET_CLIENT_OPTS, // dwIoControlCode NULL, // lpvInBuffer 0, // cbInBuffer (LPVOID)&SslClientOpts, // lpvOutBuffer sizeof(SslClientOpts), // cbOutBuffer &cbBytesRead, // lpcbBytesReturned NULL, // lpOverlapped NULL); // lpCompletionRoutine if(err == SOCKET_ERROR) { printf("**** Error reading default client options!\n"); return FALSE; } // Set the session cache timeout period to 10 minutes. Leave // everything else at the default value. SslClientOpts.CacheTimeout = 600; // Set the client parameters. err = WSAIoctl(Socket, // socket SO_SSL_SET_CLIENT_OPTS, // dwIoControlCode (LPVOID)&SslClientOpts, // lpvInBuffer sizeof(SslClientOpts), // cbInBuffer NULL, // lpvOutBuffer 0, // cbOutBuffer NULL, // lpcbBytesReturned NULL, // lpOverlapped NULL); // lpCompletionRoutine if(err == SOCKET_ERROR) { printf("**** Error setting client options!\n"); return FALSE; } } // // We could additionally set up authentication call back functions, etc. // using WSAIoctl API, depending on what else may be involved in setting // up a secure socket. //
Note: The code above is for demonstration purposes only, no such WinSock provider is currently available from Microsoft.
Once the socket is set up, the application can use WSAConnect API to connect to the server and the underlying provider will use the socket security settings to authenticate the connection using an appropriate security package, and so forth. From then on, all the communication can occur transparent of any message signing and sealing that may be done by the provider via SSPI.