1 /* 2 * RPC transport layer 3 * 4 * Copyright 2001 Ove Kåven, TransGaming Technologies 5 * Copyright 2003 Mike Hearn 6 * Copyright 2004 Filip Navara 7 * Copyright 2006 Mike McCormack 8 * Copyright 2006 Damjan Jovanovic 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 * 24 */ 25 26 #include "ntstatus.h" 27 #define WIN32_NO_STATUS 28 #ifdef __REACTOS__ 29 #define NONAMELESSUNION 30 #endif 31 #include "ws2tcpip.h" 32 33 #include <stdarg.h> 34 #include <stdio.h> 35 #include <string.h> 36 #include <assert.h> 37 38 39 40 #include "windef.h" 41 #include "winbase.h" 42 #include "winnls.h" 43 #include "winerror.h" 44 #include "wininet.h" 45 #include "wine/winternl.h" 46 #include "winioctl.h" 47 #include "wine/unicode.h" 48 49 #include "rpc.h" 50 #include "rpcndr.h" 51 52 #include "wine/debug.h" 53 54 #include "rpc_binding.h" 55 #include "rpc_assoc.h" 56 #include "rpc_message.h" 57 #include "rpc_server.h" 58 #include "epm_towers.h" 59 60 #define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000) 61 62 #undef ARRAYSIZE 63 #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0])) 64 65 WINE_DEFAULT_DEBUG_CHANNEL(rpc); 66 67 #ifdef __REACTOS__ /* FIXME: Inspect */ 68 BOOL WINAPI CancelIoEx(HANDLE handle, LPOVERLAPPED lpOverlapped) 69 { 70 IO_STATUS_BLOCK io_status; 71 72 NtCancelIoFile(handle, &io_status); 73 if (io_status.u.Status) 74 { 75 SetLastError( RtlNtStatusToDosError( io_status.u.Status ) ); 76 return FALSE; 77 } 78 return TRUE; 79 } 80 #endif 81 82 static RpcConnection *rpcrt4_spawn_connection(RpcConnection *old_connection); 83 84 /**** ncacn_np support ****/ 85 86 typedef struct _RpcConnection_np 87 { 88 RpcConnection common; 89 HANDLE pipe; 90 HANDLE listen_event; 91 char *listen_pipe; 92 IO_STATUS_BLOCK io_status; 93 HANDLE event_cache; 94 BOOL read_closed; 95 } RpcConnection_np; 96 97 static RpcConnection *rpcrt4_conn_np_alloc(void) 98 { 99 RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcConnection_np)); 100 return &npc->common; 101 } 102 103 static HANDLE get_np_event(RpcConnection_np *connection) 104 { 105 HANDLE event = InterlockedExchangePointer(&connection->event_cache, NULL); 106 return event ? event : CreateEventW(NULL, TRUE, FALSE, NULL); 107 } 108 109 static void release_np_event(RpcConnection_np *connection, HANDLE event) 110 { 111 event = InterlockedExchangePointer(&connection->event_cache, event); 112 if (event) 113 CloseHandle(event); 114 } 115 116 static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *conn) 117 { 118 RpcConnection_np *connection = (RpcConnection_np *) conn; 119 120 TRACE("listening on %s\n", connection->listen_pipe); 121 122 connection->pipe = CreateNamedPipeA(connection->listen_pipe, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 123 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 124 PIPE_UNLIMITED_INSTANCES, 125 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); 126 if (connection->pipe == INVALID_HANDLE_VALUE) 127 { 128 WARN("CreateNamedPipe failed with error %d\n", GetLastError()); 129 if (GetLastError() == ERROR_FILE_EXISTS) 130 return RPC_S_DUPLICATE_ENDPOINT; 131 else 132 return RPC_S_CANT_CREATE_ENDPOINT; 133 } 134 135 return RPC_S_OK; 136 } 137 138 static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait) 139 { 140 RpcConnection_np *npc = (RpcConnection_np *) Connection; 141 HANDLE pipe; 142 DWORD err, dwMode; 143 144 TRACE("connecting to %s\n", pname); 145 146 while (TRUE) { 147 DWORD dwFlags = 0; 148 if (Connection->QOS) 149 { 150 dwFlags = SECURITY_SQOS_PRESENT; 151 switch (Connection->QOS->qos->ImpersonationType) 152 { 153 case RPC_C_IMP_LEVEL_DEFAULT: 154 /* FIXME: what to do here? */ 155 break; 156 case RPC_C_IMP_LEVEL_ANONYMOUS: 157 dwFlags |= SECURITY_ANONYMOUS; 158 break; 159 case RPC_C_IMP_LEVEL_IDENTIFY: 160 dwFlags |= SECURITY_IDENTIFICATION; 161 break; 162 case RPC_C_IMP_LEVEL_IMPERSONATE: 163 dwFlags |= SECURITY_IMPERSONATION; 164 break; 165 case RPC_C_IMP_LEVEL_DELEGATE: 166 dwFlags |= SECURITY_DELEGATION; 167 break; 168 } 169 if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC) 170 dwFlags |= SECURITY_CONTEXT_TRACKING; 171 } 172 pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL, 173 OPEN_EXISTING, dwFlags | FILE_FLAG_OVERLAPPED, 0); 174 if (pipe != INVALID_HANDLE_VALUE) break; 175 err = GetLastError(); 176 if (err == ERROR_PIPE_BUSY) { 177 if (WaitNamedPipeA(pname, NMPWAIT_USE_DEFAULT_WAIT)) { 178 TRACE("retrying busy server\n"); 179 continue; 180 } 181 TRACE("connection failed, error=%x\n", err); 182 return RPC_S_SERVER_TOO_BUSY; 183 } 184 if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { 185 err = GetLastError(); 186 WARN("connection failed, error=%x\n", err); 187 return RPC_S_SERVER_UNAVAILABLE; 188 } 189 } 190 191 /* success */ 192 /* pipe is connected; change to message-read mode. */ 193 dwMode = PIPE_READMODE_MESSAGE; 194 SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL); 195 npc->pipe = pipe; 196 197 return RPC_S_OK; 198 } 199 200 static char *ncalrpc_pipe_name(const char *endpoint) 201 { 202 static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; 203 char *pipe_name; 204 205 /* protseq=ncalrpc: supposed to use NT LPC ports, 206 * but we'll implement it with named pipes for now */ 207 pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(endpoint)); 208 strcat(strcpy(pipe_name, prefix), endpoint); 209 return pipe_name; 210 } 211 212 static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection) 213 { 214 RpcConnection_np *npc = (RpcConnection_np *) Connection; 215 RPC_STATUS r; 216 LPSTR pname; 217 218 /* already connected? */ 219 if (npc->pipe) 220 return RPC_S_OK; 221 222 pname = ncalrpc_pipe_name(Connection->Endpoint); 223 r = rpcrt4_conn_open_pipe(Connection, pname, TRUE); 224 I_RpcFree(pname); 225 226 return r; 227 } 228 229 static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, const char *endpoint) 230 { 231 RPC_STATUS r; 232 RpcConnection *Connection; 233 char generated_endpoint[22]; 234 235 if (!endpoint) 236 { 237 static LONG lrpc_nameless_id; 238 DWORD process_id = GetCurrentProcessId(); 239 ULONG id = InterlockedIncrement(&lrpc_nameless_id); 240 snprintf(generated_endpoint, sizeof(generated_endpoint), 241 "LRPC%08x.%08x", process_id, id); 242 endpoint = generated_endpoint; 243 } 244 245 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, 246 endpoint, NULL, NULL, NULL, NULL); 247 if (r != RPC_S_OK) 248 return r; 249 250 ((RpcConnection_np*)Connection)->listen_pipe = ncalrpc_pipe_name(Connection->Endpoint); 251 r = rpcrt4_conn_create_pipe(Connection); 252 253 EnterCriticalSection(&protseq->cs); 254 list_add_head(&protseq->listeners, &Connection->protseq_entry); 255 Connection->protseq = protseq; 256 LeaveCriticalSection(&protseq->cs); 257 258 return r; 259 } 260 261 static char *ncacn_pipe_name(const char *server, const char *endpoint) 262 { 263 static const char prefix[] = "\\\\"; 264 static const char local[] = "."; 265 char ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; 266 char *pipe_name; 267 DWORD bufLen = ARRAYSIZE(ComputerName); 268 269 GetComputerNameA(ComputerName, &bufLen); 270 271 if (server == NULL || *server == 0 || stricmp(ComputerName, server) == 0) 272 server = local; 273 274 /* protseq=ncacn_np: named pipes */ 275 pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(server) + strlen(endpoint)); 276 strcpy(pipe_name, prefix); 277 strcat(pipe_name, server); 278 strcat(pipe_name, endpoint); 279 return pipe_name; 280 } 281 282 static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) 283 { 284 RpcConnection_np *npc = (RpcConnection_np *) Connection; 285 RPC_STATUS r; 286 LPSTR pname; 287 288 /* already connected? */ 289 if (npc->pipe) 290 return RPC_S_OK; 291 292 pname = ncacn_pipe_name(Connection->NetworkAddr, Connection->Endpoint); 293 r = rpcrt4_conn_open_pipe(Connection, pname, FALSE); 294 I_RpcFree(pname); 295 296 return r; 297 } 298 299 static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, const char *endpoint) 300 { 301 RPC_STATUS r; 302 RpcConnection *Connection; 303 char generated_endpoint[26]; 304 305 if (!endpoint) 306 { 307 static LONG np_nameless_id; 308 DWORD process_id = GetCurrentProcessId(); 309 ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 ); 310 snprintf(generated_endpoint, sizeof(generated_endpoint), 311 "\\\\pipe\\\\%08x.%03x", process_id, id); 312 endpoint = generated_endpoint; 313 } 314 315 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, 316 endpoint, NULL, NULL, NULL, NULL); 317 if (r != RPC_S_OK) 318 return r; 319 320 ((RpcConnection_np*)Connection)->listen_pipe = ncacn_pipe_name(NULL, Connection->Endpoint); 321 r = rpcrt4_conn_create_pipe(Connection); 322 323 EnterCriticalSection(&protseq->cs); 324 list_add_head(&protseq->listeners, &Connection->protseq_entry); 325 Connection->protseq = protseq; 326 LeaveCriticalSection(&protseq->cs); 327 328 return r; 329 } 330 331 static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc) 332 { 333 /* because of the way named pipes work, we'll transfer the connected pipe 334 * to the child, then reopen the server binding to continue listening */ 335 336 new_npc->pipe = old_npc->pipe; 337 old_npc->pipe = 0; 338 assert(!old_npc->listen_event); 339 } 340 341 static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn) 342 { 343 DWORD len = MAX_COMPUTERNAME_LENGTH + 1; 344 RPC_STATUS status; 345 346 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); 347 status = rpcrt4_conn_create_pipe(old_conn); 348 349 /* Store the local computer name as the NetworkAddr for ncacn_np as long as 350 * we don't support named pipes over the network. */ 351 new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, len); 352 if (!GetComputerNameA(new_conn->NetworkAddr, &len)) 353 { 354 ERR("Failed to retrieve the computer name, error %u\n", GetLastError()); 355 return RPC_S_OUT_OF_RESOURCES; 356 } 357 358 return status; 359 } 360 361 static RPC_STATUS is_pipe_listening(const char *pipe_name) 362 { 363 return WaitNamedPipeA(pipe_name, 1) ? RPC_S_OK : RPC_S_NOT_LISTENING; 364 } 365 366 static RPC_STATUS rpcrt4_ncacn_np_is_server_listening(const char *endpoint) 367 { 368 char *pipe_name; 369 RPC_STATUS status; 370 371 pipe_name = ncacn_pipe_name(NULL, endpoint); 372 status = is_pipe_listening(pipe_name); 373 I_RpcFree(pipe_name); 374 return status; 375 } 376 377 static RPC_STATUS rpcrt4_ncalrpc_np_is_server_listening(const char *endpoint) 378 { 379 char *pipe_name; 380 RPC_STATUS status; 381 382 pipe_name = ncalrpc_pipe_name(endpoint); 383 status = is_pipe_listening(pipe_name); 384 I_RpcFree(pipe_name); 385 return status; 386 } 387 388 static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn) 389 { 390 DWORD len = MAX_COMPUTERNAME_LENGTH + 1; 391 RPC_STATUS status; 392 393 TRACE("%s\n", old_conn->Endpoint); 394 395 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); 396 status = rpcrt4_conn_create_pipe(old_conn); 397 398 /* Store the local computer name as the NetworkAddr for ncalrpc. */ 399 new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, len); 400 if (!GetComputerNameA(new_conn->NetworkAddr, &len)) 401 { 402 ERR("Failed to retrieve the computer name, error %u\n", GetLastError()); 403 return RPC_S_OUT_OF_RESOURCES; 404 } 405 406 return status; 407 } 408 409 static int rpcrt4_conn_np_read(RpcConnection *conn, void *buffer, unsigned int count) 410 { 411 RpcConnection_np *connection = (RpcConnection_np *) conn; 412 HANDLE event; 413 NTSTATUS status; 414 415 event = get_np_event(connection); 416 if (!event) 417 return -1; 418 419 if (connection->read_closed) 420 status = STATUS_CANCELLED; 421 else 422 status = NtReadFile(connection->pipe, event, NULL, NULL, &connection->io_status, buffer, count, NULL, NULL); 423 if (status == STATUS_PENDING) 424 { 425 /* check read_closed again before waiting to avoid a race */ 426 if (connection->read_closed) 427 { 428 IO_STATUS_BLOCK io_status; 429 #ifdef __REACTOS__ /* FIXME: We should also cancel I/O for other threads */ 430 NtCancelIoFile(connection->pipe, &io_status); 431 #else 432 NtCancelIoFileEx(connection->pipe, &connection->io_status, &io_status); 433 #endif 434 } 435 WaitForSingleObject(event, INFINITE); 436 status = connection->io_status.u.Status; 437 } 438 release_np_event(connection, event); 439 return status && status != STATUS_BUFFER_OVERFLOW ? -1 : connection->io_status.Information; 440 } 441 442 static int rpcrt4_conn_np_write(RpcConnection *conn, const void *buffer, unsigned int count) 443 { 444 RpcConnection_np *connection = (RpcConnection_np *) conn; 445 IO_STATUS_BLOCK io_status; 446 HANDLE event; 447 NTSTATUS status; 448 449 event = get_np_event(connection); 450 if (!event) 451 return -1; 452 453 status = NtWriteFile(connection->pipe, event, NULL, NULL, &io_status, buffer, count, NULL, NULL); 454 if (status == STATUS_PENDING) 455 { 456 WaitForSingleObject(event, INFINITE); 457 status = io_status.u.Status; 458 } 459 release_np_event(connection, event); 460 if (status) 461 return -1; 462 463 assert(io_status.Information == count); 464 return count; 465 } 466 467 static int rpcrt4_conn_np_close(RpcConnection *conn) 468 { 469 RpcConnection_np *connection = (RpcConnection_np *) conn; 470 if (connection->pipe) 471 { 472 FlushFileBuffers(connection->pipe); 473 CloseHandle(connection->pipe); 474 connection->pipe = 0; 475 } 476 if (connection->listen_event) 477 { 478 CloseHandle(connection->listen_event); 479 connection->listen_event = 0; 480 } 481 if (connection->event_cache) 482 { 483 CloseHandle(connection->event_cache); 484 connection->event_cache = 0; 485 } 486 return 0; 487 } 488 489 static void rpcrt4_conn_np_close_read(RpcConnection *conn) 490 { 491 RpcConnection_np *connection = (RpcConnection_np*)conn; 492 IO_STATUS_BLOCK io_status; 493 494 connection->read_closed = TRUE; 495 #ifdef __REACTOS__ /* FIXME: We should also cancel I/O for other threads */ 496 NtCancelIoFile(connection->pipe, &io_status); 497 #else 498 NtCancelIoFileEx(connection->pipe, &connection->io_status, &io_status); 499 #endif 500 } 501 502 static void rpcrt4_conn_np_cancel_call(RpcConnection *conn) 503 { 504 RpcConnection_np *connection = (RpcConnection_np *)conn; 505 CancelIoEx(connection->pipe, NULL); 506 } 507 508 static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *Connection) 509 { 510 /* FIXME: implement when named pipe writes use overlapped I/O */ 511 return -1; 512 } 513 514 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data, 515 const char *networkaddr, 516 const char *endpoint) 517 { 518 twr_empty_floor_t *smb_floor; 519 twr_empty_floor_t *nb_floor; 520 size_t size; 521 size_t networkaddr_size; 522 size_t endpoint_size; 523 524 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); 525 526 networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1; 527 endpoint_size = endpoint ? strlen(endpoint) + 1 : 1; 528 size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size; 529 530 if (!tower_data) 531 return size; 532 533 smb_floor = (twr_empty_floor_t *)tower_data; 534 535 tower_data += sizeof(*smb_floor); 536 537 smb_floor->count_lhs = sizeof(smb_floor->protid); 538 smb_floor->protid = EPM_PROTOCOL_SMB; 539 smb_floor->count_rhs = endpoint_size; 540 541 if (endpoint) 542 memcpy(tower_data, endpoint, endpoint_size); 543 else 544 tower_data[0] = 0; 545 tower_data += endpoint_size; 546 547 nb_floor = (twr_empty_floor_t *)tower_data; 548 549 tower_data += sizeof(*nb_floor); 550 551 nb_floor->count_lhs = sizeof(nb_floor->protid); 552 nb_floor->protid = EPM_PROTOCOL_NETBIOS; 553 nb_floor->count_rhs = networkaddr_size; 554 555 if (networkaddr) 556 memcpy(tower_data, networkaddr, networkaddr_size); 557 else 558 tower_data[0] = 0; 559 560 return size; 561 } 562 563 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data, 564 size_t tower_size, 565 char **networkaddr, 566 char **endpoint) 567 { 568 const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data; 569 const twr_empty_floor_t *nb_floor; 570 571 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); 572 573 if (tower_size < sizeof(*smb_floor)) 574 return EPT_S_NOT_REGISTERED; 575 576 tower_data += sizeof(*smb_floor); 577 tower_size -= sizeof(*smb_floor); 578 579 if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) || 580 (smb_floor->protid != EPM_PROTOCOL_SMB) || 581 (smb_floor->count_rhs > tower_size) || 582 (tower_data[smb_floor->count_rhs - 1] != '\0')) 583 return EPT_S_NOT_REGISTERED; 584 585 if (endpoint) 586 { 587 *endpoint = I_RpcAllocate(smb_floor->count_rhs); 588 if (!*endpoint) 589 return RPC_S_OUT_OF_RESOURCES; 590 memcpy(*endpoint, tower_data, smb_floor->count_rhs); 591 } 592 tower_data += smb_floor->count_rhs; 593 tower_size -= smb_floor->count_rhs; 594 595 if (tower_size < sizeof(*nb_floor)) 596 return EPT_S_NOT_REGISTERED; 597 598 nb_floor = (const twr_empty_floor_t *)tower_data; 599 600 tower_data += sizeof(*nb_floor); 601 tower_size -= sizeof(*nb_floor); 602 603 if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) || 604 (nb_floor->protid != EPM_PROTOCOL_NETBIOS) || 605 (nb_floor->count_rhs > tower_size) || 606 (tower_data[nb_floor->count_rhs - 1] != '\0')) 607 return EPT_S_NOT_REGISTERED; 608 609 if (networkaddr) 610 { 611 *networkaddr = I_RpcAllocate(nb_floor->count_rhs); 612 if (!*networkaddr) 613 { 614 if (endpoint) 615 { 616 I_RpcFree(*endpoint); 617 *endpoint = NULL; 618 } 619 return RPC_S_OUT_OF_RESOURCES; 620 } 621 memcpy(*networkaddr, tower_data, nb_floor->count_rhs); 622 } 623 624 return RPC_S_OK; 625 } 626 627 static RPC_STATUS rpcrt4_conn_np_impersonate_client(RpcConnection *conn) 628 { 629 RpcConnection_np *npc = (RpcConnection_np *)conn; 630 BOOL ret; 631 632 TRACE("(%p)\n", conn); 633 634 if (conn->AuthInfo && SecIsValidHandle(&conn->ctx)) 635 return RPCRT4_default_impersonate_client(conn); 636 637 ret = ImpersonateNamedPipeClient(npc->pipe); 638 if (!ret) 639 { 640 DWORD error = GetLastError(); 641 WARN("ImpersonateNamedPipeClient failed with error %u\n", error); 642 switch (error) 643 { 644 case ERROR_CANNOT_IMPERSONATE: 645 return RPC_S_NO_CONTEXT_AVAILABLE; 646 } 647 } 648 return RPC_S_OK; 649 } 650 651 static RPC_STATUS rpcrt4_conn_np_revert_to_self(RpcConnection *conn) 652 { 653 BOOL ret; 654 655 TRACE("(%p)\n", conn); 656 657 if (conn->AuthInfo && SecIsValidHandle(&conn->ctx)) 658 return RPCRT4_default_revert_to_self(conn); 659 660 ret = RevertToSelf(); 661 if (!ret) 662 { 663 WARN("RevertToSelf failed with error %u\n", GetLastError()); 664 return RPC_S_NO_CONTEXT_AVAILABLE; 665 } 666 return RPC_S_OK; 667 } 668 669 typedef struct _RpcServerProtseq_np 670 { 671 RpcServerProtseq common; 672 HANDLE mgr_event; 673 } RpcServerProtseq_np; 674 675 static RpcServerProtseq *rpcrt4_protseq_np_alloc(void) 676 { 677 RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ps)); 678 if (ps) 679 ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL); 680 return &ps->common; 681 } 682 683 static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq) 684 { 685 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); 686 SetEvent(npps->mgr_event); 687 } 688 689 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) 690 { 691 HANDLE *objs = prev_array; 692 RpcConnection_np *conn; 693 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); 694 695 EnterCriticalSection(&protseq->cs); 696 697 /* open and count connections */ 698 *count = 1; 699 LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry) 700 { 701 if (!conn->pipe && rpcrt4_conn_create_pipe(&conn->common) != RPC_S_OK) 702 continue; 703 if (!conn->listen_event) 704 { 705 NTSTATUS status; 706 HANDLE event; 707 708 event = get_np_event(conn); 709 if (!event) 710 continue; 711 712 status = NtFsControlFile(conn->pipe, event, NULL, NULL, &conn->io_status, FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0); 713 switch (status) 714 { 715 case STATUS_SUCCESS: 716 case STATUS_PIPE_CONNECTED: 717 conn->io_status.u.Status = status; 718 SetEvent(event); 719 break; 720 case STATUS_PENDING: 721 break; 722 default: 723 ERR("pipe listen error %x\n", status); 724 continue; 725 } 726 727 conn->listen_event = event; 728 } 729 (*count)++; 730 } 731 732 /* make array of connections */ 733 if (objs) 734 objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE)); 735 else 736 objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE)); 737 if (!objs) 738 { 739 ERR("couldn't allocate objs\n"); 740 LeaveCriticalSection(&protseq->cs); 741 return NULL; 742 } 743 744 objs[0] = npps->mgr_event; 745 *count = 1; 746 LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry) 747 { 748 if (conn->listen_event) 749 objs[(*count)++] = conn->listen_event; 750 } 751 LeaveCriticalSection(&protseq->cs); 752 return objs; 753 } 754 755 static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array) 756 { 757 HeapFree(GetProcessHeap(), 0, array); 758 } 759 760 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) 761 { 762 HANDLE b_handle; 763 HANDLE *objs = wait_array; 764 DWORD res; 765 RpcConnection *cconn = NULL; 766 RpcConnection_np *conn; 767 768 if (!objs) 769 return -1; 770 771 do 772 { 773 /* an alertable wait isn't strictly necessary, but due to our 774 * overlapped I/O implementation in Wine we need to free some memory 775 * by the file user APC being called, even if no completion routine was 776 * specified at the time of starting the async operation */ 777 res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE); 778 } while (res == WAIT_IO_COMPLETION); 779 780 if (res == WAIT_OBJECT_0) 781 return 0; 782 else if (res == WAIT_FAILED) 783 { 784 ERR("wait failed with error %d\n", GetLastError()); 785 return -1; 786 } 787 else 788 { 789 b_handle = objs[res - WAIT_OBJECT_0]; 790 /* find which connection got a RPC */ 791 EnterCriticalSection(&protseq->cs); 792 LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry) 793 { 794 if (b_handle == conn->listen_event) 795 { 796 release_np_event(conn, conn->listen_event); 797 conn->listen_event = NULL; 798 if (conn->io_status.u.Status == STATUS_SUCCESS || conn->io_status.u.Status == STATUS_PIPE_CONNECTED) 799 cconn = rpcrt4_spawn_connection(&conn->common); 800 else 801 ERR("listen failed %x\n", conn->io_status.u.Status); 802 break; 803 } 804 } 805 LeaveCriticalSection(&protseq->cs); 806 if (!cconn) 807 { 808 ERR("failed to locate connection for handle %p\n", b_handle); 809 return -1; 810 } 811 RPCRT4_new_client(cconn); 812 return 1; 813 } 814 } 815 816 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data, 817 const char *networkaddr, 818 const char *endpoint) 819 { 820 twr_empty_floor_t *pipe_floor; 821 size_t size; 822 size_t endpoint_size; 823 824 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); 825 826 endpoint_size = strlen(endpoint) + 1; 827 size = sizeof(*pipe_floor) + endpoint_size; 828 829 if (!tower_data) 830 return size; 831 832 pipe_floor = (twr_empty_floor_t *)tower_data; 833 834 tower_data += sizeof(*pipe_floor); 835 836 pipe_floor->count_lhs = sizeof(pipe_floor->protid); 837 pipe_floor->protid = EPM_PROTOCOL_PIPE; 838 pipe_floor->count_rhs = endpoint_size; 839 840 memcpy(tower_data, endpoint, endpoint_size); 841 842 return size; 843 } 844 845 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data, 846 size_t tower_size, 847 char **networkaddr, 848 char **endpoint) 849 { 850 const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data; 851 852 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); 853 854 if (tower_size < sizeof(*pipe_floor)) 855 return EPT_S_NOT_REGISTERED; 856 857 tower_data += sizeof(*pipe_floor); 858 tower_size -= sizeof(*pipe_floor); 859 860 if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) || 861 (pipe_floor->protid != EPM_PROTOCOL_PIPE) || 862 (pipe_floor->count_rhs > tower_size) || 863 (tower_data[pipe_floor->count_rhs - 1] != '\0')) 864 return EPT_S_NOT_REGISTERED; 865 866 if (networkaddr) 867 *networkaddr = NULL; 868 869 if (endpoint) 870 { 871 *endpoint = I_RpcAllocate(pipe_floor->count_rhs); 872 if (!*endpoint) 873 return RPC_S_OUT_OF_RESOURCES; 874 memcpy(*endpoint, tower_data, pipe_floor->count_rhs); 875 } 876 877 return RPC_S_OK; 878 } 879 880 static BOOL rpcrt4_ncalrpc_is_authorized(RpcConnection *conn) 881 { 882 return FALSE; 883 } 884 885 static RPC_STATUS rpcrt4_ncalrpc_authorize(RpcConnection *conn, BOOL first_time, 886 unsigned char *in_buffer, 887 unsigned int in_size, 888 unsigned char *out_buffer, 889 unsigned int *out_size) 890 { 891 /* since this protocol is local to the machine there is no need to 892 * authenticate the caller */ 893 *out_size = 0; 894 return RPC_S_OK; 895 } 896 897 static RPC_STATUS rpcrt4_ncalrpc_secure_packet(RpcConnection *conn, 898 enum secure_packet_direction dir, 899 RpcPktHdr *hdr, unsigned int hdr_size, 900 unsigned char *stub_data, unsigned int stub_data_size, 901 RpcAuthVerifier *auth_hdr, 902 unsigned char *auth_value, unsigned int auth_value_size) 903 { 904 /* since this protocol is local to the machine there is no need to secure 905 * the packet */ 906 return RPC_S_OK; 907 } 908 909 static RPC_STATUS rpcrt4_ncalrpc_inquire_auth_client( 910 RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name, 911 ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags) 912 { 913 TRACE("(%p, %p, %p, %p, %p, %p, 0x%x)\n", conn, privs, 914 server_princ_name, authn_level, authn_svc, authz_svc, flags); 915 916 if (privs) 917 { 918 FIXME("privs not implemented\n"); 919 *privs = NULL; 920 } 921 if (server_princ_name) 922 { 923 FIXME("server_princ_name not implemented\n"); 924 *server_princ_name = NULL; 925 } 926 if (authn_level) *authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY; 927 if (authn_svc) *authn_svc = RPC_C_AUTHN_WINNT; 928 if (authz_svc) 929 { 930 FIXME("authorization service not implemented\n"); 931 *authz_svc = RPC_C_AUTHZ_NONE; 932 } 933 if (flags) 934 FIXME("flags 0x%x not implemented\n", flags); 935 936 return RPC_S_OK; 937 } 938 939 /**** ncacn_ip_tcp support ****/ 940 941 static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data, 942 const char *networkaddr, 943 unsigned char tcp_protid, 944 const char *endpoint) 945 { 946 twr_tcp_floor_t *tcp_floor; 947 twr_ipv4_floor_t *ipv4_floor; 948 struct addrinfo *ai; 949 struct addrinfo hints; 950 int ret; 951 size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor); 952 953 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); 954 955 if (!tower_data) 956 return size; 957 958 tcp_floor = (twr_tcp_floor_t *)tower_data; 959 tower_data += sizeof(*tcp_floor); 960 961 ipv4_floor = (twr_ipv4_floor_t *)tower_data; 962 963 tcp_floor->count_lhs = sizeof(tcp_floor->protid); 964 tcp_floor->protid = tcp_protid; 965 tcp_floor->count_rhs = sizeof(tcp_floor->port); 966 967 ipv4_floor->count_lhs = sizeof(ipv4_floor->protid); 968 ipv4_floor->protid = EPM_PROTOCOL_IP; 969 ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr); 970 971 hints.ai_flags = AI_NUMERICHOST; 972 /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */ 973 hints.ai_family = PF_INET; 974 hints.ai_socktype = SOCK_STREAM; 975 hints.ai_protocol = IPPROTO_TCP; 976 hints.ai_addrlen = 0; 977 hints.ai_addr = NULL; 978 hints.ai_canonname = NULL; 979 hints.ai_next = NULL; 980 981 ret = getaddrinfo(networkaddr, endpoint, &hints, &ai); 982 if (ret) 983 { 984 ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai); 985 if (ret) 986 { 987 ERR("getaddrinfo failed: %s\n", gai_strerror(ret)); 988 return 0; 989 } 990 } 991 992 if (ai->ai_family == PF_INET) 993 { 994 const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr; 995 tcp_floor->port = sin->sin_port; 996 ipv4_floor->ipv4addr = sin->sin_addr.s_addr; 997 } 998 else 999 { 1000 ERR("unexpected protocol family %d\n", ai->ai_family); 1001 freeaddrinfo(ai); 1002 return 0; 1003 } 1004 1005 freeaddrinfo(ai); 1006 1007 return size; 1008 } 1009 1010 static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, 1011 size_t tower_size, 1012 char **networkaddr, 1013 unsigned char tcp_protid, 1014 char **endpoint) 1015 { 1016 const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data; 1017 const twr_ipv4_floor_t *ipv4_floor; 1018 struct in_addr in_addr; 1019 1020 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); 1021 1022 if (tower_size < sizeof(*tcp_floor)) 1023 return EPT_S_NOT_REGISTERED; 1024 1025 tower_data += sizeof(*tcp_floor); 1026 tower_size -= sizeof(*tcp_floor); 1027 1028 if (tower_size < sizeof(*ipv4_floor)) 1029 return EPT_S_NOT_REGISTERED; 1030 1031 ipv4_floor = (const twr_ipv4_floor_t *)tower_data; 1032 1033 if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) || 1034 (tcp_floor->protid != tcp_protid) || 1035 (tcp_floor->count_rhs != sizeof(tcp_floor->port)) || 1036 (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) || 1037 (ipv4_floor->protid != EPM_PROTOCOL_IP) || 1038 (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr))) 1039 return EPT_S_NOT_REGISTERED; 1040 1041 if (endpoint) 1042 { 1043 *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */); 1044 if (!*endpoint) 1045 return RPC_S_OUT_OF_RESOURCES; 1046 sprintf(*endpoint, "%u", ntohs(tcp_floor->port)); 1047 } 1048 1049 if (networkaddr) 1050 { 1051 *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN); 1052 if (!*networkaddr) 1053 { 1054 if (endpoint) 1055 { 1056 I_RpcFree(*endpoint); 1057 *endpoint = NULL; 1058 } 1059 return RPC_S_OUT_OF_RESOURCES; 1060 } 1061 in_addr.s_addr = ipv4_floor->ipv4addr; 1062 if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN)) 1063 { 1064 ERR("inet_ntop: %u\n", WSAGetLastError()); 1065 I_RpcFree(*networkaddr); 1066 *networkaddr = NULL; 1067 if (endpoint) 1068 { 1069 I_RpcFree(*endpoint); 1070 *endpoint = NULL; 1071 } 1072 return EPT_S_NOT_REGISTERED; 1073 } 1074 } 1075 1076 return RPC_S_OK; 1077 } 1078 1079 typedef struct _RpcConnection_tcp 1080 { 1081 RpcConnection common; 1082 int sock; 1083 HANDLE sock_event; 1084 HANDLE cancel_event; 1085 } RpcConnection_tcp; 1086 1087 static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc) 1088 { 1089 static BOOL wsa_inited; 1090 if (!wsa_inited) 1091 { 1092 WSADATA wsadata; 1093 WSAStartup(MAKEWORD(2, 2), &wsadata); 1094 /* Note: WSAStartup can be called more than once so we don't bother with 1095 * making accesses to wsa_inited thread-safe */ 1096 wsa_inited = TRUE; 1097 } 1098 tcpc->sock_event = CreateEventW(NULL, FALSE, FALSE, NULL); 1099 tcpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL); 1100 if (!tcpc->sock_event || !tcpc->cancel_event) 1101 { 1102 ERR("event creation failed\n"); 1103 if (tcpc->sock_event) CloseHandle(tcpc->sock_event); 1104 return FALSE; 1105 } 1106 return TRUE; 1107 } 1108 1109 static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc) 1110 { 1111 HANDLE wait_handles[2]; 1112 DWORD res; 1113 if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR) 1114 { 1115 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError()); 1116 return FALSE; 1117 } 1118 wait_handles[0] = tcpc->sock_event; 1119 wait_handles[1] = tcpc->cancel_event; 1120 res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE); 1121 switch (res) 1122 { 1123 case WAIT_OBJECT_0: 1124 return TRUE; 1125 case WAIT_OBJECT_0 + 1: 1126 return FALSE; 1127 default: 1128 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError()); 1129 return FALSE; 1130 } 1131 } 1132 1133 static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc) 1134 { 1135 DWORD res; 1136 if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR) 1137 { 1138 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError()); 1139 return FALSE; 1140 } 1141 res = WaitForSingleObject(tcpc->sock_event, INFINITE); 1142 switch (res) 1143 { 1144 case WAIT_OBJECT_0: 1145 return TRUE; 1146 default: 1147 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError()); 1148 return FALSE; 1149 } 1150 } 1151 1152 static RpcConnection *rpcrt4_conn_tcp_alloc(void) 1153 { 1154 RpcConnection_tcp *tcpc; 1155 tcpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcConnection_tcp)); 1156 if (tcpc == NULL) 1157 return NULL; 1158 tcpc->sock = -1; 1159 if (!rpcrt4_sock_wait_init(tcpc)) 1160 { 1161 HeapFree(GetProcessHeap(), 0, tcpc); 1162 return NULL; 1163 } 1164 return &tcpc->common; 1165 } 1166 1167 static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection) 1168 { 1169 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 1170 int sock; 1171 int ret; 1172 struct addrinfo *ai; 1173 struct addrinfo *ai_cur; 1174 struct addrinfo hints; 1175 1176 TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); 1177 1178 if (tcpc->sock != -1) 1179 return RPC_S_OK; 1180 1181 hints.ai_flags = 0; 1182 hints.ai_family = PF_UNSPEC; 1183 hints.ai_socktype = SOCK_STREAM; 1184 hints.ai_protocol = IPPROTO_TCP; 1185 hints.ai_addrlen = 0; 1186 hints.ai_addr = NULL; 1187 hints.ai_canonname = NULL; 1188 hints.ai_next = NULL; 1189 1190 ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai); 1191 if (ret) 1192 { 1193 ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr, 1194 Connection->Endpoint, gai_strerror(ret)); 1195 return RPC_S_SERVER_UNAVAILABLE; 1196 } 1197 1198 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) 1199 { 1200 int val; 1201 u_long nonblocking; 1202 1203 if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6) 1204 { 1205 TRACE("skipping non-IP/IPv6 address family\n"); 1206 continue; 1207 } 1208 1209 if (TRACE_ON(rpc)) 1210 { 1211 char host[256]; 1212 char service[256]; 1213 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, 1214 host, sizeof(host), service, sizeof(service), 1215 NI_NUMERICHOST | NI_NUMERICSERV); 1216 TRACE("trying %s:%s\n", host, service); 1217 } 1218 1219 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); 1220 if (sock == -1) 1221 { 1222 WARN("socket() failed: %u\n", WSAGetLastError()); 1223 continue; 1224 } 1225 1226 if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen)) 1227 { 1228 WARN("connect() failed: %u\n", WSAGetLastError()); 1229 closesocket(sock); 1230 continue; 1231 } 1232 1233 /* RPC depends on having minimal latency so disable the Nagle algorithm */ 1234 val = 1; 1235 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); 1236 nonblocking = 1; 1237 ioctlsocket(sock, FIONBIO, &nonblocking); 1238 1239 tcpc->sock = sock; 1240 1241 freeaddrinfo(ai); 1242 TRACE("connected\n"); 1243 return RPC_S_OK; 1244 } 1245 1246 freeaddrinfo(ai); 1247 ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint); 1248 return RPC_S_SERVER_UNAVAILABLE; 1249 } 1250 1251 static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, const char *endpoint) 1252 { 1253 RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT; 1254 int sock; 1255 int ret; 1256 struct addrinfo *ai; 1257 struct addrinfo *ai_cur; 1258 struct addrinfo hints; 1259 1260 TRACE("(%p, %s)\n", protseq, endpoint); 1261 1262 hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */; 1263 hints.ai_family = PF_UNSPEC; 1264 hints.ai_socktype = SOCK_STREAM; 1265 hints.ai_protocol = IPPROTO_TCP; 1266 hints.ai_addrlen = 0; 1267 hints.ai_addr = NULL; 1268 hints.ai_canonname = NULL; 1269 hints.ai_next = NULL; 1270 1271 ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai); 1272 if (ret) 1273 { 1274 ERR("getaddrinfo for port %s failed: %s\n", endpoint, 1275 gai_strerror(ret)); 1276 if ((ret == EAI_SERVICE) || (ret == EAI_NONAME)) 1277 return RPC_S_INVALID_ENDPOINT_FORMAT; 1278 return RPC_S_CANT_CREATE_ENDPOINT; 1279 } 1280 1281 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) 1282 { 1283 RpcConnection_tcp *tcpc; 1284 RPC_STATUS create_status; 1285 struct sockaddr_storage sa; 1286 socklen_t sa_len; 1287 char service[NI_MAXSERV]; 1288 u_long nonblocking; 1289 1290 if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6) 1291 { 1292 TRACE("skipping non-IP/IPv6 address family\n"); 1293 continue; 1294 } 1295 1296 if (TRACE_ON(rpc)) 1297 { 1298 char host[256]; 1299 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, 1300 host, sizeof(host), service, sizeof(service), 1301 NI_NUMERICHOST | NI_NUMERICSERV); 1302 TRACE("trying %s:%s\n", host, service); 1303 } 1304 1305 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); 1306 if (sock == -1) 1307 { 1308 WARN("socket() failed: %u\n", WSAGetLastError()); 1309 status = RPC_S_CANT_CREATE_ENDPOINT; 1310 continue; 1311 } 1312 1313 ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen); 1314 if (ret < 0) 1315 { 1316 WARN("bind failed: %u\n", WSAGetLastError()); 1317 closesocket(sock); 1318 if (WSAGetLastError() == WSAEADDRINUSE) 1319 status = RPC_S_DUPLICATE_ENDPOINT; 1320 else 1321 status = RPC_S_CANT_CREATE_ENDPOINT; 1322 continue; 1323 } 1324 1325 sa_len = sizeof(sa); 1326 if (getsockname(sock, (struct sockaddr *)&sa, &sa_len)) 1327 { 1328 WARN("getsockname() failed: %u\n", WSAGetLastError()); 1329 closesocket(sock); 1330 status = RPC_S_CANT_CREATE_ENDPOINT; 1331 continue; 1332 } 1333 1334 ret = getnameinfo((struct sockaddr *)&sa, sa_len, 1335 NULL, 0, service, sizeof(service), 1336 NI_NUMERICSERV); 1337 if (ret) 1338 { 1339 WARN("getnameinfo failed: %s\n", gai_strerror(ret)); 1340 closesocket(sock); 1341 status = RPC_S_CANT_CREATE_ENDPOINT; 1342 continue; 1343 } 1344 1345 create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE, 1346 protseq->Protseq, NULL, 1347 service, NULL, NULL, NULL, NULL); 1348 if (create_status != RPC_S_OK) 1349 { 1350 closesocket(sock); 1351 status = create_status; 1352 continue; 1353 } 1354 1355 tcpc->sock = sock; 1356 ret = listen(sock, protseq->MaxCalls); 1357 if (ret < 0) 1358 { 1359 WARN("listen failed: %u\n", WSAGetLastError()); 1360 RPCRT4_ReleaseConnection(&tcpc->common); 1361 status = RPC_S_OUT_OF_RESOURCES; 1362 continue; 1363 } 1364 /* need a non-blocking socket, otherwise accept() has a potential 1365 * race-condition (poll() says it is readable, connection drops, 1366 * and accept() blocks until the next connection comes...) 1367 */ 1368 nonblocking = 1; 1369 ret = ioctlsocket(sock, FIONBIO, &nonblocking); 1370 if (ret < 0) 1371 { 1372 WARN("couldn't make socket non-blocking, error %d\n", ret); 1373 RPCRT4_ReleaseConnection(&tcpc->common); 1374 status = RPC_S_OUT_OF_RESOURCES; 1375 continue; 1376 } 1377 1378 EnterCriticalSection(&protseq->cs); 1379 list_add_tail(&protseq->listeners, &tcpc->common.protseq_entry); 1380 tcpc->common.protseq = protseq; 1381 LeaveCriticalSection(&protseq->cs); 1382 1383 freeaddrinfo(ai); 1384 1385 /* since IPv4 and IPv6 share the same port space, we only need one 1386 * successful bind to listen for both */ 1387 TRACE("listening on %s\n", endpoint); 1388 return RPC_S_OK; 1389 } 1390 1391 freeaddrinfo(ai); 1392 ERR("couldn't listen on port %s\n", endpoint); 1393 return status; 1394 } 1395 1396 static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn) 1397 { 1398 int ret; 1399 struct sockaddr_in address; 1400 socklen_t addrsize; 1401 RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn; 1402 RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn; 1403 u_long nonblocking; 1404 1405 addrsize = sizeof(address); 1406 ret = accept(server->sock, (struct sockaddr*) &address, &addrsize); 1407 if (ret < 0) 1408 { 1409 ERR("Failed to accept a TCP connection: error %d\n", ret); 1410 return RPC_S_OUT_OF_RESOURCES; 1411 } 1412 1413 nonblocking = 1; 1414 ioctlsocket(ret, FIONBIO, &nonblocking); 1415 client->sock = ret; 1416 1417 client->common.NetworkAddr = HeapAlloc(GetProcessHeap(), 0, INET6_ADDRSTRLEN); 1418 ret = getnameinfo((struct sockaddr*)&address, addrsize, client->common.NetworkAddr, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); 1419 if (ret != 0) 1420 { 1421 ERR("Failed to retrieve the IP address, error %d\n", ret); 1422 return RPC_S_OUT_OF_RESOURCES; 1423 } 1424 1425 TRACE("Accepted a new TCP connection from %s\n", client->common.NetworkAddr); 1426 return RPC_S_OK; 1427 } 1428 1429 static int rpcrt4_conn_tcp_read(RpcConnection *Connection, 1430 void *buffer, unsigned int count) 1431 { 1432 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 1433 int bytes_read = 0; 1434 while (bytes_read != count) 1435 { 1436 int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0); 1437 if (!r) 1438 return -1; 1439 else if (r > 0) 1440 bytes_read += r; 1441 else if (WSAGetLastError() == WSAEINTR) 1442 continue; 1443 else if (WSAGetLastError() != WSAEWOULDBLOCK) 1444 { 1445 WARN("recv() failed: %u\n", WSAGetLastError()); 1446 return -1; 1447 } 1448 else 1449 { 1450 if (!rpcrt4_sock_wait_for_recv(tcpc)) 1451 return -1; 1452 } 1453 } 1454 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read); 1455 return bytes_read; 1456 } 1457 1458 static int rpcrt4_conn_tcp_write(RpcConnection *Connection, 1459 const void *buffer, unsigned int count) 1460 { 1461 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 1462 int bytes_written = 0; 1463 while (bytes_written != count) 1464 { 1465 int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0); 1466 if (r >= 0) 1467 bytes_written += r; 1468 else if (WSAGetLastError() == WSAEINTR) 1469 continue; 1470 else if (WSAGetLastError() != WSAEWOULDBLOCK) 1471 return -1; 1472 else 1473 { 1474 if (!rpcrt4_sock_wait_for_send(tcpc)) 1475 return -1; 1476 } 1477 } 1478 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written); 1479 return bytes_written; 1480 } 1481 1482 static int rpcrt4_conn_tcp_close(RpcConnection *conn) 1483 { 1484 RpcConnection_tcp *connection = (RpcConnection_tcp *) conn; 1485 1486 TRACE("%d\n", connection->sock); 1487 1488 if (connection->sock != -1) 1489 closesocket(connection->sock); 1490 connection->sock = -1; 1491 CloseHandle(connection->sock_event); 1492 CloseHandle(connection->cancel_event); 1493 return 0; 1494 } 1495 1496 static void rpcrt4_conn_tcp_close_read(RpcConnection *conn) 1497 { 1498 RpcConnection_tcp *connection = (RpcConnection_tcp *) conn; 1499 shutdown(connection->sock, SD_RECEIVE); 1500 } 1501 1502 static void rpcrt4_conn_tcp_cancel_call(RpcConnection *conn) 1503 { 1504 RpcConnection_tcp *connection = (RpcConnection_tcp *) conn; 1505 1506 TRACE("%p\n", connection); 1507 1508 SetEvent(connection->cancel_event); 1509 } 1510 1511 static RPC_STATUS rpcrt4_conn_tcp_is_server_listening(const char *endpoint) 1512 { 1513 FIXME("\n"); 1514 return RPC_S_ACCESS_DENIED; 1515 } 1516 1517 static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection) 1518 { 1519 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 1520 1521 TRACE("%p\n", Connection); 1522 1523 if (!rpcrt4_sock_wait_for_recv(tcpc)) 1524 return -1; 1525 return 0; 1526 } 1527 1528 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data, 1529 const char *networkaddr, 1530 const char *endpoint) 1531 { 1532 return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr, 1533 EPM_PROTOCOL_TCP, endpoint); 1534 } 1535 1536 typedef struct _RpcServerProtseq_sock 1537 { 1538 RpcServerProtseq common; 1539 HANDLE mgr_event; 1540 } RpcServerProtseq_sock; 1541 1542 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void) 1543 { 1544 RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ps)); 1545 if (ps) 1546 { 1547 static BOOL wsa_inited; 1548 if (!wsa_inited) 1549 { 1550 WSADATA wsadata; 1551 WSAStartup(MAKEWORD(2, 2), &wsadata); 1552 /* Note: WSAStartup can be called more than once so we don't bother with 1553 * making accesses to wsa_inited thread-safe */ 1554 wsa_inited = TRUE; 1555 } 1556 ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL); 1557 } 1558 return &ps->common; 1559 } 1560 1561 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq) 1562 { 1563 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); 1564 SetEvent(sockps->mgr_event); 1565 } 1566 1567 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) 1568 { 1569 HANDLE *objs = prev_array; 1570 RpcConnection_tcp *conn; 1571 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); 1572 1573 EnterCriticalSection(&protseq->cs); 1574 1575 /* open and count connections */ 1576 *count = 1; 1577 LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_tcp, common.protseq_entry) 1578 { 1579 if (conn->sock != -1) 1580 (*count)++; 1581 } 1582 1583 /* make array of connections */ 1584 if (objs) 1585 objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE)); 1586 else 1587 objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE)); 1588 if (!objs) 1589 { 1590 ERR("couldn't allocate objs\n"); 1591 LeaveCriticalSection(&protseq->cs); 1592 return NULL; 1593 } 1594 1595 objs[0] = sockps->mgr_event; 1596 *count = 1; 1597 LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_tcp, common.protseq_entry) 1598 { 1599 if (conn->sock != -1) 1600 { 1601 int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT); 1602 if (res == SOCKET_ERROR) 1603 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError()); 1604 else 1605 { 1606 objs[*count] = conn->sock_event; 1607 (*count)++; 1608 } 1609 } 1610 } 1611 LeaveCriticalSection(&protseq->cs); 1612 return objs; 1613 } 1614 1615 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array) 1616 { 1617 HeapFree(GetProcessHeap(), 0, array); 1618 } 1619 1620 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) 1621 { 1622 HANDLE b_handle; 1623 HANDLE *objs = wait_array; 1624 DWORD res; 1625 RpcConnection *cconn = NULL; 1626 RpcConnection_tcp *conn; 1627 1628 if (!objs) 1629 return -1; 1630 1631 do 1632 { 1633 /* an alertable wait isn't strictly necessary, but due to our 1634 * overlapped I/O implementation in Wine we need to free some memory 1635 * by the file user APC being called, even if no completion routine was 1636 * specified at the time of starting the async operation */ 1637 res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE); 1638 } while (res == WAIT_IO_COMPLETION); 1639 1640 if (res == WAIT_OBJECT_0) 1641 return 0; 1642 if (res == WAIT_FAILED) 1643 { 1644 ERR("wait failed with error %d\n", GetLastError()); 1645 return -1; 1646 } 1647 1648 b_handle = objs[res - WAIT_OBJECT_0]; 1649 1650 /* find which connection got a RPC */ 1651 EnterCriticalSection(&protseq->cs); 1652 LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_tcp, common.protseq_entry) 1653 { 1654 if (b_handle == conn->sock_event) 1655 { 1656 cconn = rpcrt4_spawn_connection(&conn->common); 1657 break; 1658 } 1659 } 1660 LeaveCriticalSection(&protseq->cs); 1661 if (!cconn) 1662 { 1663 ERR("failed to locate connection for handle %p\n", b_handle); 1664 return -1; 1665 } 1666 1667 RPCRT4_new_client(cconn); 1668 return 1; 1669 } 1670 1671 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, 1672 size_t tower_size, 1673 char **networkaddr, 1674 char **endpoint) 1675 { 1676 return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size, 1677 networkaddr, EPM_PROTOCOL_TCP, 1678 endpoint); 1679 } 1680 1681 /**** ncacn_http support ****/ 1682 1683 /* 60 seconds is the period native uses */ 1684 #define HTTP_IDLE_TIME 60000 1685 1686 /* reference counted to avoid a race between a cancelled call's connection 1687 * being destroyed and the asynchronous InternetReadFileEx call being 1688 * completed */ 1689 typedef struct _RpcHttpAsyncData 1690 { 1691 LONG refs; 1692 HANDLE completion_event; 1693 WORD async_result; 1694 INTERNET_BUFFERSW inet_buffers; 1695 CRITICAL_SECTION cs; 1696 } RpcHttpAsyncData; 1697 1698 static ULONG RpcHttpAsyncData_AddRef(RpcHttpAsyncData *data) 1699 { 1700 return InterlockedIncrement(&data->refs); 1701 } 1702 1703 static ULONG RpcHttpAsyncData_Release(RpcHttpAsyncData *data) 1704 { 1705 ULONG refs = InterlockedDecrement(&data->refs); 1706 if (!refs) 1707 { 1708 TRACE("destroying async data %p\n", data); 1709 CloseHandle(data->completion_event); 1710 HeapFree(GetProcessHeap(), 0, data->inet_buffers.lpvBuffer); 1711 data->cs.DebugInfo->Spare[0] = 0; 1712 DeleteCriticalSection(&data->cs); 1713 HeapFree(GetProcessHeap(), 0, data); 1714 } 1715 return refs; 1716 } 1717 1718 static void prepare_async_request(RpcHttpAsyncData *async_data) 1719 { 1720 ResetEvent(async_data->completion_event); 1721 RpcHttpAsyncData_AddRef(async_data); 1722 } 1723 1724 static RPC_STATUS wait_async_request(RpcHttpAsyncData *async_data, BOOL call_ret, HANDLE cancel_event) 1725 { 1726 HANDLE handles[2] = { async_data->completion_event, cancel_event }; 1727 DWORD res; 1728 1729 if(call_ret) { 1730 RpcHttpAsyncData_Release(async_data); 1731 return RPC_S_OK; 1732 } 1733 1734 if(GetLastError() != ERROR_IO_PENDING) { 1735 RpcHttpAsyncData_Release(async_data); 1736 ERR("Request failed with error %d\n", GetLastError()); 1737 return RPC_S_SERVER_UNAVAILABLE; 1738 } 1739 1740 res = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT); 1741 if(res != WAIT_OBJECT_0) { 1742 TRACE("Cancelled\n"); 1743 return RPC_S_CALL_CANCELLED; 1744 } 1745 1746 if(async_data->async_result) { 1747 ERR("Async request failed with error %d\n", async_data->async_result); 1748 return RPC_S_SERVER_UNAVAILABLE; 1749 } 1750 1751 return RPC_S_OK; 1752 } 1753 1754 struct authinfo 1755 { 1756 DWORD scheme; 1757 CredHandle cred; 1758 CtxtHandle ctx; 1759 TimeStamp exp; 1760 ULONG attr; 1761 ULONG max_token; 1762 char *data; 1763 unsigned int data_len; 1764 BOOL finished; /* finished authenticating */ 1765 }; 1766 1767 typedef struct _RpcConnection_http 1768 { 1769 RpcConnection common; 1770 HINTERNET app_info; 1771 HINTERNET session; 1772 HINTERNET in_request; 1773 HINTERNET out_request; 1774 WCHAR *servername; 1775 HANDLE timer_cancelled; 1776 HANDLE cancel_event; 1777 DWORD last_sent_time; 1778 ULONG bytes_received; 1779 ULONG flow_control_mark; /* send a control packet to the server when this many bytes received */ 1780 ULONG flow_control_increment; /* number of bytes to increment flow_control_mark by */ 1781 UUID connection_uuid; 1782 UUID in_pipe_uuid; 1783 UUID out_pipe_uuid; 1784 RpcHttpAsyncData *async_data; 1785 } RpcConnection_http; 1786 1787 static RpcConnection *rpcrt4_ncacn_http_alloc(void) 1788 { 1789 RpcConnection_http *httpc; 1790 httpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*httpc)); 1791 if (!httpc) return NULL; 1792 httpc->async_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcHttpAsyncData)); 1793 if (!httpc->async_data) 1794 { 1795 HeapFree(GetProcessHeap(), 0, httpc); 1796 return NULL; 1797 } 1798 TRACE("async data = %p\n", httpc->async_data); 1799 httpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL); 1800 httpc->async_data->refs = 1; 1801 httpc->async_data->inet_buffers.dwStructSize = sizeof(INTERNET_BUFFERSW); 1802 InitializeCriticalSection(&httpc->async_data->cs); 1803 httpc->async_data->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RpcHttpAsyncData.cs"); 1804 return &httpc->common; 1805 } 1806 1807 typedef struct _HttpTimerThreadData 1808 { 1809 PVOID timer_param; 1810 DWORD *last_sent_time; 1811 HANDLE timer_cancelled; 1812 } HttpTimerThreadData; 1813 1814 static VOID rpcrt4_http_keep_connection_active_timer_proc(PVOID param, BOOLEAN dummy) 1815 { 1816 HINTERNET in_request = param; 1817 RpcPktHdr *idle_pkt; 1818 1819 idle_pkt = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x0001, 1820 0, 0); 1821 if (idle_pkt) 1822 { 1823 DWORD bytes_written; 1824 InternetWriteFile(in_request, idle_pkt, idle_pkt->common.frag_len, &bytes_written); 1825 RPCRT4_FreeHeader(idle_pkt); 1826 } 1827 } 1828 1829 static inline DWORD rpcrt4_http_timer_calc_timeout(DWORD *last_sent_time) 1830 { 1831 DWORD cur_time = GetTickCount(); 1832 DWORD cached_last_sent_time = *last_sent_time; 1833 return HTTP_IDLE_TIME - (cur_time - cached_last_sent_time > HTTP_IDLE_TIME ? 0 : cur_time - cached_last_sent_time); 1834 } 1835 1836 static DWORD CALLBACK rpcrt4_http_timer_thread(PVOID param) 1837 { 1838 HttpTimerThreadData *data_in = param; 1839 HttpTimerThreadData data; 1840 DWORD timeout; 1841 1842 data = *data_in; 1843 HeapFree(GetProcessHeap(), 0, data_in); 1844 1845 for (timeout = HTTP_IDLE_TIME; 1846 WaitForSingleObject(data.timer_cancelled, timeout) == WAIT_TIMEOUT; 1847 timeout = rpcrt4_http_timer_calc_timeout(data.last_sent_time)) 1848 { 1849 /* are we too soon after last send? */ 1850 if (GetTickCount() - *data.last_sent_time < HTTP_IDLE_TIME) 1851 continue; 1852 rpcrt4_http_keep_connection_active_timer_proc(data.timer_param, TRUE); 1853 } 1854 1855 CloseHandle(data.timer_cancelled); 1856 return 0; 1857 } 1858 1859 static VOID WINAPI rpcrt4_http_internet_callback( 1860 HINTERNET hInternet, 1861 DWORD_PTR dwContext, 1862 DWORD dwInternetStatus, 1863 LPVOID lpvStatusInformation, 1864 DWORD dwStatusInformationLength) 1865 { 1866 RpcHttpAsyncData *async_data = (RpcHttpAsyncData *)dwContext; 1867 1868 switch (dwInternetStatus) 1869 { 1870 case INTERNET_STATUS_REQUEST_COMPLETE: 1871 TRACE("INTERNET_STATUS_REQUEST_COMPLETED\n"); 1872 if (async_data) 1873 { 1874 INTERNET_ASYNC_RESULT *async_result = lpvStatusInformation; 1875 1876 async_data->async_result = async_result->dwResult ? ERROR_SUCCESS : async_result->dwError; 1877 SetEvent(async_data->completion_event); 1878 RpcHttpAsyncData_Release(async_data); 1879 } 1880 break; 1881 } 1882 } 1883 1884 static RPC_STATUS rpcrt4_http_check_response(HINTERNET hor) 1885 { 1886 BOOL ret; 1887 DWORD status_code; 1888 DWORD size; 1889 DWORD index; 1890 WCHAR buf[32]; 1891 WCHAR *status_text = buf; 1892 TRACE("\n"); 1893 1894 index = 0; 1895 size = sizeof(status_code); 1896 ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status_code, &size, &index); 1897 if (!ret) 1898 return GetLastError(); 1899 if (status_code == HTTP_STATUS_OK) 1900 return RPC_S_OK; 1901 index = 0; 1902 size = sizeof(buf); 1903 ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index); 1904 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 1905 { 1906 status_text = HeapAlloc(GetProcessHeap(), 0, size); 1907 ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index); 1908 } 1909 1910 ERR("server returned: %d %s\n", status_code, ret ? debugstr_w(status_text) : "<status text unavailable>"); 1911 if(status_text != buf) HeapFree(GetProcessHeap(), 0, status_text); 1912 1913 if (status_code == HTTP_STATUS_DENIED) 1914 return ERROR_ACCESS_DENIED; 1915 return RPC_S_SERVER_UNAVAILABLE; 1916 } 1917 1918 static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc) 1919 { 1920 static const WCHAR wszUserAgent[] = {'M','S','R','P','C',0}; 1921 LPWSTR proxy = NULL; 1922 LPWSTR user = NULL; 1923 LPWSTR password = NULL; 1924 LPWSTR servername = NULL; 1925 const WCHAR *option; 1926 INTERNET_PORT port; 1927 1928 if (httpc->common.QOS && 1929 (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)) 1930 { 1931 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_cred = httpc->common.QOS->qos->u.HttpCredentials; 1932 if (http_cred->TransportCredentials) 1933 { 1934 WCHAR *p; 1935 const SEC_WINNT_AUTH_IDENTITY_W *cred = http_cred->TransportCredentials; 1936 ULONG len = cred->DomainLength + 1 + cred->UserLength; 1937 user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 1938 if (!user) 1939 return RPC_S_OUT_OF_RESOURCES; 1940 p = user; 1941 if (cred->DomainLength) 1942 { 1943 memcpy(p, cred->Domain, cred->DomainLength * sizeof(WCHAR)); 1944 p += cred->DomainLength; 1945 *p = '\\'; 1946 p++; 1947 } 1948 memcpy(p, cred->User, cred->UserLength * sizeof(WCHAR)); 1949 p[cred->UserLength] = 0; 1950 1951 password = RPCRT4_strndupW(cred->Password, cred->PasswordLength); 1952 } 1953 } 1954 1955 for (option = httpc->common.NetworkOptions; option; 1956 option = (strchrW(option, ',') ? strchrW(option, ',')+1 : NULL)) 1957 { 1958 static const WCHAR wszRpcProxy[] = {'R','p','c','P','r','o','x','y','=',0}; 1959 static const WCHAR wszHttpProxy[] = {'H','t','t','p','P','r','o','x','y','=',0}; 1960 1961 if (!strncmpiW(option, wszRpcProxy, sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1)) 1962 { 1963 const WCHAR *value_start = option + sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1; 1964 const WCHAR *value_end; 1965 const WCHAR *p; 1966 1967 value_end = strchrW(option, ','); 1968 if (!value_end) 1969 value_end = value_start + strlenW(value_start); 1970 for (p = value_start; p < value_end; p++) 1971 if (*p == ':') 1972 { 1973 port = atoiW(p+1); 1974 value_end = p; 1975 break; 1976 } 1977 TRACE("RpcProxy value is %s\n", debugstr_wn(value_start, value_end-value_start)); 1978 servername = RPCRT4_strndupW(value_start, value_end-value_start); 1979 } 1980 else if (!strncmpiW(option, wszHttpProxy, sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1)) 1981 { 1982 const WCHAR *value_start = option + sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1; 1983 const WCHAR *value_end; 1984 1985 value_end = strchrW(option, ','); 1986 if (!value_end) 1987 value_end = value_start + strlenW(value_start); 1988 TRACE("HttpProxy value is %s\n", debugstr_wn(value_start, value_end-value_start)); 1989 proxy = RPCRT4_strndupW(value_start, value_end-value_start); 1990 } 1991 else 1992 FIXME("unhandled option %s\n", debugstr_w(option)); 1993 } 1994 1995 httpc->app_info = InternetOpenW(wszUserAgent, proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG, 1996 NULL, NULL, INTERNET_FLAG_ASYNC); 1997 if (!httpc->app_info) 1998 { 1999 HeapFree(GetProcessHeap(), 0, password); 2000 HeapFree(GetProcessHeap(), 0, user); 2001 HeapFree(GetProcessHeap(), 0, proxy); 2002 HeapFree(GetProcessHeap(), 0, servername); 2003 ERR("InternetOpenW failed with error %d\n", GetLastError()); 2004 return RPC_S_SERVER_UNAVAILABLE; 2005 } 2006 InternetSetStatusCallbackW(httpc->app_info, rpcrt4_http_internet_callback); 2007 2008 /* if no RpcProxy option specified, set the HTTP server address to the 2009 * RPC server address */ 2010 if (!servername) 2011 { 2012 servername = HeapAlloc(GetProcessHeap(), 0, (strlen(httpc->common.NetworkAddr) + 1)*sizeof(WCHAR)); 2013 if (!servername) 2014 { 2015 HeapFree(GetProcessHeap(), 0, password); 2016 HeapFree(GetProcessHeap(), 0, user); 2017 HeapFree(GetProcessHeap(), 0, proxy); 2018 return RPC_S_OUT_OF_RESOURCES; 2019 } 2020 MultiByteToWideChar(CP_ACP, 0, httpc->common.NetworkAddr, -1, servername, strlen(httpc->common.NetworkAddr) + 1); 2021 } 2022 2023 port = (httpc->common.QOS && 2024 (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) && 2025 (httpc->common.QOS->qos->u.HttpCredentials->Flags & RPC_C_HTTP_FLAG_USE_SSL)) ? 2026 INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT; 2027 2028 httpc->session = InternetConnectW(httpc->app_info, servername, port, user, password, 2029 INTERNET_SERVICE_HTTP, 0, 0); 2030 2031 HeapFree(GetProcessHeap(), 0, password); 2032 HeapFree(GetProcessHeap(), 0, user); 2033 HeapFree(GetProcessHeap(), 0, proxy); 2034 2035 if (!httpc->session) 2036 { 2037 ERR("InternetConnectW failed with error %d\n", GetLastError()); 2038 HeapFree(GetProcessHeap(), 0, servername); 2039 return RPC_S_SERVER_UNAVAILABLE; 2040 } 2041 httpc->servername = servername; 2042 return RPC_S_OK; 2043 } 2044 2045 static int rpcrt4_http_async_read(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event, 2046 void *buffer, unsigned int count) 2047 { 2048 char *buf = buffer; 2049 BOOL ret; 2050 unsigned int bytes_left = count; 2051 RPC_STATUS status = RPC_S_OK; 2052 2053 async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, count); 2054 2055 while (bytes_left) 2056 { 2057 async_data->inet_buffers.dwBufferLength = bytes_left; 2058 prepare_async_request(async_data); 2059 ret = InternetReadFileExW(req, &async_data->inet_buffers, IRF_ASYNC, 0); 2060 status = wait_async_request(async_data, ret, cancel_event); 2061 if (status != RPC_S_OK) 2062 { 2063 if (status == RPC_S_CALL_CANCELLED) 2064 TRACE("call cancelled\n"); 2065 break; 2066 } 2067 2068 if (!async_data->inet_buffers.dwBufferLength) 2069 break; 2070 memcpy(buf, async_data->inet_buffers.lpvBuffer, 2071 async_data->inet_buffers.dwBufferLength); 2072 2073 bytes_left -= async_data->inet_buffers.dwBufferLength; 2074 buf += async_data->inet_buffers.dwBufferLength; 2075 } 2076 2077 HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer); 2078 async_data->inet_buffers.lpvBuffer = NULL; 2079 2080 TRACE("%p %p %u -> %u\n", req, buffer, count, status); 2081 return status == RPC_S_OK ? count : -1; 2082 } 2083 2084 static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event) 2085 { 2086 BYTE buf[20]; 2087 BOOL ret; 2088 RPC_STATUS status; 2089 2090 TRACE("sending echo request to server\n"); 2091 2092 prepare_async_request(async_data); 2093 ret = HttpSendRequestW(req, NULL, 0, NULL, 0); 2094 status = wait_async_request(async_data, ret, cancel_event); 2095 if (status != RPC_S_OK) return status; 2096 2097 status = rpcrt4_http_check_response(req); 2098 if (status != RPC_S_OK) return status; 2099 2100 rpcrt4_http_async_read(req, async_data, cancel_event, buf, sizeof(buf)); 2101 /* FIXME: do something with retrieved data */ 2102 2103 return RPC_S_OK; 2104 } 2105 2106 static RPC_STATUS insert_content_length_header(HINTERNET request, DWORD len) 2107 { 2108 static const WCHAR fmtW[] = 2109 {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','u','\r','\n',0}; 2110 WCHAR header[sizeof(fmtW) / sizeof(fmtW[0]) + 10]; 2111 2112 sprintfW(header, fmtW, len); 2113 if ((HttpAddRequestHeadersW(request, header, -1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD))) return RPC_S_OK; 2114 return RPC_S_SERVER_UNAVAILABLE; 2115 } 2116 2117 /* prepare the in pipe for use by RPC packets */ 2118 static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data, HANDLE cancel_event, 2119 const UUID *connection_uuid, const UUID *in_pipe_uuid, 2120 const UUID *association_uuid, BOOL authorized) 2121 { 2122 BOOL ret; 2123 RPC_STATUS status; 2124 RpcPktHdr *hdr; 2125 INTERNET_BUFFERSW buffers_in; 2126 DWORD bytes_written; 2127 2128 if (!authorized) 2129 { 2130 /* ask wininet to authorize, if necessary */ 2131 status = send_echo_request(in_request, async_data, cancel_event); 2132 if (status != RPC_S_OK) return status; 2133 } 2134 memset(&buffers_in, 0, sizeof(buffers_in)); 2135 buffers_in.dwStructSize = sizeof(buffers_in); 2136 /* FIXME: get this from the registry */ 2137 buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */ 2138 status = insert_content_length_header(in_request, buffers_in.dwBufferTotal); 2139 if (status != RPC_S_OK) return status; 2140 2141 prepare_async_request(async_data); 2142 ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0); 2143 status = wait_async_request(async_data, ret, cancel_event); 2144 if (status != RPC_S_OK) return status; 2145 2146 TRACE("sending HTTP connect header to server\n"); 2147 hdr = RPCRT4_BuildHttpConnectHeader(FALSE, connection_uuid, in_pipe_uuid, association_uuid); 2148 if (!hdr) return RPC_S_OUT_OF_RESOURCES; 2149 ret = InternetWriteFile(in_request, hdr, hdr->common.frag_len, &bytes_written); 2150 RPCRT4_FreeHeader(hdr); 2151 if (!ret) 2152 { 2153 ERR("InternetWriteFile failed with error %d\n", GetLastError()); 2154 return RPC_S_SERVER_UNAVAILABLE; 2155 } 2156 2157 return RPC_S_OK; 2158 } 2159 2160 static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcHttpAsyncData *async_data, 2161 HANDLE cancel_event, RpcPktHdr *hdr, BYTE **data) 2162 { 2163 unsigned short data_len; 2164 unsigned int size; 2165 2166 if (rpcrt4_http_async_read(request, async_data, cancel_event, hdr, sizeof(hdr->common)) < 0) 2167 return RPC_S_SERVER_UNAVAILABLE; 2168 if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http)) 2169 { 2170 ERR("wrong packet type received %d or wrong frag_len %d\n", 2171 hdr->common.ptype, hdr->common.frag_len); 2172 return RPC_S_PROTOCOL_ERROR; 2173 } 2174 2175 size = sizeof(hdr->http) - sizeof(hdr->common); 2176 if (rpcrt4_http_async_read(request, async_data, cancel_event, &hdr->common + 1, size) < 0) 2177 return RPC_S_SERVER_UNAVAILABLE; 2178 2179 data_len = hdr->common.frag_len - sizeof(hdr->http); 2180 if (data_len) 2181 { 2182 *data = HeapAlloc(GetProcessHeap(), 0, data_len); 2183 if (!*data) 2184 return RPC_S_OUT_OF_RESOURCES; 2185 if (rpcrt4_http_async_read(request, async_data, cancel_event, *data, data_len) < 0) 2186 { 2187 HeapFree(GetProcessHeap(), 0, *data); 2188 return RPC_S_SERVER_UNAVAILABLE; 2189 } 2190 } 2191 else 2192 *data = NULL; 2193 2194 if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len)) 2195 { 2196 ERR("invalid http packet\n"); 2197 HeapFree(GetProcessHeap(), 0, *data); 2198 return RPC_S_PROTOCOL_ERROR; 2199 } 2200 2201 return RPC_S_OK; 2202 } 2203 2204 /* prepare the out pipe for use by RPC packets */ 2205 static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsyncData *async_data, 2206 HANDLE cancel_event, const UUID *connection_uuid, 2207 const UUID *out_pipe_uuid, ULONG *flow_control_increment, 2208 BOOL authorized) 2209 { 2210 BOOL ret; 2211 RPC_STATUS status; 2212 RpcPktHdr *hdr; 2213 BYTE *data_from_server; 2214 RpcPktHdr pkt_from_server; 2215 ULONG field1, field3; 2216 BYTE buf[20]; 2217 2218 if (!authorized) 2219 { 2220 /* ask wininet to authorize, if necessary */ 2221 status = send_echo_request(out_request, async_data, cancel_event); 2222 if (status != RPC_S_OK) return status; 2223 } 2224 else 2225 rpcrt4_http_async_read(out_request, async_data, cancel_event, buf, sizeof(buf)); 2226 2227 hdr = RPCRT4_BuildHttpConnectHeader(TRUE, connection_uuid, out_pipe_uuid, NULL); 2228 if (!hdr) return RPC_S_OUT_OF_RESOURCES; 2229 2230 status = insert_content_length_header(out_request, hdr->common.frag_len); 2231 if (status != RPC_S_OK) 2232 { 2233 RPCRT4_FreeHeader(hdr); 2234 return status; 2235 } 2236 2237 TRACE("sending HTTP connect header to server\n"); 2238 prepare_async_request(async_data); 2239 ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len); 2240 status = wait_async_request(async_data, ret, cancel_event); 2241 RPCRT4_FreeHeader(hdr); 2242 if (status != RPC_S_OK) return status; 2243 2244 status = rpcrt4_http_check_response(out_request); 2245 if (status != RPC_S_OK) return status; 2246 2247 status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event, 2248 &pkt_from_server, &data_from_server); 2249 if (status != RPC_S_OK) return status; 2250 status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server, 2251 &field1); 2252 HeapFree(GetProcessHeap(), 0, data_from_server); 2253 if (status != RPC_S_OK) return status; 2254 TRACE("received (%d) from first prepare header\n", field1); 2255 2256 for (;;) 2257 { 2258 status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event, 2259 &pkt_from_server, &data_from_server); 2260 if (status != RPC_S_OK) return status; 2261 if (pkt_from_server.http.flags != 0x0001) break; 2262 2263 TRACE("http idle packet, waiting for real packet\n"); 2264 HeapFree(GetProcessHeap(), 0, data_from_server); 2265 if (pkt_from_server.http.num_data_items != 0) 2266 { 2267 ERR("HTTP idle packet should have no data items instead of %d\n", 2268 pkt_from_server.http.num_data_items); 2269 return RPC_S_PROTOCOL_ERROR; 2270 } 2271 } 2272 status = RPCRT4_ParseHttpPrepareHeader2(&pkt_from_server, data_from_server, 2273 &field1, flow_control_increment, 2274 &field3); 2275 HeapFree(GetProcessHeap(), 0, data_from_server); 2276 if (status != RPC_S_OK) return status; 2277 TRACE("received (0x%08x 0x%08x %d) from second prepare header\n", field1, *flow_control_increment, field3); 2278 2279 return RPC_S_OK; 2280 } 2281 2282 static UINT encode_base64(const char *bin, unsigned int len, WCHAR *base64) 2283 { 2284 static const char enc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 2285 UINT i = 0, x; 2286 2287 while (len > 0) 2288 { 2289 /* first 6 bits, all from bin[0] */ 2290 base64[i++] = enc[(bin[0] & 0xfc) >> 2]; 2291 x = (bin[0] & 3) << 4; 2292 2293 /* next 6 bits, 2 from bin[0] and 4 from bin[1] */ 2294 if (len == 1) 2295 { 2296 base64[i++] = enc[x]; 2297 base64[i++] = '='; 2298 base64[i++] = '='; 2299 break; 2300 } 2301 base64[i++] = enc[x | ((bin[1] & 0xf0) >> 4)]; 2302 x = (bin[1] & 0x0f) << 2; 2303 2304 /* next 6 bits 4 from bin[1] and 2 from bin[2] */ 2305 if (len == 2) 2306 { 2307 base64[i++] = enc[x]; 2308 base64[i++] = '='; 2309 break; 2310 } 2311 base64[i++] = enc[x | ((bin[2] & 0xc0) >> 6)]; 2312 2313 /* last 6 bits, all from bin [2] */ 2314 base64[i++] = enc[bin[2] & 0x3f]; 2315 bin += 3; 2316 len -= 3; 2317 } 2318 base64[i] = 0; 2319 return i; 2320 } 2321 2322 static inline char decode_char( WCHAR c ) 2323 { 2324 if (c >= 'A' && c <= 'Z') return c - 'A'; 2325 if (c >= 'a' && c <= 'z') return c - 'a' + 26; 2326 if (c >= '0' && c <= '9') return c - '0' + 52; 2327 if (c == '+') return 62; 2328 if (c == '/') return 63; 2329 return 64; 2330 } 2331 2332 static unsigned int decode_base64( const WCHAR *base64, unsigned int len, char *buf ) 2333 { 2334 unsigned int i = 0; 2335 char c0, c1, c2, c3; 2336 const WCHAR *p = base64; 2337 2338 while (len > 4) 2339 { 2340 if ((c0 = decode_char( p[0] )) > 63) return 0; 2341 if ((c1 = decode_char( p[1] )) > 63) return 0; 2342 if ((c2 = decode_char( p[2] )) > 63) return 0; 2343 if ((c3 = decode_char( p[3] )) > 63) return 0; 2344 2345 if (buf) 2346 { 2347 buf[i + 0] = (c0 << 2) | (c1 >> 4); 2348 buf[i + 1] = (c1 << 4) | (c2 >> 2); 2349 buf[i + 2] = (c2 << 6) | c3; 2350 } 2351 len -= 4; 2352 i += 3; 2353 p += 4; 2354 } 2355 if (p[2] == '=') 2356 { 2357 if ((c0 = decode_char( p[0] )) > 63) return 0; 2358 if ((c1 = decode_char( p[1] )) > 63) return 0; 2359 2360 if (buf) buf[i] = (c0 << 2) | (c1 >> 4); 2361 i++; 2362 } 2363 else if (p[3] == '=') 2364 { 2365 if ((c0 = decode_char( p[0] )) > 63) return 0; 2366 if ((c1 = decode_char( p[1] )) > 63) return 0; 2367 if ((c2 = decode_char( p[2] )) > 63) return 0; 2368 2369 if (buf) 2370 { 2371 buf[i + 0] = (c0 << 2) | (c1 >> 4); 2372 buf[i + 1] = (c1 << 4) | (c2 >> 2); 2373 } 2374 i += 2; 2375 } 2376 else 2377 { 2378 if ((c0 = decode_char( p[0] )) > 63) return 0; 2379 if ((c1 = decode_char( p[1] )) > 63) return 0; 2380 if ((c2 = decode_char( p[2] )) > 63) return 0; 2381 if ((c3 = decode_char( p[3] )) > 63) return 0; 2382 2383 if (buf) 2384 { 2385 buf[i + 0] = (c0 << 2) | (c1 >> 4); 2386 buf[i + 1] = (c1 << 4) | (c2 >> 2); 2387 buf[i + 2] = (c2 << 6) | c3; 2388 } 2389 i += 3; 2390 } 2391 return i; 2392 } 2393 2394 static struct authinfo *alloc_authinfo(void) 2395 { 2396 struct authinfo *ret; 2397 2398 if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret) ))) return NULL; 2399 2400 SecInvalidateHandle(&ret->cred); 2401 SecInvalidateHandle(&ret->ctx); 2402 memset(&ret->exp, 0, sizeof(ret->exp)); 2403 ret->scheme = 0; 2404 ret->attr = 0; 2405 ret->max_token = 0; 2406 ret->data = NULL; 2407 ret->data_len = 0; 2408 ret->finished = FALSE; 2409 return ret; 2410 } 2411 2412 static void destroy_authinfo(struct authinfo *info) 2413 { 2414 if (!info) return; 2415 2416 if (SecIsValidHandle(&info->ctx)) 2417 DeleteSecurityContext(&info->ctx); 2418 if (SecIsValidHandle(&info->cred)) 2419 FreeCredentialsHandle(&info->cred); 2420 2421 HeapFree(GetProcessHeap(), 0, info->data); 2422 HeapFree(GetProcessHeap(), 0, info); 2423 } 2424 2425 static const WCHAR basicW[] = {'B','a','s','i','c',0}; 2426 static const WCHAR ntlmW[] = {'N','T','L','M',0}; 2427 static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t',0}; 2428 static const WCHAR digestW[] = {'D','i','g','e','s','t',0}; 2429 static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',0}; 2430 2431 static const struct 2432 { 2433 const WCHAR *str; 2434 unsigned int len; 2435 DWORD scheme; 2436 } 2437 auth_schemes[] = 2438 { 2439 { basicW, ARRAYSIZE(basicW) - 1, RPC_C_HTTP_AUTHN_SCHEME_BASIC }, 2440 { ntlmW, ARRAYSIZE(ntlmW) - 1, RPC_C_HTTP_AUTHN_SCHEME_NTLM }, 2441 { passportW, ARRAYSIZE(passportW) - 1, RPC_C_HTTP_AUTHN_SCHEME_PASSPORT }, 2442 { digestW, ARRAYSIZE(digestW) - 1, RPC_C_HTTP_AUTHN_SCHEME_DIGEST }, 2443 { negotiateW, ARRAYSIZE(negotiateW) - 1, RPC_C_HTTP_AUTHN_SCHEME_NEGOTIATE } 2444 }; 2445 static const unsigned int num_auth_schemes = sizeof(auth_schemes)/sizeof(auth_schemes[0]); 2446 2447 static DWORD auth_scheme_from_header( const WCHAR *header ) 2448 { 2449 unsigned int i; 2450 for (i = 0; i < num_auth_schemes; i++) 2451 { 2452 if (!strncmpiW( header, auth_schemes[i].str, auth_schemes[i].len ) && 2453 (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme; 2454 } 2455 return 0; 2456 } 2457 2458 static BOOL get_authvalue(HINTERNET request, DWORD scheme, WCHAR *buffer, DWORD buflen) 2459 { 2460 DWORD len, index = 0; 2461 for (;;) 2462 { 2463 len = buflen; 2464 if (!HttpQueryInfoW(request, HTTP_QUERY_WWW_AUTHENTICATE, buffer, &len, &index)) return FALSE; 2465 if (auth_scheme_from_header(buffer) == scheme) break; 2466 } 2467 return TRUE; 2468 } 2469 2470 static RPC_STATUS do_authorization(HINTERNET request, SEC_WCHAR *servername, 2471 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *creds, struct authinfo **auth_ptr) 2472 { 2473 struct authinfo *info = *auth_ptr; 2474 SEC_WINNT_AUTH_IDENTITY_W *id = creds->TransportCredentials; 2475 RPC_STATUS status = RPC_S_SERVER_UNAVAILABLE; 2476 2477 if ((!info && !(info = alloc_authinfo()))) return RPC_S_SERVER_UNAVAILABLE; 2478 2479 switch (creds->AuthnSchemes[0]) 2480 { 2481 case RPC_C_HTTP_AUTHN_SCHEME_BASIC: 2482 { 2483 int userlen = WideCharToMultiByte(CP_UTF8, 0, id->User, id->UserLength, NULL, 0, NULL, NULL); 2484 int passlen = WideCharToMultiByte(CP_UTF8, 0, id->Password, id->PasswordLength, NULL, 0, NULL, NULL); 2485 2486 info->data_len = userlen + passlen + 1; 2487 if (!(info->data = HeapAlloc(GetProcessHeap(), 0, info->data_len))) 2488 { 2489 status = RPC_S_OUT_OF_MEMORY; 2490 break; 2491 } 2492 WideCharToMultiByte(CP_UTF8, 0, id->User, id->UserLength, info->data, userlen, NULL, NULL); 2493 info->data[userlen] = ':'; 2494 WideCharToMultiByte(CP_UTF8, 0, id->Password, id->PasswordLength, info->data + userlen + 1, passlen, NULL, NULL); 2495 2496 info->scheme = RPC_C_HTTP_AUTHN_SCHEME_BASIC; 2497 info->finished = TRUE; 2498 status = RPC_S_OK; 2499 break; 2500 } 2501 case RPC_C_HTTP_AUTHN_SCHEME_NTLM: 2502 case RPC_C_HTTP_AUTHN_SCHEME_NEGOTIATE: 2503 { 2504 2505 static SEC_WCHAR ntlmW[] = {'N','T','L','M',0}, negotiateW[] = {'N','e','g','o','t','i','a','t','e',0}; 2506 SECURITY_STATUS ret; 2507 SecBufferDesc out_desc, in_desc; 2508 SecBuffer out, in; 2509 ULONG flags = ISC_REQ_CONNECTION|ISC_REQ_USE_DCE_STYLE|ISC_REQ_MUTUAL_AUTH|ISC_REQ_DELEGATE; 2510 SEC_WCHAR *scheme; 2511 int scheme_len; 2512 const WCHAR *p; 2513 WCHAR auth_value[2048]; 2514 DWORD size = sizeof(auth_value); 2515 BOOL first = FALSE; 2516 2517 if (creds->AuthnSchemes[0] == RPC_C_HTTP_AUTHN_SCHEME_NTLM) scheme = ntlmW; 2518 else scheme = negotiateW; 2519 scheme_len = strlenW( scheme ); 2520 2521 if (!*auth_ptr) 2522 { 2523 TimeStamp exp; 2524 SecPkgInfoW *pkg_info; 2525 2526 ret = AcquireCredentialsHandleW(NULL, scheme, SECPKG_CRED_OUTBOUND, NULL, id, NULL, NULL, &info->cred, &exp); 2527 if (ret != SEC_E_OK) break; 2528 2529 ret = QuerySecurityPackageInfoW(scheme, &pkg_info); 2530 if (ret != SEC_E_OK) break; 2531 2532 info->max_token = pkg_info->cbMaxToken; 2533 FreeContextBuffer(pkg_info); 2534 first = TRUE; 2535 } 2536 else 2537 { 2538 if (info->finished || !get_authvalue(request, creds->AuthnSchemes[0], auth_value, size)) break; 2539 if (auth_scheme_from_header(auth_value) != info->scheme) 2540 { 2541 ERR("authentication scheme changed\n"); 2542 break; 2543 } 2544 } 2545 in.BufferType = SECBUFFER_TOKEN; 2546 in.cbBuffer = 0; 2547 in.pvBuffer = NULL; 2548 2549 in_desc.ulVersion = 0; 2550 in_desc.cBuffers = 1; 2551 in_desc.pBuffers = ∈ 2552 2553 p = auth_value + scheme_len; 2554 if (!first && *p == ' ') 2555 { 2556 int len = strlenW(++p); 2557 in.cbBuffer = decode_base64(p, len, NULL); 2558 if (!(in.pvBuffer = HeapAlloc(GetProcessHeap(), 0, in.cbBuffer))) break; 2559 decode_base64(p, len, in.pvBuffer); 2560 } 2561 out.BufferType = SECBUFFER_TOKEN; 2562 out.cbBuffer = info->max_token; 2563 if (!(out.pvBuffer = HeapAlloc(GetProcessHeap(), 0, out.cbBuffer))) 2564 { 2565 HeapFree(GetProcessHeap(), 0, in.pvBuffer); 2566 break; 2567 } 2568 out_desc.ulVersion = 0; 2569 out_desc.cBuffers = 1; 2570 out_desc.pBuffers = &out; 2571 2572 ret = InitializeSecurityContextW(first ? &info->cred : NULL, first ? NULL : &info->ctx, 2573 first ? servername : NULL, flags, 0, SECURITY_NETWORK_DREP, 2574 in.pvBuffer ? &in_desc : NULL, 0, &info->ctx, &out_desc, 2575 &info->attr, &info->exp); 2576 HeapFree(GetProcessHeap(), 0, in.pvBuffer); 2577 if (ret == SEC_E_OK) 2578 { 2579 HeapFree(GetProcessHeap(), 0, info->data); 2580 info->data = out.pvBuffer; 2581 info->data_len = out.cbBuffer; 2582 info->finished = TRUE; 2583 TRACE("sending last auth packet\n"); 2584 status = RPC_S_OK; 2585 } 2586 else if (ret == SEC_I_CONTINUE_NEEDED) 2587 { 2588 HeapFree(GetProcessHeap(), 0, info->data); 2589 info->data = out.pvBuffer; 2590 info->data_len = out.cbBuffer; 2591 TRACE("sending next auth packet\n"); 2592 status = RPC_S_OK; 2593 } 2594 else 2595 { 2596 ERR("InitializeSecurityContextW failed with error 0x%08x\n", ret); 2597 HeapFree(GetProcessHeap(), 0, out.pvBuffer); 2598 break; 2599 } 2600 info->scheme = creds->AuthnSchemes[0]; 2601 break; 2602 } 2603 default: 2604 FIXME("scheme %u not supported\n", creds->AuthnSchemes[0]); 2605 break; 2606 } 2607 2608 if (status != RPC_S_OK) 2609 { 2610 destroy_authinfo(info); 2611 *auth_ptr = NULL; 2612 return status; 2613 } 2614 *auth_ptr = info; 2615 return RPC_S_OK; 2616 } 2617 2618 static RPC_STATUS insert_authorization_header(HINTERNET request, ULONG scheme, char *data, int data_len) 2619 { 2620 static const WCHAR authW[] = {'A','u','t','h','o','r','i','z','a','t','i','o','n',':',' '}; 2621 static const WCHAR basicW[] = {'B','a','s','i','c',' '}; 2622 static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',' '}; 2623 static const WCHAR ntlmW[] = {'N','T','L','M',' '}; 2624 int scheme_len, auth_len = sizeof(authW) / sizeof(authW[0]), len = ((data_len + 2) * 4) / 3; 2625 const WCHAR *scheme_str; 2626 WCHAR *header, *ptr; 2627 RPC_STATUS status = RPC_S_SERVER_UNAVAILABLE; 2628 2629 switch (scheme) 2630 { 2631 case RPC_C_HTTP_AUTHN_SCHEME_BASIC: 2632 scheme_str = basicW; 2633 scheme_len = sizeof(basicW) / sizeof(basicW[0]); 2634 break; 2635 case RPC_C_HTTP_AUTHN_SCHEME_NEGOTIATE: 2636 scheme_str = negotiateW; 2637 scheme_len = sizeof(negotiateW) / sizeof(negotiateW[0]); 2638 break; 2639 case RPC_C_HTTP_AUTHN_SCHEME_NTLM: 2640 scheme_str = ntlmW; 2641 scheme_len = sizeof(ntlmW) / sizeof(ntlmW[0]); 2642 break; 2643 default: 2644 ERR("unknown scheme %u\n", scheme); 2645 return RPC_S_SERVER_UNAVAILABLE; 2646 } 2647 if ((header = HeapAlloc(GetProcessHeap(), 0, (auth_len + scheme_len + len + 2) * sizeof(WCHAR)))) 2648 { 2649 memcpy(header, authW, auth_len * sizeof(WCHAR)); 2650 ptr = header + auth_len; 2651 memcpy(ptr, scheme_str, scheme_len * sizeof(WCHAR)); 2652 ptr += scheme_len; 2653 len = encode_base64(data, data_len, ptr); 2654 ptr[len++] = '\r'; 2655 ptr[len++] = '\n'; 2656 ptr[len] = 0; 2657 if (HttpAddRequestHeadersW(request, header, -1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE)) 2658 status = RPC_S_OK; 2659 HeapFree(GetProcessHeap(), 0, header); 2660 } 2661 return status; 2662 } 2663 2664 static void drain_content(HINTERNET request, RpcHttpAsyncData *async_data, HANDLE cancel_event) 2665 { 2666 DWORD count, len = 0, size = sizeof(len); 2667 char buf[2048]; 2668 2669 HttpQueryInfoW(request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, &len, &size, NULL); 2670 if (!len) return; 2671 for (;;) 2672 { 2673 count = min(sizeof(buf), len); 2674 if (rpcrt4_http_async_read(request, async_data, cancel_event, buf, count) <= 0) return; 2675 len -= count; 2676 } 2677 } 2678 2679 static RPC_STATUS authorize_request(RpcConnection_http *httpc, HINTERNET request) 2680 { 2681 static const WCHAR authW[] = {'A','u','t','h','o','r','i','z','a','t','i','o','n',':','\r','\n',0}; 2682 struct authinfo *info = NULL; 2683 RPC_STATUS status; 2684 BOOL ret; 2685 2686 for (;;) 2687 { 2688 status = do_authorization(request, httpc->servername, httpc->common.QOS->qos->u.HttpCredentials, &info); 2689 if (status != RPC_S_OK) break; 2690 2691 status = insert_authorization_header(request, info->scheme, info->data, info->data_len); 2692 if (status != RPC_S_OK) break; 2693 2694 prepare_async_request(httpc->async_data); 2695 ret = HttpSendRequestW(request, NULL, 0, NULL, 0); 2696 status = wait_async_request(httpc->async_data, ret, httpc->cancel_event); 2697 if (status != RPC_S_OK || info->finished) break; 2698 2699 status = rpcrt4_http_check_response(request); 2700 if (status != RPC_S_OK && status != ERROR_ACCESS_DENIED) break; 2701 drain_content(request, httpc->async_data, httpc->cancel_event); 2702 } 2703 2704 if (info->scheme != RPC_C_HTTP_AUTHN_SCHEME_BASIC) 2705 HttpAddRequestHeadersW(request, authW, -1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD); 2706 2707 destroy_authinfo(info); 2708 return status; 2709 } 2710 2711 static BOOL has_credentials(RpcConnection_http *httpc) 2712 { 2713 RPC_HTTP_TRANSPORT_CREDENTIALS_W *creds; 2714 SEC_WINNT_AUTH_IDENTITY_W *id; 2715 2716 if (!httpc->common.QOS || httpc->common.QOS->qos->AdditionalSecurityInfoType != RPC_C_AUTHN_INFO_TYPE_HTTP) 2717 return FALSE; 2718 2719 creds = httpc->common.QOS->qos->u.HttpCredentials; 2720 if (creds->AuthenticationTarget != RPC_C_HTTP_AUTHN_TARGET_SERVER || !creds->NumberOfAuthnSchemes) 2721 return FALSE; 2722 2723 id = creds->TransportCredentials; 2724 if (!id || !id->User || !id->Password) return FALSE; 2725 2726 return TRUE; 2727 } 2728 2729 static BOOL is_secure(RpcConnection_http *httpc) 2730 { 2731 return httpc->common.QOS && 2732 (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) && 2733 (httpc->common.QOS->qos->u.HttpCredentials->Flags & RPC_C_HTTP_FLAG_USE_SSL); 2734 } 2735 2736 static RPC_STATUS set_auth_cookie(RpcConnection_http *httpc, const WCHAR *value) 2737 { 2738 static WCHAR httpW[] = {'h','t','t','p',0}; 2739 static WCHAR httpsW[] = {'h','t','t','p','s',0}; 2740 URL_COMPONENTSW uc; 2741 DWORD len; 2742 WCHAR *url; 2743 BOOL ret; 2744 2745 if (!value) return RPC_S_OK; 2746 2747 uc.dwStructSize = sizeof(uc); 2748 uc.lpszScheme = is_secure(httpc) ? httpsW : httpW; 2749 uc.dwSchemeLength = 0; 2750 uc.lpszHostName = httpc->servername; 2751 uc.dwHostNameLength = 0; 2752 uc.nPort = 0; 2753 uc.lpszUserName = NULL; 2754 uc.dwUserNameLength = 0; 2755 uc.lpszPassword = NULL; 2756 uc.dwPasswordLength = 0; 2757 uc.lpszUrlPath = NULL; 2758 uc.dwUrlPathLength = 0; 2759 uc.lpszExtraInfo = NULL; 2760 uc.dwExtraInfoLength = 0; 2761 2762 if (!InternetCreateUrlW(&uc, 0, NULL, &len) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) 2763 return RPC_S_SERVER_UNAVAILABLE; 2764 2765 if (!(url = HeapAlloc(GetProcessHeap(), 0, len))) return RPC_S_OUT_OF_MEMORY; 2766 2767 len = len / sizeof(WCHAR) - 1; 2768 if (!InternetCreateUrlW(&uc, 0, url, &len)) 2769 { 2770 HeapFree(GetProcessHeap(), 0, url); 2771 return RPC_S_SERVER_UNAVAILABLE; 2772 } 2773 2774 ret = InternetSetCookieW(url, NULL, value); 2775 HeapFree(GetProcessHeap(), 0, url); 2776 if (!ret) return RPC_S_SERVER_UNAVAILABLE; 2777 2778 return RPC_S_OK; 2779 } 2780 2781 static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection) 2782 { 2783 RpcConnection_http *httpc = (RpcConnection_http *)Connection; 2784 static const WCHAR wszVerbIn[] = {'R','P','C','_','I','N','_','D','A','T','A',0}; 2785 static const WCHAR wszVerbOut[] = {'R','P','C','_','O','U','T','_','D','A','T','A',0}; 2786 static const WCHAR wszRpcProxyPrefix[] = {'/','r','p','c','/','r','p','c','p','r','o','x','y','.','d','l','l','?',0}; 2787 static const WCHAR wszColon[] = {':',0}; 2788 static const WCHAR wszAcceptType[] = {'a','p','p','l','i','c','a','t','i','o','n','/','r','p','c',0}; 2789 LPCWSTR wszAcceptTypes[] = { wszAcceptType, NULL }; 2790 DWORD flags; 2791 WCHAR *url; 2792 RPC_STATUS status; 2793 BOOL secure, credentials; 2794 HttpTimerThreadData *timer_data; 2795 HANDLE thread; 2796 2797 TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); 2798 2799 if (Connection->server) 2800 { 2801 ERR("ncacn_http servers not supported yet\n"); 2802 return RPC_S_SERVER_UNAVAILABLE; 2803 } 2804 2805 if (httpc->in_request) 2806 return RPC_S_OK; 2807 2808 httpc->async_data->completion_event = CreateEventW(NULL, FALSE, FALSE, NULL); 2809 2810 UuidCreate(&httpc->connection_uuid); 2811 UuidCreate(&httpc->in_pipe_uuid); 2812 UuidCreate(&httpc->out_pipe_uuid); 2813 2814 status = rpcrt4_http_internet_connect(httpc); 2815 if (status != RPC_S_OK) 2816 return status; 2817 2818 url = HeapAlloc(GetProcessHeap(), 0, sizeof(wszRpcProxyPrefix) + (strlen(Connection->NetworkAddr) + 1 + strlen(Connection->Endpoint))*sizeof(WCHAR)); 2819 if (!url) 2820 return RPC_S_OUT_OF_MEMORY; 2821 memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix)); 2822 MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+sizeof(wszRpcProxyPrefix)/sizeof(wszRpcProxyPrefix[0])-1, strlen(Connection->NetworkAddr)+1); 2823 strcatW(url, wszColon); 2824 MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+strlenW(url), strlen(Connection->Endpoint)+1); 2825 2826 secure = is_secure(httpc); 2827 credentials = has_credentials(httpc); 2828 2829 flags = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE | 2830 INTERNET_FLAG_NO_AUTO_REDIRECT; 2831 if (secure) flags |= INTERNET_FLAG_SECURE; 2832 if (credentials) flags |= INTERNET_FLAG_NO_AUTH; 2833 2834 status = set_auth_cookie(httpc, Connection->CookieAuth); 2835 if (status != RPC_S_OK) 2836 { 2837 HeapFree(GetProcessHeap(), 0, url); 2838 return status; 2839 } 2840 httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL, wszAcceptTypes, 2841 flags, (DWORD_PTR)httpc->async_data); 2842 if (!httpc->in_request) 2843 { 2844 ERR("HttpOpenRequestW failed with error %d\n", GetLastError()); 2845 HeapFree(GetProcessHeap(), 0, url); 2846 return RPC_S_SERVER_UNAVAILABLE; 2847 } 2848 2849 if (credentials) 2850 { 2851 status = authorize_request(httpc, httpc->in_request); 2852 if (status != RPC_S_OK) 2853 { 2854 HeapFree(GetProcessHeap(), 0, url); 2855 return status; 2856 } 2857 status = rpcrt4_http_check_response(httpc->in_request); 2858 if (status != RPC_S_OK) 2859 { 2860 HeapFree(GetProcessHeap(), 0, url); 2861 return status; 2862 } 2863 drain_content(httpc->in_request, httpc->async_data, httpc->cancel_event); 2864 } 2865 2866 httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, wszAcceptTypes, 2867 flags, (DWORD_PTR)httpc->async_data); 2868 HeapFree(GetProcessHeap(), 0, url); 2869 if (!httpc->out_request) 2870 { 2871 ERR("HttpOpenRequestW failed with error %d\n", GetLastError()); 2872 return RPC_S_SERVER_UNAVAILABLE; 2873 } 2874 2875 if (credentials) 2876 { 2877 status = authorize_request(httpc, httpc->out_request); 2878 if (status != RPC_S_OK) 2879 return status; 2880 } 2881 2882 status = rpcrt4_http_prepare_in_pipe(httpc->in_request, httpc->async_data, httpc->cancel_event, 2883 &httpc->connection_uuid, &httpc->in_pipe_uuid, 2884 &Connection->assoc->http_uuid, credentials); 2885 if (status != RPC_S_OK) 2886 return status; 2887 2888 status = rpcrt4_http_prepare_out_pipe(httpc->out_request, httpc->async_data, httpc->cancel_event, 2889 &httpc->connection_uuid, &httpc->out_pipe_uuid, 2890 &httpc->flow_control_increment, credentials); 2891 if (status != RPC_S_OK) 2892 return status; 2893 2894 httpc->flow_control_mark = httpc->flow_control_increment / 2; 2895 httpc->last_sent_time = GetTickCount(); 2896 httpc->timer_cancelled = CreateEventW(NULL, FALSE, FALSE, NULL); 2897 2898 timer_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*timer_data)); 2899 if (!timer_data) 2900 return ERROR_OUTOFMEMORY; 2901 timer_data->timer_param = httpc->in_request; 2902 timer_data->last_sent_time = &httpc->last_sent_time; 2903 timer_data->timer_cancelled = httpc->timer_cancelled; 2904 /* FIXME: should use CreateTimerQueueTimer when implemented */ 2905 thread = CreateThread(NULL, 0, rpcrt4_http_timer_thread, timer_data, 0, NULL); 2906 if (!thread) 2907 { 2908 HeapFree(GetProcessHeap(), 0, timer_data); 2909 return GetLastError(); 2910 } 2911 CloseHandle(thread); 2912 2913 return RPC_S_OK; 2914 } 2915 2916 static RPC_STATUS rpcrt4_ncacn_http_handoff(RpcConnection *old_conn, RpcConnection *new_conn) 2917 { 2918 assert(0); 2919 return RPC_S_SERVER_UNAVAILABLE; 2920 } 2921 2922 static int rpcrt4_ncacn_http_read(RpcConnection *Connection, 2923 void *buffer, unsigned int count) 2924 { 2925 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 2926 return rpcrt4_http_async_read(httpc->out_request, httpc->async_data, httpc->cancel_event, buffer, count); 2927 } 2928 2929 static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) 2930 { 2931 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 2932 RPC_STATUS status; 2933 DWORD hdr_length; 2934 LONG dwRead; 2935 RpcPktCommonHdr common_hdr; 2936 2937 *Header = NULL; 2938 2939 TRACE("(%p, %p, %p)\n", Connection, Header, Payload); 2940 2941 again: 2942 /* read packet common header */ 2943 dwRead = rpcrt4_ncacn_http_read(Connection, &common_hdr, sizeof(common_hdr)); 2944 if (dwRead != sizeof(common_hdr)) { 2945 WARN("Short read of header, %d bytes\n", dwRead); 2946 status = RPC_S_PROTOCOL_ERROR; 2947 goto fail; 2948 } 2949 if (!memcmp(&common_hdr, "HTTP/1.1", sizeof("HTTP/1.1")) || 2950 !memcmp(&common_hdr, "HTTP/1.0", sizeof("HTTP/1.0"))) 2951 { 2952 FIXME("server returned %s\n", debugstr_a((const char *)&common_hdr)); 2953 status = RPC_S_PROTOCOL_ERROR; 2954 goto fail; 2955 } 2956 2957 status = RPCRT4_ValidateCommonHeader(&common_hdr); 2958 if (status != RPC_S_OK) goto fail; 2959 2960 hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr); 2961 if (hdr_length == 0) { 2962 WARN("header length == 0\n"); 2963 status = RPC_S_PROTOCOL_ERROR; 2964 goto fail; 2965 } 2966 2967 *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length); 2968 if (!*Header) 2969 { 2970 status = RPC_S_OUT_OF_RESOURCES; 2971 goto fail; 2972 } 2973 memcpy(*Header, &common_hdr, sizeof(common_hdr)); 2974 2975 /* read the rest of packet header */ 2976 dwRead = rpcrt4_ncacn_http_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr)); 2977 if (dwRead != hdr_length - sizeof(common_hdr)) { 2978 WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length); 2979 status = RPC_S_PROTOCOL_ERROR; 2980 goto fail; 2981 } 2982 2983 if (common_hdr.frag_len - hdr_length) 2984 { 2985 *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length); 2986 if (!*Payload) 2987 { 2988 status = RPC_S_OUT_OF_RESOURCES; 2989 goto fail; 2990 } 2991 2992 dwRead = rpcrt4_ncacn_http_read(Connection, *Payload, common_hdr.frag_len - hdr_length); 2993 if (dwRead != common_hdr.frag_len - hdr_length) 2994 { 2995 WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length); 2996 status = RPC_S_PROTOCOL_ERROR; 2997 goto fail; 2998 } 2999 } 3000 else 3001 *Payload = NULL; 3002 3003 if ((*Header)->common.ptype == PKT_HTTP) 3004 { 3005 if (!RPCRT4_IsValidHttpPacket(*Header, *Payload, common_hdr.frag_len - hdr_length)) 3006 { 3007 ERR("invalid http packet of length %d bytes\n", (*Header)->common.frag_len); 3008 status = RPC_S_PROTOCOL_ERROR; 3009 goto fail; 3010 } 3011 if ((*Header)->http.flags == 0x0001) 3012 { 3013 TRACE("http idle packet, waiting for real packet\n"); 3014 if ((*Header)->http.num_data_items != 0) 3015 { 3016 ERR("HTTP idle packet should have no data items instead of %d\n", (*Header)->http.num_data_items); 3017 status = RPC_S_PROTOCOL_ERROR; 3018 goto fail; 3019 } 3020 } 3021 else if ((*Header)->http.flags == 0x0002) 3022 { 3023 ULONG bytes_transmitted; 3024 ULONG flow_control_increment; 3025 UUID pipe_uuid; 3026 status = RPCRT4_ParseHttpFlowControlHeader(*Header, *Payload, 3027 Connection->server, 3028 &bytes_transmitted, 3029 &flow_control_increment, 3030 &pipe_uuid); 3031 if (status != RPC_S_OK) 3032 goto fail; 3033 TRACE("received http flow control header (0x%x, 0x%x, %s)\n", 3034 bytes_transmitted, flow_control_increment, debugstr_guid(&pipe_uuid)); 3035 /* FIXME: do something with parsed data */ 3036 } 3037 else 3038 { 3039 FIXME("unrecognised http packet with flags 0x%04x\n", (*Header)->http.flags); 3040 status = RPC_S_PROTOCOL_ERROR; 3041 goto fail; 3042 } 3043 RPCRT4_FreeHeader(*Header); 3044 *Header = NULL; 3045 HeapFree(GetProcessHeap(), 0, *Payload); 3046 *Payload = NULL; 3047 goto again; 3048 } 3049 3050 /* success */ 3051 status = RPC_S_OK; 3052 3053 httpc->bytes_received += common_hdr.frag_len; 3054 3055 TRACE("httpc->bytes_received = 0x%x\n", httpc->bytes_received); 3056 3057 if (httpc->bytes_received > httpc->flow_control_mark) 3058 { 3059 RpcPktHdr *hdr = RPCRT4_BuildHttpFlowControlHeader(httpc->common.server, 3060 httpc->bytes_received, 3061 httpc->flow_control_increment, 3062 &httpc->out_pipe_uuid); 3063 if (hdr) 3064 { 3065 DWORD bytes_written; 3066 BOOL ret2; 3067 TRACE("sending flow control packet at 0x%x\n", httpc->bytes_received); 3068 ret2 = InternetWriteFile(httpc->in_request, hdr, hdr->common.frag_len, &bytes_written); 3069 RPCRT4_FreeHeader(hdr); 3070 if (ret2) 3071 httpc->flow_control_mark = httpc->bytes_received + httpc->flow_control_increment / 2; 3072 } 3073 } 3074 3075 fail: 3076 if (status != RPC_S_OK) { 3077 RPCRT4_FreeHeader(*Header); 3078 *Header = NULL; 3079 HeapFree(GetProcessHeap(), 0, *Payload); 3080 *Payload = NULL; 3081 } 3082 return status; 3083 } 3084 3085 static int rpcrt4_ncacn_http_write(RpcConnection *Connection, 3086 const void *buffer, unsigned int count) 3087 { 3088 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 3089 DWORD bytes_written; 3090 BOOL ret; 3091 3092 httpc->last_sent_time = ~0U; /* disable idle packet sending */ 3093 ret = InternetWriteFile(httpc->in_request, buffer, count, &bytes_written); 3094 httpc->last_sent_time = GetTickCount(); 3095 TRACE("%p %p %u -> %s\n", httpc->in_request, buffer, count, ret ? "TRUE" : "FALSE"); 3096 return ret ? bytes_written : -1; 3097 } 3098 3099 static int rpcrt4_ncacn_http_close(RpcConnection *Connection) 3100 { 3101 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 3102 3103 TRACE("\n"); 3104 3105 SetEvent(httpc->timer_cancelled); 3106 if (httpc->in_request) 3107 InternetCloseHandle(httpc->in_request); 3108 httpc->in_request = NULL; 3109 if (httpc->out_request) 3110 InternetCloseHandle(httpc->out_request); 3111 httpc->out_request = NULL; 3112 if (httpc->app_info) 3113 InternetCloseHandle(httpc->app_info); 3114 httpc->app_info = NULL; 3115 if (httpc->session) 3116 InternetCloseHandle(httpc->session); 3117 httpc->session = NULL; 3118 RpcHttpAsyncData_Release(httpc->async_data); 3119 if (httpc->cancel_event) 3120 CloseHandle(httpc->cancel_event); 3121 HeapFree(GetProcessHeap(), 0, httpc->servername); 3122 httpc->servername = NULL; 3123 3124 return 0; 3125 } 3126 3127 static void rpcrt4_ncacn_http_close_read(RpcConnection *conn) 3128 { 3129 rpcrt4_ncacn_http_close(conn); /* FIXME */ 3130 } 3131 3132 static void rpcrt4_ncacn_http_cancel_call(RpcConnection *Connection) 3133 { 3134 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 3135 3136 SetEvent(httpc->cancel_event); 3137 } 3138 3139 static RPC_STATUS rpcrt4_ncacn_http_is_server_listening(const char *endpoint) 3140 { 3141 FIXME("\n"); 3142 return RPC_S_ACCESS_DENIED; 3143 } 3144 3145 static int rpcrt4_ncacn_http_wait_for_incoming_data(RpcConnection *Connection) 3146 { 3147 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 3148 BOOL ret; 3149 RPC_STATUS status; 3150 3151 prepare_async_request(httpc->async_data); 3152 ret = InternetQueryDataAvailable(httpc->out_request, 3153 &httpc->async_data->inet_buffers.dwBufferLength, IRF_ASYNC, 0); 3154 status = wait_async_request(httpc->async_data, ret, httpc->cancel_event); 3155 return status == RPC_S_OK ? 0 : -1; 3156 } 3157 3158 static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data, 3159 const char *networkaddr, 3160 const char *endpoint) 3161 { 3162 return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr, 3163 EPM_PROTOCOL_HTTP, endpoint); 3164 } 3165 3166 static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data, 3167 size_t tower_size, 3168 char **networkaddr, 3169 char **endpoint) 3170 { 3171 return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size, 3172 networkaddr, EPM_PROTOCOL_HTTP, 3173 endpoint); 3174 } 3175 3176 static const struct connection_ops conn_protseq_list[] = { 3177 { "ncacn_np", 3178 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB }, 3179 rpcrt4_conn_np_alloc, 3180 rpcrt4_ncacn_np_open, 3181 rpcrt4_ncacn_np_handoff, 3182 rpcrt4_conn_np_read, 3183 rpcrt4_conn_np_write, 3184 rpcrt4_conn_np_close, 3185 rpcrt4_conn_np_close_read, 3186 rpcrt4_conn_np_cancel_call, 3187 rpcrt4_ncacn_np_is_server_listening, 3188 rpcrt4_conn_np_wait_for_incoming_data, 3189 rpcrt4_ncacn_np_get_top_of_tower, 3190 rpcrt4_ncacn_np_parse_top_of_tower, 3191 NULL, 3192 RPCRT4_default_is_authorized, 3193 RPCRT4_default_authorize, 3194 RPCRT4_default_secure_packet, 3195 rpcrt4_conn_np_impersonate_client, 3196 rpcrt4_conn_np_revert_to_self, 3197 RPCRT4_default_inquire_auth_client, 3198 }, 3199 { "ncalrpc", 3200 { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE }, 3201 rpcrt4_conn_np_alloc, 3202 rpcrt4_ncalrpc_open, 3203 rpcrt4_ncalrpc_handoff, 3204 rpcrt4_conn_np_read, 3205 rpcrt4_conn_np_write, 3206 rpcrt4_conn_np_close, 3207 rpcrt4_conn_np_close_read, 3208 rpcrt4_conn_np_cancel_call, 3209 rpcrt4_ncalrpc_np_is_server_listening, 3210 rpcrt4_conn_np_wait_for_incoming_data, 3211 rpcrt4_ncalrpc_get_top_of_tower, 3212 rpcrt4_ncalrpc_parse_top_of_tower, 3213 NULL, 3214 rpcrt4_ncalrpc_is_authorized, 3215 rpcrt4_ncalrpc_authorize, 3216 rpcrt4_ncalrpc_secure_packet, 3217 rpcrt4_conn_np_impersonate_client, 3218 rpcrt4_conn_np_revert_to_self, 3219 rpcrt4_ncalrpc_inquire_auth_client, 3220 }, 3221 { "ncacn_ip_tcp", 3222 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP }, 3223 rpcrt4_conn_tcp_alloc, 3224 rpcrt4_ncacn_ip_tcp_open, 3225 rpcrt4_conn_tcp_handoff, 3226 rpcrt4_conn_tcp_read, 3227 rpcrt4_conn_tcp_write, 3228 rpcrt4_conn_tcp_close, 3229 rpcrt4_conn_tcp_close_read, 3230 rpcrt4_conn_tcp_cancel_call, 3231 rpcrt4_conn_tcp_is_server_listening, 3232 rpcrt4_conn_tcp_wait_for_incoming_data, 3233 rpcrt4_ncacn_ip_tcp_get_top_of_tower, 3234 rpcrt4_ncacn_ip_tcp_parse_top_of_tower, 3235 NULL, 3236 RPCRT4_default_is_authorized, 3237 RPCRT4_default_authorize, 3238 RPCRT4_default_secure_packet, 3239 RPCRT4_default_impersonate_client, 3240 RPCRT4_default_revert_to_self, 3241 RPCRT4_default_inquire_auth_client, 3242 }, 3243 { "ncacn_http", 3244 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP }, 3245 rpcrt4_ncacn_http_alloc, 3246 rpcrt4_ncacn_http_open, 3247 rpcrt4_ncacn_http_handoff, 3248 rpcrt4_ncacn_http_read, 3249 rpcrt4_ncacn_http_write, 3250 rpcrt4_ncacn_http_close, 3251 rpcrt4_ncacn_http_close_read, 3252 rpcrt4_ncacn_http_cancel_call, 3253 rpcrt4_ncacn_http_is_server_listening, 3254 rpcrt4_ncacn_http_wait_for_incoming_data, 3255 rpcrt4_ncacn_http_get_top_of_tower, 3256 rpcrt4_ncacn_http_parse_top_of_tower, 3257 rpcrt4_ncacn_http_receive_fragment, 3258 RPCRT4_default_is_authorized, 3259 RPCRT4_default_authorize, 3260 RPCRT4_default_secure_packet, 3261 RPCRT4_default_impersonate_client, 3262 RPCRT4_default_revert_to_self, 3263 RPCRT4_default_inquire_auth_client, 3264 }, 3265 }; 3266 3267 3268 static const struct protseq_ops protseq_list[] = 3269 { 3270 { 3271 "ncacn_np", 3272 rpcrt4_protseq_np_alloc, 3273 rpcrt4_protseq_np_signal_state_changed, 3274 rpcrt4_protseq_np_get_wait_array, 3275 rpcrt4_protseq_np_free_wait_array, 3276 rpcrt4_protseq_np_wait_for_new_connection, 3277 rpcrt4_protseq_ncacn_np_open_endpoint, 3278 }, 3279 { 3280 "ncalrpc", 3281 rpcrt4_protseq_np_alloc, 3282 rpcrt4_protseq_np_signal_state_changed, 3283 rpcrt4_protseq_np_get_wait_array, 3284 rpcrt4_protseq_np_free_wait_array, 3285 rpcrt4_protseq_np_wait_for_new_connection, 3286 rpcrt4_protseq_ncalrpc_open_endpoint, 3287 }, 3288 { 3289 "ncacn_ip_tcp", 3290 rpcrt4_protseq_sock_alloc, 3291 rpcrt4_protseq_sock_signal_state_changed, 3292 rpcrt4_protseq_sock_get_wait_array, 3293 rpcrt4_protseq_sock_free_wait_array, 3294 rpcrt4_protseq_sock_wait_for_new_connection, 3295 rpcrt4_protseq_ncacn_ip_tcp_open_endpoint, 3296 }, 3297 }; 3298 3299 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq) 3300 { 3301 unsigned int i; 3302 for(i=0; i<ARRAYSIZE(protseq_list); i++) 3303 if (!strcmp(protseq_list[i].name, protseq)) 3304 return &protseq_list[i]; 3305 return NULL; 3306 } 3307 3308 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq) 3309 { 3310 unsigned int i; 3311 for(i=0; i<ARRAYSIZE(conn_protseq_list); i++) 3312 if (!strcmp(conn_protseq_list[i].name, protseq)) 3313 return &conn_protseq_list[i]; 3314 return NULL; 3315 } 3316 3317 /**** interface to rest of code ****/ 3318 3319 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection) 3320 { 3321 TRACE("(Connection == ^%p)\n", Connection); 3322 3323 assert(!Connection->server); 3324 return Connection->ops->open_connection_client(Connection); 3325 } 3326 3327 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) 3328 { 3329 TRACE("(Connection == ^%p)\n", Connection); 3330 if (SecIsValidHandle(&Connection->ctx)) 3331 { 3332 DeleteSecurityContext(&Connection->ctx); 3333 SecInvalidateHandle(&Connection->ctx); 3334 } 3335 rpcrt4_conn_close(Connection); 3336 return RPC_S_OK; 3337 } 3338 3339 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, 3340 LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, 3341 LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS, LPCWSTR CookieAuth) 3342 { 3343 static LONG next_id; 3344 const struct connection_ops *ops; 3345 RpcConnection* NewConnection; 3346 3347 ops = rpcrt4_get_conn_protseq_ops(Protseq); 3348 if (!ops) 3349 { 3350 FIXME("not supported for protseq %s\n", Protseq); 3351 return RPC_S_PROTSEQ_NOT_SUPPORTED; 3352 } 3353 3354 NewConnection = ops->alloc(); 3355 NewConnection->ref = 1; 3356 NewConnection->server = server; 3357 NewConnection->ops = ops; 3358 NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr); 3359 NewConnection->Endpoint = RPCRT4_strdupA(Endpoint); 3360 NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions); 3361 NewConnection->CookieAuth = RPCRT4_strdupW(CookieAuth); 3362 NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE; 3363 NewConnection->NextCallId = 1; 3364 3365 SecInvalidateHandle(&NewConnection->ctx); 3366 if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo); 3367 NewConnection->AuthInfo = AuthInfo; 3368 NewConnection->auth_context_id = InterlockedIncrement( &next_id ); 3369 if (QOS) RpcQualityOfService_AddRef(QOS); 3370 NewConnection->QOS = QOS; 3371 3372 list_init(&NewConnection->conn_pool_entry); 3373 list_init(&NewConnection->protseq_entry); 3374 3375 TRACE("connection: %p\n", NewConnection); 3376 *Connection = NewConnection; 3377 3378 return RPC_S_OK; 3379 } 3380 3381 static RpcConnection *rpcrt4_spawn_connection(RpcConnection *old_connection) 3382 { 3383 RpcConnection *connection; 3384 RPC_STATUS err; 3385 3386 err = RPCRT4_CreateConnection(&connection, old_connection->server, rpcrt4_conn_get_name(old_connection), 3387 old_connection->NetworkAddr, old_connection->Endpoint, NULL, 3388 old_connection->AuthInfo, old_connection->QOS, old_connection->CookieAuth); 3389 if (err != RPC_S_OK) 3390 return NULL; 3391 3392 rpcrt4_conn_handoff(old_connection, connection); 3393 if (old_connection->protseq) 3394 { 3395 EnterCriticalSection(&old_connection->protseq->cs); 3396 connection->protseq = old_connection->protseq; 3397 list_add_tail(&old_connection->protseq->connections, &connection->protseq_entry); 3398 LeaveCriticalSection(&old_connection->protseq->cs); 3399 } 3400 return connection; 3401 } 3402 3403 void rpcrt4_conn_release_and_wait(RpcConnection *connection) 3404 { 3405 HANDLE event = NULL; 3406 3407 if (connection->ref > 1) 3408 event = connection->wait_release = CreateEventW(NULL, TRUE, FALSE, NULL); 3409 3410 RPCRT4_ReleaseConnection(connection); 3411 3412 if(event) 3413 { 3414 WaitForSingleObject(event, INFINITE); 3415 CloseHandle(event); 3416 } 3417 } 3418 3419 RpcConnection *RPCRT4_GrabConnection(RpcConnection *connection) 3420 { 3421 LONG ref = InterlockedIncrement(&connection->ref); 3422 TRACE("%p ref=%u\n", connection, ref); 3423 return connection; 3424 } 3425 3426 void RPCRT4_ReleaseConnection(RpcConnection *connection) 3427 { 3428 LONG ref; 3429 3430 /* protseq stores a list of active connections, but does not own references to them. 3431 * It may need to grab a connection from the list, which could lead to a race if 3432 * connection is being released, but not yet removed from the list. We handle that 3433 * by synchronizing on CS here. */ 3434 if (connection->protseq) 3435 { 3436 EnterCriticalSection(&connection->protseq->cs); 3437 ref = InterlockedDecrement(&connection->ref); 3438 if (!ref) 3439 list_remove(&connection->protseq_entry); 3440 LeaveCriticalSection(&connection->protseq->cs); 3441 } 3442 else 3443 { 3444 ref = InterlockedDecrement(&connection->ref); 3445 } 3446 3447 TRACE("%p ref=%u\n", connection, ref); 3448 3449 if (!ref) 3450 { 3451 RPCRT4_CloseConnection(connection); 3452 RPCRT4_strfree(connection->Endpoint); 3453 RPCRT4_strfree(connection->NetworkAddr); 3454 HeapFree(GetProcessHeap(), 0, connection->NetworkOptions); 3455 HeapFree(GetProcessHeap(), 0, connection->CookieAuth); 3456 if (connection->AuthInfo) RpcAuthInfo_Release(connection->AuthInfo); 3457 if (connection->QOS) RpcQualityOfService_Release(connection->QOS); 3458 3459 /* server-only */ 3460 if (connection->server_binding) RPCRT4_ReleaseBinding(connection->server_binding); 3461 3462 if (connection->wait_release) SetEvent(connection->wait_release); 3463 3464 HeapFree(GetProcessHeap(), 0, connection); 3465 } 3466 } 3467 3468 RPC_STATUS RPCRT4_IsServerListening(const char *protseq, const char *endpoint) 3469 { 3470 const struct connection_ops *ops; 3471 3472 ops = rpcrt4_get_conn_protseq_ops(protseq); 3473 if (!ops) 3474 { 3475 FIXME("not supported for protseq %s\n", protseq); 3476 return RPC_S_INVALID_BINDING; 3477 } 3478 3479 return ops->is_server_listening(endpoint); 3480 } 3481 3482 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, 3483 size_t *tower_size, 3484 const char *protseq, 3485 const char *networkaddr, 3486 const char *endpoint) 3487 { 3488 twr_empty_floor_t *protocol_floor; 3489 const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq); 3490 3491 *tower_size = 0; 3492 3493 if (!protseq_ops) 3494 return RPC_S_INVALID_RPC_PROTSEQ; 3495 3496 if (!tower_data) 3497 { 3498 *tower_size = sizeof(*protocol_floor); 3499 *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint); 3500 return RPC_S_OK; 3501 } 3502 3503 protocol_floor = (twr_empty_floor_t *)tower_data; 3504 protocol_floor->count_lhs = sizeof(protocol_floor->protid); 3505 protocol_floor->protid = protseq_ops->epm_protocols[0]; 3506 protocol_floor->count_rhs = 0; 3507 3508 tower_data += sizeof(*protocol_floor); 3509 3510 *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint); 3511 if (!*tower_size) 3512 return EPT_S_NOT_REGISTERED; 3513 3514 *tower_size += sizeof(*protocol_floor); 3515 3516 return RPC_S_OK; 3517 } 3518 3519 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, 3520 size_t tower_size, 3521 char **protseq, 3522 char **networkaddr, 3523 char **endpoint) 3524 { 3525 const twr_empty_floor_t *protocol_floor; 3526 const twr_empty_floor_t *floor4; 3527 const struct connection_ops *protseq_ops = NULL; 3528 RPC_STATUS status; 3529 unsigned int i; 3530 3531 if (tower_size < sizeof(*protocol_floor)) 3532 return EPT_S_NOT_REGISTERED; 3533 3534 protocol_floor = (const twr_empty_floor_t *)tower_data; 3535 tower_data += sizeof(*protocol_floor); 3536 tower_size -= sizeof(*protocol_floor); 3537 if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) || 3538 (protocol_floor->count_rhs > tower_size)) 3539 return EPT_S_NOT_REGISTERED; 3540 tower_data += protocol_floor->count_rhs; 3541 tower_size -= protocol_floor->count_rhs; 3542 3543 floor4 = (const twr_empty_floor_t *)tower_data; 3544 if ((tower_size < sizeof(*floor4)) || 3545 (floor4->count_lhs != sizeof(floor4->protid))) 3546 return EPT_S_NOT_REGISTERED; 3547 3548 for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++) 3549 if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) && 3550 (floor4->protid == conn_protseq_list[i].epm_protocols[1])) 3551 { 3552 protseq_ops = &conn_protseq_list[i]; 3553 break; 3554 } 3555 3556 if (!protseq_ops) 3557 return EPT_S_NOT_REGISTERED; 3558 3559 status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint); 3560 3561 if ((status == RPC_S_OK) && protseq) 3562 { 3563 *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1); 3564 strcpy(*protseq, protseq_ops->name); 3565 } 3566 3567 return status; 3568 } 3569 3570 /*********************************************************************** 3571 * RpcNetworkIsProtseqValidW (RPCRT4.@) 3572 * 3573 * Checks if the given protocol sequence is known by the RPC system. 3574 * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED. 3575 * 3576 */ 3577 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq) 3578 { 3579 char ps[0x10]; 3580 3581 WideCharToMultiByte(CP_ACP, 0, protseq, -1, 3582 ps, sizeof ps, NULL, NULL); 3583 if (rpcrt4_get_conn_protseq_ops(ps)) 3584 return RPC_S_OK; 3585 3586 FIXME("Unknown protseq %s\n", debugstr_w(protseq)); 3587 3588 return RPC_S_INVALID_RPC_PROTSEQ; 3589 } 3590 3591 /*********************************************************************** 3592 * RpcNetworkIsProtseqValidA (RPCRT4.@) 3593 */ 3594 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq) 3595 { 3596 UNICODE_STRING protseqW; 3597 3598 if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq)) 3599 { 3600 RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer); 3601 RtlFreeUnicodeString(&protseqW); 3602 return ret; 3603 } 3604 return RPC_S_OUT_OF_MEMORY; 3605 } 3606 3607 /*********************************************************************** 3608 * RpcProtseqVectorFreeA (RPCRT4.@) 3609 */ 3610 RPC_STATUS WINAPI RpcProtseqVectorFreeA(RPC_PROTSEQ_VECTORA **protseqs) 3611 { 3612 TRACE("(%p)\n", protseqs); 3613 3614 if (*protseqs) 3615 { 3616 unsigned int i; 3617 for (i = 0; i < (*protseqs)->Count; i++) 3618 HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]); 3619 HeapFree(GetProcessHeap(), 0, *protseqs); 3620 *protseqs = NULL; 3621 } 3622 return RPC_S_OK; 3623 } 3624 3625 /*********************************************************************** 3626 * RpcProtseqVectorFreeW (RPCRT4.@) 3627 */ 3628 RPC_STATUS WINAPI RpcProtseqVectorFreeW(RPC_PROTSEQ_VECTORW **protseqs) 3629 { 3630 TRACE("(%p)\n", protseqs); 3631 3632 if (*protseqs) 3633 { 3634 unsigned int i; 3635 for (i = 0; i < (*protseqs)->Count; i++) 3636 HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]); 3637 HeapFree(GetProcessHeap(), 0, *protseqs); 3638 *protseqs = NULL; 3639 } 3640 return RPC_S_OK; 3641 } 3642 3643 /*********************************************************************** 3644 * RpcNetworkInqProtseqsW (RPCRT4.@) 3645 */ 3646 RPC_STATUS WINAPI RpcNetworkInqProtseqsW( RPC_PROTSEQ_VECTORW** protseqs ) 3647 { 3648 RPC_PROTSEQ_VECTORW *pvector; 3649 unsigned int i; 3650 RPC_STATUS status = RPC_S_OUT_OF_MEMORY; 3651 3652 TRACE("(%p)\n", protseqs); 3653 3654 *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned short*)*ARRAYSIZE(protseq_list))); 3655 if (!*protseqs) 3656 goto end; 3657 pvector = *protseqs; 3658 pvector->Count = 0; 3659 for (i = 0; i < ARRAYSIZE(protseq_list); i++) 3660 { 3661 pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, (strlen(protseq_list[i].name)+1)*sizeof(unsigned short)); 3662 if (pvector->Protseq[i] == NULL) 3663 goto end; 3664 MultiByteToWideChar(CP_ACP, 0, (CHAR*)protseq_list[i].name, -1, 3665 (WCHAR*)pvector->Protseq[i], strlen(protseq_list[i].name) + 1); 3666 pvector->Count++; 3667 } 3668 status = RPC_S_OK; 3669 3670 end: 3671 if (status != RPC_S_OK) 3672 RpcProtseqVectorFreeW(protseqs); 3673 return status; 3674 } 3675 3676 /*********************************************************************** 3677 * RpcNetworkInqProtseqsA (RPCRT4.@) 3678 */ 3679 RPC_STATUS WINAPI RpcNetworkInqProtseqsA(RPC_PROTSEQ_VECTORA** protseqs) 3680 { 3681 RPC_PROTSEQ_VECTORA *pvector; 3682 unsigned int i; 3683 RPC_STATUS status = RPC_S_OUT_OF_MEMORY; 3684 3685 TRACE("(%p)\n", protseqs); 3686 3687 *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned char*)*ARRAYSIZE(protseq_list))); 3688 if (!*protseqs) 3689 goto end; 3690 pvector = *protseqs; 3691 pvector->Count = 0; 3692 for (i = 0; i < ARRAYSIZE(protseq_list); i++) 3693 { 3694 pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, strlen(protseq_list[i].name)+1); 3695 if (pvector->Protseq[i] == NULL) 3696 goto end; 3697 strcpy((char*)pvector->Protseq[i], protseq_list[i].name); 3698 pvector->Count++; 3699 } 3700 status = RPC_S_OK; 3701 3702 end: 3703 if (status != RPC_S_OK) 3704 RpcProtseqVectorFreeA(protseqs); 3705 return status; 3706 } 3707