Platform SDK: Active Directory, ADSI, and Directory Services

Mutual Authentication in Windows Sockets Applications

Microsoft® Windows® Sockets services can use the Registration and Resolution (RnR) APIs to publish services, or they can use service connection points.

For discussion and sample code that shows how to perform mutual authentication for a Windows Sockets service that publishes using a service connection point, see Mutual Authentication in a Windows Sockets Service with an SCP. This example uses an SSPI security package to manage the authentication negotiations between a client and the WinSock service.

Mutual Authentication for Windows Sockets RnR Services

A WinSock RnR service can use similar code to perform mutual authentication using an SSPI package. In this case, the service would compose its SPNs using the distinguished name of the service's entry in the WinsockServices container in the directory.

For example, if the service registers itself with the name "WinSockRnRSampleService", you could compose the service's SPN with the following code. A client could use similar code to construct an SPN to authenticate the service.

DWORD
SpnCompose(TCHAR ***pspn, unsigned long *pulSpn) 
{
DWORD   status;
TCHAR   szDsEntryName[MAX_PATH];
 
// Items for ADSI.
IADs    *pRoot=NULL;
VARIANT varDSRoot;
HRESULT hr;
 
hr = CoInitialize(NULL);
 
// First get the defaultNamingContext for the local domain.
hr = ADsGetObject(TEXT("LDAP://RootDSE"),
                  IID_IADs,
                  (void**)&pRoot);
 
hr = pRoot->Get(TEXT("defaultNamingContext"), &varDSRoot);
_tprintf(TEXT("\nDS Root :%s\n"), varDSRoot.bstrVal);
 
if (pRoot)
    pRoot->Release();
 
CoUninitialize();
 
// Compose the DN of the entry in the WinsockServices container.
_tcscpy(szDsEntryName,
        TEXT("cn=WinSockRnRSampleService,cn=WinsockServices,cn=System,"));
_tcscat(szDsEntryName,varDSRoot.bstrVal);
 
// Build the SPN for this service using the DN and 
// our service's class, "RpcExample".
status = DsGetSpn(
    DS_SPN_SERVICE,     // Type of SPN to create.
    TEXT("RnRExample"), // Service class - a name in this case.
    szDsEntryName,      // DN of the RpcServices for this RPC service.
    0,                  // Use the default instance port.
    0,                  // Number of additional instance names.
    NULL,               // No additional instance names.
    NULL,               // No additional instance ports.
    pulSpn,             // Size of SPN array.
    pspn                // Returned SPN(s).
    );
 
return status;
}