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