4.3 TermSrvBindSecure Example

The following example creates an RPC binding to an endpoint that uses authentication, authorization, and security quality-of-service information.

 RPC_STATUS
 TermSrvBindSecure(
     LPCWSTR pszUuid,
     LPCWSTR pszProtocolSequence,
     LPCWSTR pszNetworkAddress,
     LPCWSTR pszEndPoint,
     LPCWSTR pszOptions,
     RPC_BINDING_HANDLE *pHandle
     )
 {
     RPC_STATUS Status;
     RPC_SECURITY_QOS qos;
     LPWSTR wszServerSPN = NULL;
  
     *pHandle = NULL;
  
     Status = TermSrvBind(
                     pszUuid,
                     pszProtocolSequence,
                     pszNetworkAddress,
                     pszEndPoint,
                     pszOptions,
                     pHandle);
  
     if( Status != RPC_S_OK ) 
     {
         wprintf ( L"Error %d in TermSrvBind", Status );
         goto TS_EXIT_POINT;
     }
  
     qos.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
     qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
     qos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
     qos.Version = RPC_C_SECURITY_QOS_VERSION;
  
     if( PrepareServerSPN( pszNetworkAddress, &wszServerSPN ))
     {
         Status = RpcBindingSetAuthInfoEx(
                         *pHandle,
                         wszServerSPN,
                         RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
                         RPC_C_AUTHN_GSS_NEGOTIATE,
                         NULL,
                         RPC_C_AUTHZ_NAME,
                         &qos);
  
         LocalFree(wszServerSPN);
     }
     else
     {
         Status = RpcBindingSetAuthInfoEx(
                         *pHandle,
                         (LPWSTR)pszNetworkAddress,
                         RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
                         RPC_C_AUTHN_GSS_NEGOTIATE,
                         NULL,
                         RPC_C_AUTHZ_NAME,
                         &qos);
     }
  
     if ( RPC_S_OK != Status )
     {
         wprintf ( L"Error %d in RpcBindingSetAuthInfoEx", Status );
         goto TS_EXIT_POINT;
     }
  
 TS_EXIT_POINT:
  
     if ( RPC_S_OK != Status &&
          NULL != *pHandle )
     {
         RpcBindingFree( pHandle );
     }
  
     return Status;
 }
  

Generate a standard RPC binding from the protocol sequence, security options, and UUID, for example.

  
  
 RPC_STATUS
 TermSrvBind(
     IN LPCWSTR pszUuid,
     IN LPCWSTR pszProtocolSequence,
     IN LPCWSTR pszNetworkAddress,
     IN LPCWSTR pszEndPoint,
     IN LPCWSTR pszOptions,
     OUT RPC_BINDING_HANDLE *pHandle
     )
 {
     RPC_STATUS Status;
     LPWSTR pszString = NULL;
  
     /*
      * Compose the binding string using the helper routine
      * and our protocol sequence, security options, UUID, and so on.
      */
     Status = RpcStringBindingCompose(
                  (LPWSTR)pszUuid,
                  (LPWSTR)pszProtocolSequence,
                  (LPWSTR)pszNetworkAddress,
                  (LPWSTR)pszEndPoint,
                  (LPWSTR)pszOptions,
                  &pszString
                  );
  
     if( Status != RPC_S_OK ) 
     {
         wprintf ( L"Error %d in RpcStringBindingCompose", Status );
         goto TS_EXIT_POINT;
     }
  
     /*
      * Now generate the RPC binding from the canonical RPC
      * binding string.
      */
     Status = RpcBindingFromStringBinding(
                  pszString,
                  pHandle
                  );
  
     if( Status != RPC_S_OK ) 
     {
         wprintf ( L"Error %d in RpcBindingFromStringBinding", Status );
         goto TS_EXIT_POINT;
     }
  
 TS_EXIT_POINT:
  
     if ( NULL != pszString )
     {
         /*
          * Free the memory returned from RpcStringBindingCompose()
          */
         RpcStringFree( &pszString );
     }
  
     return( Status );
 }
  

Recreate a valid SPN for Windows Vista operating system from an existing SPN.

  
  
 BOOL
 PrepareServerSPN(
     IN LPCWSTR pszNetworkAddress,
     __deref_out_opt LPWSTR *ppwszServerSPN
     )
 {
     // Windows Server 2008 RPC does not accept "net use" credential anymore.    
     // <Domain>\<Machine> is not a valid SPN, a valid SPN is host/<Machine Name>
  
     LPWSTR pszTemplate = L"host/%s";
     *ppwszServerSPN = NULL;
     HRESULT hr = S_OK;
  
     UINT stringLength = wcslen(pszTemplate)+wcslen(pszNetworkAddress)+1;
  
     *ppwszServerSPN = (LPWSTR)LocalAlloc(LPTR, stringLength * sizeof(WCHAR));
     if(*ppwszServerSPN)
     {
         hr = StringCchPrintf( *ppwszServerSPN, stringLength, pszTemplate, 
                               pszNetworkAddress );
         ASSERT( SUCCEEDED( hr ));
     }
  
     if( FAILED(hr) )
     {
         if( NULL != *ppwszServerSPN )
         {
             LocalFree( *ppwszServerSPN );
             *ppwszServerSPN = NULL;
         }
     }
  
     return SUCCEEDED(hr);
 }