1 /* 2 * RPC messages 3 * 4 * Copyright 2001-2002 Ove Kåven, TransGaming Technologies 5 * Copyright 2004 Filip Navara 6 * Copyright 2006 CodeWeavers 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include <stdarg.h> 24 #include <stdio.h> 25 #include <string.h> 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "winerror.h" 30 #include "winuser.h" 31 32 #include "rpc.h" 33 #include "rpcndr.h" 34 #include "rpcdcep.h" 35 36 #include "wine/debug.h" 37 38 #include "rpc_binding.h" 39 #include "rpc_defs.h" 40 #include "rpc_message.h" 41 #include "rpc_assoc.h" 42 #include "ncastatus.h" 43 44 WINE_DEFAULT_DEBUG_CHANNEL(rpc); 45 46 /* note: the DCE/RPC spec says the alignment amount should be 4, but 47 * MS/RPC servers seem to always use 16 */ 48 #define AUTH_ALIGNMENT 16 49 50 /* gets the amount needed to round a value up to the specified alignment */ 51 #define ROUND_UP_AMOUNT(value, alignment) \ 52 (((alignment) - (((value) % (alignment)))) % (alignment)) 53 #define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1)) 54 55 static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg); 56 57 DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header) 58 { 59 static const DWORD header_sizes[] = { 60 sizeof(Header->request), 0, sizeof(Header->response), 61 sizeof(Header->fault), 0, 0, 0, 0, 0, 0, 0, sizeof(Header->bind), 62 sizeof(Header->bind_ack), sizeof(Header->bind_nack), 63 0, 0, sizeof(Header->auth3), 0, 0, 0, sizeof(Header->http) 64 }; 65 ULONG ret = 0; 66 67 if (Header->common.ptype < ARRAY_SIZE(header_sizes)) { 68 ret = header_sizes[Header->common.ptype]; 69 if (ret == 0) 70 FIXME("unhandled packet type %u\n", Header->common.ptype); 71 if (Header->common.flags & RPC_FLG_OBJECT_UUID) 72 ret += sizeof(UUID); 73 } else { 74 WARN("invalid packet type %u\n", Header->common.ptype); 75 } 76 77 return ret; 78 } 79 80 static BOOL packet_has_body(const RpcPktHdr *Header) 81 { 82 return (Header->common.ptype == PKT_FAULT) || 83 (Header->common.ptype == PKT_REQUEST) || 84 (Header->common.ptype == PKT_RESPONSE); 85 } 86 87 static BOOL packet_has_auth_verifier(const RpcPktHdr *Header) 88 { 89 return !(Header->common.ptype == PKT_BIND_NACK) && 90 !(Header->common.ptype == PKT_SHUTDOWN); 91 } 92 93 static BOOL packet_does_auth_negotiation(const RpcPktHdr *Header) 94 { 95 switch (Header->common.ptype) 96 { 97 case PKT_BIND: 98 case PKT_BIND_ACK: 99 case PKT_AUTH3: 100 case PKT_ALTER_CONTEXT: 101 case PKT_ALTER_CONTEXT_RESP: 102 return TRUE; 103 default: 104 return FALSE; 105 } 106 } 107 108 static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType, 109 ULONG DataRepresentation) 110 { 111 Header->common.rpc_ver = RPC_VER_MAJOR; 112 Header->common.rpc_ver_minor = RPC_VER_MINOR; 113 Header->common.ptype = PacketType; 114 Header->common.drep[0] = LOBYTE(LOWORD(DataRepresentation)); 115 Header->common.drep[1] = HIBYTE(LOWORD(DataRepresentation)); 116 Header->common.drep[2] = LOBYTE(HIWORD(DataRepresentation)); 117 Header->common.drep[3] = HIBYTE(HIWORD(DataRepresentation)); 118 Header->common.auth_len = 0; 119 Header->common.call_id = 1; 120 Header->common.flags = 0; 121 /* Flags and fragment length are computed in RPCRT4_Send. */ 122 } 123 124 static RpcPktHdr *RPCRT4_BuildRequestHeader(ULONG DataRepresentation, 125 ULONG BufferLength, 126 unsigned short ProcNum, 127 UUID *ObjectUuid) 128 { 129 RpcPktHdr *header; 130 BOOL has_object; 131 RPC_STATUS status; 132 133 has_object = (ObjectUuid != NULL && !UuidIsNil(ObjectUuid, &status)); 134 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 135 sizeof(header->request) + (has_object ? sizeof(UUID) : 0)); 136 if (header == NULL) { 137 return NULL; 138 } 139 140 RPCRT4_BuildCommonHeader(header, PKT_REQUEST, DataRepresentation); 141 header->common.frag_len = sizeof(header->request); 142 header->request.alloc_hint = BufferLength; 143 header->request.context_id = 0; 144 header->request.opnum = ProcNum; 145 if (has_object) { 146 header->common.flags |= RPC_FLG_OBJECT_UUID; 147 header->common.frag_len += sizeof(UUID); 148 memcpy(&header->request + 1, ObjectUuid, sizeof(UUID)); 149 } 150 151 return header; 152 } 153 154 RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength) 155 { 156 RpcPktHdr *header; 157 158 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->response)); 159 if (header == NULL) { 160 return NULL; 161 } 162 163 RPCRT4_BuildCommonHeader(header, PKT_RESPONSE, DataRepresentation); 164 header->common.frag_len = sizeof(header->response); 165 header->response.alloc_hint = BufferLength; 166 167 return header; 168 } 169 170 RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status) 171 { 172 RpcPktHdr *header; 173 174 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->fault)); 175 if (header == NULL) { 176 return NULL; 177 } 178 179 RPCRT4_BuildCommonHeader(header, PKT_FAULT, DataRepresentation); 180 header->common.frag_len = sizeof(header->fault); 181 header->fault.status = Status; 182 183 return header; 184 } 185 186 RpcPktHdr *RPCRT4_BuildBindHeader(ULONG DataRepresentation, 187 unsigned short MaxTransmissionSize, 188 unsigned short MaxReceiveSize, 189 ULONG AssocGroupId, 190 const RPC_SYNTAX_IDENTIFIER *AbstractId, 191 const RPC_SYNTAX_IDENTIFIER *TransferId) 192 { 193 RpcPktHdr *header; 194 RpcContextElement *ctxt_elem; 195 196 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 197 sizeof(header->bind) + FIELD_OFFSET(RpcContextElement, transfer_syntaxes[1])); 198 if (header == NULL) { 199 return NULL; 200 } 201 ctxt_elem = (RpcContextElement *)(&header->bind + 1); 202 203 RPCRT4_BuildCommonHeader(header, PKT_BIND, DataRepresentation); 204 header->common.frag_len = sizeof(header->bind) + FIELD_OFFSET(RpcContextElement, transfer_syntaxes[1]); 205 header->bind.max_tsize = MaxTransmissionSize; 206 header->bind.max_rsize = MaxReceiveSize; 207 header->bind.assoc_gid = AssocGroupId; 208 header->bind.num_elements = 1; 209 ctxt_elem->num_syntaxes = 1; 210 ctxt_elem->abstract_syntax = *AbstractId; 211 ctxt_elem->transfer_syntaxes[0] = *TransferId; 212 213 return header; 214 } 215 216 static RpcPktHdr *RPCRT4_BuildAuthHeader(ULONG DataRepresentation) 217 { 218 RpcPktHdr *header; 219 220 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 221 sizeof(header->auth3)); 222 if (header == NULL) 223 return NULL; 224 225 RPCRT4_BuildCommonHeader(header, PKT_AUTH3, DataRepresentation); 226 header->common.frag_len = sizeof(header->auth3); 227 228 return header; 229 } 230 231 RpcPktHdr *RPCRT4_BuildBindNackHeader(ULONG DataRepresentation, 232 unsigned char RpcVersion, 233 unsigned char RpcVersionMinor, 234 unsigned short RejectReason) 235 { 236 RpcPktHdr *header; 237 238 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(RpcPktHdr, bind_nack.protocols[1])); 239 if (header == NULL) { 240 return NULL; 241 } 242 243 RPCRT4_BuildCommonHeader(header, PKT_BIND_NACK, DataRepresentation); 244 header->common.frag_len = FIELD_OFFSET(RpcPktHdr, bind_nack.protocols[1]); 245 header->bind_nack.reject_reason = RejectReason; 246 header->bind_nack.protocols_count = 1; 247 header->bind_nack.protocols[0].rpc_ver = RpcVersion; 248 header->bind_nack.protocols[0].rpc_ver_minor = RpcVersionMinor; 249 250 return header; 251 } 252 253 RpcPktHdr *RPCRT4_BuildBindAckHeader(ULONG DataRepresentation, 254 unsigned short MaxTransmissionSize, 255 unsigned short MaxReceiveSize, 256 ULONG AssocGroupId, 257 LPCSTR ServerAddress, 258 unsigned char ResultCount, 259 const RpcResult *Results) 260 { 261 RpcPktHdr *header; 262 ULONG header_size; 263 RpcAddressString *server_address; 264 RpcResultList *results; 265 266 header_size = sizeof(header->bind_ack) + 267 ROUND_UP(FIELD_OFFSET(RpcAddressString, string[strlen(ServerAddress) + 1]), 4) + 268 FIELD_OFFSET(RpcResultList, results[ResultCount]); 269 270 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, header_size); 271 if (header == NULL) { 272 return NULL; 273 } 274 275 RPCRT4_BuildCommonHeader(header, PKT_BIND_ACK, DataRepresentation); 276 header->common.frag_len = header_size; 277 header->bind_ack.max_tsize = MaxTransmissionSize; 278 header->bind_ack.max_rsize = MaxReceiveSize; 279 header->bind_ack.assoc_gid = AssocGroupId; 280 server_address = (RpcAddressString*)(&header->bind_ack + 1); 281 server_address->length = strlen(ServerAddress) + 1; 282 strcpy(server_address->string, ServerAddress); 283 /* results is 4-byte aligned */ 284 results = (RpcResultList*)((ULONG_PTR)server_address + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); 285 results->num_results = ResultCount; 286 memcpy(&results->results[0], Results, ResultCount * sizeof(*Results)); 287 288 return header; 289 } 290 291 RpcPktHdr *RPCRT4_BuildHttpHeader(ULONG DataRepresentation, 292 unsigned short flags, 293 unsigned short num_data_items, 294 unsigned int payload_size) 295 { 296 RpcPktHdr *header; 297 298 header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->http) + payload_size); 299 if (header == NULL) { 300 ERR("failed to allocate memory\n"); 301 return NULL; 302 } 303 304 RPCRT4_BuildCommonHeader(header, PKT_HTTP, DataRepresentation); 305 /* since the packet isn't current sent using RPCRT4_Send, set the flags 306 * manually here */ 307 header->common.flags = RPC_FLG_FIRST|RPC_FLG_LAST; 308 header->common.call_id = 0; 309 header->common.frag_len = sizeof(header->http) + payload_size; 310 header->http.flags = flags; 311 header->http.num_data_items = num_data_items; 312 313 return header; 314 } 315 316 #define WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, type, value) \ 317 do { \ 318 *(unsigned int *)(payload) = (type); \ 319 (payload) += 4; \ 320 *(unsigned int *)(payload) = (value); \ 321 (payload) += 4; \ 322 } while (0) 323 324 #define WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, type, uuid) \ 325 do { \ 326 *(unsigned int *)(payload) = (type); \ 327 (payload) += 4; \ 328 *(UUID *)(payload) = (uuid); \ 329 (payload) += sizeof(UUID); \ 330 } while (0) 331 332 #define WRITE_HTTP_PAYLOAD_FIELD_FLOW_CONTROL(payload, bytes_transmitted, flow_control_increment, uuid) \ 333 do { \ 334 *(unsigned int *)(payload) = 0x00000001; \ 335 (payload) += 4; \ 336 *(unsigned int *)(payload) = (bytes_transmitted); \ 337 (payload) += 4; \ 338 *(unsigned int *)(payload) = (flow_control_increment); \ 339 (payload) += 4; \ 340 *(UUID *)(payload) = (uuid); \ 341 (payload) += sizeof(UUID); \ 342 } while (0) 343 344 RpcPktHdr *RPCRT4_BuildHttpConnectHeader(int out_pipe, 345 const UUID *connection_uuid, 346 const UUID *pipe_uuid, 347 const UUID *association_uuid) 348 { 349 RpcPktHdr *header; 350 unsigned int size; 351 char *payload; 352 353 size = 8 + 4 + sizeof(UUID) + 4 + sizeof(UUID) + 8; 354 if (!out_pipe) 355 size += 8 + 4 + sizeof(UUID); 356 357 header = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0, 358 out_pipe ? 4 : 6, size); 359 if (!header) return NULL; 360 payload = (char *)(&header->http+1); 361 362 /* FIXME: what does this part of the payload do? */ 363 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000006, 0x00000001); 364 365 WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x00000003, *connection_uuid); 366 WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x00000003, *pipe_uuid); 367 368 if (out_pipe) 369 /* FIXME: what does this part of the payload do? */ 370 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000000, 0x00010000); 371 else 372 { 373 /* FIXME: what does this part of the payload do? */ 374 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000004, 0x40000000); 375 /* FIXME: what does this part of the payload do? */ 376 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000005, 0x000493e0); 377 378 WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x0000000c, *association_uuid); 379 } 380 381 return header; 382 } 383 384 RpcPktHdr *RPCRT4_BuildHttpFlowControlHeader(BOOL server, ULONG bytes_transmitted, 385 ULONG flow_control_increment, 386 const UUID *pipe_uuid) 387 { 388 RpcPktHdr *header; 389 char *payload; 390 391 header = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x2, 2, 392 5 * sizeof(ULONG) + sizeof(UUID)); 393 if (!header) return NULL; 394 payload = (char *)(&header->http+1); 395 396 WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x0000000d, (server ? 0x0 : 0x3)); 397 398 WRITE_HTTP_PAYLOAD_FIELD_FLOW_CONTROL(payload, bytes_transmitted, 399 flow_control_increment, *pipe_uuid); 400 return header; 401 } 402 403 VOID RPCRT4_FreeHeader(RpcPktHdr *Header) 404 { 405 HeapFree(GetProcessHeap(), 0, Header); 406 } 407 408 NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status) 409 { 410 switch (status) 411 { 412 case ERROR_INVALID_HANDLE: return NCA_S_FAULT_CONTEXT_MISMATCH; 413 case ERROR_OUTOFMEMORY: return NCA_S_FAULT_REMOTE_NO_MEMORY; 414 case RPC_S_NOT_LISTENING: return NCA_S_SERVER_TOO_BUSY; 415 case RPC_S_UNKNOWN_IF: return NCA_S_UNK_IF; 416 case RPC_S_SERVER_TOO_BUSY: return NCA_S_SERVER_TOO_BUSY; 417 case RPC_S_CALL_FAILED: return NCA_S_FAULT_UNSPEC; 418 case RPC_S_CALL_FAILED_DNE: return NCA_S_MANAGER_NOT_ENTERED; 419 case RPC_S_PROTOCOL_ERROR: return NCA_S_PROTO_ERROR; 420 case RPC_S_UNSUPPORTED_TYPE: return NCA_S_UNSUPPORTED_TYPE; 421 case RPC_S_INVALID_TAG: return NCA_S_FAULT_INVALID_TAG; 422 case RPC_S_INVALID_BOUND: return NCA_S_FAULT_INVALID_BOUND; 423 case RPC_S_PROCNUM_OUT_OF_RANGE: return NCA_S_OP_RNG_ERROR; 424 case RPC_X_SS_HANDLES_MISMATCH: return NCA_S_FAULT_CONTEXT_MISMATCH; 425 case RPC_S_CALL_CANCELLED: return NCA_S_FAULT_CANCEL; 426 case RPC_S_COMM_FAILURE: return NCA_S_COMM_FAILURE; 427 case RPC_X_WRONG_PIPE_ORDER: return NCA_S_FAULT_PIPE_ORDER; 428 case RPC_X_PIPE_CLOSED: return NCA_S_FAULT_PIPE_CLOSED; 429 case RPC_X_PIPE_DISCIPLINE_ERROR: return NCA_S_FAULT_PIPE_DISCIPLINE; 430 case RPC_X_PIPE_EMPTY: return NCA_S_FAULT_PIPE_EMPTY; 431 case STATUS_FLOAT_DIVIDE_BY_ZERO: return NCA_S_FAULT_FP_DIV_ZERO; 432 case STATUS_FLOAT_INVALID_OPERATION: return NCA_S_FAULT_FP_ERROR; 433 case STATUS_FLOAT_OVERFLOW: return NCA_S_FAULT_FP_OVERFLOW; 434 case STATUS_FLOAT_UNDERFLOW: return NCA_S_FAULT_FP_UNDERFLOW; 435 case STATUS_INTEGER_DIVIDE_BY_ZERO: return NCA_S_FAULT_INT_DIV_BY_ZERO; 436 case STATUS_INTEGER_OVERFLOW: return NCA_S_FAULT_INT_OVERFLOW; 437 default: return status; 438 } 439 } 440 441 static RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status) 442 { 443 switch (status) 444 { 445 case NCA_S_COMM_FAILURE: return RPC_S_COMM_FAILURE; 446 case NCA_S_OP_RNG_ERROR: return RPC_S_PROCNUM_OUT_OF_RANGE; 447 case NCA_S_UNK_IF: return RPC_S_UNKNOWN_IF; 448 case NCA_S_YOU_CRASHED: return RPC_S_CALL_FAILED; 449 case NCA_S_PROTO_ERROR: return RPC_S_PROTOCOL_ERROR; 450 case NCA_S_OUT_ARGS_TOO_BIG: return ERROR_NOT_ENOUGH_SERVER_MEMORY; 451 case NCA_S_SERVER_TOO_BUSY: return RPC_S_SERVER_TOO_BUSY; 452 case NCA_S_UNSUPPORTED_TYPE: return RPC_S_UNSUPPORTED_TYPE; 453 case NCA_S_FAULT_INT_DIV_BY_ZERO: return RPC_S_ZERO_DIVIDE; 454 case NCA_S_FAULT_ADDR_ERROR: return RPC_S_ADDRESS_ERROR; 455 case NCA_S_FAULT_FP_DIV_ZERO: return RPC_S_FP_DIV_ZERO; 456 case NCA_S_FAULT_FP_UNDERFLOW: return RPC_S_FP_UNDERFLOW; 457 case NCA_S_FAULT_FP_OVERFLOW: return RPC_S_FP_OVERFLOW; 458 case NCA_S_FAULT_INVALID_TAG: return RPC_S_INVALID_TAG; 459 case NCA_S_FAULT_INVALID_BOUND: return RPC_S_INVALID_BOUND; 460 case NCA_S_RPC_VERSION_MISMATCH: return RPC_S_PROTOCOL_ERROR; 461 case NCA_S_UNSPEC_REJECT: return RPC_S_CALL_FAILED_DNE; 462 case NCA_S_BAD_ACTID: return RPC_S_CALL_FAILED_DNE; 463 case NCA_S_WHO_ARE_YOU_FAILED: return RPC_S_CALL_FAILED; 464 case NCA_S_MANAGER_NOT_ENTERED: return RPC_S_CALL_FAILED_DNE; 465 case NCA_S_FAULT_CANCEL: return RPC_S_CALL_CANCELLED; 466 case NCA_S_FAULT_ILL_INST: return RPC_S_ADDRESS_ERROR; 467 case NCA_S_FAULT_FP_ERROR: return RPC_S_FP_OVERFLOW; 468 case NCA_S_FAULT_INT_OVERFLOW: return RPC_S_ADDRESS_ERROR; 469 case NCA_S_FAULT_UNSPEC: return RPC_S_CALL_FAILED; 470 case NCA_S_FAULT_PIPE_EMPTY: return RPC_X_PIPE_EMPTY; 471 case NCA_S_FAULT_PIPE_CLOSED: return RPC_X_PIPE_CLOSED; 472 case NCA_S_FAULT_PIPE_ORDER: return RPC_X_WRONG_PIPE_ORDER; 473 case NCA_S_FAULT_PIPE_DISCIPLINE: return RPC_X_PIPE_DISCIPLINE_ERROR; 474 case NCA_S_FAULT_PIPE_COMM_ERROR: return RPC_S_COMM_FAILURE; 475 case NCA_S_FAULT_PIPE_MEMORY: return ERROR_OUTOFMEMORY; 476 case NCA_S_FAULT_CONTEXT_MISMATCH: return ERROR_INVALID_HANDLE; 477 case NCA_S_FAULT_REMOTE_NO_MEMORY: return ERROR_NOT_ENOUGH_SERVER_MEMORY; 478 default: return status; 479 } 480 } 481 482 /* assumes the common header fields have already been validated */ 483 BOOL RPCRT4_IsValidHttpPacket(RpcPktHdr *hdr, unsigned char *data, 484 unsigned short data_len) 485 { 486 unsigned short i; 487 BYTE *p = data; 488 489 for (i = 0; i < hdr->http.num_data_items; i++) 490 { 491 ULONG type; 492 493 if (data_len < sizeof(ULONG)) 494 return FALSE; 495 496 type = *(ULONG *)p; 497 p += sizeof(ULONG); 498 data_len -= sizeof(ULONG); 499 500 switch (type) 501 { 502 case 0x3: 503 case 0xc: 504 if (data_len < sizeof(GUID)) 505 return FALSE; 506 p += sizeof(GUID); 507 data_len -= sizeof(GUID); 508 break; 509 case 0x0: 510 case 0x2: 511 case 0x4: 512 case 0x5: 513 case 0x6: 514 case 0xd: 515 if (data_len < sizeof(ULONG)) 516 return FALSE; 517 p += sizeof(ULONG); 518 data_len -= sizeof(ULONG); 519 break; 520 case 0x1: 521 if (data_len < 24) 522 return FALSE; 523 p += 24; 524 data_len -= 24; 525 break; 526 default: 527 FIXME("unimplemented type 0x%x\n", type); 528 break; 529 } 530 } 531 return TRUE; 532 } 533 534 /* assumes the HTTP packet has been validated */ 535 static unsigned char *RPCRT4_NextHttpHeaderField(unsigned char *data) 536 { 537 ULONG type; 538 539 type = *(ULONG *)data; 540 data += sizeof(ULONG); 541 542 switch (type) 543 { 544 case 0x3: 545 case 0xc: 546 return data + sizeof(GUID); 547 case 0x0: 548 case 0x2: 549 case 0x4: 550 case 0x5: 551 case 0x6: 552 case 0xd: 553 return data + sizeof(ULONG); 554 case 0x1: 555 return data + 24; 556 default: 557 FIXME("unimplemented type 0x%x\n", type); 558 return data; 559 } 560 } 561 562 #define READ_HTTP_PAYLOAD_FIELD_TYPE(data) *(ULONG *)(data) 563 #define GET_HTTP_PAYLOAD_FIELD_DATA(data) ((data) + sizeof(ULONG)) 564 565 /* assumes the HTTP packet has been validated */ 566 RPC_STATUS RPCRT4_ParseHttpPrepareHeader1(RpcPktHdr *header, 567 unsigned char *data, ULONG *field1) 568 { 569 ULONG type; 570 if (header->http.flags != 0x0) 571 { 572 ERR("invalid flags 0x%x\n", header->http.flags); 573 return RPC_S_PROTOCOL_ERROR; 574 } 575 if (header->http.num_data_items != 1) 576 { 577 ERR("invalid number of data items %d\n", header->http.num_data_items); 578 return RPC_S_PROTOCOL_ERROR; 579 } 580 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 581 if (type != 0x00000002) 582 { 583 ERR("invalid type 0x%08x\n", type); 584 return RPC_S_PROTOCOL_ERROR; 585 } 586 *field1 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 587 return RPC_S_OK; 588 } 589 590 /* assumes the HTTP packet has been validated */ 591 RPC_STATUS RPCRT4_ParseHttpPrepareHeader2(RpcPktHdr *header, 592 unsigned char *data, ULONG *field1, 593 ULONG *bytes_until_next_packet, 594 ULONG *field3) 595 { 596 ULONG type; 597 if (header->http.flags != 0x0) 598 { 599 ERR("invalid flags 0x%x\n", header->http.flags); 600 return RPC_S_PROTOCOL_ERROR; 601 } 602 if (header->http.num_data_items != 3) 603 { 604 ERR("invalid number of data items %d\n", header->http.num_data_items); 605 return RPC_S_PROTOCOL_ERROR; 606 } 607 608 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 609 if (type != 0x00000006) 610 { 611 ERR("invalid type for field 1: 0x%08x\n", type); 612 return RPC_S_PROTOCOL_ERROR; 613 } 614 *field1 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 615 data = RPCRT4_NextHttpHeaderField(data); 616 617 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 618 if (type != 0x00000000) 619 { 620 ERR("invalid type for field 2: 0x%08x\n", type); 621 return RPC_S_PROTOCOL_ERROR; 622 } 623 *bytes_until_next_packet = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 624 data = RPCRT4_NextHttpHeaderField(data); 625 626 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 627 if (type != 0x00000002) 628 { 629 ERR("invalid type for field 3: 0x%08x\n", type); 630 return RPC_S_PROTOCOL_ERROR; 631 } 632 *field3 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 633 634 return RPC_S_OK; 635 } 636 637 RPC_STATUS RPCRT4_ParseHttpFlowControlHeader(RpcPktHdr *header, 638 unsigned char *data, BOOL server, 639 ULONG *bytes_transmitted, 640 ULONG *flow_control_increment, 641 UUID *pipe_uuid) 642 { 643 ULONG type; 644 if (header->http.flags != 0x2) 645 { 646 ERR("invalid flags 0x%x\n", header->http.flags); 647 return RPC_S_PROTOCOL_ERROR; 648 } 649 if (header->http.num_data_items != 2) 650 { 651 ERR("invalid number of data items %d\n", header->http.num_data_items); 652 return RPC_S_PROTOCOL_ERROR; 653 } 654 655 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 656 if (type != 0x0000000d) 657 { 658 ERR("invalid type for field 1: 0x%08x\n", type); 659 return RPC_S_PROTOCOL_ERROR; 660 } 661 if (*(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data) != (server ? 0x3 : 0x0)) 662 { 663 ERR("invalid type for 0xd field data: 0x%08x\n", *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data)); 664 return RPC_S_PROTOCOL_ERROR; 665 } 666 data = RPCRT4_NextHttpHeaderField(data); 667 668 type = READ_HTTP_PAYLOAD_FIELD_TYPE(data); 669 if (type != 0x00000001) 670 { 671 ERR("invalid type for field 2: 0x%08x\n", type); 672 return RPC_S_PROTOCOL_ERROR; 673 } 674 *bytes_transmitted = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data); 675 *flow_control_increment = *(ULONG *)(GET_HTTP_PAYLOAD_FIELD_DATA(data) + 4); 676 *pipe_uuid = *(UUID *)(GET_HTTP_PAYLOAD_FIELD_DATA(data) + 8); 677 678 return RPC_S_OK; 679 } 680 681 682 RPC_STATUS RPCRT4_default_secure_packet(RpcConnection *Connection, 683 enum secure_packet_direction dir, 684 RpcPktHdr *hdr, unsigned int hdr_size, 685 unsigned char *stub_data, unsigned int stub_data_size, 686 RpcAuthVerifier *auth_hdr, 687 unsigned char *auth_value, unsigned int auth_value_size) 688 { 689 SecBufferDesc message; 690 SecBuffer buffers[4]; 691 SECURITY_STATUS sec_status; 692 693 message.ulVersion = SECBUFFER_VERSION; 694 message.cBuffers = ARRAY_SIZE(buffers); 695 message.pBuffers = buffers; 696 697 buffers[0].cbBuffer = hdr_size; 698 buffers[0].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; 699 buffers[0].pvBuffer = hdr; 700 buffers[1].cbBuffer = stub_data_size; 701 buffers[1].BufferType = SECBUFFER_DATA; 702 buffers[1].pvBuffer = stub_data; 703 buffers[2].cbBuffer = sizeof(*auth_hdr); 704 buffers[2].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; 705 buffers[2].pvBuffer = auth_hdr; 706 buffers[3].cbBuffer = auth_value_size; 707 buffers[3].BufferType = SECBUFFER_TOKEN; 708 buffers[3].pvBuffer = auth_value; 709 710 if (dir == SECURE_PACKET_SEND) 711 { 712 if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) 713 { 714 sec_status = EncryptMessage(&Connection->ctx, 0, &message, 0 /* FIXME */); 715 if (sec_status != SEC_E_OK) 716 { 717 ERR("EncryptMessage failed with 0x%08x\n", sec_status); 718 return RPC_S_SEC_PKG_ERROR; 719 } 720 } 721 else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) 722 { 723 sec_status = MakeSignature(&Connection->ctx, 0, &message, 0 /* FIXME */); 724 if (sec_status != SEC_E_OK) 725 { 726 ERR("MakeSignature failed with 0x%08x\n", sec_status); 727 return RPC_S_SEC_PKG_ERROR; 728 } 729 } 730 } 731 else if (dir == SECURE_PACKET_RECEIVE) 732 { 733 if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) 734 { 735 sec_status = DecryptMessage(&Connection->ctx, &message, 0 /* FIXME */, 0); 736 if (sec_status != SEC_E_OK) 737 { 738 ERR("DecryptMessage failed with 0x%08x\n", sec_status); 739 return RPC_S_SEC_PKG_ERROR; 740 } 741 } 742 else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) 743 { 744 sec_status = VerifySignature(&Connection->ctx, &message, 0 /* FIXME */, NULL); 745 if (sec_status != SEC_E_OK) 746 { 747 ERR("VerifySignature failed with 0x%08x\n", sec_status); 748 return RPC_S_SEC_PKG_ERROR; 749 } 750 } 751 } 752 753 return RPC_S_OK; 754 } 755 756 /*********************************************************************** 757 * RPCRT4_SendWithAuth (internal) 758 * 759 * Transmit a packet with authorization data over connection in acceptable fragments. 760 */ 761 RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Header, 762 void *Buffer, unsigned int BufferLength, 763 const void *Auth, unsigned int AuthLength) 764 { 765 PUCHAR buffer_pos; 766 DWORD hdr_size; 767 LONG count; 768 unsigned char *pkt; 769 LONG alen; 770 RPC_STATUS status; 771 772 RPCRT4_SetThreadCurrentConnection(Connection); 773 774 buffer_pos = Buffer; 775 /* The packet building functions save the packet header size, so we can use it. */ 776 hdr_size = Header->common.frag_len; 777 if (AuthLength) 778 Header->common.auth_len = AuthLength; 779 else if (Connection->AuthInfo && packet_has_auth_verifier(Header)) 780 { 781 if ((Connection->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(Header)) 782 Header->common.auth_len = Connection->encryption_auth_len; 783 else 784 Header->common.auth_len = Connection->signature_auth_len; 785 } 786 else 787 Header->common.auth_len = 0; 788 Header->common.flags |= RPC_FLG_FIRST; 789 Header->common.flags &= ~RPC_FLG_LAST; 790 791 alen = RPC_AUTH_VERIFIER_LEN(&Header->common); 792 793 while (!(Header->common.flags & RPC_FLG_LAST)) { 794 unsigned char auth_pad_len = Header->common.auth_len ? ROUND_UP_AMOUNT(BufferLength, AUTH_ALIGNMENT) : 0; 795 unsigned int pkt_size = BufferLength + hdr_size + alen + auth_pad_len; 796 797 /* decide if we need to split the packet into fragments */ 798 if (pkt_size <= Connection->MaxTransmissionSize) { 799 Header->common.flags |= RPC_FLG_LAST; 800 Header->common.frag_len = pkt_size; 801 } else { 802 auth_pad_len = 0; 803 /* make sure packet payload will be a multiple of 16 */ 804 Header->common.frag_len = 805 ((Connection->MaxTransmissionSize - hdr_size - alen) & ~(AUTH_ALIGNMENT-1)) + 806 hdr_size + alen; 807 } 808 809 pkt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Header->common.frag_len); 810 811 memcpy(pkt, Header, hdr_size); 812 813 /* fragment consisted of header only and is the last one */ 814 if (hdr_size == Header->common.frag_len) 815 goto write; 816 817 memcpy(pkt + hdr_size, buffer_pos, Header->common.frag_len - hdr_size - auth_pad_len - alen); 818 819 /* add the authorization info */ 820 if (Header->common.auth_len) 821 { 822 RpcAuthVerifier *auth_hdr = (RpcAuthVerifier *)&pkt[Header->common.frag_len - alen]; 823 824 auth_hdr->auth_type = Connection->AuthInfo->AuthnSvc; 825 auth_hdr->auth_level = Connection->AuthInfo->AuthnLevel; 826 auth_hdr->auth_pad_length = auth_pad_len; 827 auth_hdr->auth_reserved = 0; 828 /* a unique number... */ 829 auth_hdr->auth_context_id = Connection->auth_context_id; 830 831 if (AuthLength) 832 memcpy(auth_hdr + 1, Auth, AuthLength); 833 else 834 { 835 status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_SEND, 836 (RpcPktHdr *)pkt, hdr_size, 837 pkt + hdr_size, Header->common.frag_len - hdr_size - alen, 838 auth_hdr, 839 (unsigned char *)(auth_hdr + 1), Header->common.auth_len); 840 if (status != RPC_S_OK) 841 { 842 HeapFree(GetProcessHeap(), 0, pkt); 843 RPCRT4_SetThreadCurrentConnection(NULL); 844 return status; 845 } 846 } 847 } 848 849 write: 850 count = rpcrt4_conn_write(Connection, pkt, Header->common.frag_len); 851 HeapFree(GetProcessHeap(), 0, pkt); 852 if (count<0) { 853 WARN("rpcrt4_conn_write failed (auth)\n"); 854 RPCRT4_SetThreadCurrentConnection(NULL); 855 return RPC_S_CALL_FAILED; 856 } 857 858 buffer_pos += Header->common.frag_len - hdr_size - alen - auth_pad_len; 859 BufferLength -= Header->common.frag_len - hdr_size - alen - auth_pad_len; 860 Header->common.flags &= ~RPC_FLG_FIRST; 861 } 862 863 RPCRT4_SetThreadCurrentConnection(NULL); 864 return RPC_S_OK; 865 } 866 867 /*********************************************************************** 868 * RPCRT4_default_authorize (internal) 869 * 870 * Authorize a client connection. 871 */ 872 RPC_STATUS RPCRT4_default_authorize(RpcConnection *conn, BOOL first_time, 873 unsigned char *in_buffer, 874 unsigned int in_size, 875 unsigned char *out_buffer, 876 unsigned int *out_size) 877 { 878 SECURITY_STATUS r; 879 SecBufferDesc out_desc; 880 SecBufferDesc inp_desc; 881 SecPkgContext_Sizes secctx_sizes; 882 BOOL continue_needed; 883 ULONG context_req; 884 SecBuffer in, out; 885 886 if (!out_buffer) 887 { 888 *out_size = conn->AuthInfo->cbMaxToken; 889 return RPC_S_OK; 890 } 891 892 in.BufferType = SECBUFFER_TOKEN; 893 in.pvBuffer = in_buffer; 894 in.cbBuffer = in_size; 895 896 out.BufferType = SECBUFFER_TOKEN; 897 out.pvBuffer = out_buffer; 898 out.cbBuffer = *out_size; 899 900 out_desc.ulVersion = 0; 901 out_desc.cBuffers = 1; 902 out_desc.pBuffers = &out; 903 904 inp_desc.ulVersion = 0; 905 inp_desc.cBuffers = 1; 906 inp_desc.pBuffers = ∈ 907 908 if (conn->server) 909 { 910 context_req = ASC_REQ_CONNECTION | ASC_REQ_USE_DCE_STYLE | 911 ASC_REQ_DELEGATE; 912 913 if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) 914 context_req |= ASC_REQ_INTEGRITY; 915 else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) 916 context_req |= ASC_REQ_CONFIDENTIALITY | ASC_REQ_INTEGRITY; 917 918 r = AcceptSecurityContext(&conn->AuthInfo->cred, 919 first_time ? NULL : &conn->ctx, 920 &inp_desc, context_req, SECURITY_NETWORK_DREP, 921 &conn->ctx, 922 &out_desc, &conn->attr, &conn->exp); 923 if (r == SEC_E_OK || r == SEC_I_COMPLETE_NEEDED) 924 { 925 /* authorisation done, so nothing more to send */ 926 out.cbBuffer = 0; 927 } 928 } 929 else 930 { 931 context_req = ISC_REQ_CONNECTION | ISC_REQ_USE_DCE_STYLE | 932 ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE; 933 934 if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) 935 context_req |= ISC_REQ_INTEGRITY; 936 else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) 937 context_req |= ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY; 938 939 r = InitializeSecurityContextW(&conn->AuthInfo->cred, 940 first_time ? NULL: &conn->ctx, 941 first_time ? conn->AuthInfo->server_principal_name : NULL, 942 context_req, 0, SECURITY_NETWORK_DREP, 943 first_time ? NULL : &inp_desc, 0, &conn->ctx, 944 &out_desc, &conn->attr, &conn->exp); 945 } 946 if (FAILED(r)) 947 { 948 WARN("InitializeSecurityContext failed with error 0x%08x\n", r); 949 goto failed; 950 } 951 952 TRACE("r = 0x%08x, attr = 0x%08x\n", r, conn->attr); 953 continue_needed = ((r == SEC_I_CONTINUE_NEEDED) || 954 (r == SEC_I_COMPLETE_AND_CONTINUE)); 955 956 if ((r == SEC_I_COMPLETE_NEEDED) || (r == SEC_I_COMPLETE_AND_CONTINUE)) 957 { 958 TRACE("complete needed\n"); 959 r = CompleteAuthToken(&conn->ctx, &out_desc); 960 if (FAILED(r)) 961 { 962 WARN("CompleteAuthToken failed with error 0x%08x\n", r); 963 goto failed; 964 } 965 } 966 967 TRACE("cbBuffer = %d\n", out.cbBuffer); 968 969 if (!continue_needed) 970 { 971 r = QueryContextAttributesA(&conn->ctx, SECPKG_ATTR_SIZES, &secctx_sizes); 972 if (FAILED(r)) 973 { 974 WARN("QueryContextAttributes failed with error 0x%08x\n", r); 975 goto failed; 976 } 977 conn->signature_auth_len = secctx_sizes.cbMaxSignature; 978 conn->encryption_auth_len = secctx_sizes.cbSecurityTrailer; 979 } 980 981 *out_size = out.cbBuffer; 982 return RPC_S_OK; 983 984 failed: 985 *out_size = 0; 986 return ERROR_ACCESS_DENIED; /* FIXME: is this correct? */ 987 } 988 989 /*********************************************************************** 990 * RPCRT4_ClientConnectionAuth (internal) 991 */ 992 RPC_STATUS RPCRT4_ClientConnectionAuth(RpcConnection* conn, BYTE *challenge, 993 ULONG count) 994 { 995 RpcPktHdr *resp_hdr; 996 RPC_STATUS status; 997 unsigned char *out_buffer; 998 unsigned int out_len = 0; 999 1000 TRACE("challenge %s, %d bytes\n", challenge, count); 1001 1002 status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, NULL, &out_len); 1003 if (status) return status; 1004 out_buffer = HeapAlloc(GetProcessHeap(), 0, out_len); 1005 if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; 1006 status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, out_buffer, &out_len); 1007 if (status) return status; 1008 1009 resp_hdr = RPCRT4_BuildAuthHeader(NDR_LOCAL_DATA_REPRESENTATION); 1010 1011 if (resp_hdr) 1012 status = RPCRT4_SendWithAuth(conn, resp_hdr, NULL, 0, out_buffer, out_len); 1013 else 1014 status = RPC_S_OUT_OF_RESOURCES; 1015 1016 HeapFree(GetProcessHeap(), 0, out_buffer); 1017 RPCRT4_FreeHeader(resp_hdr); 1018 1019 return status; 1020 } 1021 1022 /*********************************************************************** 1023 * RPCRT4_ServerConnectionAuth (internal) 1024 */ 1025 RPC_STATUS RPCRT4_ServerConnectionAuth(RpcConnection* conn, 1026 BOOL start, 1027 RpcAuthVerifier *auth_data_in, 1028 ULONG auth_length_in, 1029 unsigned char **auth_data_out, 1030 ULONG *auth_length_out) 1031 { 1032 unsigned char *out_buffer; 1033 unsigned int out_size; 1034 RPC_STATUS status; 1035 1036 if (start) 1037 { 1038 /* remove any existing authentication information */ 1039 if (conn->AuthInfo) 1040 { 1041 RpcAuthInfo_Release(conn->AuthInfo); 1042 conn->AuthInfo = NULL; 1043 } 1044 if (SecIsValidHandle(&conn->ctx)) 1045 { 1046 DeleteSecurityContext(&conn->ctx); 1047 SecInvalidateHandle(&conn->ctx); 1048 } 1049 if (auth_length_in >= sizeof(RpcAuthVerifier)) 1050 { 1051 CredHandle cred; 1052 TimeStamp exp; 1053 ULONG max_token; 1054 1055 status = RPCRT4_ServerGetRegisteredAuthInfo( 1056 auth_data_in->auth_type, &cred, &exp, &max_token); 1057 if (status != RPC_S_OK) 1058 { 1059 ERR("unknown authentication service %u\n", auth_data_in->auth_type); 1060 return status; 1061 } 1062 1063 status = RpcAuthInfo_Create(auth_data_in->auth_level, 1064 auth_data_in->auth_type, cred, exp, 1065 max_token, NULL, &conn->AuthInfo); 1066 if (status != RPC_S_OK) 1067 { 1068 FreeCredentialsHandle(&cred); 1069 return status; 1070 } 1071 1072 /* FIXME: should auth_data_in->auth_context_id be checked in the !start case? */ 1073 conn->auth_context_id = auth_data_in->auth_context_id; 1074 } 1075 } 1076 1077 if (auth_length_in < sizeof(RpcAuthVerifier)) 1078 return RPC_S_OK; 1079 1080 if (!conn->AuthInfo) 1081 /* should have filled in authentication info by now */ 1082 return RPC_S_PROTOCOL_ERROR; 1083 1084 status = rpcrt4_conn_authorize( 1085 conn, start, (unsigned char *)(auth_data_in + 1), 1086 auth_length_in - sizeof(RpcAuthVerifier), NULL, &out_size); 1087 if (status) return status; 1088 1089 out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size); 1090 if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; 1091 1092 status = rpcrt4_conn_authorize( 1093 conn, start, (unsigned char *)(auth_data_in + 1), 1094 auth_length_in - sizeof(RpcAuthVerifier), out_buffer, &out_size); 1095 if (status != RPC_S_OK) 1096 { 1097 HeapFree(GetProcessHeap(), 0, out_buffer); 1098 return status; 1099 } 1100 1101 if (out_size && !auth_length_out) 1102 { 1103 ERR("expected authentication to be complete but SSP returned data of " 1104 "%u bytes to be sent back to client\n", out_size); 1105 HeapFree(GetProcessHeap(), 0, out_buffer); 1106 return RPC_S_SEC_PKG_ERROR; 1107 } 1108 else 1109 { 1110 *auth_data_out = out_buffer; 1111 *auth_length_out = out_size; 1112 } 1113 1114 return status; 1115 } 1116 1117 /*********************************************************************** 1118 * RPCRT4_default_is_authorized (internal) 1119 * 1120 * Has a connection started the process of authorizing with the server? 1121 */ 1122 BOOL RPCRT4_default_is_authorized(RpcConnection *Connection) 1123 { 1124 return Connection->AuthInfo && SecIsValidHandle(&Connection->ctx); 1125 } 1126 1127 /*********************************************************************** 1128 * RPCRT4_default_impersonate_client (internal) 1129 * 1130 */ 1131 RPC_STATUS RPCRT4_default_impersonate_client(RpcConnection *conn) 1132 { 1133 SECURITY_STATUS sec_status; 1134 1135 TRACE("(%p)\n", conn); 1136 1137 if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx)) 1138 return RPC_S_NO_CONTEXT_AVAILABLE; 1139 sec_status = ImpersonateSecurityContext(&conn->ctx); 1140 if (sec_status != SEC_E_OK) 1141 WARN("ImpersonateSecurityContext returned 0x%08x\n", sec_status); 1142 switch (sec_status) 1143 { 1144 case SEC_E_UNSUPPORTED_FUNCTION: 1145 return RPC_S_CANNOT_SUPPORT; 1146 case SEC_E_NO_IMPERSONATION: 1147 return RPC_S_NO_CONTEXT_AVAILABLE; 1148 case SEC_E_OK: 1149 return RPC_S_OK; 1150 default: 1151 return RPC_S_SEC_PKG_ERROR; 1152 } 1153 } 1154 1155 /*********************************************************************** 1156 * RPCRT4_default_revert_to_self (internal) 1157 * 1158 */ 1159 RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn) 1160 { 1161 SECURITY_STATUS sec_status; 1162 1163 TRACE("(%p)\n", conn); 1164 1165 if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx)) 1166 return RPC_S_NO_CONTEXT_AVAILABLE; 1167 sec_status = RevertSecurityContext(&conn->ctx); 1168 if (sec_status != SEC_E_OK) 1169 WARN("RevertSecurityContext returned 0x%08x\n", sec_status); 1170 switch (sec_status) 1171 { 1172 case SEC_E_UNSUPPORTED_FUNCTION: 1173 return RPC_S_CANNOT_SUPPORT; 1174 case SEC_E_NO_IMPERSONATION: 1175 return RPC_S_NO_CONTEXT_AVAILABLE; 1176 case SEC_E_OK: 1177 return RPC_S_OK; 1178 default: 1179 return RPC_S_SEC_PKG_ERROR; 1180 } 1181 } 1182 1183 /*********************************************************************** 1184 * RPCRT4_default_inquire_auth_client (internal) 1185 * 1186 * Default function to retrieve the authentication details that the client 1187 * is using to call the server. 1188 */ 1189 RPC_STATUS RPCRT4_default_inquire_auth_client( 1190 RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name, 1191 ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags) 1192 { 1193 if (!conn->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH; 1194 1195 if (privs) 1196 { 1197 FIXME("privs not implemented\n"); 1198 *privs = NULL; 1199 } 1200 if (server_princ_name) 1201 { 1202 *server_princ_name = RPCRT4_strdupW(conn->AuthInfo->server_principal_name); 1203 if (!*server_princ_name) return ERROR_OUTOFMEMORY; 1204 } 1205 if (authn_level) *authn_level = conn->AuthInfo->AuthnLevel; 1206 if (authn_svc) *authn_svc = conn->AuthInfo->AuthnSvc; 1207 if (authz_svc) 1208 { 1209 FIXME("authorization service not implemented\n"); 1210 *authz_svc = RPC_C_AUTHZ_NONE; 1211 } 1212 if (flags) 1213 FIXME("flags 0x%x not implemented\n", flags); 1214 1215 return RPC_S_OK; 1216 } 1217 1218 /*********************************************************************** 1219 * RPCRT4_Send (internal) 1220 * 1221 * Transmit a packet over connection in acceptable fragments. 1222 */ 1223 RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, 1224 void *Buffer, unsigned int BufferLength) 1225 { 1226 RPC_STATUS r; 1227 1228 if (packet_does_auth_negotiation(Header) && 1229 Connection->AuthInfo && 1230 !rpcrt4_conn_is_authorized(Connection)) 1231 { 1232 unsigned int out_size = 0; 1233 unsigned char *out_buffer; 1234 1235 r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, NULL, &out_size); 1236 if (r != RPC_S_OK) return r; 1237 1238 out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size); 1239 if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; 1240 1241 /* tack on a negotiate packet */ 1242 r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, out_buffer, &out_size); 1243 if (r == RPC_S_OK) 1244 r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, out_buffer, out_size); 1245 1246 HeapFree(GetProcessHeap(), 0, out_buffer); 1247 } 1248 else 1249 r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, NULL, 0); 1250 1251 return r; 1252 } 1253 1254 /* validates version and frag_len fields */ 1255 RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) 1256 { 1257 DWORD hdr_length; 1258 1259 /* verify if the header really makes sense */ 1260 if (hdr->rpc_ver != RPC_VER_MAJOR || 1261 hdr->rpc_ver_minor != RPC_VER_MINOR) 1262 { 1263 WARN("unhandled packet version\n"); 1264 return RPC_S_PROTOCOL_ERROR; 1265 } 1266 1267 hdr_length = RPCRT4_GetHeaderSize((const RpcPktHdr*)hdr); 1268 if (hdr_length == 0) 1269 { 1270 WARN("header length == 0\n"); 1271 return RPC_S_PROTOCOL_ERROR; 1272 } 1273 1274 if (hdr->frag_len < hdr_length) 1275 { 1276 WARN("bad frag length %d\n", hdr->frag_len); 1277 return RPC_S_PROTOCOL_ERROR; 1278 } 1279 1280 return RPC_S_OK; 1281 } 1282 1283 /*********************************************************************** 1284 * RPCRT4_default_receive_fragment (internal) 1285 * 1286 * Receive a fragment from a connection. 1287 */ 1288 static RPC_STATUS RPCRT4_default_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) 1289 { 1290 RPC_STATUS status; 1291 DWORD hdr_length; 1292 LONG dwRead; 1293 RpcPktCommonHdr common_hdr; 1294 1295 *Header = NULL; 1296 *Payload = NULL; 1297 1298 TRACE("(%p, %p, %p)\n", Connection, Header, Payload); 1299 1300 /* read packet common header */ 1301 dwRead = rpcrt4_conn_read(Connection, &common_hdr, sizeof(common_hdr)); 1302 if (dwRead != sizeof(common_hdr)) { 1303 WARN("Short read of header, %d bytes\n", dwRead); 1304 status = RPC_S_CALL_FAILED; 1305 goto fail; 1306 } 1307 1308 status = RPCRT4_ValidateCommonHeader(&common_hdr); 1309 if (status != RPC_S_OK) goto fail; 1310 1311 hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr); 1312 if (hdr_length == 0) { 1313 WARN("header length == 0\n"); 1314 status = RPC_S_PROTOCOL_ERROR; 1315 goto fail; 1316 } 1317 1318 *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length); 1319 memcpy(*Header, &common_hdr, sizeof(common_hdr)); 1320 1321 /* read the rest of packet header */ 1322 dwRead = rpcrt4_conn_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr)); 1323 if (dwRead != hdr_length - sizeof(common_hdr)) { 1324 WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length); 1325 status = RPC_S_CALL_FAILED; 1326 goto fail; 1327 } 1328 1329 if (common_hdr.frag_len - hdr_length) 1330 { 1331 *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length); 1332 if (!*Payload) 1333 { 1334 status = RPC_S_OUT_OF_RESOURCES; 1335 goto fail; 1336 } 1337 1338 dwRead = rpcrt4_conn_read(Connection, *Payload, common_hdr.frag_len - hdr_length); 1339 if (dwRead != common_hdr.frag_len - hdr_length) 1340 { 1341 WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length); 1342 status = RPC_S_CALL_FAILED; 1343 goto fail; 1344 } 1345 } 1346 else 1347 *Payload = NULL; 1348 1349 /* success */ 1350 status = RPC_S_OK; 1351 1352 fail: 1353 if (status != RPC_S_OK) { 1354 RPCRT4_FreeHeader(*Header); 1355 *Header = NULL; 1356 HeapFree(GetProcessHeap(), 0, *Payload); 1357 *Payload = NULL; 1358 } 1359 return status; 1360 } 1361 1362 static RPC_STATUS RPCRT4_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) 1363 { 1364 if (Connection->ops->receive_fragment) 1365 return Connection->ops->receive_fragment(Connection, Header, Payload); 1366 else 1367 return RPCRT4_default_receive_fragment(Connection, Header, Payload); 1368 } 1369 1370 /*********************************************************************** 1371 * RPCRT4_ReceiveWithAuth (internal) 1372 * 1373 * Receive a packet from connection, merge the fragments and return the auth 1374 * data. 1375 */ 1376 RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, 1377 PRPC_MESSAGE pMsg, 1378 unsigned char **auth_data_out, 1379 ULONG *auth_length_out) 1380 { 1381 RPC_STATUS status; 1382 DWORD hdr_length; 1383 unsigned short first_flag; 1384 ULONG data_length; 1385 ULONG buffer_length; 1386 ULONG auth_length = 0; 1387 unsigned char *auth_data = NULL; 1388 RpcPktHdr *CurrentHeader = NULL; 1389 void *payload = NULL; 1390 1391 *Header = NULL; 1392 pMsg->Buffer = NULL; 1393 if (auth_data_out) *auth_data_out = NULL; 1394 if (auth_length_out) *auth_length_out = 0; 1395 1396 TRACE("(%p, %p, %p, %p)\n", Connection, Header, pMsg, auth_data_out); 1397 1398 RPCRT4_SetThreadCurrentConnection(Connection); 1399 1400 status = RPCRT4_receive_fragment(Connection, Header, &payload); 1401 if (status != RPC_S_OK) goto fail; 1402 1403 hdr_length = RPCRT4_GetHeaderSize(*Header); 1404 1405 /* read packet body */ 1406 switch ((*Header)->common.ptype) { 1407 case PKT_RESPONSE: 1408 pMsg->BufferLength = (*Header)->response.alloc_hint; 1409 break; 1410 case PKT_REQUEST: 1411 pMsg->BufferLength = (*Header)->request.alloc_hint; 1412 break; 1413 default: 1414 pMsg->BufferLength = (*Header)->common.frag_len - hdr_length - RPC_AUTH_VERIFIER_LEN(&(*Header)->common); 1415 } 1416 1417 TRACE("buffer length = %u\n", pMsg->BufferLength); 1418 1419 pMsg->Buffer = I_RpcAllocate(pMsg->BufferLength); 1420 if (!pMsg->Buffer) 1421 { 1422 status = ERROR_OUTOFMEMORY; 1423 goto fail; 1424 } 1425 1426 first_flag = RPC_FLG_FIRST; 1427 auth_length = (*Header)->common.auth_len; 1428 if (auth_length) { 1429 auth_data = HeapAlloc(GetProcessHeap(), 0, RPC_AUTH_VERIFIER_LEN(&(*Header)->common)); 1430 if (!auth_data) { 1431 status = RPC_S_OUT_OF_RESOURCES; 1432 goto fail; 1433 } 1434 } 1435 CurrentHeader = *Header; 1436 buffer_length = 0; 1437 while (TRUE) 1438 { 1439 unsigned int header_auth_len = RPC_AUTH_VERIFIER_LEN(&CurrentHeader->common); 1440 1441 /* verify header fields */ 1442 1443 if ((CurrentHeader->common.frag_len < hdr_length) || 1444 (CurrentHeader->common.frag_len - hdr_length < header_auth_len)) { 1445 WARN("frag_len %d too small for hdr_length %d and auth_len %d\n", 1446 CurrentHeader->common.frag_len, hdr_length, CurrentHeader->common.auth_len); 1447 status = RPC_S_PROTOCOL_ERROR; 1448 goto fail; 1449 } 1450 1451 if (CurrentHeader->common.auth_len != auth_length) { 1452 WARN("auth_len header field changed from %d to %d\n", 1453 auth_length, CurrentHeader->common.auth_len); 1454 status = RPC_S_PROTOCOL_ERROR; 1455 goto fail; 1456 } 1457 1458 if ((CurrentHeader->common.flags & RPC_FLG_FIRST) != first_flag) { 1459 TRACE("invalid packet flags\n"); 1460 status = RPC_S_PROTOCOL_ERROR; 1461 goto fail; 1462 } 1463 1464 data_length = CurrentHeader->common.frag_len - hdr_length - header_auth_len; 1465 if (data_length + buffer_length > pMsg->BufferLength) { 1466 TRACE("allocation hint exceeded, new buffer length = %d\n", 1467 data_length + buffer_length); 1468 pMsg->BufferLength = data_length + buffer_length; 1469 status = I_RpcReAllocateBuffer(pMsg); 1470 if (status != RPC_S_OK) goto fail; 1471 } 1472 1473 memcpy((unsigned char *)pMsg->Buffer + buffer_length, payload, data_length); 1474 1475 if (header_auth_len) { 1476 if (header_auth_len < sizeof(RpcAuthVerifier) || 1477 header_auth_len > RPC_AUTH_VERIFIER_LEN(&(*Header)->common)) { 1478 WARN("bad auth verifier length %d\n", header_auth_len); 1479 status = RPC_S_PROTOCOL_ERROR; 1480 goto fail; 1481 } 1482 1483 /* FIXME: we should accumulate authentication data for the bind, 1484 * bind_ack, alter_context and alter_context_response if necessary. 1485 * however, the details of how this is done is very sketchy in the 1486 * DCE/RPC spec. for all other packet types that have authentication 1487 * verifier data then it is just duplicated in all the fragments */ 1488 memcpy(auth_data, (unsigned char *)payload + data_length, header_auth_len); 1489 1490 /* these packets are handled specially, not by the generic SecurePacket 1491 * function */ 1492 if (!packet_does_auth_negotiation(*Header) && rpcrt4_conn_is_authorized(Connection)) 1493 { 1494 status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_RECEIVE, 1495 CurrentHeader, hdr_length, 1496 (unsigned char *)pMsg->Buffer + buffer_length, data_length, 1497 (RpcAuthVerifier *)auth_data, 1498 auth_data + sizeof(RpcAuthVerifier), 1499 header_auth_len - sizeof(RpcAuthVerifier)); 1500 if (status != RPC_S_OK) goto fail; 1501 } 1502 } 1503 1504 buffer_length += data_length; 1505 if (!(CurrentHeader->common.flags & RPC_FLG_LAST)) { 1506 TRACE("next header\n"); 1507 1508 if (*Header != CurrentHeader) 1509 { 1510 RPCRT4_FreeHeader(CurrentHeader); 1511 CurrentHeader = NULL; 1512 } 1513 HeapFree(GetProcessHeap(), 0, payload); 1514 payload = NULL; 1515 1516 status = RPCRT4_receive_fragment(Connection, &CurrentHeader, &payload); 1517 if (status != RPC_S_OK) goto fail; 1518 1519 first_flag = 0; 1520 } else { 1521 break; 1522 } 1523 } 1524 pMsg->BufferLength = buffer_length; 1525 1526 /* success */ 1527 status = RPC_S_OK; 1528 1529 fail: 1530 RPCRT4_SetThreadCurrentConnection(NULL); 1531 if (CurrentHeader != *Header) 1532 RPCRT4_FreeHeader(CurrentHeader); 1533 if (status != RPC_S_OK) { 1534 I_RpcFree(pMsg->Buffer); 1535 pMsg->Buffer = NULL; 1536 RPCRT4_FreeHeader(*Header); 1537 *Header = NULL; 1538 } 1539 if (auth_data_out && status == RPC_S_OK) { 1540 *auth_length_out = auth_length; 1541 *auth_data_out = auth_data; 1542 } 1543 else 1544 HeapFree(GetProcessHeap(), 0, auth_data); 1545 HeapFree(GetProcessHeap(), 0, payload); 1546 return status; 1547 } 1548 1549 /*********************************************************************** 1550 * RPCRT4_Receive (internal) 1551 * 1552 * Receive a packet from connection and merge the fragments. 1553 */ 1554 static RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, 1555 PRPC_MESSAGE pMsg) 1556 { 1557 return RPCRT4_ReceiveWithAuth(Connection, Header, pMsg, NULL, NULL); 1558 } 1559 1560 /*********************************************************************** 1561 * I_RpcNegotiateTransferSyntax [RPCRT4.@] 1562 * 1563 * Negotiates the transfer syntax used by a client connection by connecting 1564 * to the server. 1565 * 1566 * PARAMS 1567 * pMsg [I] RPC Message structure. 1568 * pAsync [I] Asynchronous state to set. 1569 * 1570 * RETURNS 1571 * Success: RPC_S_OK. 1572 * Failure: Any error code. 1573 */ 1574 RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg) 1575 { 1576 RpcBinding* bind = pMsg->Handle; 1577 RpcConnection* conn; 1578 RPC_STATUS status = RPC_S_OK; 1579 1580 TRACE("(%p)\n", pMsg); 1581 1582 if (!bind || bind->server) 1583 { 1584 ERR("no binding\n"); 1585 return RPC_S_INVALID_BINDING; 1586 } 1587 1588 /* if we already have a connection, we don't need to negotiate again */ 1589 if (!pMsg->ReservedForRuntime) 1590 { 1591 RPC_CLIENT_INTERFACE *cif = pMsg->RpcInterfaceInformation; 1592 if (!cif) return RPC_S_INTERFACE_NOT_FOUND; 1593 1594 if (!bind->Endpoint || !bind->Endpoint[0]) 1595 { 1596 TRACE("automatically resolving partially bound binding\n"); 1597 status = RpcEpResolveBinding(bind, cif); 1598 if (status != RPC_S_OK) return status; 1599 } 1600 1601 status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax, 1602 &cif->InterfaceId, NULL); 1603 1604 if (status == RPC_S_OK) 1605 { 1606 pMsg->ReservedForRuntime = conn; 1607 RPCRT4_AddRefBinding(bind); 1608 } 1609 } 1610 1611 return status; 1612 } 1613 1614 /*********************************************************************** 1615 * I_RpcGetBuffer [RPCRT4.@] 1616 * 1617 * Allocates a buffer for use by I_RpcSend or I_RpcSendReceive and binds to the 1618 * server interface. 1619 * 1620 * PARAMS 1621 * pMsg [I/O] RPC message information. 1622 * 1623 * RETURNS 1624 * Success: RPC_S_OK. 1625 * Failure: RPC_S_INVALID_BINDING if pMsg->Handle is invalid. 1626 * RPC_S_SERVER_UNAVAILABLE if unable to connect to server. 1627 * ERROR_OUTOFMEMORY if buffer allocation failed. 1628 * 1629 * NOTES 1630 * The pMsg->BufferLength field determines the size of the buffer to allocate, 1631 * in bytes. 1632 * 1633 * Use I_RpcFreeBuffer() to unbind from the server and free the message buffer. 1634 * 1635 * SEE ALSO 1636 * I_RpcFreeBuffer(), I_RpcSend(), I_RpcReceive(), I_RpcSendReceive(). 1637 */ 1638 RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) 1639 { 1640 RPC_STATUS status; 1641 RpcBinding* bind = pMsg->Handle; 1642 1643 TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); 1644 1645 if (!bind) 1646 { 1647 ERR("no binding\n"); 1648 return RPC_S_INVALID_BINDING; 1649 } 1650 1651 pMsg->Buffer = I_RpcAllocate(pMsg->BufferLength); 1652 TRACE("Buffer=%p\n", pMsg->Buffer); 1653 1654 if (!pMsg->Buffer) 1655 return ERROR_OUTOFMEMORY; 1656 1657 if (!bind->server) 1658 { 1659 status = I_RpcNegotiateTransferSyntax(pMsg); 1660 if (status != RPC_S_OK) 1661 I_RpcFree(pMsg->Buffer); 1662 } 1663 else 1664 status = RPC_S_OK; 1665 1666 return status; 1667 } 1668 1669 /*********************************************************************** 1670 * I_RpcReAllocateBuffer (internal) 1671 */ 1672 static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg) 1673 { 1674 TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); 1675 pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength); 1676 1677 TRACE("Buffer=%p\n", pMsg->Buffer); 1678 return pMsg->Buffer ? RPC_S_OK : ERROR_OUTOFMEMORY; 1679 } 1680 1681 /*********************************************************************** 1682 * I_RpcFreeBuffer [RPCRT4.@] 1683 * 1684 * Frees a buffer allocated by I_RpcGetBuffer or I_RpcReceive and unbinds from 1685 * the server interface. 1686 * 1687 * PARAMS 1688 * pMsg [I/O] RPC message information. 1689 * 1690 * RETURNS 1691 * RPC_S_OK. 1692 * 1693 * SEE ALSO 1694 * I_RpcGetBuffer(), I_RpcReceive(). 1695 */ 1696 RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) 1697 { 1698 RpcBinding* bind = pMsg->Handle; 1699 1700 TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer); 1701 1702 if (!bind) 1703 { 1704 ERR("no binding\n"); 1705 return RPC_S_INVALID_BINDING; 1706 } 1707 1708 if (pMsg->ReservedForRuntime) 1709 { 1710 RpcConnection *conn = pMsg->ReservedForRuntime; 1711 RPCRT4_CloseBinding(bind, conn); 1712 RPCRT4_ReleaseBinding(bind); 1713 pMsg->ReservedForRuntime = NULL; 1714 } 1715 I_RpcFree(pMsg->Buffer); 1716 return RPC_S_OK; 1717 } 1718 1719 static void CALLBACK async_apc_notifier_proc(ULONG_PTR ulParam) 1720 { 1721 RPC_ASYNC_STATE *state = (RPC_ASYNC_STATE *)ulParam; 1722 state->u.APC.NotificationRoutine(state, NULL, state->Event); 1723 } 1724 1725 static DWORD WINAPI async_notifier_proc(LPVOID p) 1726 { 1727 RpcConnection *conn = p; 1728 RPC_ASYNC_STATE *state = conn->async_state; 1729 1730 if (state && conn->ops->wait_for_incoming_data(conn) != -1) 1731 { 1732 state->Event = RpcCallComplete; 1733 switch (state->NotificationType) 1734 { 1735 case RpcNotificationTypeEvent: 1736 TRACE("RpcNotificationTypeEvent %p\n", state->u.hEvent); 1737 SetEvent(state->u.hEvent); 1738 break; 1739 case RpcNotificationTypeApc: 1740 TRACE("RpcNotificationTypeApc %p\n", state->u.APC.hThread); 1741 QueueUserAPC(async_apc_notifier_proc, state->u.APC.hThread, (ULONG_PTR)state); 1742 break; 1743 case RpcNotificationTypeIoc: 1744 TRACE("RpcNotificationTypeIoc %p, 0x%x, 0x%lx, %p\n", 1745 state->u.IOC.hIOPort, state->u.IOC.dwNumberOfBytesTransferred, 1746 state->u.IOC.dwCompletionKey, state->u.IOC.lpOverlapped); 1747 PostQueuedCompletionStatus(state->u.IOC.hIOPort, 1748 state->u.IOC.dwNumberOfBytesTransferred, 1749 state->u.IOC.dwCompletionKey, 1750 state->u.IOC.lpOverlapped); 1751 break; 1752 case RpcNotificationTypeHwnd: 1753 TRACE("RpcNotificationTypeHwnd %p 0x%x\n", state->u.HWND.hWnd, 1754 state->u.HWND.Msg); 1755 PostMessageW(state->u.HWND.hWnd, state->u.HWND.Msg, 0, 0); 1756 break; 1757 case RpcNotificationTypeCallback: 1758 TRACE("RpcNotificationTypeCallback %p\n", state->u.NotificationRoutine); 1759 state->u.NotificationRoutine(state, NULL, state->Event); 1760 break; 1761 case RpcNotificationTypeNone: 1762 TRACE("RpcNotificationTypeNone\n"); 1763 break; 1764 default: 1765 FIXME("unknown NotificationType: %d/0x%x\n", state->NotificationType, state->NotificationType); 1766 break; 1767 } 1768 } 1769 1770 return 0; 1771 } 1772 1773 /*********************************************************************** 1774 * I_RpcSend [RPCRT4.@] 1775 * 1776 * Sends a message to the server. 1777 * 1778 * PARAMS 1779 * pMsg [I/O] RPC message information. 1780 * 1781 * RETURNS 1782 * Unknown. 1783 * 1784 * NOTES 1785 * The buffer must have been allocated with I_RpcGetBuffer(). 1786 * 1787 * SEE ALSO 1788 * I_RpcGetBuffer(), I_RpcReceive(), I_RpcSendReceive(). 1789 */ 1790 RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) 1791 { 1792 RpcBinding* bind = pMsg->Handle; 1793 RPC_CLIENT_INTERFACE *cif; 1794 RpcConnection* conn; 1795 RPC_STATUS status; 1796 RpcPktHdr *hdr; 1797 BOOL from_cache = TRUE; 1798 1799 TRACE("(%p)\n", pMsg); 1800 if (!bind || bind->server || !pMsg->ReservedForRuntime) return RPC_S_INVALID_BINDING; 1801 1802 for (;;) 1803 { 1804 conn = pMsg->ReservedForRuntime; 1805 hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation, 1806 pMsg->BufferLength, 1807 pMsg->ProcNum & ~RPC_FLAGS_VALID_BIT, 1808 &bind->ObjectUuid); 1809 if (!hdr) 1810 return ERROR_OUTOFMEMORY; 1811 1812 hdr->common.call_id = conn->NextCallId++; 1813 status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength); 1814 RPCRT4_FreeHeader(hdr); 1815 if (status == RPC_S_OK || conn->server || !from_cache) 1816 break; 1817 1818 WARN("Send failed, trying to reconnect\n"); 1819 cif = pMsg->RpcInterfaceInformation; 1820 RPCRT4_ReleaseConnection(conn); 1821 pMsg->ReservedForRuntime = NULL; 1822 status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax, &cif->InterfaceId, &from_cache); 1823 if (status != RPC_S_OK) break; 1824 pMsg->ReservedForRuntime = conn; 1825 } 1826 1827 if (status == RPC_S_OK && pMsg->RpcFlags & RPC_BUFFER_ASYNC) 1828 { 1829 if (!QueueUserWorkItem(async_notifier_proc, conn, WT_EXECUTEDEFAULT | WT_EXECUTELONGFUNCTION)) 1830 status = RPC_S_OUT_OF_RESOURCES; 1831 } 1832 1833 return status; 1834 } 1835 1836 /* is this status something that the server can't recover from? */ 1837 static inline BOOL is_hard_error(RPC_STATUS status) 1838 { 1839 switch (status) 1840 { 1841 case 0: /* user-defined fault */ 1842 case ERROR_ACCESS_DENIED: 1843 case ERROR_INVALID_PARAMETER: 1844 case RPC_S_PROTOCOL_ERROR: 1845 case RPC_S_CALL_FAILED: 1846 case RPC_S_CALL_FAILED_DNE: 1847 case RPC_S_SEC_PKG_ERROR: 1848 return TRUE; 1849 default: 1850 return FALSE; 1851 } 1852 } 1853 1854 /*********************************************************************** 1855 * I_RpcReceive [RPCRT4.@] 1856 */ 1857 RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) 1858 { 1859 RpcBinding* bind = pMsg->Handle; 1860 RPC_STATUS status; 1861 RpcPktHdr *hdr = NULL; 1862 RpcConnection *conn; 1863 1864 TRACE("(%p)\n", pMsg); 1865 if (!bind || bind->server || !pMsg->ReservedForRuntime) return RPC_S_INVALID_BINDING; 1866 1867 conn = pMsg->ReservedForRuntime; 1868 status = RPCRT4_Receive(conn, &hdr, pMsg); 1869 if (status != RPC_S_OK) { 1870 WARN("receive failed with error %x\n", status); 1871 goto fail; 1872 } 1873 1874 switch (hdr->common.ptype) { 1875 case PKT_RESPONSE: 1876 break; 1877 case PKT_FAULT: 1878 ERR ("we got fault packet with status 0x%x\n", hdr->fault.status); 1879 status = NCA2RPC_STATUS(hdr->fault.status); 1880 if (is_hard_error(status)) 1881 goto fail; 1882 break; 1883 default: 1884 WARN("bad packet type %d\n", hdr->common.ptype); 1885 status = RPC_S_PROTOCOL_ERROR; 1886 goto fail; 1887 } 1888 1889 /* success */ 1890 RPCRT4_FreeHeader(hdr); 1891 return status; 1892 1893 fail: 1894 RPCRT4_FreeHeader(hdr); 1895 RPCRT4_ReleaseConnection(conn); 1896 pMsg->ReservedForRuntime = NULL; 1897 return status; 1898 } 1899 1900 /*********************************************************************** 1901 * I_RpcSendReceive [RPCRT4.@] 1902 * 1903 * Sends a message to the server and receives the response. 1904 * 1905 * PARAMS 1906 * pMsg [I/O] RPC message information. 1907 * 1908 * RETURNS 1909 * Success: RPC_S_OK. 1910 * Failure: Any error code. 1911 * 1912 * NOTES 1913 * The buffer must have been allocated with I_RpcGetBuffer(). 1914 * 1915 * SEE ALSO 1916 * I_RpcGetBuffer(), I_RpcSend(), I_RpcReceive(). 1917 */ 1918 RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg) 1919 { 1920 RPC_STATUS status; 1921 void *original_buffer; 1922 1923 TRACE("(%p)\n", pMsg); 1924 1925 original_buffer = pMsg->Buffer; 1926 status = I_RpcSend(pMsg); 1927 if (status == RPC_S_OK) 1928 status = I_RpcReceive(pMsg); 1929 /* free the buffer replaced by a new buffer in I_RpcReceive */ 1930 if (status == RPC_S_OK) 1931 I_RpcFree(original_buffer); 1932 return status; 1933 } 1934 1935 /*********************************************************************** 1936 * I_RpcAsyncSetHandle [RPCRT4.@] 1937 * 1938 * Sets the asynchronous state of the handle contained in the RPC message 1939 * structure. 1940 * 1941 * PARAMS 1942 * pMsg [I] RPC Message structure. 1943 * pAsync [I] Asynchronous state to set. 1944 * 1945 * RETURNS 1946 * Success: RPC_S_OK. 1947 * Failure: Any error code. 1948 */ 1949 RPC_STATUS WINAPI I_RpcAsyncSetHandle(PRPC_MESSAGE pMsg, PRPC_ASYNC_STATE pAsync) 1950 { 1951 RpcBinding* bind = pMsg->Handle; 1952 RpcConnection *conn; 1953 1954 TRACE("(%p, %p)\n", pMsg, pAsync); 1955 1956 if (!bind || bind->server || !pMsg->ReservedForRuntime) return RPC_S_INVALID_BINDING; 1957 1958 conn = pMsg->ReservedForRuntime; 1959 conn->async_state = pAsync; 1960 1961 return RPC_S_OK; 1962 } 1963 1964 /*********************************************************************** 1965 * I_RpcAsyncAbortCall [RPCRT4.@] 1966 * 1967 * Aborts an asynchronous call. 1968 * 1969 * PARAMS 1970 * pAsync [I] Asynchronous state. 1971 * ExceptionCode [I] Exception code. 1972 * 1973 * RETURNS 1974 * Success: RPC_S_OK. 1975 * Failure: Any error code. 1976 */ 1977 RPC_STATUS WINAPI I_RpcAsyncAbortCall(PRPC_ASYNC_STATE pAsync, ULONG ExceptionCode) 1978 { 1979 FIXME("(%p, %d): stub\n", pAsync, ExceptionCode); 1980 return RPC_S_INVALID_ASYNC_HANDLE; 1981 } 1982