ReactOS  0.4.15-dev-4570-g4f8bbd1
rpc_transport.c
Go to the documentation of this file.
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 #include "windef.h"
39 #include "winbase.h"
40 #include "winnls.h"
41 #include "winerror.h"
42 #include "wininet.h"
43 #include "wine/winternl.h"
44 #include "winioctl.h"
45 
46 #include "rpc.h"
47 #include "rpcndr.h"
48 
49 #include "wine/debug.h"
50 
51 #include "rpc_binding.h"
52 #include "rpc_assoc.h"
53 #include "rpc_message.h"
54 #include "rpc_server.h"
55 #include "epm_towers.h"
56 
57 #define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000)
58 
60 
61 #ifdef __REACTOS__ /* FIXME: Inspect */
63 {
65 
67  if (io_status.u.Status)
68  {
70  return FALSE;
71  }
72  return TRUE;
73 }
74 #endif
75 
76 static RpcConnection *rpcrt4_spawn_connection(RpcConnection *old_connection);
77 
78 /**** ncacn_np support ****/
79 
80 typedef struct _RpcConnection_np
81 {
85  char *listen_pipe;
90 
92 {
94  return &npc->common;
95 }
96 
98 {
99  HANDLE event = InterlockedExchangePointer(&connection->event_cache, NULL);
100  return event ? event : CreateEventW(NULL, TRUE, FALSE, NULL);
101 }
102 
104 {
105  event = InterlockedExchangePointer(&connection->event_cache, event);
106  if (event)
108 }
109 
110 #ifdef __REACTOS__
111 
128 static DWORD rpcrt4_create_pipe_security(PSECURITY_DESCRIPTOR *SecDesc)
129 {
130  DWORD ErrCode;
131  PACL Dacl;
132  ULONG DaclSize, RelSDSize = 0;
133  PSID EveryoneSid = NULL, AnonymousSid = NULL, AdminsSid = NULL;
134  PSECURITY_DESCRIPTOR AbsSD = NULL, RelSD = NULL;
137 
139  1,
141  0, 0, 0, 0, 0, 0, 0,
142  &EveryoneSid))
143  {
144  ERR("rpcrt4_create_pipe_security(): Failed to allocate Everyone SID (error code %d)\n", GetLastError());
145  return GetLastError();
146  }
147 
149  1,
151  0, 0, 0, 0, 0, 0, 0,
152  &AnonymousSid))
153  {
154  ERR("rpcrt4_create_pipe_security(): Failed to allocate Anonymous SID (error code %d)\n", GetLastError());
155  ErrCode = GetLastError();
156  goto Quit;
157  }
158 
160  2,
163  0, 0, 0, 0, 0, 0,
164  &AdminsSid))
165  {
166  ERR("rpcrt4_create_pipe_security(): Failed to allocate Admins SID (error code %d)\n", GetLastError());
167  ErrCode = GetLastError();
168  goto Quit;
169  }
170 
172  if (AbsSD == NULL)
173  {
174  ERR("rpcrt4_create_pipe_security(): Failed to allocate absolute SD!\n");
175  ErrCode = ERROR_OUTOFMEMORY;
176  goto Quit;
177  }
178 
180  {
181  ERR("rpcrt4_create_pipe_security(): Failed to create absolute SD (error code %d)\n", GetLastError());
182  ErrCode = GetLastError();
183  goto Quit;
184  }
185 
186  DaclSize = sizeof(ACL) +
187  sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(EveryoneSid) +
188  sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(AnonymousSid) +
189  sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(AdminsSid);
190 
191 
193  if (Dacl == NULL)
194  {
195  ERR("rpcrt4_create_pipe_security(): Failed to allocate DACL!\n");
196  ErrCode = ERROR_OUTOFMEMORY;
197  goto Quit;
198  }
199 
201  {
202  ERR("rpcrt4_create_pipe_security(): Failed to create DACL (error code %d)\n", GetLastError());
203  ErrCode = GetLastError();
204  goto Quit;
205  }
206 
208  ACL_REVISION,
210  EveryoneSid))
211  {
212  ERR("rpcrt4_create_pipe_security(): Failed to set up ACE for Everyone SID (error code %d)\n", GetLastError());
213  ErrCode = GetLastError();
214  goto Quit;
215  }
216 
218  ACL_REVISION,
220  AnonymousSid))
221  {
222  ERR("rpcrt4_create_pipe_security(): Failed to set up ACE for Anonymous SID (error code %d)\n", GetLastError());
223  ErrCode = GetLastError();
224  goto Quit;
225  }
226 
228  ACL_REVISION,
229  GENERIC_ALL,
230  AdminsSid))
231  {
232  ERR("rpcrt4_create_pipe_security(): Failed to set up ACE for Admins SID (error code %d)\n", GetLastError());
233  ErrCode = GetLastError();
234  goto Quit;
235  }
236 
237  if (!SetSecurityDescriptorDacl(AbsSD, TRUE, Dacl, FALSE))
238  {
239  ERR("rpcrt4_create_pipe_security(): Failed to set DACL to absolute SD (error code %d)\n", GetLastError());
240  ErrCode = GetLastError();
241  goto Quit;
242  }
243 
244  if (!SetSecurityDescriptorOwner(AbsSD, AdminsSid, FALSE))
245  {
246  ERR("rpcrt4_create_pipe_security(): Failed to set SD owner (error code %d)\n", GetLastError());
247  ErrCode = GetLastError();
248  goto Quit;
249  }
250 
251  if (!SetSecurityDescriptorGroup(AbsSD, AdminsSid, FALSE))
252  {
253  ERR("rpcrt4_create_pipe_security(): Failed to set SD group (error code %d)\n", GetLastError());
254  ErrCode = GetLastError();
255  goto Quit;
256  }
257 
258  if (!MakeSelfRelativeSD(AbsSD, NULL, &RelSDSize) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
259  {
260  ERR("rpcrt4_create_pipe_security(): Unexpected error code (error code %d -- must be ERROR_INSUFFICIENT_BUFFER)\n", GetLastError());
261  ErrCode = GetLastError();
262  goto Quit;
263  }
264 
265  RelSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, RelSDSize);
266  if (RelSD == NULL)
267  {
268  ERR("rpcrt4_create_pipe_security(): Failed to allocate relative SD!\n");
269  ErrCode = ERROR_OUTOFMEMORY;
270  goto Quit;
271  }
272 
273  if (!MakeSelfRelativeSD(AbsSD, RelSD, &RelSDSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
274  {
275  ERR("rpcrt4_create_pipe_security(): Failed to allocate relative SD, buffer too smal (expected size %lu)\n", RelSDSize);
276  ErrCode = ERROR_INSUFFICIENT_BUFFER;
277  goto Quit;
278  }
279 
280  TRACE("rpcrt4_create_pipe_security(): Success!\n");
281  *SecDesc = RelSD;
282  ErrCode = ERROR_SUCCESS;
283 
284 Quit:
285  if (ErrCode != ERROR_SUCCESS)
286  {
287  if (RelSD != NULL)
288  {
289  HeapFree(GetProcessHeap(), 0, RelSD);
290  }
291  }
292 
293  if (EveryoneSid != NULL)
294  {
295  FreeSid(EveryoneSid);
296  }
297 
298  if (AnonymousSid != NULL)
299  {
300  FreeSid(AnonymousSid);
301  }
302 
303  if (AdminsSid != NULL)
304  {
305  FreeSid(AdminsSid);
306  }
307 
308  if (Dacl != NULL)
309  {
311  }
312 
313  if (AbsSD != NULL)
314  {
315  HeapFree(GetProcessHeap(), 0, AbsSD);
316  }
317 
318  return ErrCode;
319 }
320 #endif
321 
323 {
324  RpcConnection_np *connection = (RpcConnection_np *) conn;
325 #ifdef __REACTOS__
326  DWORD ErrCode;
327  SECURITY_ATTRIBUTES SecurityAttributes;
328  PSECURITY_DESCRIPTOR PipeSecDesc;
329 #endif
330 
331  TRACE("listening on %s\n", connection->listen_pipe);
332 
333 #ifdef __REACTOS__
334  ErrCode = rpcrt4_create_pipe_security(&PipeSecDesc);
335  if (ErrCode != ERROR_SUCCESS)
336  {
337  ERR("rpcrt4_conn_create_pipe(): Pipe security descriptor creation failed!\n");
339  }
340 
341  SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
342  SecurityAttributes.lpSecurityDescriptor = PipeSecDesc;
343  SecurityAttributes.bInheritHandle = FALSE;
344 
348  RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, &SecurityAttributes);
349  HeapFree(GetProcessHeap(), 0, PipeSecDesc);
350 #else
355 #endif
356  if (connection->pipe == INVALID_HANDLE_VALUE)
357  {
358  WARN("CreateNamedPipe failed with error %d\n", GetLastError());
360  {
362  }
363  else
364  {
366  }
367  }
368 
369  return RPC_S_OK;
370 }
371 
373 {
374  RpcConnection_np *npc = (RpcConnection_np *) Connection;
375  HANDLE pipe;
376  DWORD err, dwMode;
377 
378  TRACE("connecting to %s\n", pname);
379 
380  while (TRUE) {
381  DWORD dwFlags = 0;
382  if (Connection->QOS)
383  {
385  switch (Connection->QOS->qos->ImpersonationType)
386  {
388  /* FIXME: what to do here? */
389  break;
392  break;
395  break;
398  break;
401  break;
402  }
403  if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC)
405  }
408  if (pipe != INVALID_HANDLE_VALUE) break;
409  err = GetLastError();
410  if (err == ERROR_PIPE_BUSY) {
412  TRACE("retrying busy server\n");
413  continue;
414  }
415  TRACE("connection failed, error=%x\n", err);
416  return RPC_S_SERVER_TOO_BUSY;
417 #ifdef __REACTOS__
418  } else if (err == ERROR_BAD_NETPATH) {
419  TRACE("connection failed, error=%x\n", err);
421 #endif
422  }
423  if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
424  err = GetLastError();
425  WARN("connection failed, error=%x\n", err);
427  }
428  }
429 
430  /* success */
431  /* pipe is connected; change to message-read mode. */
432  dwMode = PIPE_READMODE_MESSAGE;
433  SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
434  npc->pipe = pipe;
435 
436  return RPC_S_OK;
437 }
438 
439 static char *ncalrpc_pipe_name(const char *endpoint)
440 {
441  static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
442  char *pipe_name;
443 
444  /* protseq=ncalrpc: supposed to use NT LPC ports,
445  * but we'll implement it with named pipes for now */
446  pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(endpoint));
447  strcat(strcpy(pipe_name, prefix), endpoint);
448  return pipe_name;
449 }
450 
452 {
453  RpcConnection_np *npc = (RpcConnection_np *) Connection;
454  RPC_STATUS r;
455  LPSTR pname;
456 
457  /* already connected? */
458  if (npc->pipe)
459  return RPC_S_OK;
460 
461  pname = ncalrpc_pipe_name(Connection->Endpoint);
462  r = rpcrt4_conn_open_pipe(Connection, pname, TRUE);
463  I_RpcFree(pname);
464 
465  return r;
466 }
467 
469 {
470  RPC_STATUS r;
471  RpcConnection *Connection;
472  char generated_endpoint[22];
473 
474  if (!endpoint)
475  {
476  static LONG lrpc_nameless_id;
477  DWORD process_id = GetCurrentProcessId();
478  ULONG id = InterlockedIncrement(&lrpc_nameless_id);
479  snprintf(generated_endpoint, sizeof(generated_endpoint),
480  "LRPC%08x.%08x", process_id, id);
481  endpoint = generated_endpoint;
482  }
483 
484  r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
485  endpoint, NULL, NULL, NULL, NULL);
486  if (r != RPC_S_OK)
487  return r;
488 
489  ((RpcConnection_np*)Connection)->listen_pipe = ncalrpc_pipe_name(Connection->Endpoint);
490  r = rpcrt4_conn_create_pipe(Connection);
491 
492  EnterCriticalSection(&protseq->cs);
493  list_add_head(&protseq->listeners, &Connection->protseq_entry);
494  Connection->protseq = protseq;
495  LeaveCriticalSection(&protseq->cs);
496 
497  return r;
498 }
499 
500 #ifdef __REACTOS__
501 static char *ncacn_pipe_name(const char *server, const char *endpoint)
502 #else
503 static char *ncacn_pipe_name(const char *endpoint)
504 #endif
505 {
506 #ifdef __REACTOS__
507  static const char prefix[] = "\\\\";
508  static const char local[] = ".";
509  char ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
510  DWORD bufLen = ARRAY_SIZE(ComputerName);
511 #else
512  static const char prefix[] = "\\\\.";
513 #endif
514  char *pipe_name;
515 
516 #ifdef __REACTOS__
517  if (server != NULL && *server != 0)
518  {
519  /* Trim any leading UNC server prefix. */
520  if (server[0] == '\\' && server[1] == '\\')
521  server += 2;
522 
523  /* If the server represents the local computer, use instead
524  * the local prefix to avoid a round in UNC name resolution. */
525  if (GetComputerNameA(ComputerName, &bufLen) &&
526  (stricmp(ComputerName, server) == 0))
527  {
528  server = local;
529  }
530  }
531  else
532  {
533  server = local;
534  }
535 #endif
536 
537  /* protseq=ncacn_np: named pipes */
538 #ifdef __REACTOS__
539  pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(server) + strlen(endpoint));
540  strcpy(pipe_name, prefix);
541  strcat(pipe_name, server);
542  strcat(pipe_name, endpoint);
543 #else
544  pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(endpoint));
545  strcat(strcpy(pipe_name, prefix), endpoint);
546 #endif
547  return pipe_name;
548 }
549 
551 {
552  RpcConnection_np *npc = (RpcConnection_np *) Connection;
553  RPC_STATUS r;
554  LPSTR pname;
555 
556  /* already connected? */
557  if (npc->pipe)
558  return RPC_S_OK;
559 
560 #ifdef __REACTOS__
561  pname = ncacn_pipe_name(Connection->NetworkAddr, Connection->Endpoint);
562 #else
563  pname = ncacn_pipe_name(Connection->Endpoint);
564 #endif
565  r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);
566  I_RpcFree(pname);
567 
568  return r;
569 }
570 
572 {
573  RPC_STATUS r;
574  RpcConnection *Connection;
575  char generated_endpoint[26];
576 
577  if (!endpoint)
578  {
579  static LONG np_nameless_id;
580  DWORD process_id = GetCurrentProcessId();
581  ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 );
582  snprintf(generated_endpoint, sizeof(generated_endpoint),
583  "\\\\pipe\\\\%08x.%03x", process_id, id);
584  endpoint = generated_endpoint;
585  }
586 
587  r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
588  endpoint, NULL, NULL, NULL, NULL);
589  if (r != RPC_S_OK)
590  return r;
591 
592 #ifdef __REACTOS__
593  ((RpcConnection_np*)Connection)->listen_pipe = ncacn_pipe_name(NULL, Connection->Endpoint);
594 #else
595  ((RpcConnection_np*)Connection)->listen_pipe = ncacn_pipe_name(Connection->Endpoint);
596 #endif
597  r = rpcrt4_conn_create_pipe(Connection);
598 
599  EnterCriticalSection(&protseq->cs);
600  list_add_head(&protseq->listeners, &Connection->protseq_entry);
601  Connection->protseq = protseq;
602  LeaveCriticalSection(&protseq->cs);
603 
604  return r;
605 }
606 
608 {
609  /* because of the way named pipes work, we'll transfer the connected pipe
610  * to the child, then reopen the server binding to continue listening */
611 
612  new_npc->pipe = old_npc->pipe;
613  old_npc->pipe = 0;
614  assert(!old_npc->listen_event);
615 }
616 
618 {
621 
622  rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
623  status = rpcrt4_conn_create_pipe(old_conn);
624 
625  /* Store the local computer name as the NetworkAddr for ncacn_np as long as
626  * we don't support named pipes over the network. */
627  new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, len);
628  if (!GetComputerNameA(new_conn->NetworkAddr, &len))
629  {
630  ERR("Failed to retrieve the computer name, error %u\n", GetLastError());
631  return RPC_S_OUT_OF_RESOURCES;
632  }
633 
634  return status;
635 }
636 
637 static RPC_STATUS is_pipe_listening(const char *pipe_name)
638 {
639  return WaitNamedPipeA(pipe_name, 1) ? RPC_S_OK : RPC_S_NOT_LISTENING;
640 }
641 
643 {
644  char *pipe_name;
646 
647 #ifdef __REACTOS__
648  pipe_name = ncacn_pipe_name(NULL, endpoint);
649 #else
650  pipe_name = ncacn_pipe_name(endpoint);
651 #endif
652  status = is_pipe_listening(pipe_name);
653  I_RpcFree(pipe_name);
654  return status;
655 }
656 
658 {
659  char *pipe_name;
661 
662  pipe_name = ncalrpc_pipe_name(endpoint);
663  status = is_pipe_listening(pipe_name);
664  I_RpcFree(pipe_name);
665  return status;
666 }
667 
669 {
672 
673  TRACE("%s\n", old_conn->Endpoint);
674 
675  rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
676  status = rpcrt4_conn_create_pipe(old_conn);
677 
678  /* Store the local computer name as the NetworkAddr for ncalrpc. */
679  new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, len);
680  if (!GetComputerNameA(new_conn->NetworkAddr, &len))
681  {
682  ERR("Failed to retrieve the computer name, error %u\n", GetLastError());
683  return RPC_S_OUT_OF_RESOURCES;
684  }
685 
686  return status;
687 }
688 
689 static int rpcrt4_conn_np_read(RpcConnection *conn, void *buffer, unsigned int count)
690 {
691  RpcConnection_np *connection = (RpcConnection_np *) conn;
692  HANDLE event;
694 
695  event = get_np_event(connection);
696  if (!event)
697  return -1;
698 
699  if (connection->read_closed)
701  else
702  status = NtReadFile(connection->pipe, event, NULL, NULL, &connection->io_status, buffer, count, NULL, NULL);
703  if (status == STATUS_PENDING)
704  {
705  /* check read_closed again before waiting to avoid a race */
706  if (connection->read_closed)
707  {
709 #ifdef __REACTOS__ /* FIXME: We should also cancel I/O for other threads */
710  NtCancelIoFile(connection->pipe, &io_status);
711 #else
712  NtCancelIoFileEx(connection->pipe, &connection->io_status, &io_status);
713 #endif
714  }
716  status = connection->io_status.u.Status;
717  }
718  release_np_event(connection, event);
719  return status && status != STATUS_BUFFER_OVERFLOW ? -1 : connection->io_status.Information;
720 }
721 
722 static int rpcrt4_conn_np_write(RpcConnection *conn, const void *buffer, unsigned int count)
723 {
724  RpcConnection_np *connection = (RpcConnection_np *) conn;
726  HANDLE event;
728 
729  event = get_np_event(connection);
730  if (!event)
731  return -1;
732 
733  status = NtWriteFile(connection->pipe, event, NULL, NULL, &io_status, buffer, count, NULL, NULL);
734  if (status == STATUS_PENDING)
735  {
737  status = io_status.u.Status;
738  }
739  release_np_event(connection, event);
740  if (status)
741  return -1;
742 
743  assert(io_status.Information == count);
744  return count;
745 }
746 
748 {
749  RpcConnection_np *connection = (RpcConnection_np *) conn;
750  if (connection->pipe)
751  {
752  FlushFileBuffers(connection->pipe);
753  CloseHandle(connection->pipe);
754  connection->pipe = 0;
755  }
756  if (connection->listen_event)
757  {
758  CloseHandle(connection->listen_event);
759  connection->listen_event = 0;
760  }
761  if (connection->event_cache)
762  {
763  CloseHandle(connection->event_cache);
764  connection->event_cache = 0;
765  }
766  return 0;
767 }
768 
770 {
771  RpcConnection_np *connection = (RpcConnection_np*)conn;
773 
774  connection->read_closed = TRUE;
775 #ifdef __REACTOS__ /* FIXME: We should also cancel I/O for other threads */
776  NtCancelIoFile(connection->pipe, &io_status);
777 #else
778  NtCancelIoFileEx(connection->pipe, &connection->io_status, &io_status);
779 #endif
780 }
781 
783 {
784  RpcConnection_np *connection = (RpcConnection_np *)conn;
785  CancelIoEx(connection->pipe, NULL);
786 }
787 
789 {
790  return rpcrt4_conn_np_read(conn, NULL, 0);
791 }
792 
793 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,
794  const char *networkaddr,
795  const char *endpoint)
796 {
797  twr_empty_floor_t *smb_floor;
798  twr_empty_floor_t *nb_floor;
799  size_t size;
800  size_t networkaddr_size;
801  size_t endpoint_size;
802 
803  TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
804 
805  networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1;
806  endpoint_size = endpoint ? strlen(endpoint) + 1 : 1;
807  size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size;
808 
809  if (!tower_data)
810  return size;
811 
812  smb_floor = (twr_empty_floor_t *)tower_data;
813 
814  tower_data += sizeof(*smb_floor);
815 
816  smb_floor->count_lhs = sizeof(smb_floor->protid);
817  smb_floor->protid = EPM_PROTOCOL_SMB;
818  smb_floor->count_rhs = endpoint_size;
819 
820  if (endpoint)
821  memcpy(tower_data, endpoint, endpoint_size);
822  else
823  tower_data[0] = 0;
824  tower_data += endpoint_size;
825 
826  nb_floor = (twr_empty_floor_t *)tower_data;
827 
828  tower_data += sizeof(*nb_floor);
829 
830  nb_floor->count_lhs = sizeof(nb_floor->protid);
831  nb_floor->protid = EPM_PROTOCOL_NETBIOS;
832  nb_floor->count_rhs = networkaddr_size;
833 
834  if (networkaddr)
835  memcpy(tower_data, networkaddr, networkaddr_size);
836  else
837  tower_data[0] = 0;
838 
839  return size;
840 }
841 
842 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data,
843  size_t tower_size,
844  char **networkaddr,
845  char **endpoint)
846 {
847  const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data;
848  const twr_empty_floor_t *nb_floor;
849 
850  TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
851 
852  if (tower_size < sizeof(*smb_floor))
853  return EPT_S_NOT_REGISTERED;
854 
855  tower_data += sizeof(*smb_floor);
856  tower_size -= sizeof(*smb_floor);
857 
858  if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) ||
859  (smb_floor->protid != EPM_PROTOCOL_SMB) ||
860  (smb_floor->count_rhs > tower_size) ||
861  (tower_data[smb_floor->count_rhs - 1] != '\0'))
862  return EPT_S_NOT_REGISTERED;
863 
864  if (endpoint)
865  {
866  *endpoint = I_RpcAllocate(smb_floor->count_rhs);
867  if (!*endpoint)
868  return RPC_S_OUT_OF_RESOURCES;
869  memcpy(*endpoint, tower_data, smb_floor->count_rhs);
870  }
871  tower_data += smb_floor->count_rhs;
872  tower_size -= smb_floor->count_rhs;
873 
874  if (tower_size < sizeof(*nb_floor))
875  return EPT_S_NOT_REGISTERED;
876 
877  nb_floor = (const twr_empty_floor_t *)tower_data;
878 
879  tower_data += sizeof(*nb_floor);
880  tower_size -= sizeof(*nb_floor);
881 
882  if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) ||
883  (nb_floor->protid != EPM_PROTOCOL_NETBIOS) ||
884  (nb_floor->count_rhs > tower_size) ||
885  (tower_data[nb_floor->count_rhs - 1] != '\0'))
886  return EPT_S_NOT_REGISTERED;
887 
888  if (networkaddr)
889  {
890  *networkaddr = I_RpcAllocate(nb_floor->count_rhs);
891  if (!*networkaddr)
892  {
893  if (endpoint)
894  {
896  *endpoint = NULL;
897  }
898  return RPC_S_OUT_OF_RESOURCES;
899  }
900  memcpy(*networkaddr, tower_data, nb_floor->count_rhs);
901  }
902 
903  return RPC_S_OK;
904 }
905 
907 {
908  RpcConnection_np *npc = (RpcConnection_np *)conn;
909  BOOL ret;
910 
911  TRACE("(%p)\n", conn);
912 
913  if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
915 
917  if (!ret)
918  {
920  WARN("ImpersonateNamedPipeClient failed with error %u\n", error);
921  switch (error)
922  {
925  }
926  }
927  return RPC_S_OK;
928 }
929 
931 {
932  BOOL ret;
933 
934  TRACE("(%p)\n", conn);
935 
936  if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
937  return RPCRT4_default_revert_to_self(conn);
938 
939  ret = RevertToSelf();
940  if (!ret)
941  {
942  WARN("RevertToSelf failed with error %u\n", GetLastError());
944  }
945  return RPC_S_OK;
946 }
947 
948 typedef struct _RpcServerProtseq_np
949 {
953 
955 {
957  if (ps)
959  return &ps->common;
960 }
961 
963 {
965  SetEvent(npps->mgr_event);
966 }
967 
968 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
969 {
970  HANDLE *objs = prev_array;
971  RpcConnection_np *conn;
973 
974  EnterCriticalSection(&protseq->cs);
975 
976  /* open and count connections */
977  *count = 1;
978  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry)
979  {
980  if (!conn->pipe && rpcrt4_conn_create_pipe(&conn->common) != RPC_S_OK)
981  continue;
982  if (!conn->listen_event)
983  {
985  HANDLE event;
986 
987  event = get_np_event(conn);
988  if (!event)
989  continue;
990 
992  switch (status)
993  {
994  case STATUS_SUCCESS:
996  conn->io_status.u.Status = status;
997  SetEvent(event);
998  break;
999  case STATUS_PENDING:
1000  break;
1001  default:
1002  ERR("pipe listen error %x\n", status);
1003  continue;
1004  }
1005 
1006  conn->listen_event = event;
1007  }
1008  (*count)++;
1009  }
1010 
1011  /* make array of connections */
1012  if (objs)
1013  objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
1014  else
1015  objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
1016  if (!objs)
1017  {
1018  ERR("couldn't allocate objs\n");
1019  LeaveCriticalSection(&protseq->cs);
1020  return NULL;
1021  }
1022 
1023  objs[0] = npps->mgr_event;
1024  *count = 1;
1025  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry)
1026  {
1027  if (conn->listen_event)
1028  objs[(*count)++] = conn->listen_event;
1029  }
1030  LeaveCriticalSection(&protseq->cs);
1031  return objs;
1032 }
1033 
1035 {
1036  HeapFree(GetProcessHeap(), 0, array);
1037 }
1038 
1039 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1040 {
1041  HANDLE b_handle;
1042  HANDLE *objs = wait_array;
1043  DWORD res;
1044  RpcConnection *cconn = NULL;
1045  RpcConnection_np *conn;
1046 
1047  if (!objs)
1048  return -1;
1049 
1050  do
1051  {
1052  /* an alertable wait isn't strictly necessary, but due to our
1053  * overlapped I/O implementation in Wine we need to free some memory
1054  * by the file user APC being called, even if no completion routine was
1055  * specified at the time of starting the async operation */
1057  } while (res == WAIT_IO_COMPLETION);
1058 
1059  if (res == WAIT_OBJECT_0)
1060  return 0;
1061  else if (res == WAIT_FAILED)
1062  {
1063  ERR("wait failed with error %d\n", GetLastError());
1064  return -1;
1065  }
1066  else
1067  {
1068  b_handle = objs[res - WAIT_OBJECT_0];
1069  /* find which connection got a RPC */
1070  EnterCriticalSection(&protseq->cs);
1071  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry)
1072  {
1073  if (b_handle == conn->listen_event)
1074  {
1075  release_np_event(conn, conn->listen_event);
1076  conn->listen_event = NULL;
1078  cconn = rpcrt4_spawn_connection(&conn->common);
1079  else
1080  ERR("listen failed %x\n", conn->io_status.u.Status);
1081  break;
1082  }
1083  }
1084  LeaveCriticalSection(&protseq->cs);
1085  if (!cconn)
1086  {
1087  ERR("failed to locate connection for handle %p\n", b_handle);
1088  return -1;
1089  }
1090  RPCRT4_new_client(cconn);
1091  return 1;
1092  }
1093 }
1094 
1095 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data,
1096  const char *networkaddr,
1097  const char *endpoint)
1098 {
1099  twr_empty_floor_t *pipe_floor;
1100  size_t size;
1101  size_t endpoint_size;
1102 
1103  TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
1104 
1105  endpoint_size = strlen(endpoint) + 1;
1106  size = sizeof(*pipe_floor) + endpoint_size;
1107 
1108  if (!tower_data)
1109  return size;
1110 
1111  pipe_floor = (twr_empty_floor_t *)tower_data;
1112 
1113  tower_data += sizeof(*pipe_floor);
1114 
1115  pipe_floor->count_lhs = sizeof(pipe_floor->protid);
1116  pipe_floor->protid = EPM_PROTOCOL_PIPE;
1117  pipe_floor->count_rhs = endpoint_size;
1118 
1119  memcpy(tower_data, endpoint, endpoint_size);
1120 
1121  return size;
1122 }
1123 
1124 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data,
1125  size_t tower_size,
1126  char **networkaddr,
1127  char **endpoint)
1128 {
1129  const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data;
1130 
1131  TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
1132 
1133  if (tower_size < sizeof(*pipe_floor))
1134  return EPT_S_NOT_REGISTERED;
1135 
1136  tower_data += sizeof(*pipe_floor);
1137  tower_size -= sizeof(*pipe_floor);
1138 
1139  if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) ||
1140  (pipe_floor->protid != EPM_PROTOCOL_PIPE) ||
1141  (pipe_floor->count_rhs > tower_size) ||
1142  (tower_data[pipe_floor->count_rhs - 1] != '\0'))
1143  return EPT_S_NOT_REGISTERED;
1144 
1145  if (networkaddr)
1146  *networkaddr = NULL;
1147 
1148  if (endpoint)
1149  {
1150  *endpoint = I_RpcAllocate(pipe_floor->count_rhs);
1151  if (!*endpoint)
1152  return RPC_S_OUT_OF_RESOURCES;
1153  memcpy(*endpoint, tower_data, pipe_floor->count_rhs);
1154  }
1155 
1156  return RPC_S_OK;
1157 }
1158 
1160 {
1161  return FALSE;
1162 }
1163 
1165  unsigned char *in_buffer,
1166  unsigned int in_size,
1167  unsigned char *out_buffer,
1168  unsigned int *out_size)
1169 {
1170  /* since this protocol is local to the machine there is no need to
1171  * authenticate the caller */
1172  *out_size = 0;
1173  return RPC_S_OK;
1174 }
1175 
1178  RpcPktHdr *hdr, unsigned int hdr_size,
1179  unsigned char *stub_data, unsigned int stub_data_size,
1180  RpcAuthVerifier *auth_hdr,
1181  unsigned char *auth_value, unsigned int auth_value_size)
1182 {
1183  /* since this protocol is local to the machine there is no need to secure
1184  * the packet */
1185  return RPC_S_OK;
1186 }
1187 
1189  RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name,
1190  ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags)
1191 {
1192  TRACE("(%p, %p, %p, %p, %p, %p, 0x%x)\n", conn, privs,
1193  server_princ_name, authn_level, authn_svc, authz_svc, flags);
1194 
1195  if (privs)
1196  {
1197  FIXME("privs not implemented\n");
1198  *privs = NULL;
1199  }
1200  if (server_princ_name)
1201  {
1202  FIXME("server_princ_name not implemented\n");
1203  *server_princ_name = NULL;
1204  }
1205  if (authn_level) *authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
1206  if (authn_svc) *authn_svc = RPC_C_AUTHN_WINNT;
1207  if (authz_svc)
1208  {
1209  FIXME("authorization service not implemented\n");
1210  *authz_svc = RPC_C_AUTHZ_NONE;
1211  }
1212  if (flags)
1213  FIXME("flags 0x%x not implemented\n", flags);
1214 
1215  return RPC_S_OK;
1216 }
1217 
1218 /**** ncacn_ip_tcp support ****/
1219 
1220 static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1221  const char *networkaddr,
1222  unsigned char tcp_protid,
1223  const char *endpoint)
1224 {
1225  twr_tcp_floor_t *tcp_floor;
1226  twr_ipv4_floor_t *ipv4_floor;
1227  struct addrinfo *ai;
1228  struct addrinfo hints;
1229  int ret;
1230  size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
1231 
1232  TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
1233 
1234  if (!tower_data)
1235  return size;
1236 
1237  tcp_floor = (twr_tcp_floor_t *)tower_data;
1238  tower_data += sizeof(*tcp_floor);
1239 
1240  ipv4_floor = (twr_ipv4_floor_t *)tower_data;
1241 
1242  tcp_floor->count_lhs = sizeof(tcp_floor->protid);
1243  tcp_floor->protid = tcp_protid;
1244  tcp_floor->count_rhs = sizeof(tcp_floor->port);
1245 
1246  ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
1247  ipv4_floor->protid = EPM_PROTOCOL_IP;
1248  ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
1249 
1250  hints.ai_flags = AI_NUMERICHOST;
1251  /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
1252  hints.ai_family = PF_INET;
1253  hints.ai_socktype = SOCK_STREAM;
1254  hints.ai_protocol = IPPROTO_TCP;
1255  hints.ai_addrlen = 0;
1256  hints.ai_addr = NULL;
1257  hints.ai_canonname = NULL;
1258  hints.ai_next = NULL;
1259 
1260  ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
1261  if (ret)
1262  {
1263  ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
1264  if (ret)
1265  {
1266  ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
1267  return 0;
1268  }
1269  }
1270 
1271  if (ai->ai_family == PF_INET)
1272  {
1273  const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
1274  tcp_floor->port = sin->sin_port;
1275  ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
1276  }
1277  else
1278  {
1279  ERR("unexpected protocol family %d\n", ai->ai_family);
1280  freeaddrinfo(ai);
1281  return 0;
1282  }
1283 
1284  freeaddrinfo(ai);
1285 
1286  return size;
1287 }
1288 
1289 static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1290  size_t tower_size,
1291  char **networkaddr,
1292  unsigned char tcp_protid,
1293  char **endpoint)
1294 {
1295  const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
1296  const twr_ipv4_floor_t *ipv4_floor;
1297  struct in_addr in_addr;
1298 
1299  TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
1300 
1301  if (tower_size < sizeof(*tcp_floor))
1302  return EPT_S_NOT_REGISTERED;
1303 
1304  tower_data += sizeof(*tcp_floor);
1305  tower_size -= sizeof(*tcp_floor);
1306 
1307  if (tower_size < sizeof(*ipv4_floor))
1308  return EPT_S_NOT_REGISTERED;
1309 
1310  ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
1311 
1312  if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
1313  (tcp_floor->protid != tcp_protid) ||
1314  (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
1315  (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
1316  (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
1317  (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
1318  return EPT_S_NOT_REGISTERED;
1319 
1320  if (endpoint)
1321  {
1322  *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
1323  if (!*endpoint)
1324  return RPC_S_OUT_OF_RESOURCES;
1325  sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
1326  }
1327 
1328  if (networkaddr)
1329  {
1330  *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
1331  if (!*networkaddr)
1332  {
1333  if (endpoint)
1334  {
1335  I_RpcFree(*endpoint);
1336  *endpoint = NULL;
1337  }
1338  return RPC_S_OUT_OF_RESOURCES;
1339  }
1340  in_addr.s_addr = ipv4_floor->ipv4addr;
1341  if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
1342  {
1343  ERR("inet_ntop: %u\n", WSAGetLastError());
1344  I_RpcFree(*networkaddr);
1345  *networkaddr = NULL;
1346  if (endpoint)
1347  {
1348  I_RpcFree(*endpoint);
1349  *endpoint = NULL;
1350  }
1351  return EPT_S_NOT_REGISTERED;
1352  }
1353  }
1354 
1355  return RPC_S_OK;
1356 }
1357 
1358 typedef struct _RpcConnection_tcp
1359 {
1361  int sock;
1365 
1367 {
1368  static BOOL wsa_inited;
1369  if (!wsa_inited)
1370  {
1371  WSADATA wsadata;
1372  WSAStartup(MAKEWORD(2, 2), &wsadata);
1373  /* Note: WSAStartup can be called more than once so we don't bother with
1374  * making accesses to wsa_inited thread-safe */
1375  wsa_inited = TRUE;
1376  }
1379  if (!tcpc->sock_event || !tcpc->cancel_event)
1380  {
1381  ERR("event creation failed\n");
1382  if (tcpc->sock_event) CloseHandle(tcpc->sock_event);
1383  return FALSE;
1384  }
1385  return TRUE;
1386 }
1387 
1389 {
1390  HANDLE wait_handles[2];
1391  DWORD res;
1392  if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR)
1393  {
1394  ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1395  return FALSE;
1396  }
1397  wait_handles[0] = tcpc->sock_event;
1398  wait_handles[1] = tcpc->cancel_event;
1399  res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE);
1400  switch (res)
1401  {
1402  case WAIT_OBJECT_0:
1403  return TRUE;
1404  case WAIT_OBJECT_0 + 1:
1405  return FALSE;
1406  default:
1407  ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1408  return FALSE;
1409  }
1410 }
1411 
1413 {
1414  DWORD res;
1415  if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
1416  {
1417  ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1418  return FALSE;
1419  }
1421  switch (res)
1422  {
1423  case WAIT_OBJECT_0:
1424  return TRUE;
1425  default:
1426  ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1427  return FALSE;
1428  }
1429 }
1430 
1432 {
1433  RpcConnection_tcp *tcpc;
1435  if (tcpc == NULL)
1436  return NULL;
1437  tcpc->sock = -1;
1438  if (!rpcrt4_sock_wait_init(tcpc))
1439  {
1440  HeapFree(GetProcessHeap(), 0, tcpc);
1441  return NULL;
1442  }
1443  return &tcpc->common;
1444 }
1445 
1447 {
1448  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1449  int sock;
1450  int ret;
1451  struct addrinfo *ai;
1452  struct addrinfo *ai_cur;
1453  struct addrinfo hints;
1454 
1455  TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
1456 
1457  if (tcpc->sock != -1)
1458  return RPC_S_OK;
1459 
1460  hints.ai_flags = 0;
1461  hints.ai_family = PF_UNSPEC;
1462  hints.ai_socktype = SOCK_STREAM;
1463  hints.ai_protocol = IPPROTO_TCP;
1464  hints.ai_addrlen = 0;
1465  hints.ai_addr = NULL;
1466  hints.ai_canonname = NULL;
1467  hints.ai_next = NULL;
1468 
1469  ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai);
1470  if (ret)
1471  {
1472  ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr,
1473  Connection->Endpoint, gai_strerror(ret));
1474  return RPC_S_SERVER_UNAVAILABLE;
1475  }
1476 
1477  for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1478  {
1479  int val;
1480  u_long nonblocking;
1481 
1482  if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1483  {
1484  TRACE("skipping non-IP/IPv6 address family\n");
1485  continue;
1486  }
1487 
1488  if (TRACE_ON(rpc))
1489  {
1490  char host[256];
1491  char service[256];
1492  getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1493  host, sizeof(host), service, sizeof(service),
1495  TRACE("trying %s:%s\n", host, service);
1496  }
1497 
1498  sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1499  if (sock == -1)
1500  {
1501  WARN("socket() failed: %u\n", WSAGetLastError());
1502  continue;
1503  }
1504 
1505  if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
1506  {
1507  WARN("connect() failed: %u\n", WSAGetLastError());
1508  closesocket(sock);
1509  continue;
1510  }
1511 
1512  /* RPC depends on having minimal latency so disable the Nagle algorithm */
1513  val = 1;
1514  setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
1515  nonblocking = 1;
1516  ioctlsocket(sock, FIONBIO, &nonblocking);
1517 
1518  tcpc->sock = sock;
1519 
1520  freeaddrinfo(ai);
1521  TRACE("connected\n");
1522  return RPC_S_OK;
1523  }
1524 
1525  freeaddrinfo(ai);
1526  ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
1527  return RPC_S_SERVER_UNAVAILABLE;
1528 }
1529 
1531 {
1533  int sock;
1534  int ret;
1535  struct addrinfo *ai;
1536  struct addrinfo *ai_cur;
1537  struct addrinfo hints;
1538 
1539  TRACE("(%p, %s)\n", protseq, endpoint);
1540 
1541  hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */;
1542  hints.ai_family = PF_UNSPEC;
1543  hints.ai_socktype = SOCK_STREAM;
1544  hints.ai_protocol = IPPROTO_TCP;
1545  hints.ai_addrlen = 0;
1546  hints.ai_addr = NULL;
1547  hints.ai_canonname = NULL;
1548  hints.ai_next = NULL;
1549 
1550  ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai);
1551  if (ret)
1552  {
1553  ERR("getaddrinfo for port %s failed: %s\n", endpoint,
1554  gai_strerror(ret));
1555  if ((ret == EAI_SERVICE) || (ret == EAI_NONAME))
1558  }
1559 
1560  for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1561  {
1562  RpcConnection_tcp *tcpc;
1563  RPC_STATUS create_status;
1564  struct sockaddr_storage sa;
1565  socklen_t sa_len;
1566  char service[NI_MAXSERV];
1567  u_long nonblocking;
1568 
1569  if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1570  {
1571  TRACE("skipping non-IP/IPv6 address family\n");
1572  continue;
1573  }
1574 
1575  if (TRACE_ON(rpc))
1576  {
1577  char host[256];
1578  getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1579  host, sizeof(host), service, sizeof(service),
1581  TRACE("trying %s:%s\n", host, service);
1582  }
1583 
1584  sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1585  if (sock == -1)
1586  {
1587  WARN("socket() failed: %u\n", WSAGetLastError());
1589  continue;
1590  }
1591 
1592  ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
1593  if (ret < 0)
1594  {
1595  WARN("bind failed: %u\n", WSAGetLastError());
1596  closesocket(sock);
1597  if (WSAGetLastError() == WSAEADDRINUSE)
1599  else
1601  continue;
1602  }
1603 
1604  sa_len = sizeof(sa);
1605  if (getsockname(sock, (struct sockaddr *)&sa, &sa_len))
1606  {
1607  WARN("getsockname() failed: %u\n", WSAGetLastError());
1608  closesocket(sock);
1610  continue;
1611  }
1612 
1613  ret = getnameinfo((struct sockaddr *)&sa, sa_len,
1614  NULL, 0, service, sizeof(service),
1615  NI_NUMERICSERV);
1616  if (ret)
1617  {
1618  WARN("getnameinfo failed: %s\n", gai_strerror(ret));
1619  closesocket(sock);
1621  continue;
1622  }
1623 
1624  create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
1625  protseq->Protseq, NULL,
1626  service, NULL, NULL, NULL, NULL);
1627  if (create_status != RPC_S_OK)
1628  {
1629  closesocket(sock);
1630  status = create_status;
1631  continue;
1632  }
1633 
1634  tcpc->sock = sock;
1635  ret = listen(sock, protseq->MaxCalls);
1636  if (ret < 0)
1637  {
1638  WARN("listen failed: %u\n", WSAGetLastError());
1639  RPCRT4_ReleaseConnection(&tcpc->common);
1641  continue;
1642  }
1643  /* need a non-blocking socket, otherwise accept() has a potential
1644  * race-condition (poll() says it is readable, connection drops,
1645  * and accept() blocks until the next connection comes...)
1646  */
1647  nonblocking = 1;
1648  ret = ioctlsocket(sock, FIONBIO, &nonblocking);
1649  if (ret < 0)
1650  {
1651  WARN("couldn't make socket non-blocking, error %d\n", ret);
1652  RPCRT4_ReleaseConnection(&tcpc->common);
1654  continue;
1655  }
1656 
1657  EnterCriticalSection(&protseq->cs);
1658  list_add_tail(&protseq->listeners, &tcpc->common.protseq_entry);
1659  tcpc->common.protseq = protseq;
1660  LeaveCriticalSection(&protseq->cs);
1661 
1662  freeaddrinfo(ai);
1663 
1664  /* since IPv4 and IPv6 share the same port space, we only need one
1665  * successful bind to listen for both */
1666  TRACE("listening on %s\n", endpoint);
1667  return RPC_S_OK;
1668  }
1669 
1670  freeaddrinfo(ai);
1671  ERR("couldn't listen on port %s\n", endpoint);
1672  return status;
1673 }
1674 
1676 {
1677  int ret;
1678  struct sockaddr_in address;
1679  socklen_t addrsize;
1682  u_long nonblocking;
1683 
1684  addrsize = sizeof(address);
1685  ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);
1686  if (ret < 0)
1687  {
1688  ERR("Failed to accept a TCP connection: error %d\n", ret);
1689  return RPC_S_OUT_OF_RESOURCES;
1690  }
1691 
1692  nonblocking = 1;
1693  ioctlsocket(ret, FIONBIO, &nonblocking);
1694  client->sock = ret;
1695 
1696  client->common.NetworkAddr = HeapAlloc(GetProcessHeap(), 0, INET6_ADDRSTRLEN);
1697  ret = getnameinfo((struct sockaddr*)&address, addrsize, client->common.NetworkAddr, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
1698  if (ret != 0)
1699  {
1700  ERR("Failed to retrieve the IP address, error %d\n", ret);
1701  return RPC_S_OUT_OF_RESOURCES;
1702  }
1703 
1704  TRACE("Accepted a new TCP connection from %s\n", client->common.NetworkAddr);
1705  return RPC_S_OK;
1706 }
1707 
1708 static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
1709  void *buffer, unsigned int count)
1710 {
1711  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1712  int bytes_read = 0;
1713  while (bytes_read != count)
1714  {
1715  int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0);
1716  if (!r)
1717  return -1;
1718  else if (r > 0)
1719  bytes_read += r;
1720  else if (WSAGetLastError() == WSAEINTR)
1721  continue;
1722  else if (WSAGetLastError() != WSAEWOULDBLOCK)
1723  {
1724  WARN("recv() failed: %u\n", WSAGetLastError());
1725  return -1;
1726  }
1727  else
1728  {
1729  if (!rpcrt4_sock_wait_for_recv(tcpc))
1730  return -1;
1731  }
1732  }
1733  TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
1734  return bytes_read;
1735 }
1736 
1737 static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
1738  const void *buffer, unsigned int count)
1739 {
1740  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1741  int bytes_written = 0;
1742  while (bytes_written != count)
1743  {
1744  int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
1745  if (r >= 0)
1746  bytes_written += r;
1747  else if (WSAGetLastError() == WSAEINTR)
1748  continue;
1749  else if (WSAGetLastError() != WSAEWOULDBLOCK)
1750  return -1;
1751  else
1752  {
1753  if (!rpcrt4_sock_wait_for_send(tcpc))
1754  return -1;
1755  }
1756  }
1757  TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
1758  return bytes_written;
1759 }
1760 
1762 {
1763  RpcConnection_tcp *connection = (RpcConnection_tcp *) conn;
1764 
1765  TRACE("%d\n", connection->sock);
1766 
1767  if (connection->sock != -1)
1768  closesocket(connection->sock);
1769  connection->sock = -1;
1770  CloseHandle(connection->sock_event);
1771  CloseHandle(connection->cancel_event);
1772  return 0;
1773 }
1774 
1776 {
1777  RpcConnection_tcp *connection = (RpcConnection_tcp *) conn;
1778  shutdown(connection->sock, SD_RECEIVE);
1779 }
1780 
1782 {
1783  RpcConnection_tcp *connection = (RpcConnection_tcp *) conn;
1784 
1785  TRACE("%p\n", connection);
1786 
1787  SetEvent(connection->cancel_event);
1788 }
1789 
1791 {
1792  FIXME("\n");
1793  return RPC_S_ACCESS_DENIED;
1794 }
1795 
1797 {
1798  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1799 
1800  TRACE("%p\n", Connection);
1801 
1802  if (!rpcrt4_sock_wait_for_recv(tcpc))
1803  return -1;
1804  return 0;
1805 }
1806 
1807 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1808  const char *networkaddr,
1809  const char *endpoint)
1810 {
1811  return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
1813 }
1814 
1816 {
1820 
1822 {
1824  if (ps)
1825  {
1826  static BOOL wsa_inited;
1827  if (!wsa_inited)
1828  {
1829  WSADATA wsadata;
1830  WSAStartup(MAKEWORD(2, 2), &wsadata);
1831  /* Note: WSAStartup can be called more than once so we don't bother with
1832  * making accesses to wsa_inited thread-safe */
1833  wsa_inited = TRUE;
1834  }
1836  }
1837  return &ps->common;
1838 }
1839 
1841 {
1843  SetEvent(sockps->mgr_event);
1844 }
1845 
1846 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1847 {
1848  HANDLE *objs = prev_array;
1849  RpcConnection_tcp *conn;
1851 
1852  EnterCriticalSection(&protseq->cs);
1853 
1854  /* open and count connections */
1855  *count = 1;
1856  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_tcp, common.protseq_entry)
1857  {
1858  if (conn->sock != -1)
1859  (*count)++;
1860  }
1861 
1862  /* make array of connections */
1863  if (objs)
1864  objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
1865  else
1866  objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
1867  if (!objs)
1868  {
1869  ERR("couldn't allocate objs\n");
1870  LeaveCriticalSection(&protseq->cs);
1871  return NULL;
1872  }
1873 
1874  objs[0] = sockps->mgr_event;
1875  *count = 1;
1876  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_tcp, common.protseq_entry)
1877  {
1878  if (conn->sock != -1)
1879  {
1880  int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT);
1881  if (res == SOCKET_ERROR)
1882  ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1883  else
1884  {
1885  objs[*count] = conn->sock_event;
1886  (*count)++;
1887  }
1888  }
1889  }
1890  LeaveCriticalSection(&protseq->cs);
1891  return objs;
1892 }
1893 
1895 {
1896  HeapFree(GetProcessHeap(), 0, array);
1897 }
1898 
1899 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1900 {
1901  HANDLE b_handle;
1902  HANDLE *objs = wait_array;
1903  DWORD res;
1904  RpcConnection *cconn = NULL;
1905  RpcConnection_tcp *conn;
1906 
1907  if (!objs)
1908  return -1;
1909 
1910  do
1911  {
1912  /* an alertable wait isn't strictly necessary, but due to our
1913  * overlapped I/O implementation in Wine we need to free some memory
1914  * by the file user APC being called, even if no completion routine was
1915  * specified at the time of starting the async operation */
1917  } while (res == WAIT_IO_COMPLETION);
1918 
1919  if (res == WAIT_OBJECT_0)
1920  return 0;
1921  if (res == WAIT_FAILED)
1922  {
1923  ERR("wait failed with error %d\n", GetLastError());
1924  return -1;
1925  }
1926 
1927  b_handle = objs[res - WAIT_OBJECT_0];
1928 
1929  /* find which connection got a RPC */
1930  EnterCriticalSection(&protseq->cs);
1931  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_tcp, common.protseq_entry)
1932  {
1933  if (b_handle == conn->sock_event)
1934  {
1935  cconn = rpcrt4_spawn_connection(&conn->common);
1936  break;
1937  }
1938  }
1939  LeaveCriticalSection(&protseq->cs);
1940  if (!cconn)
1941  {
1942  ERR("failed to locate connection for handle %p\n", b_handle);
1943  return -1;
1944  }
1945 
1946  RPCRT4_new_client(cconn);
1947  return 1;
1948 }
1949 
1950 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1951  size_t tower_size,
1952  char **networkaddr,
1953  char **endpoint)
1954 {
1955  return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
1956  networkaddr, EPM_PROTOCOL_TCP,
1957  endpoint);
1958 }
1959 
1960 /**** ncacn_http support ****/
1961 
1962 /* 60 seconds is the period native uses */
1963 #define HTTP_IDLE_TIME 60000
1964 
1965 /* reference counted to avoid a race between a cancelled call's connection
1966  * being destroyed and the asynchronous InternetReadFileEx call being
1967  * completed */
1968 typedef struct _RpcHttpAsyncData
1969 {
1976 
1978 {
1979  return InterlockedIncrement(&data->refs);
1980 }
1981 
1983 {
1984  ULONG refs = InterlockedDecrement(&data->refs);
1985  if (!refs)
1986  {
1987  TRACE("destroying async data %p\n", data);
1988  CloseHandle(data->completion_event);
1989  HeapFree(GetProcessHeap(), 0, data->inet_buffers.lpvBuffer);
1990  data->cs.DebugInfo->Spare[0] = 0;
1992  HeapFree(GetProcessHeap(), 0, data);
1993  }
1994  return refs;
1995 }
1996 
1997 static void prepare_async_request(RpcHttpAsyncData *async_data)
1998 {
1999  ResetEvent(async_data->completion_event);
2000  RpcHttpAsyncData_AddRef(async_data);
2001 }
2002 
2003 static RPC_STATUS wait_async_request(RpcHttpAsyncData *async_data, BOOL call_ret, HANDLE cancel_event)
2004 {
2005  HANDLE handles[2] = { async_data->completion_event, cancel_event };
2006  DWORD res;
2007 
2008  if(call_ret) {
2009  RpcHttpAsyncData_Release(async_data);
2010  return RPC_S_OK;
2011  }
2012 
2013  if(GetLastError() != ERROR_IO_PENDING) {
2014  RpcHttpAsyncData_Release(async_data);
2015  ERR("Request failed with error %d\n", GetLastError());
2016  return RPC_S_SERVER_UNAVAILABLE;
2017  }
2018 
2020  if(res != WAIT_OBJECT_0) {
2021  TRACE("Cancelled\n");
2022  return RPC_S_CALL_CANCELLED;
2023  }
2024 
2025  if(async_data->async_result) {
2026  ERR("Async request failed with error %d\n", async_data->async_result);
2027  return RPC_S_SERVER_UNAVAILABLE;
2028  }
2029 
2030  return RPC_S_OK;
2031 }
2032 
2033 struct authinfo
2034 {
2041  char *data;
2042  unsigned int data_len;
2043  BOOL finished; /* finished authenticating */
2044 };
2045 
2046 typedef struct _RpcConnection_http
2047 {
2058  ULONG flow_control_mark; /* send a control packet to the server when this many bytes received */
2059  ULONG flow_control_increment; /* number of bytes to increment flow_control_mark by */
2065 
2067 {
2068  RpcConnection_http *httpc;
2069  httpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*httpc));
2070  if (!httpc) return NULL;
2072  if (!httpc->async_data)
2073  {
2074  HeapFree(GetProcessHeap(), 0, httpc);
2075  return NULL;
2076  }
2077  TRACE("async data = %p\n", httpc->async_data);
2079  httpc->async_data->refs = 1;
2082  httpc->async_data->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RpcHttpAsyncData.cs");
2083  return &httpc->common;
2084 }
2085 
2086 typedef struct _HttpTimerThreadData
2087 {
2092 
2094 {
2095  HINTERNET in_request = param;
2096  RpcPktHdr *idle_pkt;
2097 
2099  0, 0);
2100  if (idle_pkt)
2101  {
2102  DWORD bytes_written;
2103  InternetWriteFile(in_request, idle_pkt, idle_pkt->common.frag_len, &bytes_written);
2104  RPCRT4_FreeHeader(idle_pkt);
2105  }
2106 }
2107 
2108 static inline DWORD rpcrt4_http_timer_calc_timeout(DWORD *last_sent_time)
2109 {
2111  DWORD cached_last_sent_time = *last_sent_time;
2112  return HTTP_IDLE_TIME - (cur_time - cached_last_sent_time > HTTP_IDLE_TIME ? 0 : cur_time - cached_last_sent_time);
2113 }
2114 
2116 {
2117  HttpTimerThreadData *data_in = param;
2119  DWORD timeout;
2120 
2121  data = *data_in;
2122  HeapFree(GetProcessHeap(), 0, data_in);
2123 
2124  for (timeout = HTTP_IDLE_TIME;
2125  WaitForSingleObject(data.timer_cancelled, timeout) == WAIT_TIMEOUT;
2126  timeout = rpcrt4_http_timer_calc_timeout(data.last_sent_time))
2127  {
2128  /* are we too soon after last send? */
2129  if (GetTickCount() - *data.last_sent_time < HTTP_IDLE_TIME)
2130  continue;
2132  }
2133 
2134  CloseHandle(data.timer_cancelled);
2135  return 0;
2136 }
2137 
2139  HINTERNET hInternet,
2140  DWORD_PTR dwContext,
2141  DWORD dwInternetStatus,
2142  LPVOID lpvStatusInformation,
2143  DWORD dwStatusInformationLength)
2144 {
2145  RpcHttpAsyncData *async_data = (RpcHttpAsyncData *)dwContext;
2146 
2147  switch (dwInternetStatus)
2148  {
2150  TRACE("INTERNET_STATUS_REQUEST_COMPLETED\n");
2151  if (async_data)
2152  {
2153  INTERNET_ASYNC_RESULT *async_result = lpvStatusInformation;
2154 
2155  async_data->async_result = async_result->dwResult ? ERROR_SUCCESS : async_result->dwError;
2156  SetEvent(async_data->completion_event);
2157  RpcHttpAsyncData_Release(async_data);
2158  }
2159  break;
2160  }
2161 }
2162 
2164 {
2165  BOOL ret;
2167  DWORD size;
2168  DWORD index;
2169  WCHAR buf[32];
2170  WCHAR *status_text = buf;
2171  TRACE("\n");
2172 
2173  index = 0;
2174  size = sizeof(status_code);
2176  if (!ret)
2177  return GetLastError();
2178  if (status_code == HTTP_STATUS_OK)
2179  return RPC_S_OK;
2180  index = 0;
2181  size = sizeof(buf);
2182  ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
2184  {
2185  status_text = HeapAlloc(GetProcessHeap(), 0, size);
2186  ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
2187  }
2188 
2189  ERR("server returned: %d %s\n", status_code, ret ? debugstr_w(status_text) : "<status text unavailable>");
2190  if(status_text != buf) HeapFree(GetProcessHeap(), 0, status_text);
2191 
2193  return ERROR_ACCESS_DENIED;
2194  return RPC_S_SERVER_UNAVAILABLE;
2195 }
2196 
2198 {
2199  static const WCHAR wszUserAgent[] = {'M','S','R','P','C',0};
2200  LPWSTR proxy = NULL;
2201  LPWSTR user = NULL;
2202  LPWSTR password = NULL;
2203  LPWSTR servername = NULL;
2204  const WCHAR *option;
2206 
2207  if (httpc->common.QOS &&
2209  {
2210  const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_cred = httpc->common.QOS->qos->u.HttpCredentials;
2211  if (http_cred->TransportCredentials)
2212  {
2213  WCHAR *p;
2214  const SEC_WINNT_AUTH_IDENTITY_W *cred = http_cred->TransportCredentials;
2215  ULONG len = cred->DomainLength + 1 + cred->UserLength;
2216  user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
2217  if (!user)
2218  return RPC_S_OUT_OF_RESOURCES;
2219  p = user;
2220  if (cred->DomainLength)
2221  {
2222  memcpy(p, cred->Domain, cred->DomainLength * sizeof(WCHAR));
2223  p += cred->DomainLength;
2224  *p = '\\';
2225  p++;
2226  }
2227  memcpy(p, cred->User, cred->UserLength * sizeof(WCHAR));
2228  p[cred->UserLength] = 0;
2229 
2231  }
2232  }
2233 
2234  for (option = httpc->common.NetworkOptions; option;
2235  option = (wcschr(option, ',') ? wcschr(option, ',')+1 : NULL))
2236  {
2237  static const WCHAR wszRpcProxy[] = {'R','p','c','P','r','o','x','y','=',0};
2238  static const WCHAR wszHttpProxy[] = {'H','t','t','p','P','r','o','x','y','=',0};
2239 
2240  if (!_wcsnicmp(option, wszRpcProxy, ARRAY_SIZE(wszRpcProxy)-1))
2241  {
2242  const WCHAR *value_start = option + ARRAY_SIZE(wszRpcProxy)-1;
2243  const WCHAR *value_end;
2244  const WCHAR *p;
2245 
2246  value_end = wcschr(option, ',');
2247  if (!value_end)
2248  value_end = value_start + lstrlenW(value_start);
2249  for (p = value_start; p < value_end; p++)
2250  if (*p == ':')
2251  {
2252  port = wcstol(p+1, NULL, 10);
2253  value_end = p;
2254  break;
2255  }
2256  TRACE("RpcProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
2257  servername = RPCRT4_strndupW(value_start, value_end-value_start);
2258  }
2259  else if (!_wcsnicmp(option, wszHttpProxy, ARRAY_SIZE(wszHttpProxy)-1))
2260  {
2261  const WCHAR *value_start = option + ARRAY_SIZE(wszHttpProxy)-1;
2262  const WCHAR *value_end;
2263 
2264  value_end = wcschr(option, ',');
2265  if (!value_end)
2266  value_end = value_start + lstrlenW(value_start);
2267  TRACE("HttpProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
2268  proxy = RPCRT4_strndupW(value_start, value_end-value_start);
2269  }
2270  else
2271  FIXME("unhandled option %s\n", debugstr_w(option));
2272  }
2273 
2276  if (!httpc->app_info)
2277  {
2279  HeapFree(GetProcessHeap(), 0, user);
2280  HeapFree(GetProcessHeap(), 0, proxy);
2281  HeapFree(GetProcessHeap(), 0, servername);
2282  ERR("InternetOpenW failed with error %d\n", GetLastError());
2283  return RPC_S_SERVER_UNAVAILABLE;
2284  }
2286 
2287  /* if no RpcProxy option specified, set the HTTP server address to the
2288  * RPC server address */
2289  if (!servername)
2290  {
2291  servername = HeapAlloc(GetProcessHeap(), 0, (strlen(httpc->common.NetworkAddr) + 1)*sizeof(WCHAR));
2292  if (!servername)
2293  {
2295  HeapFree(GetProcessHeap(), 0, user);
2296  HeapFree(GetProcessHeap(), 0, proxy);
2297  return RPC_S_OUT_OF_RESOURCES;
2298  }
2299  MultiByteToWideChar(CP_ACP, 0, httpc->common.NetworkAddr, -1, servername, strlen(httpc->common.NetworkAddr) + 1);
2300  }
2301 
2302  port = (httpc->common.QOS &&
2306 
2307  httpc->session = InternetConnectW(httpc->app_info, servername, port, user, password,
2308  INTERNET_SERVICE_HTTP, 0, 0);
2309 
2311  HeapFree(GetProcessHeap(), 0, user);
2312  HeapFree(GetProcessHeap(), 0, proxy);
2313 
2314  if (!httpc->session)
2315  {
2316  ERR("InternetConnectW failed with error %d\n", GetLastError());
2317  HeapFree(GetProcessHeap(), 0, servername);
2318  return RPC_S_SERVER_UNAVAILABLE;
2319  }
2320  httpc->servername = servername;
2321  return RPC_S_OK;
2322 }
2323 
2324 static int rpcrt4_http_async_read(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event,
2325  void *buffer, unsigned int count)
2326 {
2327  char *buf = buffer;
2328  BOOL ret;
2329  unsigned int bytes_left = count;
2331 
2332  async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, count);
2333 
2334  while (bytes_left)
2335  {
2336  async_data->inet_buffers.dwBufferLength = bytes_left;
2337  prepare_async_request(async_data);
2338  ret = InternetReadFileExW(req, &async_data->inet_buffers, IRF_ASYNC, 0);
2339  status = wait_async_request(async_data, ret, cancel_event);
2340  if (status != RPC_S_OK)
2341  {
2343  TRACE("call cancelled\n");
2344  break;
2345  }
2346 
2347  if (!async_data->inet_buffers.dwBufferLength)
2348  break;
2349  memcpy(buf, async_data->inet_buffers.lpvBuffer,
2350  async_data->inet_buffers.dwBufferLength);
2351 
2352  bytes_left -= async_data->inet_buffers.dwBufferLength;
2353  buf += async_data->inet_buffers.dwBufferLength;
2354  }
2355 
2356  HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer);
2357  async_data->inet_buffers.lpvBuffer = NULL;
2358 
2359  TRACE("%p %p %u -> %u\n", req, buffer, count, status);
2360  return status == RPC_S_OK ? count : -1;
2361 }
2362 
2363 static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event)
2364 {
2365  BYTE buf[20];
2366  BOOL ret;
2368 
2369  TRACE("sending echo request to server\n");
2370 
2371  prepare_async_request(async_data);
2372  ret = HttpSendRequestW(req, NULL, 0, NULL, 0);
2373  status = wait_async_request(async_data, ret, cancel_event);
2374  if (status != RPC_S_OK) return status;
2375 
2377  if (status != RPC_S_OK) return status;
2378 
2379  rpcrt4_http_async_read(req, async_data, cancel_event, buf, sizeof(buf));
2380  /* FIXME: do something with retrieved data */
2381 
2382  return RPC_S_OK;
2383 }
2384 
2386 {
2387  static const WCHAR fmtW[] =
2388  {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','u','\r','\n',0};
2389  WCHAR header[ARRAY_SIZE(fmtW) + 10];
2390 
2391  swprintf(header, fmtW, len);
2393  return RPC_S_SERVER_UNAVAILABLE;
2394 }
2395 
2396 /* prepare the in pipe for use by RPC packets */
2397 static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data, HANDLE cancel_event,
2398  const UUID *connection_uuid, const UUID *in_pipe_uuid,
2399  const UUID *association_uuid, BOOL authorized)
2400 {
2401  BOOL ret;
2403  RpcPktHdr *hdr;
2404  INTERNET_BUFFERSW buffers_in;
2405  DWORD bytes_written;
2406 
2407  if (!authorized)
2408  {
2409  /* ask wininet to authorize, if necessary */
2410  status = send_echo_request(in_request, async_data, cancel_event);
2411  if (status != RPC_S_OK) return status;
2412  }
2413  memset(&buffers_in, 0, sizeof(buffers_in));
2414  buffers_in.dwStructSize = sizeof(buffers_in);
2415  /* FIXME: get this from the registry */
2416  buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */
2417  status = insert_content_length_header(in_request, buffers_in.dwBufferTotal);
2418  if (status != RPC_S_OK) return status;
2419 
2420  prepare_async_request(async_data);
2421  ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0);
2422  status = wait_async_request(async_data, ret, cancel_event);
2423  if (status != RPC_S_OK) return status;
2424 
2425  TRACE("sending HTTP connect header to server\n");
2426  hdr = RPCRT4_BuildHttpConnectHeader(FALSE, connection_uuid, in_pipe_uuid, association_uuid);
2427  if (!hdr) return RPC_S_OUT_OF_RESOURCES;
2428  ret = InternetWriteFile(in_request, hdr, hdr->common.frag_len, &bytes_written);
2430  if (!ret)
2431  {
2432  ERR("InternetWriteFile failed with error %d\n", GetLastError());
2433  return RPC_S_SERVER_UNAVAILABLE;
2434  }
2435 
2436  return RPC_S_OK;
2437 }
2438 
2440  HANDLE cancel_event, RpcPktHdr *hdr, BYTE **data)
2441 {
2442  unsigned short data_len;
2443  unsigned int size;
2444 
2445  if (rpcrt4_http_async_read(request, async_data, cancel_event, hdr, sizeof(hdr->common)) < 0)
2446  return RPC_S_SERVER_UNAVAILABLE;
2447  if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
2448  {
2449  ERR("wrong packet type received %d or wrong frag_len %d\n",
2450  hdr->common.ptype, hdr->common.frag_len);
2451  return RPC_S_PROTOCOL_ERROR;
2452  }
2453 
2454  size = sizeof(hdr->http) - sizeof(hdr->common);
2455  if (rpcrt4_http_async_read(request, async_data, cancel_event, &hdr->common + 1, size) < 0)
2456  return RPC_S_SERVER_UNAVAILABLE;
2457 
2458  data_len = hdr->common.frag_len - sizeof(hdr->http);
2459  if (data_len)
2460  {
2461  *data = HeapAlloc(GetProcessHeap(), 0, data_len);
2462  if (!*data)
2463  return RPC_S_OUT_OF_RESOURCES;
2464  if (rpcrt4_http_async_read(request, async_data, cancel_event, *data, data_len) < 0)
2465  {
2466  HeapFree(GetProcessHeap(), 0, *data);
2467  return RPC_S_SERVER_UNAVAILABLE;
2468  }
2469  }
2470  else
2471  *data = NULL;
2472 
2473  if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len))
2474  {
2475  ERR("invalid http packet\n");
2476  HeapFree(GetProcessHeap(), 0, *data);
2477  return RPC_S_PROTOCOL_ERROR;
2478  }
2479 
2480  return RPC_S_OK;
2481 }
2482 
2483 /* prepare the out pipe for use by RPC packets */
2485  HANDLE cancel_event, const UUID *connection_uuid,
2486  const UUID *out_pipe_uuid, ULONG *flow_control_increment,
2487  BOOL authorized)
2488 {
2489  BOOL ret;
2491  RpcPktHdr *hdr;
2492  BYTE *data_from_server;
2493  RpcPktHdr pkt_from_server;
2494  ULONG field1, field3;
2495  BYTE buf[20];
2496 
2497  if (!authorized)
2498  {
2499  /* ask wininet to authorize, if necessary */
2500  status = send_echo_request(out_request, async_data, cancel_event);
2501  if (status != RPC_S_OK) return status;
2502  }
2503  else
2504  rpcrt4_http_async_read(out_request, async_data, cancel_event, buf, sizeof(buf));
2505 
2506  hdr = RPCRT4_BuildHttpConnectHeader(TRUE, connection_uuid, out_pipe_uuid, NULL);
2507  if (!hdr) return RPC_S_OUT_OF_RESOURCES;
2508 
2509  status = insert_content_length_header(out_request, hdr->common.frag_len);
2510  if (status != RPC_S_OK)
2511  {
2513  return status;
2514  }
2515 
2516  TRACE("sending HTTP connect header to server\n");
2517  prepare_async_request(async_data);
2518  ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len);
2519  status = wait_async_request(async_data, ret, cancel_event);
2521  if (status != RPC_S_OK) return status;
2522 
2523  status = rpcrt4_http_check_response(out_request);
2524  if (status != RPC_S_OK) return status;
2525 
2526  status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
2527  &pkt_from_server, &data_from_server);
2528  if (status != RPC_S_OK) return status;
2529  status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
2530  &field1);
2531  HeapFree(GetProcessHeap(), 0, data_from_server);
2532  if (status != RPC_S_OK) return status;
2533  TRACE("received (%d) from first prepare header\n", field1);
2534 
2535  for (;;)
2536  {
2537  status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
2538  &pkt_from_server, &data_from_server);
2539  if (status != RPC_S_OK) return status;
2540  if (pkt_from_server.http.flags != 0x0001) break;
2541 
2542  TRACE("http idle packet, waiting for real packet\n");
2543  HeapFree(GetProcessHeap(), 0, data_from_server);
2544  if (pkt_from_server.http.num_data_items != 0)
2545  {
2546  ERR("HTTP idle packet should have no data items instead of %d\n",
2547  pkt_from_server.http.num_data_items);
2548  return RPC_S_PROTOCOL_ERROR;
2549  }
2550  }
2551  status = RPCRT4_ParseHttpPrepareHeader2(&pkt_from_server, data_from_server,
2552  &field1, flow_control_increment,
2553  &field3);
2554  HeapFree(GetProcessHeap(), 0, data_from_server);
2555  if (status != RPC_S_OK) return status;
2556  TRACE("received (0x%08x 0x%08x %d) from second prepare header\n", field1, *flow_control_increment, field3);
2557 
2558  return RPC_S_OK;
2559 }
2560 
2561 static UINT encode_base64(const char *bin, unsigned int len, WCHAR *base64)
2562 {
2563  static const char enc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2564  UINT i = 0, x;
2565 
2566  while (len > 0)
2567  {
2568  /* first 6 bits, all from bin[0] */
2569  base64[i++] = enc[(bin[0] & 0xfc) >> 2];
2570  x = (bin[0] & 3) << 4;
2571 
2572  /* next 6 bits, 2 from bin[0] and 4 from bin[1] */
2573  if (len == 1)
2574  {
2575  base64[i++] = enc[x];
2576  base64[i++] = '=';
2577  base64[i++] = '=';
2578  break;
2579  }
2580  base64[i++] = enc[x | ((bin[1] & 0xf0) >> 4)];
2581  x = (bin[1] & 0x0f) << 2;
2582 
2583  /* next 6 bits 4 from bin[1] and 2 from bin[2] */
2584  if (len == 2)
2585  {
2586  base64[i++] = enc[x];
2587  base64[i++] = '=';
2588  break;
2589  }
2590  base64[i++] = enc[x | ((bin[2] & 0xc0) >> 6)];
2591 
2592  /* last 6 bits, all from bin [2] */
2593  base64[i++] = enc[bin[2] & 0x3f];
2594  bin += 3;
2595  len -= 3;
2596  }
2597  base64[i] = 0;
2598  return i;
2599 }
2600 
2601 static inline char decode_char( WCHAR c )
2602 {
2603  if (c >= 'A' && c <= 'Z') return c - 'A';
2604  if (c >= 'a' && c <= 'z') return c - 'a' + 26;
2605  if (c >= '0' && c <= '9') return c - '0' + 52;
2606  if (c == '+') return 62;
2607  if (c == '/') return 63;
2608  return 64;
2609 }
2610 
2611 static unsigned int decode_base64( const WCHAR *base64, unsigned int len, char *buf )
2612 {
2613  unsigned int i = 0;
2614  char c0, c1, c2, c3;
2615  const WCHAR *p = base64;
2616 
2617  while (len > 4)
2618  {
2619  if ((c0 = decode_char( p[0] )) > 63) return 0;
2620  if ((c1 = decode_char( p[1] )) > 63) return 0;
2621  if ((c2 = decode_char( p[2] )) > 63) return 0;
2622  if ((c3 = decode_char( p[3] )) > 63) return 0;
2623 
2624  if (buf)
2625  {
2626  buf[i + 0] = (c0 << 2) | (c1 >> 4);
2627  buf[i + 1] = (c1 << 4) | (c2 >> 2);
2628  buf[i + 2] = (c2 << 6) | c3;
2629  }
2630  len -= 4;
2631  i += 3;
2632  p += 4;
2633  }
2634  if (p[2] == '=')
2635  {
2636  if ((c0 = decode_char( p[0] )) > 63) return 0;
2637  if ((c1 = decode_char( p[1] )) > 63) return 0;
2638 
2639  if (buf) buf[i] = (c0 << 2) | (c1 >> 4);
2640  i++;
2641  }
2642  else if (p[3] == '=')
2643  {
2644  if ((c0 = decode_char( p[0] )) > 63) return 0;
2645  if ((c1 = decode_char( p[1] )) > 63) return 0;
2646  if ((c2 = decode_char( p[2] )) > 63) return 0;
2647 
2648  if (buf)
2649  {
2650  buf[i + 0] = (c0 << 2) | (c1 >> 4);
2651  buf[i + 1] = (c1 << 4) | (c2 >> 2);
2652  }
2653  i += 2;
2654  }
2655  else
2656  {
2657  if ((c0 = decode_char( p[0] )) > 63) return 0;
2658  if ((c1 = decode_char( p[1] )) > 63) return 0;
2659  if ((c2 = decode_char( p[2] )) > 63) return 0;
2660  if ((c3 = decode_char( p[3] )) > 63) return 0;
2661 
2662  if (buf)
2663  {
2664  buf[i + 0] = (c0 << 2) | (c1 >> 4);
2665  buf[i + 1] = (c1 << 4) | (c2 >> 2);
2666  buf[i + 2] = (c2 << 6) | c3;
2667  }
2668  i += 3;
2669  }
2670  return i;
2671 }
2672 
2673 static struct authinfo *alloc_authinfo(void)
2674 {
2675  struct authinfo *ret;
2676 
2677  if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret) ))) return NULL;
2678 
2679  SecInvalidateHandle(&ret->cred);
2680  SecInvalidateHandle(&ret->ctx);
2681  memset(&ret->exp, 0, sizeof(ret->exp));
2682  ret->scheme = 0;
2683  ret->attr = 0;
2684  ret->max_token = 0;
2685  ret->data = NULL;
2686  ret->data_len = 0;
2687  ret->finished = FALSE;
2688  return ret;
2689 }
2690 
2691 static void destroy_authinfo(struct authinfo *info)
2692 {
2693  if (!info) return;
2694 
2695  if (SecIsValidHandle(&info->ctx))
2696  DeleteSecurityContext(&info->ctx);
2697  if (SecIsValidHandle(&info->cred))
2698  FreeCredentialsHandle(&info->cred);
2699 
2700  HeapFree(GetProcessHeap(), 0, info->data);
2701  HeapFree(GetProcessHeap(), 0, info);
2702 }
2703 
2704 static const WCHAR basicW[] = {'B','a','s','i','c',0};
2705 static const WCHAR ntlmW[] = {'N','T','L','M',0};
2706 static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t',0};
2707 static const WCHAR digestW[] = {'D','i','g','e','s','t',0};
2708 static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',0};
2709 
2710 static const struct
2711 {
2712  const WCHAR *str;
2713  unsigned int len;
2715 }
2716 auth_schemes[] =
2717 {
2723 };
2724 
2726 {
2727  unsigned int i;
2728  for (i = 0; i < ARRAY_SIZE(auth_schemes); i++)
2729  {
2731  (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme;
2732  }
2733  return 0;
2734 }
2735 
2737 {
2738  DWORD len, index = 0;
2739  for (;;)
2740  {
2741  len = buflen;
2743  if (auth_scheme_from_header(buffer) == scheme) break;
2744  }
2745  return TRUE;
2746 }
2747 
2749  const RPC_HTTP_TRANSPORT_CREDENTIALS_W *creds, struct authinfo **auth_ptr)
2750 {
2751  struct authinfo *info = *auth_ptr;
2754 
2755  if ((!info && !(info = alloc_authinfo()))) return RPC_S_SERVER_UNAVAILABLE;
2756 
2757  switch (creds->AuthnSchemes[0])
2758  {
2760  {
2761  int userlen = WideCharToMultiByte(CP_UTF8, 0, id->User, id->UserLength, NULL, 0, NULL, NULL);
2762  int passlen = WideCharToMultiByte(CP_UTF8, 0, id->Password, id->PasswordLength, NULL, 0, NULL, NULL);
2763 
2764  info->data_len = userlen + passlen + 1;
2765  if (!(info->data = HeapAlloc(GetProcessHeap(), 0, info->data_len)))
2766  {
2768  break;
2769  }
2770  WideCharToMultiByte(CP_UTF8, 0, id->User, id->UserLength, info->data, userlen, NULL, NULL);
2771  info->data[userlen] = ':';
2772  WideCharToMultiByte(CP_UTF8, 0, id->Password, id->PasswordLength, info->data + userlen + 1, passlen, NULL, NULL);
2773 
2775  info->finished = TRUE;
2776  status = RPC_S_OK;
2777  break;
2778  }
2781  {
2782 
2783  static SEC_WCHAR ntlmW[] = {'N','T','L','M',0}, negotiateW[] = {'N','e','g','o','t','i','a','t','e',0};
2785  SecBufferDesc out_desc, in_desc;
2786  SecBuffer out, in;
2788  SEC_WCHAR *scheme;
2789  int scheme_len;
2790  const WCHAR *p;
2791  WCHAR auth_value[2048];
2792  DWORD size = sizeof(auth_value);
2793  BOOL first = FALSE;
2794 
2796  else scheme = negotiateW;
2797  scheme_len = lstrlenW( scheme );
2798 
2799  if (!*auth_ptr)
2800  {
2801  TimeStamp exp;
2802  SecPkgInfoW *pkg_info;
2803 
2805  if (ret != SEC_E_OK) break;
2806 
2807  ret = QuerySecurityPackageInfoW(scheme, &pkg_info);
2808  if (ret != SEC_E_OK) break;
2809 
2810  info->max_token = pkg_info->cbMaxToken;
2811  FreeContextBuffer(pkg_info);
2812  first = TRUE;
2813  }
2814  else
2815  {
2816  if (info->finished || !get_authvalue(request, creds->AuthnSchemes[0], auth_value, size)) break;
2817  if (auth_scheme_from_header(auth_value) != info->scheme)
2818  {
2819  ERR("authentication scheme changed\n");
2820  break;
2821  }
2822  }
2823  in.BufferType = SECBUFFER_TOKEN;
2824  in.cbBuffer = 0;
2825  in.pvBuffer = NULL;
2826 
2827  in_desc.ulVersion = 0;
2828  in_desc.cBuffers = 1;
2829  in_desc.pBuffers = &in;
2830 
2831  p = auth_value + scheme_len;
2832  if (!first && *p == ' ')
2833  {
2834  int len = lstrlenW(++p);
2835  in.cbBuffer = decode_base64(p, len, NULL);
2836  if (!(in.pvBuffer = HeapAlloc(GetProcessHeap(), 0, in.cbBuffer))) break;
2837  decode_base64(p, len, in.pvBuffer);
2838  }
2839  out.BufferType = SECBUFFER_TOKEN;
2840  out.cbBuffer = info->max_token;
2841  if (!(out.pvBuffer = HeapAlloc(GetProcessHeap(), 0, out.cbBuffer)))
2842  {
2843  HeapFree(GetProcessHeap(), 0, in.pvBuffer);
2844  break;
2845  }
2846  out_desc.ulVersion = 0;
2847  out_desc.cBuffers = 1;
2848  out_desc.pBuffers = &out;
2849 
2850  ret = InitializeSecurityContextW(first ? &info->cred : NULL, first ? NULL : &info->ctx,
2851  first ? servername : NULL, flags, 0, SECURITY_NETWORK_DREP,
2852  in.pvBuffer ? &in_desc : NULL, 0, &info->ctx, &out_desc,
2853  &info->attr, &info->exp);
2854  HeapFree(GetProcessHeap(), 0, in.pvBuffer);
2855  if (ret == SEC_E_OK)
2856  {
2857  HeapFree(GetProcessHeap(), 0, info->data);
2858  info->data = out.pvBuffer;
2859  info->data_len = out.cbBuffer;
2860  info->finished = TRUE;
2861  TRACE("sending last auth packet\n");
2862  status = RPC_S_OK;
2863  }
2864  else if (ret == SEC_I_CONTINUE_NEEDED)
2865  {
2866  HeapFree(GetProcessHeap(), 0, info->data);
2867  info->data = out.pvBuffer;
2868  info->data_len = out.cbBuffer;
2869  TRACE("sending next auth packet\n");
2870  status = RPC_S_OK;
2871  }
2872  else
2873  {
2874  ERR("InitializeSecurityContextW failed with error 0x%08x\n", ret);
2875  HeapFree(GetProcessHeap(), 0, out.pvBuffer);
2876  break;
2877  }
2878  info->scheme = creds->AuthnSchemes[0];
2879  break;
2880  }
2881  default:
2882  FIXME("scheme %u not supported\n", creds->AuthnSchemes[0]);
2883  break;
2884  }
2885 
2886  if (status != RPC_S_OK)
2887  {
2889  *auth_ptr = NULL;
2890  return status;
2891  }
2892  *auth_ptr = info;
2893  return RPC_S_OK;
2894 }
2895 
2897 {
2898  static const WCHAR authW[] = {'A','u','t','h','o','r','i','z','a','t','i','o','n',':',' '};
2899  static const WCHAR basicW[] = {'B','a','s','i','c',' '};
2900  static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',' '};
2901  static const WCHAR ntlmW[] = {'N','T','L','M',' '};
2902  int scheme_len, auth_len = ARRAY_SIZE(authW), len = ((data_len + 2) * 4) / 3;
2903  const WCHAR *scheme_str;
2904  WCHAR *header, *ptr;
2906 
2907  switch (scheme)
2908  {
2910  scheme_str = basicW;
2911  scheme_len = ARRAY_SIZE(basicW);
2912  break;
2914  scheme_str = negotiateW;
2915  scheme_len = ARRAY_SIZE(negotiateW);
2916  break;
2918  scheme_str = ntlmW;
2919  scheme_len = ARRAY_SIZE(ntlmW);
2920  break;
2921  default:
2922  ERR("unknown scheme %u\n", scheme);
2923  return RPC_S_SERVER_UNAVAILABLE;
2924  }
2925  if ((header = HeapAlloc(GetProcessHeap(), 0, (auth_len + scheme_len + len + 2) * sizeof(WCHAR))))
2926  {
2927  memcpy(header, authW, auth_len * sizeof(WCHAR));
2928  ptr = header + auth_len;
2929  memcpy(ptr, scheme_str, scheme_len * sizeof(WCHAR));
2930  ptr += scheme_len;
2932  ptr[len++] = '\r';
2933  ptr[len++] = '\n';
2934  ptr[len] = 0;
2936  status = RPC_S_OK;
2938  }
2939  return status;
2940 }
2941 
2942 static void drain_content(HINTERNET request, RpcHttpAsyncData *async_data, HANDLE cancel_event)
2943 {
2944  DWORD count, len = 0, size = sizeof(len);
2945  char buf[2048];
2946 
2948  if (!len) return;
2949  for (;;)
2950  {
2951  count = min(sizeof(buf), len);
2952  if (rpcrt4_http_async_read(request, async_data, cancel_event, buf, count) <= 0) return;
2953  len -= count;
2954  }
2955 }
2956 
2958 {
2959  static const WCHAR authW[] = {'A','u','t','h','o','r','i','z','a','t','i','o','n',':','\r','\n',0};
2960  struct authinfo *info = NULL;
2962  BOOL ret;
2963 
2964  for (;;)
2965  {
2967  if (status != RPC_S_OK) break;
2968 
2969  status = insert_authorization_header(request, info->scheme, info->data, info->data_len);
2970  if (status != RPC_S_OK) break;
2971 
2973  ret = HttpSendRequestW(request, NULL, 0, NULL, 0);
2975  if (status != RPC_S_OK || info->finished) break;
2976 
2978  if (status != RPC_S_OK && status != ERROR_ACCESS_DENIED) break;
2979  drain_content(request, httpc->async_data, httpc->cancel_event);
2980  }
2981 
2982  if (info->scheme != RPC_C_HTTP_AUTHN_SCHEME_BASIC)
2984 
2986  return status;
2987 }
2988 
2990 {
2993 
2995  return FALSE;
2996 
2997  creds = httpc->common.QOS->qos->u.HttpCredentials;
2999  return FALSE;
3000 
3001  id = creds->TransportCredentials;
3002  if (!id || !id->User || !id->Password) return FALSE;
3003 
3004  return TRUE;
3005 }
3006 
3008 {
3009  return httpc->common.QOS &&
3012 }
3013 
3015 {
3016  static WCHAR httpW[] = {'h','t','t','p',0};
3017  static WCHAR httpsW[] = {'h','t','t','p','s',0};
3018  URL_COMPONENTSW uc;
3019  DWORD len;
3020  WCHAR *url;
3021  BOOL ret;
3022 
3023  if (!value) return RPC_S_OK;
3024 
3025  uc.dwStructSize = sizeof(uc);
3026  uc.lpszScheme = is_secure(httpc) ? httpsW : httpW;
3027  uc.dwSchemeLength = 0;
3028  uc.lpszHostName = httpc->servername;
3029  uc.dwHostNameLength = 0;
3030  uc.nPort = 0;
3031  uc.lpszUserName = NULL;
3032  uc.dwUserNameLength = 0;
3033  uc.lpszPassword = NULL;
3034  uc.dwPasswordLength = 0;
3035  uc.lpszUrlPath = NULL;
3036  uc.dwUrlPathLength = 0;
3037  uc.lpszExtraInfo = NULL;
3038  uc.dwExtraInfoLength = 0;
3039 
3041  return RPC_S_SERVER_UNAVAILABLE;
3042 
3043  if (!(url = HeapAlloc(GetProcessHeap(), 0, len))) return RPC_S_OUT_OF_MEMORY;
3044 
3045  len = len / sizeof(WCHAR) - 1;
3046  if (!InternetCreateUrlW(&uc, 0, url, &len))
3047  {
3048  HeapFree(GetProcessHeap(), 0, url);
3049  return RPC_S_SERVER_UNAVAILABLE;
3050  }
3051 
3053  HeapFree(GetProcessHeap(), 0, url);
3054  if (!ret) return RPC_S_SERVER_UNAVAILABLE;
3055 
3056  return RPC_S_OK;
3057 }
3058 
3060 {
3061  RpcConnection_http *httpc = (RpcConnection_http *)Connection;
3062  static const WCHAR wszVerbIn[] = {'R','P','C','_','I','N','_','D','A','T','A',0};
3063  static const WCHAR wszVerbOut[] = {'R','P','C','_','O','U','T','_','D','A','T','A',0};
3064  static const WCHAR wszRpcProxyPrefix[] = {'/','r','p','c','/','r','p','c','p','r','o','x','y','.','d','l','l','?',0};
3065  static const WCHAR wszColon[] = {':',0};
3066  static const WCHAR wszAcceptType[] = {'a','p','p','l','i','c','a','t','i','o','n','/','r','p','c',0};
3067  LPCWSTR wszAcceptTypes[] = { wszAcceptType, NULL };
3068  DWORD flags;
3069  WCHAR *url;
3071  BOOL secure, credentials;
3072  HttpTimerThreadData *timer_data;
3073  HANDLE thread;
3074 
3075  TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
3076 
3077  if (Connection->server)
3078  {
3079  ERR("ncacn_http servers not supported yet\n");
3080  return RPC_S_SERVER_UNAVAILABLE;
3081  }
3082 
3083  if (httpc->in_request)
3084  return RPC_S_OK;
3085 
3087 
3088  UuidCreate(&httpc->connection_uuid);
3089  UuidCreate(&httpc->in_pipe_uuid);
3090  UuidCreate(&httpc->out_pipe_uuid);
3091 
3093  if (status != RPC_S_OK)
3094  return status;
3095 
3096  url = HeapAlloc(GetProcessHeap(), 0, sizeof(wszRpcProxyPrefix) + (strlen(Connection->NetworkAddr) + 1 + strlen(Connection->Endpoint))*sizeof(WCHAR));
3097  if (!url)
3098  return RPC_S_OUT_OF_MEMORY;
3099  memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix));
3100  MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+ARRAY_SIZE(wszRpcProxyPrefix)-1,
3101  strlen(Connection->NetworkAddr)+1);
3102  lstrcatW(url, wszColon);
3103  MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+lstrlenW(url), strlen(Connection->Endpoint)+1);
3104 
3105  secure = is_secure(httpc);
3106  credentials = has_credentials(httpc);
3107 
3111  if (credentials) flags |= INTERNET_FLAG_NO_AUTH;
3112 
3113  status = set_auth_cookie(httpc, Connection->CookieAuth);
3114  if (status != RPC_S_OK)
3115  {
3116  HeapFree(GetProcessHeap(), 0, url);
3117  return status;
3118  }
3119  httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL, wszAcceptTypes,
3120  flags, (DWORD_PTR)httpc->async_data);
3121  if (!httpc->in_request)
3122  {
3123  ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
3124  HeapFree(GetProcessHeap(), 0, url);
3125  return RPC_S_SERVER_UNAVAILABLE;
3126  }
3127 
3128  if (credentials)
3129  {
3130  status = authorize_request(httpc, httpc->in_request);
3131  if (status != RPC_S_OK)
3132  {
3133  HeapFree(GetProcessHeap(), 0, url);
3134  return status;
3135  }
3137  if (status != RPC_S_OK)
3138  {
3139  HeapFree(GetProcessHeap(), 0, url);
3140  return status;
3141  }
3142  drain_content(httpc->in_request, httpc->async_data, httpc->cancel_event);
3143  }
3144 
3145  httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, wszAcceptTypes,
3146  flags, (DWORD_PTR)httpc->async_data);
3147  HeapFree(GetProcessHeap(), 0, url);
3148  if (!httpc->out_request)
3149  {
3150  ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
3151  return RPC_S_SERVER_UNAVAILABLE;
3152  }
3153 
3154  if (credentials)
3155  {
3156  status = authorize_request(httpc, httpc->out_request);
3157  if (status != RPC_S_OK)
3158  return status;
3159  }
3160 
3162  &httpc->connection_uuid, &httpc->in_pipe_uuid,
3163  &Connection->assoc->http_uuid, credentials);
3164  if (status != RPC_S_OK)
3165  return status;
3166 
3168  &httpc->connection_uuid, &httpc->out_pipe_uuid,
3169  &httpc->flow_control_increment, credentials);
3170  if (status != RPC_S_OK)
3171  return status;
3172 
3173  httpc->flow_control_mark = httpc->flow_control_increment / 2;
3174  httpc->last_sent_time = GetTickCount();
3176 
3177  timer_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*timer_data));
3178  if (!timer_data)
3179  return ERROR_OUTOFMEMORY;
3180  timer_data->timer_param = httpc->in_request;
3181  timer_data->last_sent_time = &httpc->last_sent_time;
3182  timer_data->timer_cancelled = httpc->timer_cancelled;
3183  /* FIXME: should use CreateTimerQueueTimer when implemented */
3184  thread = CreateThread(NULL, 0, rpcrt4_http_timer_thread, timer_data, 0, NULL);
3185  if (!thread)
3186  {
3187  HeapFree(GetProcessHeap(), 0, timer_data);
3188  return GetLastError();
3189  }
3191 
3192  return RPC_S_OK;
3193 }
3194 
3196 {
3197  assert(0);
3198  return RPC_S_SERVER_UNAVAILABLE;
3199 }
3200 
3201 static int rpcrt4_ncacn_http_read(RpcConnection *Connection,
3202  void *buffer, unsigned int count)
3203 {
3204  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3205  return rpcrt4_http_async_read(httpc->out_request, httpc->async_data, httpc->cancel_event, buffer, count);
3206 }
3207 
3209 {
3210  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3212  DWORD hdr_length;
3213  LONG dwRead;
3214  RpcPktCommonHdr common_hdr;
3215 
3216  *Header = NULL;
3217 
3218  TRACE("(%p, %p, %p)\n", Connection, Header, Payload);
3219 
3220 again:
3221  /* read packet common header */
3222  dwRead = rpcrt4_ncacn_http_read(Connection, &common_hdr, sizeof(common_hdr));
3223  if (dwRead != sizeof(common_hdr)) {
3224  WARN("Short read of header, %d bytes\n", dwRead);
3226  goto fail;
3227  }
3228  if (!memcmp(&common_hdr, "HTTP/1.1", sizeof("HTTP/1.1")) ||
3229  !memcmp(&common_hdr, "HTTP/1.0", sizeof("HTTP/1.0")))
3230  {
3231  FIXME("server returned %s\n", debugstr_a((const char *)&common_hdr));
3233  goto fail;
3234  }
3235 
3236  status = RPCRT4_ValidateCommonHeader(&common_hdr);
3237  if (status != RPC_S_OK) goto fail;
3238 
3239  hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr);
3240  if (hdr_length == 0) {
3241  WARN("header length == 0\n");
3243  goto fail;
3244  }
3245 
3246  *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length);
3247  if (!*Header)
3248  {
3250  goto fail;
3251  }
3252  memcpy(*Header, &common_hdr, sizeof(common_hdr));
3253 
3254  /* read the rest of packet header */
3255  dwRead = rpcrt4_ncacn_http_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr));
3256  if (dwRead != hdr_length - sizeof(common_hdr)) {
3257  WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length);
3259  goto fail;
3260  }
3261 
3262  if (common_hdr.frag_len - hdr_length)
3263  {
3264  *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length);
3265  if (!*Payload)
3266  {
3268  goto fail;
3269  }
3270 
3271  dwRead = rpcrt4_ncacn_http_read(Connection, *Payload, common_hdr.frag_len - hdr_length);
3272  if (dwRead != common_hdr.frag_len - hdr_length)
3273  {
3274  WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length);
3276  goto fail;
3277  }
3278  }
3279  else
3280  *Payload = NULL;
3281 
3282  if ((*Header)->common.ptype == PKT_HTTP)
3283  {
3284  if (!RPCRT4_IsValidHttpPacket(*Header, *Payload, common_hdr.frag_len - hdr_length))
3285  {
3286  ERR("invalid http packet of length %d bytes\n", (*Header)->common.frag_len);
3288  goto fail;
3289  }
3290  if ((*Header)->http.flags == 0x0001)
3291  {
3292  TRACE("http idle packet, waiting for real packet\n");
3293  if ((*Header)->http.num_data_items != 0)
3294  {
3295  ERR("HTTP idle packet should have no data items instead of %d\n", (*Header)->http.num_data_items);
3297  goto fail;
3298  }
3299  }
3300  else if ((*Header)->http.flags == 0x0002)
3301  {
3302  ULONG bytes_transmitted;
3303  ULONG flow_control_increment;
3304  UUID pipe_uuid;
3306  Connection->server,
3307  &bytes_transmitted,
3308  &flow_control_increment,
3309  &pipe_uuid);
3310  if (status != RPC_S_OK)
3311  goto fail;
3312  TRACE("received http flow control header (0x%x, 0x%x, %s)\n",
3313  bytes_transmitted, flow_control_increment, debugstr_guid(&pipe_uuid));
3314  /* FIXME: do something with parsed data */
3315  }
3316  else
3317  {
3318  FIXME("unrecognised http packet with flags 0x%04x\n", (*Header)->http.flags);
3320  goto fail;
3321  }
3323  *Header = NULL;
3324  HeapFree(GetProcessHeap(), 0, *Payload);
3325  *Payload = NULL;
3326  goto again;
3327  }
3328 
3329  /* success */
3330  status = RPC_S_OK;
3331 
3332  httpc->bytes_received += common_hdr.frag_len;
3333 
3334  TRACE("httpc->bytes_received = 0x%x\n", httpc->bytes_received);
3335 
3336  if (httpc->bytes_received > httpc->flow_control_mark)
3337  {
3339  httpc->bytes_received,
3340  httpc->flow_control_increment,
3341  &httpc->out_pipe_uuid);
3342  if (hdr)
3343  {
3344  DWORD bytes_written;
3345  BOOL ret2;
3346  TRACE("sending flow control packet at 0x%x\n", httpc->bytes_received);
3347  ret2 = InternetWriteFile(httpc->in_request, hdr, hdr->common.frag_len, &bytes_written);
3349  if (ret2)
3350  httpc->flow_control_mark = httpc->bytes_received + httpc->flow_control_increment / 2;
3351  }
3352  }
3353 
3354 fail:
3355  if (status != RPC_S_OK) {
3357  *Header = NULL;
3358  HeapFree(GetProcessHeap(), 0, *Payload);
3359  *Payload = NULL;
3360  }
3361  return status;
3362 }
3363 
3365  const void *buffer, unsigned int count)
3366 {
3367  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3368  DWORD bytes_written;
3369  BOOL ret;
3370 
3371  httpc->last_sent_time = ~0U; /* disable idle packet sending */
3372  ret = InternetWriteFile(httpc->in_request, buffer, count, &bytes_written);
3373  httpc->last_sent_time = GetTickCount();
3374  TRACE("%p %p %u -> %s\n", httpc->in_request, buffer, count, ret ? "TRUE" : "FALSE");
3375  return ret ? bytes_written : -1;
3376 }
3377 
3379 {
3380  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3381 
3382  TRACE("\n");
3383 
3384  SetEvent(httpc->timer_cancelled);
3385  if (httpc->in_request)
3387  httpc->in_request = NULL;
3388  if (httpc->out_request)
3390  httpc->out_request = NULL;
3391  if (httpc->app_info)
3392  InternetCloseHandle(httpc->app_info);
3393  httpc->app_info = NULL;
3394  if (httpc->session)
3395  InternetCloseHandle(httpc->session);
3396  httpc->session = NULL;
3398  if (httpc->cancel_event)
3399  CloseHandle(httpc->cancel_event);
3400  HeapFree(GetProcessHeap(), 0, httpc->servername);
3401  httpc->servername = NULL;
3402 
3403  return 0;
3404 }
3405 
3407 {
3408  rpcrt4_ncacn_http_close(conn); /* FIXME */
3409 }
3410 
3412 {
3413  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3414 
3415  SetEvent(httpc->cancel_event);
3416 }
3417 
3419 {
3420  FIXME("\n");
3421  return RPC_S_ACCESS_DENIED;
3422 }
3423 
3425 {
3426  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3427  BOOL ret;
3429 
3434  return status == RPC_S_OK ? 0 : -1;
3435 }
3436 
3437 static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data,
3438  const char *networkaddr,
3439  const char *endpoint)
3440 {
3441  return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
3443 }
3444 
3445 static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data,
3446  size_t tower_size,
3447  char **networkaddr,
3448  char **endpoint)
3449 {
3450  return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
3451  networkaddr, EPM_PROTOCOL_HTTP,
3452  endpoint);
3453 }
3454 
3455 static const struct connection_ops conn_protseq_list[] = {
3456  { "ncacn_np",
3470  NULL,
3477  },
3478  { "ncalrpc",
3492  NULL,
3499  },
3500  { "ncacn_ip_tcp",
3514  NULL,
3521  },
3522  { "ncacn_http",
3543  },
3544 };
3545 
3546 
3547 static const struct protseq_ops protseq_list[] =
3548 {
3549  {
3550  "ncacn_np",
3557  },
3558  {
3559  "ncalrpc",
3566  },
3567  {
3568  "ncacn_ip_tcp",
3575  },
3576 };
3577 
3578 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq)
3579 {
3580  unsigned int i;
3581  for(i = 0; i < ARRAY_SIZE(protseq_list); i++)
3582  if (!strcmp(protseq_list[i].name, protseq))
3583  return &protseq_list[i];
3584  return NULL;
3585 }
3586 
3587 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq)
3588 {
3589  unsigned int i;
3590  for(i = 0; i < ARRAY_SIZE(conn_protseq_list); i++)
3591  if (!strcmp(conn_protseq_list[i].name, protseq))
3592  return &conn_protseq_list[i];
3593  return NULL;
3594 }
3595 
3596 /**** interface to rest of code ****/
3597 
3599 {
3600  TRACE("(Connection == ^%p)\n", Connection);
3601 
3602  assert(!Connection->server);
3603  return Connection->ops->open_connection_client(Connection);
3604 }
3605 
3607 {
3608  TRACE("(Connection == ^%p)\n", Connection);
3609  if (SecIsValidHandle(&Connection->ctx))
3610  {
3611  DeleteSecurityContext(&Connection->ctx);
3612  SecInvalidateHandle(&Connection->ctx);
3613  }
3614  rpcrt4_conn_close(Connection);
3615  return RPC_S_OK;
3616 }
3617 
3619  LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
3620  LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS, LPCWSTR CookieAuth)
3621 {
3622  static LONG next_id;
3623  const struct connection_ops *ops;
3624  RpcConnection* NewConnection;
3625 
3626  ops = rpcrt4_get_conn_protseq_ops(Protseq);
3627  if (!ops)
3628  {
3629  FIXME("not supported for protseq %s\n", Protseq);
3631  }
3632 
3633  NewConnection = ops->alloc();
3634  NewConnection->ref = 1;
3635  NewConnection->server = server;
3636  NewConnection->ops = ops;
3637  NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
3638  NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
3639  NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
3640  NewConnection->CookieAuth = RPCRT4_strdupW(CookieAuth);
3641  NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;
3642  NewConnection->NextCallId = 1;
3643 
3644  SecInvalidateHandle(&NewConnection->ctx);
3645  if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
3646  NewConnection->AuthInfo = AuthInfo;
3647  NewConnection->auth_context_id = InterlockedIncrement( &next_id );
3649  NewConnection->QOS = QOS;
3650 
3651  list_init(&NewConnection->conn_pool_entry);
3652  list_init(&NewConnection->protseq_entry);
3653 
3654  TRACE("connection: %p\n", NewConnection);
3655  *Connection = NewConnection;
3656 
3657  return RPC_S_OK;
3658 }
3659 
3661 {
3662  RpcConnection *connection;
3663  RPC_STATUS err;
3664 
3665  err = RPCRT4_CreateConnection(&connection, old_connection->server, rpcrt4_conn_get_name(old_connection),
3666  old_connection->NetworkAddr, old_connection->Endpoint, NULL,
3667  old_connection->AuthInfo, old_connection->QOS, old_connection->CookieAuth);
3668  if (err != RPC_S_OK)
3669  return NULL;
3670 
3671  rpcrt4_conn_handoff(old_connection, connection);
3672  if (old_connection->protseq)
3673  {
3674  EnterCriticalSection(&old_connection->protseq->cs);
3675  connection->protseq = old_connection->protseq;
3676  list_add_tail(&old_connection->protseq->connections, &connection->protseq_entry);
3677  LeaveCriticalSection(&old_connection->protseq->cs);
3678  }
3679  return connection;
3680 }
3681 
3683 {
3684  HANDLE event = NULL;
3685 
3686  if (connection->ref > 1)
3687  event = connection->wait_release = CreateEventW(NULL, TRUE, FALSE, NULL);
3688 
3689  RPCRT4_ReleaseConnection(connection);
3690 
3691  if(event)
3692  {
3694  CloseHandle(event);
3695  }
3696 }
3697 
3699 {
3700  LONG ref = InterlockedIncrement(&connection->ref);
3701  TRACE("%p ref=%u\n", connection, ref);
3702  return connection;
3703 }
3704 
3706 {
3707  LONG ref;
3708 
3709  /* protseq stores a list of active connections, but does not own references to them.
3710  * It may need to grab a connection from the list, which could lead to a race if
3711  * connection is being released, but not yet removed from the list. We handle that
3712  * by synchronizing on CS here. */
3713  if (connection->protseq)
3714  {
3715  EnterCriticalSection(&connection->protseq->cs);
3716  ref = InterlockedDecrement(&connection->ref);
3717  if (!ref)
3718  list_remove(&connection->protseq_entry);
3719  LeaveCriticalSection(&connection->protseq->cs);
3720  }
3721  else
3722  {
3723  ref = InterlockedDecrement(&connection->ref);
3724  }
3725 
3726  TRACE("%p ref=%u\n", connection, ref);
3727 
3728  if (!ref)
3729  {
3730  RPCRT4_CloseConnection(connection);
3731  RPCRT4_strfree(connection->Endpoint);
3732  RPCRT4_strfree(connection->NetworkAddr);
3733  HeapFree(GetProcessHeap(), 0, connection->NetworkOptions);
3734  HeapFree(GetProcessHeap(), 0, connection->CookieAuth);
3735  if (connection->AuthInfo) RpcAuthInfo_Release(connection->AuthInfo);
3736  if (connection->QOS) RpcQualityOfService_Release(connection->QOS);
3737 
3738  /* server-only */
3739  if (connection->server_binding) RPCRT4_ReleaseBinding(connection->server_binding);
3740  else if (connection->assoc) RpcAssoc_ConnectionReleased(connection->assoc);
3741 
3742  if (connection->wait_release) SetEvent(connection->wait_release);
3743 
3744  HeapFree(GetProcessHeap(), 0, connection);
3745  }
3746 }
3747 
3748 RPC_STATUS RPCRT4_IsServerListening(const char *protseq, const char *endpoint)
3749 {
3750  const struct connection_ops *ops;
3751 
3752  ops = rpcrt4_get_conn_protseq_ops(protseq);
3753  if (!ops)
3754  {
3755  FIXME("not supported for protseq %s\n", protseq);
3756  return RPC_S_INVALID_BINDING;
3757  }
3758 
3759  return ops->is_server_listening(endpoint);
3760 }
3761 
3762 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data,
3763  size_t *tower_size,
3764  const char *protseq,
3765  const char *networkaddr,
3766  const char *endpoint)
3767 {
3768  twr_empty_floor_t *protocol_floor;
3769  const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq);
3770 
3771  *tower_size = 0;
3772 
3773  if (!protseq_ops)
3775 
3776  if (!tower_data)
3777  {
3778  *tower_size = sizeof(*protocol_floor);
3779  *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint);
3780  return RPC_S_OK;
3781  }
3782 
3783  protocol_floor = (twr_empty_floor_t *)tower_data;
3784  protocol_floor->count_lhs = sizeof(protocol_floor->protid);
3785  protocol_floor->protid = protseq_ops->epm_protocols[0];
3786  protocol_floor->count_rhs = 0;
3787 
3788  tower_data += sizeof(*protocol_floor);
3789 
3790  *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint);
3791  if (!*tower_size)
3792  return EPT_S_NOT_REGISTERED;
3793 
3794  *tower_size += sizeof(*protocol_floor);
3795 
3796  return RPC_S_OK;
3797 }
3798 
3799 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data,
3800  size_t tower_size,
3801  char **protseq,
3802  char **networkaddr,
3803  char **endpoint)
3804 {
3805  const twr_empty_floor_t *protocol_floor;
3806  const twr_empty_floor_t *floor4;
3807  const struct connection_ops *protseq_ops = NULL;
3809  unsigned int i;
3810 
3811  if (tower_size < sizeof(*protocol_floor))
3812  return EPT_S_NOT_REGISTERED;
3813 
3814  protocol_floor = (const twr_empty_floor_t *)tower_data;
3815  tower_data += sizeof(*protocol_floor);
3816  tower_size -= sizeof(*protocol_floor);
3817  if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) ||
3818  (protocol_floor->count_rhs > tower_size))
3819  return EPT_S_NOT_REGISTERED;
3820  tower_data += protocol_floor->count_rhs;
3821  tower_size -= protocol_floor->count_rhs;
3822 
3823  floor4 = (const twr_empty_floor_t *)tower_data;
3824  if ((tower_size < sizeof(*floor4)) ||
3825  (floor4->count_lhs != sizeof(floor4->protid)))
3826  return EPT_S_NOT_REGISTERED;
3827 
3828  for(i = 0; i < ARRAY_SIZE(conn_protseq_list); i++)
3829  if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) &&
3830  (floor4->protid == conn_protseq_list[i].epm_protocols[1]))
3831  {
3833  break;
3834  }
3835 
3836  if (!protseq_ops)
3837  return EPT_S_NOT_REGISTERED;
3838 
3839  status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint);
3840 
3841  if ((status == RPC_S_OK) && protseq)
3842  {
3843  *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1);
3844  strcpy(*protseq, protseq_ops->name);
3845  }
3846 
3847  return status;
3848 }
3849 
3850 /***********************************************************************
3851  * RpcNetworkIsProtseqValidW (RPCRT4.@)
3852  *
3853  * Checks if the given protocol sequence is known by the RPC system.
3854  * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
3855  *
3856  */
3858 {
3859  char ps[0x10];
3860 
3861  WideCharToMultiByte(CP_ACP, 0, protseq, -1,
3862  ps, sizeof ps, NULL, NULL);
3864  return RPC_S_OK;
3865 
3866  FIXME("Unknown protseq %s\n", debugstr_w(protseq));
3867 
3869 }
3870 
3871 /***********************************************************************
3872  * RpcNetworkIsProtseqValidA (RPCRT4.@)
3873  */
3875 {
3876  UNICODE_STRING protseqW;
3877 
3878  if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq))
3879  {
3881  RtlFreeUnicodeString(&protseqW);
3882  return ret;
3883  }
3884  return RPC_S_OUT_OF_MEMORY;
3885 }
3886 
3887 /***********************************************************************
3888  * RpcProtseqVectorFreeA (RPCRT4.@)
3889  */
3891 {
3892  TRACE("(%p)\n", protseqs);
3893 
3894  if (*protseqs)
3895  {
3896  unsigned int i;
3897  for (i = 0; i < (*protseqs)->Count; i++)
3898  HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]);
3900  *protseqs = NULL;
3901  }
3902  return RPC_S_OK;
3903 }
3904 
3905 /***********************************************************************
3906  * RpcProtseqVectorFreeW (RPCRT4.@)
3907  */
3909 {
3910  TRACE("(%p)\n", protseqs);
3911 
3912  if (*protseqs)
3913  {
3914  unsigned int i;
3915  for (i = 0; i < (*protseqs)->Count; i++)
3916  HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]);
3918  *protseqs = NULL;
3919  }
3920  return RPC_S_OK;
3921 }
3922 
3923 /***********************************************************************
3924  * RpcNetworkInqProtseqsW (RPCRT4.@)
3925  */
3927 {
3928  RPC_PROTSEQ_VECTORW *pvector;
3929  unsigned int i;
3931 
3932  TRACE("(%p)\n", protseqs);
3933 
3934  *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned short*)*ARRAY_SIZE(protseq_list)));
3935  if (!*protseqs)
3936  goto end;
3937  pvector = *protseqs;
3938  pvector->Count = 0;
3939  for (i = 0; i < ARRAY_SIZE(protseq_list); i++)
3940  {
3941  pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, (strlen(protseq_list[i].name)+1)*sizeof(unsigned short));
3942  if (pvector->Protseq[i] == NULL)
3943  goto end;
3945  (WCHAR*)pvector->Protseq[i], strlen(protseq_list[i].name) + 1);
3946  pvector->Count++;
3947  }
3948  status = RPC_S_OK;
3949 
3950 end:
3951  if (status != RPC_S_OK)
3953  return status;
3954 }
3955 
3956 /***********************************************************************
3957  * RpcNetworkInqProtseqsA (RPCRT4.@)
3958  */
3960 {
3961  RPC_PROTSEQ_VECTORA *pvector;
3962  unsigned int i;
3964 
3965  TRACE("(%p)\n", protseqs);
3966 
3967  *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned char*)*ARRAY_SIZE(protseq_list)));
3968  if (!*protseqs)
3969  goto end;
3970  pvector = *protseqs;
3971  pvector->Count = 0;
3972  for (i = 0; i < ARRAY_SIZE(protseq_list); i++)
3973  {
3974  pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, strlen(protseq_list[i].name)+1);
3975  if (pvector->Protseq[i] == NULL)
3976  goto end;
3977  strcpy((char*)pvector->Protseq[i], protseq_list[i].name);
3978  pvector->Count++;
3979  }
3980  status = RPC_S_OK;
3981 
3982 end:
3983  if (status != RPC_S_OK)
3985  return status;
3986 }
static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint)
#define HTTP_QUERY_CONTENT_LENGTH
Definition: wininet.h:1528
static RPC_STATUS rpcrt4_ncacn_np_is_server_listening(const char *endpoint)
DWORD dwStructSize
Definition: wininet.h:272
BOOL WINAPI SHIM_OBJ_NAME() GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
Definition: shimtest.c:21
USHORT MaxTransmissionSize
Definition: rpc_binding.h:71
static const WCHAR basicW[]
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
#define SOCKET_ERROR
Definition: winsock.h:333
static void rpcrt4_conn_np_cancel_call(RpcConnection *conn)
static void drain_content(HINTERNET request, RpcHttpAsyncData *async_data, HANDLE cancel_event)
static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data, const char *networkaddr, const char *endpoint)
struct list protseq_entry
Definition: rpc_binding.h:94
#define INTERNET_FLAG_NO_CACHE_WRITE
Definition: wininet.h:66
static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event)
static RPC_STATUS rpcrt4_ncacn_http_is_server_listening(const char *endpoint)
#define PIPE_UNLIMITED_INSTANCES
Definition: winbase.h:175
RPC_STATUS WINAPI RpcNetworkInqProtseqsW(RPC_PROTSEQ_VECTORW **protseqs)
static int rpcrt4_ncacn_http_write(RpcConnection *Connection, const void *buffer, unsigned int count)
static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data, const char *networkaddr, const char *endpoint)
#define RPC_C_AUTHN_WINNT
Definition: rpcdce.h:158
#define ERROR_FILE_EXISTS
Definition: winerror.h:165
static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
static struct authinfo * alloc_authinfo(void)
static int rpcrt4_http_async_read(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event, void *buffer, unsigned int count)
static int rpcrt4_conn_close(RpcConnection *Connection)
Definition: rpc_binding.h:200
BOOL WINAPI ImpersonateNamedPipeClient(HANDLE hNamedPipe)
Definition: security.c:1026
#define GENERIC_ALL
Definition: nt_native.h:92
unsigned short * Domain
Definition: rpcdce.h:225
static struct list protseqs
Definition: rpc_server.c:68
Definition: pdh_main.c:93
int proxy
Definition: main.c:67
static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, unsigned char tcp_protid, char **endpoint)
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID ULONG out_size
Definition: file.c:100
static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
static VOID WINAPI rpcrt4_http_internet_callback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
unsigned short * User
Definition: rpcdce.h:223
#define CloseHandle
Definition: compat.h:598
#define HTTP_QUERY_STATUS_TEXT
Definition: wininet.h:1543
static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
char hdr[14]
Definition: iptest.cpp:33
BOOL WINAPI MakeSelfRelativeSD(PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, LPDWORD lpdwBufferLength)
Definition: sec.c:214
#define SECPKG_CRED_OUTBOUND
Definition: sspi.h:291
static const char * rpcrt4_conn_get_name(const RpcConnection *Connection)
Definition: rpc_binding.h:183
static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint)
static RPC_STATUS rpcrt4_ncalrpc_authorize(RpcConnection *conn, BOOL first_time, unsigned char *in_buffer, unsigned int in_size, unsigned char *out_buffer, unsigned int *out_size)
void RpcAssoc_ConnectionReleased(RpcAssoc *assoc)
Definition: rpc_assoc.c:447
unsigned char * Protseq[1]
Definition: rpcdce.h:91
BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted)
Definition: sec.c:262
static int rpcrt4_conn_np_close(RpcConnection *conn)
static rfbScreenInfoPtr server
Definition: vnc.c:74
static SOCKET sock
Definition: syslog.c:45
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
SEC_WINNT_AUTH_IDENTITY_W * TransportCredentials
Definition: rpcdce.h:245
static RPC_STATUS rpcrt4_ncacn_http_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
Definition: rpc_binding.c:1184
#define AI_PASSIVE
Definition: ws2def.h:293
static HANDLE get_np_event(RpcConnection_np *connection)
Definition: rpc_transport.c:97
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define freeaddrinfo
Definition: wspiapi.h:46
static struct object_header ** handles
Definition: handle.c:45
static RPC_STATUS rpcrt4_conn_np_impersonate_client(RpcConnection *conn)
unsigned long u_long
Definition: linux.h:269
static DWORD auth_scheme_from_header(const WCHAR *header)
#define NI_NUMERICHOST
Definition: ws2def.h:354
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
#define WideCharToMultiByte
Definition: compat.h:111
SECURITY_STATUS WINAPI AcquireCredentialsHandleW(SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
Definition: wrapper.c:105
#define error(str)
Definition: mkdosfs.c:1605
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn)
Definition: rpc_message.c:1159
BOOL WINAPI InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision)
Definition: security.c:1008
void WINAPI I_RpcFree(void *Object)
Definition: rpcrt4_main.c:722
static int rpcrt4_conn_tcp_close(RpcConnection *conn)
u_int16 count_rhs
Definition: epm_towers.h:77
WCHAR SEC_WCHAR
Definition: sspi.h:29
DWORD dwStructSize
Definition: wininet.h:211
#define PIPE_TYPE_MESSAGE
Definition: winbase.h:168
static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection *Connection)
#define RPC_C_HTTP_AUTHN_TARGET_SERVER
Definition: rpcdce.h:202
RpcConnection common
Definition: rpc_transport.c:82
#define FD_ACCEPT
Definition: winsock.h:408
static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsyncData *async_data, HANDLE cancel_event, const UUID *connection_uuid, const UUID *out_pipe_uuid, ULONG *flow_control_increment, BOOL authorized)
RPC_STATUS RPCRT4_ParseHttpPrepareHeader1(RpcPktHdr *header, unsigned char *data, ULONG *field1)
Definition: rpc_message.c:566
struct list listeners
Definition: rpc_server.h:36
#define RPC_S_NO_CONTEXT_AVAILABLE
Definition: winerror.h:1073
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define MAKEWORD(a, b)
Definition: typedefs.h:248
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
#define TRUE
Definition: types.h:120
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
unsigned short * Password
Definition: rpcdce.h:227
ULONG ulVersion
Definition: sspi.h:181
u_int16 count_rhs
Definition: epm_towers.h:85
BOOL WINAPI RevertToSelf(VOID)
Definition: security.c:1610
#define SECURITY_IDENTIFICATION
Definition: winbase.h:538
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static int rpcrt4_conn_np_read(RpcConnection *conn, void *buffer, unsigned int count)
RpcServerProtseq common
struct _RpcServerProtseq_np RpcServerProtseq_np
#define CP_ACP
Definition: compat.h:109
u_int32 ipv4addr
Definition: epm_towers.h:78
BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision)
Definition: security.c:931
RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint)
HANDLE WINAPI CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:220
#define SecIsValidHandle(x)
Definition: sspi.h:63
GLuint GLuint GLsizei count
Definition: gl.h:1545
char CHAR
Definition: xmlstorage.h:175
unsigned int Count
Definition: rpcdce.h:90
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:112
#define U(x)
Definition: wordpad.c:45
DWORD dwBufferTotal
Definition: wininet.h:279
RpcConnection common
static RPC_STATUS is_pipe_listening(const char *pipe_name)
#define INTERNET_FLAG_SECURE
Definition: wininet.h:71
char * host
Definition: whois.c:55
LONG NTSTATUS
Definition: precomp.h:26
static SID_IDENTIFIER_AUTHORITY WorldAuthority
Definition: security.c:14
VOID RPCRT4_FreeHeader(RpcPktHdr *Header)
Definition: rpc_message.c:403
static ULONG RpcHttpAsyncData_Release(RpcHttpAsyncData *data)
BOOL WINAPI AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid)
Definition: security.c:1041
static int rpcrt4_conn_np_write(RpcConnection *conn, const void *buffer, unsigned int count)
#define CALLBACK
Definition: compat.h:35
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK io_status
Definition: comm.c:54
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wcha