Using Secure RPC

Any RPC application can turn security on by using simple security enabling RPC APIs. In this section we present the APIs, various associated parameters, and then discuss where to use each API to get security services.

RPC Security Interfaces

The security related RPC interfaces are:


RPC_STATUS RPC_ENTRY
RpcBindingInqAuthInfoW (
 IN RPC_BINDING_HANDLE Binding,
 OUT RPC_CHAR PAPI * PAPI * ServerPrincName, OPTIONAL
 OUT unsigned long PAPI * AuthnLevel, OPTIONAL
 OUT unsigned long PAPI * AuthnSvc, OPTIONAL
 OUT RPC_AUTH_IDENTITY_HANDLE PAPI * AuthIdentity, OPTIONAL
 OUT unsigned long PAPI * AuthzSvc OPTIONAL
 )
RPC_STATUS RPC_ENTRY
RpcBindingInqAuthInfoExW (
 IN RPC_BINDING_HANDLE Binding,
 OUT RPC_CHAR PAPI * PAPI * ServerPrincName, OPTIONAL
 OUT unsigned long PAPI * AuthnLevel, OPTIONAL
 OUT unsigned long PAPI * AuthnSvc, OPTIONAL
 OUT RPC_AUTH_IDENTITY_HANDLE PAPI * AuthIdentity, OPTIONAL
 OUT unsigned long PAPI * AuthzSvc, OPTIONAL
 IN unsigned long RpcSecurityQosVersion,
 OUT RPC_SECURITY_QOS * SecurityQos
 )

RpcBindingInqAuthInfo is a client-side API that can be used to inquire aboutthe authentication information set on the supplied binding handle. Ex-counterpart provides additional information on the security quality of service setting on the binding handle.


RPC_STATUS RPC_ENTRY
RpcBindingSetAuthInfoW (
 IN RPC_BINDING_HANDLE Binding,
 IN RPC_CHAR PAPI * ServerPrincName,
 IN unsigned long AuthnLevel,
 IN unsigned long AuthnSvc,
 IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
 IN unsigned long AuthzSvc
 )
RPC_STATUS RPC_ENTRY
RpcBindingSetAuthInfoExW (
 IN RPC_BINDING_HANDLE Binding,
 IN RPC_CHAR PAPI * ServerPrincName,
 IN unsigned long AuthnLevel,
 IN unsigned long AuthnSvc,
 IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
 IN unsigned long AuthzSvc,
 IN RPC_SECURITY_QOS *SecurityQOS
 )

RpcBindingSetAuthInfo is a client-side API that can be used by to set authentication information on the supplied binding handle. This involves setting up authentication level, authentication service, and so forth. Ex-counterpart provides additional capability to set security quality of service information on the binding handle. The mapping of various RPC security constants is described in subsections later.


RPC_STATUS RPC_ENTRY
RpcMgmtInqDefaultProtectLevel(
 IN unsigned long AuthnSvc,
 OUT unsigned long PAPI *AuthnLevel
 )

RpcMgmtInqDefaultProtectLevel returns the mapping for RPC_C_AUTHN_LEVEL_DEFAULT for the supplied authentication service.


RPC_STATUS RPC_ENTRY
RpcServerRegisterAuthInfoW (
 IN RPC_CHAR PAPI * ServerPrincName,
 IN unsigned long AuthnSvc,
 IN RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, OPTIONAL
 IN void PAPI * Arg OPTIONAL
 )

RpcServerRegisterAuthInfo is the server side API to turn on security for the various server interfaces that are registered. It sets up the server, principal name, authentication service to use, any key retrieval function (default is supplied by authentication service) in the RPC_SERVER object. The authentication service to use is specified by a constant. The mapping of these constants to packages is discussed in a subsection later.


RPC_STATUS RPC_ENTRY
RpcBindingInqAuthClientW (
 IN RPC_BINDING_HANDLE ClientBinding, OPTIONAL
 OUT RPC_AUTHZ_HANDLE PAPI * Privs,
 OUT RPC_CHAR PAPI * PAPI * ServerPrincName, OPTIONAL
 OUT unsigned long PAPI * AuthnLevel, OPTIONAL
 OUT unsigned long PAPI * AuthnSvc, OPTIONAL
 OUT unsigned long PAPI * AuthzSvc OPTIONAL
 )

The server-side application can use RpcBindingInqAuthClient to obtain authorization information about the client making the authenticated RPC.


RPC_STATUS RPC_ENTRY
RpcImpersonateClient (
 IN RPC_BINDING_HANDLE ClientBinding OPTIONAL
 )
RPC_STATUS RPC_ENTRY
RpcRevertToSelfEx (
 IN RPC_BINDING_HANDLE ClientBinding OPTIONAL
 )
RPC_STATUS RPC_ENTRY
RpcRevertToSelf (
 )

RpcImpersonateClient is used by the server thread to impersonate the client whose request it is servicing. The impersonation level is set according to the one specified by the client when making the connection.

RevertToSelf is used to return the default security context.


RPC_STATUS RPC_ENTRY
RpcMgmtInqServerPrincNameW (
 IN RPC_BINDING_HANDLE Binding,
 IN unsigned long AuthnSvc,
 OUT RPC_CHAR __RPC_FAR * __RPC_FAR * ServerPrincName
 )
RPC_STATUS RPC_ENTRY
RpcServerInqDefaultPrincNameW (
 IN unsigned long AuthnSvc,
 OUT RPC_CHAR __RPC_FAR * __RPC_FAR * PrincName
 )

RpcMgmtInqServerPrincName is used by the server application to inquire aboutthe server's principal name corresponding to the supplied binding handle and the authentication service.

RpcServerInqDefaultPrincName returns the default principal name for the server for the supplied authentication service.

RPC Authentication Service Constants

Authentication service is provided by security support packages. RPC defines six authentication service identifiers. Security support packages are loaded in the system as part of the security provider DLL. Each provider DLL can support one or more security packages. RPC loads the provider DLLs and then calls EnumerateSecurityPackages() in the DLL to get the security packages in the DLL. Each security package information contains "wRPCID" which has to be one of the six RPC identifiers. This information is used to select the security package which corresponds to the authentication service requested by the application during the security initialization calls.

RPC Authentication Service

Security Support Package

RPC_C_AUTHN_NONE

no authentication package to use, ie No security.

RPC_C_AUTHN_DCE_PRIVATE

not currently supported

RPC_C_AUTHN_DCE_PUBLIC

not currently supported

RPC_C_AUTHN_DEC_PUBLIC

not currently supported

RPC_C_AUTHN_WINNT

NTLM SSP in security.dll (NT4.0)

RPC_C_AUTHN_DEFAULT

NTLM SSP in security.dll (NT4.0)


Table 1: RPC Authentication Service Identifiers.

RPC Authentication Level Constants

RPC provides security by "levels." The authentication levels are:

Whether a particular authentication level is available is decided by the security package being used. If a security package does not support the requested level it may upgrade it to the next highest level it supports (if available) or return an error during server initialization.

RPC Authentication Level

SSP Service Level

RPC_C_AUTHN_LEVEL_CONNECT

ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH

RPC_C_AUTHN_LEVEL_CALL

bumped to RPC_C_AUTHN_LEVEL_PKT

RPC_C_AUTHN_LEVEL_PKT

ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH | ISC_REQ_REPLAY_DETECT

RPC_C_AUTHN_LEVEL_PKT_ INTEGRITY

ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT

RPC_C_AUTHN_LEVEL_PKT_ PRIVACY

ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH | ISC_REQ_REPLAY_DETECT |ISC_REQ_SEQUENCE_DETECT| ISC_REQ_CONFIDENTIALITY


Table 2: RPC Authentication Levels and SSP Services.

The mapping of RPC authentication levels to SSPI's capabilities is constant. It does not change with the change of authentication package. It is up to the authentication package to ignore or return an error on some of these depending on the capabilities it supports.

RPC Impersonation Levels

RPC is designed to provide all the impersonation levels defined by a native Windows NT-based system:

The delegation impersonation level is not supported by Windows NT natively but the security package may have the ability to provide it. In fact, in the current implementation, RPC always requests delegation level security context from the security package for nonauthenticated transports. It maps the requested level to the native level for authenticated transports (Namedpipes and LPC). Impersonation levels are also associated with context tracking modes. If the tracking is static, the security context is created only once and is never revised during the entire communication, even if the client side changes it. In the case of dynamic tracking, the context is revised whenever the LogonId in the client's token is changed.

NTLM security package, the default security package in Windows NT 4.0, does not currently support delegation and ignores the RPC's request.

RPC Authentication Identity

During client initialization, client process can supply a client identity handle in the RpcBindingSetAuthInfo call. This authentication identity handle points to a structure which contains the username, domainname, and plaintext password of the user. This information is not required, and if not present, the process's default identity is picked from the attached token by the security package.

RPC stores this information with the binding and passes it on to the security support package when acquiring security credentials.

RPC Authorization Service Constants

RPC currently defines three authorization service constants:

RPC currently does not use this information. It corresponds to authorization service setting by the security package. The default security package in Windows NT 4.0 (NTLM security package) sets this to 0.

RPC Client and Server Security Initialization

The RPC server initializes security by calling RpcServerRegisterAuthInfo as follows:


//
// Request Security…
//
Status = RpcServerRegisterAuthInfo(
    NULL,
    RPC_C_AUTHN_WINNT,
    NULL,
    NULL
    );
//
// where:
//    Arg1 = ServerPrincipalName (ignored by NTLM SSP).
//    Arg2 = The SSP to use based on RPC settings => default NTLM SSP
//    Arg3/Arg4 = GetKey function and its argument, not used.
// 

if(Status)
{
    // Oops.. we have a problem…
}

//
//    Standard RPC calls to register the interface, set up the endpoint, etc.
//    and then go into Listen…
//

The RPC client initializes security by calling RpcBindingSetAuthInfo(Ex) as follows:


//
//    Do the binding etc.
//

// 
// Request Security…
//
Status = RpcBindingSetAuthInfoEx(
    RpcInterfaceHandle,
    NULL,
    AuthnLevel,
    RPC_C_AUTHN_WINNT,
    NULL,
    AuthzSvc,
          SecurityQos
    );
//
// where:
//    Arg1 = Binding Handle just established.
//    Arg2 = ServerPrincipalName (NULL as it is ignored by NTLM SSP).
//    Arg3 = Authentication Leve (see above for valid values).
//    Arg4 = Auth service which be default selects NTLM SSP for NT.
//    Arg5 = Authentication Identity which can be SEC_WINNT_AUTH_IDENTITY structure
//        specifying Username, DomainName and password. NULL means use default.
//    Arg6 = Autorization Service (see above for valid values).
//    Arg7 = Impersonation Level, see above for valid values.
//

RPC Invocations and Executions.

Once the client and server sides have initialized security, the client can go ahead and start making remote procedure calls without worrying about security. Underlying RPC run time encapsulates all of the SSPI interactions to establish the authenticated connection and secure message exchange.

On the server side, when a procedure is invoked for execution, it can use RpcImpersonateClient() API to impersonate the client before servicing the request, if so required. It can then revert to original security context using RpcRevertToSelf().