/*++ Copyright (C) Microsoft Corporation, 1991 - 1999 Module Name: dcebind.cxx Abstract: This module contains the code implementing the Binding Object DCE RPC runtime APIs. APIs which are used only by server applications do not live here. Author: Michael Montague (mikemon) 25-Sep-1991 Revision History: --*/ #include #include #include RPC_STATUS RPC_ENTRY RpcBindingCopy ( IN RPC_BINDING_HANDLE SourceBinding, OUT RPC_BINDING_HANDLE PAPI * DestinationBinding ) /*++ Routine Description: This routine copies binding information and creates a new binding handle. Arguments: SourceBinding - Supplies the binding to be duplicated. DestinationBinding - Returns a new binding which is a duplicate of SourceBinding. Return Value: The status for the operation is returned. --*/ { MESSAGE_OBJECT * Binding; THREAD *Thread; InitializeIfNecessary(); Thread = ThreadSelf(); if (Thread == NULL) return RPC_S_OUT_OF_MEMORY; RpcpPurgeEEInfoFromThreadIfNecessary(Thread); Binding = (MESSAGE_OBJECT *) SourceBinding; if (Binding->InvalidHandle(BINDING_HANDLE_TYPE)) { return NDRCCopyContextHandle(SourceBinding, DestinationBinding); } return(Binding->BindingCopy((BINDING_HANDLE *PAPI *) DestinationBinding, 0)); } RPC_STATUS RPC_ENTRY I_RpcBindingCopy ( IN RPC_BINDING_HANDLE SourceBinding, OUT RPC_BINDING_HANDLE PAPI * DestinationBinding ) /*++ Routine Description: This routine copies binding information and creates a new binding handle. In addition, context is being maintained by the server over this binding handle. Arguments: SourceBinding - Supplies the binding to be duplicated. DestinationBinding - Returns a new binding which is a duplicate of SourceBinding. Return Value: The status for the operation is returned. --*/ { MESSAGE_OBJECT * Binding; InitializeIfNecessary(); Binding = (MESSAGE_OBJECT *) SourceBinding; if (Binding->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); return(Binding->BindingCopy((BINDING_HANDLE * PAPI *) DestinationBinding, 1)); } RPC_STATUS RPC_ENTRY RpcBindingFree ( IN OUT RPC_BINDING_HANDLE PAPI * Binding ) /*++ Routine Description : RpcBindingFree releases binding handle resources. Arguments: Binding - Supplies the binding handle to be freed, and returns zero. Return Value: The status of the operation is returned. --*/ { BINDING_HANDLE * BindingHandle; RPC_STATUS Status; // if we're shutting down, don't bother // Since our other threads have been nuked, data structures may // be in half modified state. Therefore it is unsafe to proceed // with freeing the binding handle during shutdown if (RtlDllShutdownInProgress()) { *Binding = 0; return RPC_S_OK; } InitializeIfNecessary(); // here it will be more efficient if we succeed, but other code will manage fine // even if we don't, so we don't really care about return value ThreadSelf(); ASSERT(!RpcpCheckHeap()); BindingHandle = (BINDING_HANDLE *) *Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); Status = BindingHandle->BindingFree(); *Binding = 0; return(Status); } RPC_STATUS RPC_ENTRY RpcBindingReset ( IN RPC_BINDING_HANDLE Binding ) /*++ Routine Description: This routine sets the endpoint in the supplied binding handle to zero. This makes the binding handle a partiallly bound binding handle. NOTE: this routine will fail if the binding handle has already been used to make remote procedure calls. Based on how this routine will be used (to iterate through the entries in the endpoint mapper database), this should not be a problem. Arguments: Binding - Supplies the binding handle for which the endpoint will be set to zero, hence making it a partially bound binding handle. Return Value: RPC_S_OK - The operation completed successfully. RPC_S_INVALID_BINDING - The supplied argument is not a valid binding. RPC_S_WRONG_KIND_OF_BINDING - Either the supplied binding is not a client binding handle or it is a client binding handle which has already been used to make remote procedure calls. --*/ { BINDING_HANDLE * BindingHandle; THREAD *Thread; Thread = ThreadSelf(); if (Thread == NULL) return RPC_S_OUT_OF_MEMORY; BindingHandle = (BINDING_HANDLE *) Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); return(BindingHandle->BindingReset()); } RPC_STATUS RPC_ENTRY RpcBindingFromStringBinding ( IN unsigned short PAPI * StringBinding, OUT RPC_BINDING_HANDLE PAPI * Binding ) /*++ Routine Description: This routine returns a binding handle from a string representation of a binding handle. Arguments: StringBinding - Supplies the string representation of a binding handle. Binding - Returns a binding handle constructed from the string representation. Return Value: The status of the operation is returned. --*/ { DCE_BINDING * DceBinding; RPC_STATUS Status; BINDING_HANDLE * BindingHandle; RPC_CHAR __RPC_FAR * CopiedStringBinding; THREAD *Thread; InitializeIfNecessary(); ASSERT(!RpcpCheckHeap()); Thread = ThreadSelf(); if (!Thread) return RPC_S_OUT_OF_MEMORY; RpcpPurgeEEInfoFromThreadIfNecessary(Thread); *Binding = 0; CopiedStringBinding = (RPC_CHAR *) _alloca( (RpcpStringLength(StringBinding)+1)*(sizeof(RPC_CHAR)) ); if (CopiedStringBinding == 0) { return (RPC_S_OUT_OF_MEMORY); } RpcpStringCopy(CopiedStringBinding, StringBinding); DceBinding = new DCE_BINDING(CopiedStringBinding, &Status); if (DceBinding == 0) Status = RPC_S_OUT_OF_MEMORY; if (Status == RPC_S_OK) { BindingHandle = DceBinding->CreateBindingHandle(&Status); if (Status == RPC_S_OK) *Binding = BindingHandle; // // DceBinding gets deleted by the callee, if the above call fails // } else { delete DceBinding; } return(Status); } RPC_STATUS RPC_ENTRY RpcBindingSetObject ( IN RPC_BINDING_HANDLE Binding, IN UUID PAPI * ObjectUuid ) /*++ Routine Description: This routine sets the object UUID value in a binding handle. Arguments: Binding - Supplies the binding handle for which the object UUID is to be set. ObjectUuid - Supplies the UUID value to put into the binding handle. Return Values: RPC_S_OK - The operation completed successfully. RPC_S_INVALID_BINDING - The binding argument does not specify a binding handle. RPC_S_WRONG_KIND_OF_BINDING - The binding argument does specify a binding handle, but it is not a client binding handle (ie. one owned by the client side rpc runtime). --*/ { BINDING_HANDLE * BindingHandle; InitializeIfNecessary(); BindingHandle = (BINDING_HANDLE *) Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); BindingHandle->SetObjectUuid((RPC_UUID PAPI *) ObjectUuid); return(RPC_S_OK); } RPC_STATUS RPC_ENTRY RpcBindingVectorFree ( IN OUT RPC_BINDING_VECTOR PAPI * PAPI * BindingVector ) /*++ Routine Description: This routine frees the binding handles contained in the vector, and the vector itself. Arguments: BindingVector - Supplies a vector of binding handles which will be freed. On return, the pointer to the binding vector will be set to zero. Return Value: The status of the operation will be returned. --*/ { unsigned int Index, Count; RPC_BINDING_VECTOR PAPI * Vector; RPC_STATUS Status; InitializeIfNecessary(); for (Index = 0, Vector = *BindingVector, Count = (unsigned int) Vector->Count; Index < Count; Index++) if (Vector->BindingH[Index] != 0) { Status = RpcBindingFree(&(Vector->BindingH[Index])); if (Status != RPC_S_OK) return(Status); } RpcpFarFree(*BindingVector); *BindingVector = 0; return(RPC_S_OK); } RPC_STATUS RPC_ENTRY RpcEpResolveBinding ( IN RPC_BINDING_HANDLE Binding, IN RPC_IF_HANDLE IfSpec ) /*++ Routine Description: This routine is used to resolve a partially-bound binding handle into a fully-bound binding handle. A partially-bound binding handle is one in which the endpoint is not specified. To make the binding handle fully-bound, we need to determine the endpoint. Arguments: Binding - Supplies a partially-bound binding handle to resolve into a fully bound one. Specifying a fully-bound binding handle to this routine is not an error; it has no effect on the binding handle. IfSpec - Supplies a handle to the description of the interface for which we wish to resolve the endpoint. This information will be used to find the correct server on the machine specified by the network address in the binding handle. Return Value: RPC_S_OK - The binding handle is now fully-bound. RPC_S_NO_ENDPOINT_FOUND - We were unable to resolve the endpoint for this particular combination of binding handle (network address) and interface. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to resolve the endpoint. RPC_S_INVALID_BINDING - The binding argument does not specify a binding handle. RPC_S_WRONG_KIND_OF_BINDING - The binding argument does specify a binding handle, but it is not a client binding handle (ie. one owned by the client side rpc runtime). --*/ { BINDING_HANDLE * BindingHandle; InitializeIfNecessary(); BindingHandle = (BINDING_HANDLE *) Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); return(BindingHandle->ResolveBinding((PRPC_CLIENT_INTERFACE) IfSpec)); } RPC_STATUS RPC_ENTRY RpcNsBindingInqEntryName ( IN RPC_BINDING_HANDLE Binding, IN unsigned long EntryNameSyntax, OUT unsigned short PAPI * PAPI * EntryName ) /*++ Routine Description: Arguments: Return Value: RPC_S_OK - The entry name for the binding handle has been successfully inquired and returned. RPC_S_INVALID_BINDING - The binding argument does not specify a binding handle. RPC_S_WRONG_KIND_OF_BINDING - The binding argument does specify a binding handle, but it is not a client binding handle (ie. one owned by the client side rpc runtime). --*/ { #if !defined(NO_LOCATOR_CODE) BINDING_HANDLE * BindingHandle; InitializeIfNecessary(); BindingHandle = (BINDING_HANDLE *) Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); return(BindingHandle->InquireEntryName(EntryNameSyntax, EntryName)); #else return RPC_S_CANNOT_SUPPORT; #endif } RPC_STATUS RPC_ENTRY THUNK_FN(I_RpcNsBindingSetEntryName) ( IN RPC_BINDING_HANDLE, IN unsigned long, IN unsigned char * ) { return RPC_S_CANNOT_SUPPORT; } RPC_STATUS RPC_ENTRY I_RpcNsBindingSetEntryName ( IN RPC_BINDING_HANDLE Binding, IN unsigned long EntryNameSyntax, IN unsigned short PAPI * EntryName ) /*++ Routine Description: This routine is a private entry point for use by name service support dlls; it allows them to set the entry name in a binding handle before returning it from import or lookup. If an entry name already exists in the binding handle, we just go ahead and overwrite the old one with new one. Arguments: Binding - Supplies the binding handle for which we want to set the entry name. EntryNameSyntax - Supplies the syntax used by the entry name. We need to save this information for when the entry name is inquired. EntryName - Supplies the entry name for this binding handle. Return Value: RPC_S_OK - The entry name has been successfully set for the binding handle. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the operation. RPC_S_INVALID_BINDING - The binding argument does not specify a binding handle. RPC_S_WRONG_KIND_OF_BINDING - The binding argument does specify a binding handle, but it is not a client binding handle (ie. one owned by the client side rpc runtime). --*/ { #if !defined(NO_LOCATOR_CODE) BINDING_HANDLE * BindingHandle; InitializeIfNecessary(); BindingHandle = (BINDING_HANDLE *) Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); return(BindingHandle->SetEntryName(EntryNameSyntax, EntryName)); #else return RPC_S_CANNOT_SUPPORT; #endif } RPC_STATUS RPC_ENTRY RpcBindingInqAuthInfo ( IN RPC_BINDING_HANDLE Binding, OUT unsigned short 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 ) /*++ Routine Description: This routine is used to return the authentication and authorization for a binding handle. You should also see RpcBindingSetAuthInfoW. Arguments: Binding - Supplies the binding handle for which we wish to query the authentication and authorization information. ServerPrincName - Optionally returns the server principal name set for the binding handle. AuthnLevel - Optionally returns the authentication level set for the binding handle. AuthnSvc - Optionally returns the authentication service set for the binding handle. AuthIdentity - Optionally returns a handle to the security context being used for authentication and authorization. AuthzSvc - Optionally returns the authorization service set for the binding handle. Return Value: RPC_S_OK - We successfully returned the information requested. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the operation. RPC_S_INVALID_BINDING - The value supplied as the binding argument is not a valid binding handle. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must be specified as the binding argument. RPC_S_BINDING_HAS_NO_AUTH - RpcBindingInqAuthInfo has not yet been called on the binding handle, so there is not authentication or authorization to be returned. --*/ { BINDING_HANDLE * BindingObject; CLIENT_AUTH_INFO * ClientAuthInfo; InitializeIfNecessary(); return( RpcBindingInqAuthInfoEx( Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvc, 0, 0 ) ); } RPC_STATUS RPC_ENTRY RpcBindingInqAuthInfoEx ( IN RPC_BINDING_HANDLE Binding, OUT unsigned short 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 ) /*++ Routine Description: This routine is used to return the authentication and authorization for a binding handle. You should also see RpcBindingSetAuthInfoW. Arguments: Binding - Supplies the binding handle for which we wish to query the authentication and authorization information. ServerPrincName - Optionally returns the server principal name set for the binding handle. AuthnLevel - Optionally returns the authentication level set for the binding handle. AuthnSvc - Optionally returns the authentication service set for the binding handle. AuthIdentity - Optionally returns a handle to the security context being used for authentication and authorization. AuthzSvc - Optionally returns the authorization service set for the binding handle. RpcSecurityQosVersion - Indicates a version for RPC_SECURITY_QOS structure, that optionally can be inquired. If SecurityQOS passes in is 0, this is ignored. SecurityQOS - is the version of the Security Quality Of Service Return Value: RPC_S_OK - We successfully returned the information requested. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the operation. RPC_S_INVALID_BINDING - The value supplied as the binding argument is not a valid binding handle. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must be specified as the binding argument. RPC_S_BINDING_HAS_NO_AUTH - RpcBindingInqAuthInfo has not yet been called on the binding handle, so there is not authentication or authorization to be returned. --*/ { BINDING_HANDLE * BindingObject; CLIENT_AUTH_INFO * ClientAuthInfo; InitializeIfNecessary(); BindingObject = (BINDING_HANDLE *) Binding; if ( BindingObject->InvalidHandle(BINDING_HANDLE_TYPE) ) { return(RPC_S_INVALID_BINDING); } ClientAuthInfo = BindingObject->InquireAuthInformation(); if ( ClientAuthInfo == 0 || ClientAuthInfo->AuthenticationLevel == RPC_C_AUTHN_LEVEL_NONE) { return(RPC_S_BINDING_HAS_NO_AUTH); } if (ARGUMENT_PRESENT(AuthnLevel)) { *AuthnLevel = ClientAuthInfo->AuthenticationLevel; } if (ARGUMENT_PRESENT(AuthnSvc)) { *AuthnSvc = ClientAuthInfo->AuthenticationService; } if (ARGUMENT_PRESENT(AuthIdentity)) { *AuthIdentity = ClientAuthInfo->AuthIdentity; } if (ARGUMENT_PRESENT(AuthzSvc)) { *AuthzSvc = ClientAuthInfo->AuthorizationService; } if (ARGUMENT_PRESENT(ServerPrincName)) { if ( ClientAuthInfo->ServerPrincipalName == 0 ) { *ServerPrincName = 0; } else { *ServerPrincName = DuplicateStringPAPI( ClientAuthInfo->ServerPrincipalName); if ( *ServerPrincName == 0 ) { return(RPC_S_OUT_OF_MEMORY); } } } if (ARGUMENT_PRESENT(SecurityQos)) { if (RpcSecurityQosVersion != RPC_C_SECURITY_QOS_VERSION) { if (ARGUMENT_PRESENT(ServerPrincName)) delete *ServerPrincName; return (RPC_S_INVALID_ARG); } SecurityQos->Version = RPC_C_SECURITY_QOS_VERSION; SecurityQos->Capabilities = ClientAuthInfo->Capabilities; SecurityQos->ImpersonationType = ClientAuthInfo->ImpersonationType; SecurityQos->IdentityTracking = ClientAuthInfo->IdentityTracking; } return(RPC_S_OK); } RPC_STATUS RPC_ENTRY RpcBindingSetAuthInfo ( IN RPC_BINDING_HANDLE Binding, IN unsigned short PAPI * ServerPrincName, IN unsigned long AuthnLevel, IN unsigned long AuthnSvc, IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL IN unsigned long AuthzSvc ) /*++ Routine Description: A client application will use this routine to specify the authentication and authorization information in a binding handle, so that the binding handle can be used to make authenticated remote procedure calls. If the this routine is not used, then all remote procedure calls on the binding handle will be unauthenticated. Arguments: Binding - Supplies binding handle for which we want to set authentication and authorization information. ServerPrincName - Supplies the expected principal name of the server referenced by the binding handle (that is supplied as the binding argument). This information is necessary for some security services to be able to authenticate with the server. AuthnLevel - Supplies a value indicating the amount (or level) of authentication to be performed on remote procedure calls using the binding handle. If we do not support the requested level, we will upgrade to the next highest supported level. RPC_C_AUTHN_LEVEL_DEFAULT - Indicates that the default level for authentication service being used should be used. RPC_C_AUTHN_LEVEL_NONE - Do not perform any authentication. RPC_C_AUTHN_LEVEL_CONNECT - Authentication will be performed only when the client first talks to the server. RPC_C_AUTHN_LEVEL_CALL - For connection based protocols, we will use RPC_C_AUTHN_LEVEL_PKT instead; for datagram based protocols, authentication will be performed at the beginning of each remote procedure call. RPC_C_AUTHN_LEVEL_PKT - All data will be authenticated to insure that the data it is received from the expected client. RPC_C_AUTHN_LEVEL_PKT_INTEGRITY - In addition, to authenticating that the data is from the expected client, we will verify that none of it has been modified. RPC_C_AUTHN_LEVEL_PKT_PRIVACY - Finally, this includes all of the support in packet integrity, as well as encrypting all remote procedure call data. AuthnSvc - Supplies the authentication service to use. AuthIdentify - Optionally supplies authentication and authorization credentials to use; if this argument is not specified, the security context for the current address space will be used. AuthzSvc - Supplies the authorization service being used by the server. The client must know this so that the correct authorization information can be sent to the server. Return Value: RPC_S_OK - The supplied authentication and authorization information has been set in the binding handle. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the operation. RPC_S_INVALID_BINDING - The value supplied as the binding argument is not a valid binding handle. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must be specified as the binding argument. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is not supported. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is not supported. RPC_S_INVALID_AUTH_IDENTITY - The specified security context (supplied by the auth identity argument) is invalid. RPC_S_UNKNOWN_AUTHZ_SERVICE - The specified authorization service is not supported. --*/ { return ( RpcBindingSetAuthInfoEx( Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvc, 0 ) ); } RPC_STATUS RPC_ENTRY RpcBindingSetAuthInfoEx ( IN RPC_BINDING_HANDLE Binding, IN unsigned short 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 ) /*++ Routine Description: A client application will use this routine to specify the authentication and authorization information in a binding handle, so that the binding handle can be used to make authenticated remote procedure calls. If the this routine is not used, then all remote procedure calls on the binding handle will be unauthenticated. Arguments: Binding - Supplies binding handle for which we want to set authentication and authorization information. ServerPrincName - Supplies the expected principal name of the server referenced by the binding handle (that is supplied as the binding argument). This information is necessary for some security services to be able to authenticate with the server. AuthnLevel - Supplies a value indicating the amount (or level) of authentication to be performed on remote procedure calls using the binding handle. If we do not support the requested level, we will upgrade to the next highest supported level. RPC_C_AUTHN_LEVEL_DEFAULT - Indicates that the default level for authentication service being used should be used. RPC_C_AUTHN_LEVEL_NONE - Do not perform any authentication. RPC_C_AUTHN_LEVEL_CONNECT - Authentication will be performed only when the client first talks to the server. RPC_C_AUTHN_LEVEL_CALL - For connection based protocols, we will use RPC_C_AUTHN_LEVEL_PKT instead; for datagram based protocols, authentication will be performed at the beginning of each remote procedure call. RPC_C_AUTHN_LEVEL_PKT - All data will be authenticated to insure that the data it is received from the expected client. RPC_C_AUTHN_LEVEL_PKT_INTEGRITY - In addition, to authenticating that the data is from the expected client, we will verify that none of it has been modified. RPC_C_AUTHN_LEVEL_PKT_PRIVACY - Finally, this includes all of the support in packet integrity, as well as encrypting all remote procedure call data. AuthnSvc - Supplies the authentication service to use. AuthIdentify - Optionally supplies authentication and authorization credentials to use; if this argument is not specified, the security context for the current address space will be used. AuthzSvc - Supplies the authorization service being used by the server. The client must know this so that the correct authorization information can be sent to the server. SecurityQOS - a security QOS stucture. Currently accepting RPC_C_SECURITY_QOS_VERSION_2 and RPC_C_SECURITY_QOS_VERSION_1 Return Value: RPC_S_OK - The supplied authentication and authorization information has been set in the binding handle. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the operation. RPC_S_INVALID_BINDING - The value supplied as the binding argument is not a valid binding handle. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must be specified as the binding argument. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is not supported. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is not supported. RPC_S_INVALID_AUTH_IDENTITY - The specified security context (supplied by the auth identity argument) is invalid. RPC_S_UNKNOWN_AUTHZ_SERVICE - The specified authorization service is not supported. --*/ { BINDING_HANDLE * BindingObject; RPC_STATUS Status; RPC_CHAR __RPC_FAR * ServerName; unsigned long ImpersonationType; unsigned long IdentityTracking; unsigned long Capabilities; void *AdditionalCredentials; ULONG AdditionalTransportCredentialsType; THREAD *Thread; RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials; unsigned int i; InitializeIfNecessary(); Thread = ThreadSelf(); if (Thread) { RpcpPurgeEEInfoFromThreadIfNecessary(Thread); } BindingObject = (BINDING_HANDLE *) Binding; if ((SecurityQOS != 0) && (SecurityQOS->Version != RPC_C_SECURITY_QOS_VERSION_1) && (SecurityQOS->Version != RPC_C_SECURITY_QOS_VERSION_2) ) { return(RPC_S_INVALID_ARG); } if ( BindingObject->InvalidHandle(BINDING_HANDLE_TYPE) ) { return(RPC_S_INVALID_BINDING); } // // For no authentication, bail out now. // if (AuthnSvc == RPC_C_AUTHN_NONE) { if ((AuthnLevel != RPC_C_AUTHN_LEVEL_NONE) && (AuthnLevel != RPC_C_AUTHN_LEVEL_DEFAULT)) { return(RPC_S_UNKNOWN_AUTHN_LEVEL); } // // Clear the authentication info.. // Status = BindingObject->SetAuthInformation( 0, RPC_C_AUTHN_LEVEL_NONE, AuthnSvc, 0, 0 ); return(Status); } if (AuthnSvc == RPC_C_AUTHN_DEFAULT) { RpcpGetDefaultSecurityProviderInfo(); AuthnSvc = DefaultProviderId; } if (AuthnSvc == RPC_C_AUTHN_GSS_SCHANNEL) { if (AuthnLevel < RPC_C_AUTHN_LEVEL_PKT_PRIVACY) { AuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY; } } if (SecurityQOS != 0) { IdentityTracking = SecurityQOS->IdentityTracking; ImpersonationType= SecurityQOS->ImpersonationType; Capabilities = SecurityQOS->Capabilities; if (SecurityQOS->Version == RPC_C_SECURITY_QOS_VERSION_1) { AdditionalTransportCredentialsType = 0; AdditionalCredentials = NULL; } else { AdditionalTransportCredentialsType = ((RPC_SECURITY_QOS_V2 *)SecurityQOS)->AdditionalSecurityInfoType; AdditionalCredentials = ((RPC_SECURITY_QOS_V2 *)SecurityQOS)->u.HttpCredentials; if (AdditionalTransportCredentialsType != RPC_C_AUTHN_INFO_TYPE_HTTP) { if (AdditionalTransportCredentialsType != 0) return(RPC_S_INVALID_ARG); if (AdditionalCredentials != NULL) return(RPC_S_INVALID_ARG); } else if (AdditionalCredentials == NULL) return(RPC_S_INVALID_ARG); else { HttpCredentials = (RPC_HTTP_TRANSPORT_CREDENTIALS_W *)AdditionalCredentials; if (HttpCredentials->TransportCredentials) { if (HttpCredentials->TransportCredentials->User) { if (RpcpStringLength(HttpCredentials->TransportCredentials->User) != HttpCredentials->TransportCredentials->UserLength) { return(RPC_S_INVALID_ARG); } } else if (HttpCredentials->TransportCredentials->UserLength) return(RPC_S_INVALID_ARG); if (HttpCredentials->TransportCredentials->Domain) { if (RpcpStringLength(HttpCredentials->TransportCredentials->Domain) != HttpCredentials->TransportCredentials->DomainLength) { return(RPC_S_INVALID_ARG); } } else if (HttpCredentials->TransportCredentials->DomainLength) return(RPC_S_INVALID_ARG); if (HttpCredentials->TransportCredentials->Password) { if (RpcpStringLength(HttpCredentials->TransportCredentials->Password) != HttpCredentials->TransportCredentials->PasswordLength) { return(RPC_S_INVALID_ARG); } } else if (HttpCredentials->TransportCredentials->PasswordLength) return(RPC_S_INVALID_ARG); if (HttpCredentials->TransportCredentials->Flags != SEC_WINNT_AUTH_IDENTITY_UNICODE) return(RPC_S_INVALID_ARG); } // if you don't want to authenticate against anyone, you can't authenticate if (HttpCredentials->AuthenticationTarget == 0) return(RPC_S_INVALID_ARG); // if you don't support any method of authentication, you can't authenticate if (HttpCredentials->NumberOfAuthnSchemes == 0) return(RPC_S_INVALID_ARG); // if you don't support any method of authentication, you can't authenticate if (HttpCredentials->AuthnSchemes == NULL) return(RPC_S_INVALID_ARG); // check whether Negotiate, Passport or Digest are in the list of auth scehemes. If yes, // reject the call since we don't support them yet. for (i = 0; i < HttpCredentials->NumberOfAuthnSchemes; i ++) { if (HttpCredentials->AuthnSchemes[i] == RPC_C_HTTP_AUTHN_SCHEME_PASSPORT) return RPC_S_CANNOT_SUPPORT; if (HttpCredentials->AuthnSchemes[i] == RPC_C_HTTP_AUTHN_SCHEME_NEGOTIATE) return RPC_S_CANNOT_SUPPORT; if (HttpCredentials->AuthnSchemes[i] == RPC_C_HTTP_AUTHN_SCHEME_DIGEST) return RPC_S_CANNOT_SUPPORT; } } } } else { IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; AdditionalTransportCredentialsType = 0; AdditionalCredentials = NULL; } Status = BindingObject->SetAuthInformation( ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvc, 0, ImpersonationType, IdentityTracking, Capabilities, TRUE, // Acquire new credentials AdditionalTransportCredentialsType, AdditionalCredentials ); return (Status); } RPC_STATUS RPC_ENTRY I_RpcBindingInqSecurityContext ( IN RPC_BINDING_HANDLE Binding, OUT void **SecurityContextHandle ) /*++ Routine Description: Arguments: Return Value: The status for the operation is returned. --*/ { CALL * Call; InitializeIfNecessary(); Call = (CALL *) Binding; if (Call->InvalidHandle(CALL_TYPE)) return(RPC_S_INVALID_BINDING); return(Call->InqSecurityContext(SecurityContextHandle)); } RPC_STATUS RPC_ENTRY I_RpcTurnOnEEInfoPropagation ( void ) /*++ Routine Description: Turns on extended error info propagation for this process. Arguments: Return Value: RPC_S_OK. --*/ { g_fSendEEInfo = TRUE; return RPC_S_OK; }