diff --git a/dlls/rpcrt4/rpc_defs.h b/dlls/rpcrt4/rpc_defs.h index 7499dcd1c1d..c0c3609f1cc 100644 --- a/dlls/rpcrt4/rpc_defs.h +++ b/dlls/rpcrt4/rpc_defs.h @@ -177,9 +177,25 @@ typedef struct #define PKT_CO_CANCEL 18 #define PKT_ORPHANED 19 -#define RESULT_ACCEPT 0 +#define RESULT_ACCEPT 0 +#define RESULT_USER_REJECTION 1 +#define RESULT_PROVIDER_REJECTION 2 -#define NO_REASON 0 +#define REASON_NONE 0 +#define REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED 1 +#define REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED 2 +#define REASON_LOCAL_LIMIT_EXCEEDED 3 + +#define REJECT_REASON_NOT_SPECIFIED 0 +#define REJECT_TEMPORARY_CONGESTION 1 +#define REJECT_LOCAL_LIMIT_EXCEEDED 2 +#define REJECT_CALLED_PADDR_UNKNOWN 3 /* not used */ +#define REJECT_PROTOCOL_VERSION_NOT_SUPPORTED 4 +#define REJECT_DEFAULT_CONTEXT_NOT_SUPPORTED 5 /* not used */ +#define REJECT_USER_DATA_NOT_READABLE 6 /* not used */ +#define REJECT_NO_PSAP_AVAILABLE 7 /* not used */ +#define REJECT_UNKNOWN_AUTHN_SERVICE 8 +#define REJECT_INVALID_CHECKSUM 9 #define NCADG_IP_UDP 0x08 #define NCACN_IP_TCP 0x07 diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c index 03e07375310..b19e7f17718 100644 --- a/dlls/rpcrt4/rpc_message.c +++ b/dlls/rpcrt4/rpc_message.c @@ -230,6 +230,7 @@ RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, RPCRT4_BuildCommonHeader(header, PKT_BIND_NACK, DataRepresentation); header->common.frag_len = sizeof(header->bind_nack); + header->bind_nack.reject_reason = REJECT_REASON_NOT_SPECIFIED; header->bind_nack.protocols_count = 1; header->bind_nack.protocols[0].rpc_ver = RpcVersion; header->bind_nack.protocols[0].rpc_ver_minor = RpcVersionMinor; diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c index 328c0d0fc96..8a72ab335ee 100644 --- a/dlls/rpcrt4/rpc_server.c +++ b/dlls/rpcrt4/rpc_server.c @@ -198,7 +198,7 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, conn->Endpoint, - RESULT_ACCEPT, NO_REASON, + RESULT_ACCEPT, REASON_NONE, &sif->If->TransferSyntax); /* save the interface for later use */ diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c index 413bcbb5f32..cc33e5ef77e 100644 --- a/dlls/rpcrt4/rpc_transport.c +++ b/dlls/rpcrt4/rpc_transport.c @@ -1473,6 +1473,8 @@ ULONG RpcAssoc_Release(RpcAssoc *assoc) return refs; } +#define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1)) + static RPC_STATUS RpcAssoc_BindConnection(RpcAssoc *assoc, RpcConnection *conn, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax) @@ -1501,23 +1503,98 @@ static RPC_STATUS RpcAssoc_BindConnection(RpcAssoc *assoc, RpcConnection *conn, return status; } - if (response_hdr->common.ptype != PKT_BIND_ACK) + switch (response_hdr->common.ptype) { - ERR("failed to bind for interface %s, %d.%d\n", - debugstr_guid(&InterfaceId->SyntaxGUID), - InterfaceId->SyntaxVersion.MajorVersion, - InterfaceId->SyntaxVersion.MinorVersion); - RPCRT4_FreeHeader(response_hdr); - return RPC_S_PROTOCOL_ERROR; + case PKT_BIND_ACK: + { + RpcAddressString *server_address = msg.Buffer; + if ((msg.BufferLength >= FIELD_OFFSET(RpcAddressString, string[0])) || + (msg.BufferLength >= ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4))) + { + unsigned short remaining = msg.BufferLength - + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4); + RpcResults *results = (RpcResults*)((ULONG_PTR)server_address + + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); + if ((results->num_results == 1) && (remaining >= sizeof(*results))) + { + switch (results->results[0].result) + { + case RESULT_ACCEPT: + conn->assoc_group_id = response_hdr->bind_ack.assoc_gid; + conn->MaxTransmissionSize = response_hdr->bind_ack.max_tsize; + conn->ActiveInterface = *InterfaceId; + break; + case RESULT_PROVIDER_REJECTION: + switch (results->results[0].reason) + { + case REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED: + ERR("syntax %s, %d.%d not supported\n", + debugstr_guid(&InterfaceId->SyntaxGUID), + InterfaceId->SyntaxVersion.MajorVersion, + InterfaceId->SyntaxVersion.MinorVersion); + status = RPC_S_UNKNOWN_IF; + break; + case REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED: + ERR("transfer syntax not supported\n"); + status = RPC_S_SERVER_UNAVAILABLE; + break; + case REASON_NONE: + default: + status = RPC_S_CALL_FAILED_DNE; + } + break; + case RESULT_USER_REJECTION: + default: + ERR("rejection result %d\n", results->results[0].result); + status = RPC_S_CALL_FAILED_DNE; + } + } + else + { + ERR("incorrect results size\n"); + status = RPC_S_CALL_FAILED_DNE; + } + } + else + { + ERR("bind ack packet too small (%d)\n", msg.BufferLength); + status = RPC_S_PROTOCOL_ERROR; + } + break; + } + case PKT_BIND_NACK: + switch (response_hdr->bind_nack.reject_reason) + { + case REJECT_LOCAL_LIMIT_EXCEEDED: + case REJECT_TEMPORARY_CONGESTION: + ERR("server too busy\n"); + status = RPC_S_SERVER_TOO_BUSY; + break; + case REJECT_PROTOCOL_VERSION_NOT_SUPPORTED: + ERR("protocol version not supported\n"); + status = RPC_S_PROTOCOL_ERROR; + break; + case REJECT_UNKNOWN_AUTHN_SERVICE: + ERR("unknown authentication service\n"); + status = RPC_S_UNKNOWN_AUTHN_SERVICE; + break; + case REJECT_INVALID_CHECKSUM: + ERR("invalid checksum\n"); + status = ERROR_ACCESS_DENIED; + break; + default: + ERR("rejected bind for reason %d\n", response_hdr->bind_nack.reject_reason); + status = RPC_S_CALL_FAILED_DNE; + } + break; + default: + ERR("wrong packet type received %d\n", response_hdr->common.ptype); + status = RPC_S_PROTOCOL_ERROR; + break; } - /* FIXME: do more checks? */ - - conn->assoc_group_id = response_hdr->bind_ack.assoc_gid; - conn->MaxTransmissionSize = response_hdr->bind_ack.max_tsize; - conn->ActiveInterface = *InterfaceId; RPCRT4_FreeHeader(response_hdr); - return RPC_S_OK; + return status; } static RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc,