Merge r55012 adding Wine3D control panel as per Amine's request.
[reactos.git] / dll / win32 / rpcrt4 / rpc_binding.c
1 /*
2 * RPC binding API
3 *
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003 Mike Hearn
6 * Copyright 2004 Filip Navara
7 * Copyright 2006 CodeWeavers
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winnls.h"
32 #include "winerror.h"
33 #include "winternl.h"
34 #include "wine/unicode.h"
35
36 #include "rpc.h"
37 #include "rpcndr.h"
38
39 #include "wine/debug.h"
40
41 #include "rpc_binding.h"
42 #include "rpc_assoc.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
45
46 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
47 {
48 DWORD len;
49 LPSTR s;
50 if (!src) return NULL;
51 if (slen == -1) slen = strlen(src);
52 len = slen;
53 s = HeapAlloc(GetProcessHeap(), 0, len+1);
54 memcpy(s, src, len);
55 s[len] = 0;
56 return s;
57 }
58
59 LPSTR RPCRT4_strdupWtoA(LPCWSTR src)
60 {
61 DWORD len;
62 LPSTR s;
63 if (!src) return NULL;
64 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
65 s = HeapAlloc(GetProcessHeap(), 0, len);
66 WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
67 return s;
68 }
69
70 LPWSTR RPCRT4_strdupAtoW(LPCSTR src)
71 {
72 DWORD len;
73 LPWSTR s;
74 if (!src) return NULL;
75 len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
76 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
77 MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
78 return s;
79 }
80
81 static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen)
82 {
83 DWORD len;
84 LPWSTR s;
85 if (!src) return NULL;
86 len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0);
87 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
88 MultiByteToWideChar(CP_ACP, 0, src, slen, s, len);
89 return s;
90 }
91
92 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen)
93 {
94 DWORD len;
95 LPWSTR s;
96 if (!src) return NULL;
97 if (slen == -1) slen = strlenW(src);
98 len = slen;
99 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
100 memcpy(s, src, len*sizeof(WCHAR));
101 s[len] = 0;
102 return s;
103 }
104
105 void RPCRT4_strfree(LPSTR src)
106 {
107 HeapFree(GetProcessHeap(), 0, src);
108 }
109
110 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
111 {
112 RpcBinding* NewBinding;
113
114 NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
115 NewBinding->refs = 1;
116 NewBinding->server = server;
117
118 *Binding = NewBinding;
119
120 return RPC_S_OK;
121 }
122
123 static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq)
124 {
125 RpcBinding* NewBinding;
126
127 RPCRT4_AllocBinding(&NewBinding, server);
128 NewBinding->Protseq = RPCRT4_strdupA(Protseq);
129
130 TRACE("binding: %p\n", NewBinding);
131 *Binding = NewBinding;
132
133 return RPC_S_OK;
134 }
135
136 static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq)
137 {
138 RpcBinding* NewBinding;
139
140 RPCRT4_AllocBinding(&NewBinding, server);
141 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
142
143 TRACE("binding: %p\n", NewBinding);
144 *Binding = NewBinding;
145
146 return RPC_S_OK;
147 }
148
149 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
150 LPCSTR Endpoint, LPCSTR NetworkOptions)
151 {
152 RPC_STATUS status;
153
154 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
155 debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
156
157 RPCRT4_strfree(Binding->NetworkAddr);
158 Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
159 RPCRT4_strfree(Binding->Endpoint);
160 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
161 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
162 Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions);
163
164 /* only attempt to get an association if the binding is complete */
165 if (Endpoint && Endpoint[0] != '\0')
166 {
167 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
168 Binding->Endpoint, Binding->NetworkOptions,
169 &Binding->Assoc);
170 if (status != RPC_S_OK)
171 return status;
172 }
173
174 return RPC_S_OK;
175 }
176
177 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
178 LPCWSTR Endpoint, LPCWSTR NetworkOptions)
179 {
180 RPC_STATUS status;
181
182 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
183 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
184
185 RPCRT4_strfree(Binding->NetworkAddr);
186 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
187 RPCRT4_strfree(Binding->Endpoint);
188 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
189 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
190 Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
191
192 /* only attempt to get an association if the binding is complete */
193 if (Endpoint && Endpoint[0] != '\0')
194 {
195 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
196 Binding->Endpoint, Binding->NetworkOptions,
197 &Binding->Assoc);
198 if (status != RPC_S_OK)
199 return status;
200 }
201
202 return RPC_S_OK;
203 }
204
205 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
206 {
207 RPC_STATUS status;
208
209 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
210
211 RPCRT4_strfree(Binding->Endpoint);
212 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
213
214 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
215 Binding->Assoc = NULL;
216 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
217 Binding->Endpoint, Binding->NetworkOptions,
218 &Binding->Assoc);
219 if (status != RPC_S_OK)
220 return status;
221
222 return RPC_S_OK;
223 }
224
225 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid)
226 {
227 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
228 if (ObjectUuid) Binding->ObjectUuid = *ObjectUuid;
229 else UuidCreateNil(&Binding->ObjectUuid);
230 return RPC_S_OK;
231 }
232
233 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
234 {
235 RpcBinding* NewBinding;
236 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
237
238 RPCRT4_AllocBinding(&NewBinding, Connection->server);
239 NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
240 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
241 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
242 NewBinding->FromConn = Connection;
243
244 TRACE("binding: %p\n", NewBinding);
245 *Binding = NewBinding;
246
247 return RPC_S_OK;
248 }
249
250 void RPCRT4_AddRefBinding(RpcBinding* Binding)
251 {
252 InterlockedIncrement(&Binding->refs);
253 }
254
255 RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding)
256 {
257 if (InterlockedDecrement(&Binding->refs))
258 return RPC_S_OK;
259
260 TRACE("binding: %p\n", Binding);
261 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
262 RPCRT4_strfree(Binding->Endpoint);
263 RPCRT4_strfree(Binding->NetworkAddr);
264 RPCRT4_strfree(Binding->Protseq);
265 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
266 if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
267 if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
268 HeapFree(GetProcessHeap(), 0, Binding);
269 return RPC_S_OK;
270 }
271
272 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
273 const RPC_SYNTAX_IDENTIFIER *TransferSyntax,
274 const RPC_SYNTAX_IDENTIFIER *InterfaceId)
275 {
276 TRACE("(Binding == ^%p)\n", Binding);
277
278 if (!Binding->server) {
279 return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId,
280 TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection);
281 } else {
282 /* we already have a connection with acceptable binding, so use it */
283 if (Binding->FromConn) {
284 *Connection = Binding->FromConn;
285 return RPC_S_OK;
286 } else {
287 ERR("no connection in binding\n");
288 return RPC_S_INTERNAL_ERROR;
289 }
290 }
291 }
292
293 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
294 {
295 TRACE("(Binding == ^%p)\n", Binding);
296 if (!Connection) return RPC_S_OK;
297 if (Binding->server) {
298 /* don't destroy a connection that is cached in the binding */
299 if (Binding->FromConn == Connection)
300 return RPC_S_OK;
301 return RPCRT4_DestroyConnection(Connection);
302 }
303 else {
304 RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
305 return RPC_S_OK;
306 }
307 }
308
309 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
310 {
311 DWORD len = strlen(dst), slen = strlen(src);
312 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
313 if (!ndst)
314 {
315 HeapFree(GetProcessHeap(), 0, dst);
316 return NULL;
317 }
318 ndst[len] = ',';
319 memcpy(ndst+len+1, src, slen+1);
320 return ndst;
321 }
322
323 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
324 {
325 DWORD len = strlenW(dst), slen = strlenW(src);
326 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
327 if (!ndst)
328 {
329 HeapFree(GetProcessHeap(), 0, dst);
330 return NULL;
331 }
332 ndst[len] = ',';
333 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
334 return ndst;
335 }
336
337 /* Copies the escaped version of a component into a string binding.
338 * Note: doesn't nul-terminate the string */
339 static RPC_CSTR escape_string_binding_component(RPC_CSTR string_binding,
340 const unsigned char *component)
341 {
342 for (; *component; component++) {
343 switch (*component) {
344 case '@':
345 case ':':
346 case '[':
347 case ']':
348 case '\\':
349 *string_binding++ = '\\';
350 *string_binding++ = *component;
351 break;
352 default:
353 *string_binding++ = *component;
354 break;
355 }
356 }
357 return string_binding;
358 }
359
360 static RPC_WSTR escape_string_binding_componentW(RPC_WSTR string_binding,
361 const WCHAR *component)
362 {
363 for (; *component; component++) {
364 switch (*component) {
365 case '@':
366 case ':':
367 case '[':
368 case ']':
369 case '\\':
370 *string_binding++ = '\\';
371 *string_binding++ = *component;
372 break;
373 default:
374 *string_binding++ = *component;
375 break;
376 }
377 }
378 return string_binding;
379 }
380
381 static const unsigned char *string_binding_find_delimiter(
382 const unsigned char *string_binding, unsigned char delim)
383 {
384 const unsigned char *next;
385 for (next = string_binding; *next; next++) {
386 if (*next == '\\') {
387 next++;
388 continue;
389 }
390 if (*next == delim)
391 return next;
392 }
393 return NULL;
394 }
395
396 static const WCHAR *string_binding_find_delimiterW(
397 const WCHAR *string_binding, WCHAR delim)
398 {
399 const WCHAR *next;
400 for (next = string_binding; *next; next++) {
401 if (*next == '\\') {
402 next++;
403 continue;
404 }
405 if (*next == delim)
406 return next;
407 }
408 return NULL;
409 }
410
411 static RPC_CSTR unescape_string_binding_component(
412 const unsigned char *string_binding, int len)
413 {
414 RPC_CSTR component, p;
415
416 if (len == -1) len = strlen((const char *)string_binding);
417
418 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
419 if (!component) return NULL;
420 for (p = component; len > 0; string_binding++, len--) {
421 if (*string_binding == '\\') {
422 string_binding++;
423 len--;
424 *p++ = *string_binding;
425 } else {
426 *p++ = *string_binding;
427 }
428 }
429 *p = '\0';
430 return component;
431 }
432
433 static RPC_WSTR unescape_string_binding_componentW(
434 const WCHAR *string_binding, int len)
435 {
436 RPC_WSTR component, p;
437
438 if (len == -1) len = strlenW(string_binding);
439
440 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
441 if (!component) return NULL;
442 for (p = component; len > 0; string_binding++, len--) {
443 if (*string_binding == '\\') {
444 string_binding++;
445 len--;
446 *p++ = *string_binding;
447 } else {
448 *p++ = *string_binding;
449 }
450 }
451 *p = '\0';
452 return component;
453 }
454
455 /***********************************************************************
456 * RpcStringBindingComposeA (RPCRT4.@)
457 */
458 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
459 RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
460 RPC_CSTR Options, RPC_CSTR *StringBinding )
461 {
462 DWORD len = 1;
463 RPC_CSTR data;
464
465 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
466 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
467 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
468 debugstr_a( (char*)Options ), StringBinding );
469
470 /* overestimate for each component for escaping of delimiters */
471 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) * 2 + 1;
472 if (Protseq && *Protseq) len += strlen((char*)Protseq) * 2 + 1;
473 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr) * 2;
474 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) * 2 + 2;
475 if (Options && *Options) len += strlen((char*)Options) * 2 + 2;
476
477 data = HeapAlloc(GetProcessHeap(), 0, len);
478 *StringBinding = data;
479
480 if (ObjUuid && *ObjUuid) {
481 data = escape_string_binding_component(data, ObjUuid);
482 *data++ = '@';
483 }
484 if (Protseq && *Protseq) {
485 data = escape_string_binding_component(data, Protseq);
486 *data++ = ':';
487 }
488 if (NetworkAddr && *NetworkAddr)
489 data = escape_string_binding_component(data, NetworkAddr);
490
491 if ((Endpoint && *Endpoint) ||
492 (Options && *Options)) {
493 *data++ = '[';
494 if (Endpoint && *Endpoint) {
495 data = escape_string_binding_component(data, Endpoint);
496 if (Options && *Options) *data++ = ',';
497 }
498 if (Options && *Options) {
499 data = escape_string_binding_component(data, Options);
500 }
501 *data++ = ']';
502 }
503 *data = 0;
504
505 return RPC_S_OK;
506 }
507
508 /***********************************************************************
509 * RpcStringBindingComposeW (RPCRT4.@)
510 */
511 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
512 RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
513 RPC_WSTR Options, RPC_WSTR* StringBinding )
514 {
515 DWORD len = 1;
516 RPC_WSTR data;
517
518 TRACE("(%s,%s,%s,%s,%s,%p)\n",
519 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
520 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
521 debugstr_w( Options ), StringBinding);
522
523 /* overestimate for each component for escaping of delimiters */
524 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) * 2 + 1;
525 if (Protseq && *Protseq) len += strlenW(Protseq) * 2 + 1;
526 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr) * 2;
527 if (Endpoint && *Endpoint) len += strlenW(Endpoint) * 2 + 2;
528 if (Options && *Options) len += strlenW(Options) * 2 + 2;
529
530 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
531 *StringBinding = data;
532
533 if (ObjUuid && *ObjUuid) {
534 data = escape_string_binding_componentW(data, ObjUuid);
535 *data++ = '@';
536 }
537 if (Protseq && *Protseq) {
538 data = escape_string_binding_componentW(data, Protseq);
539 *data++ = ':';
540 }
541 if (NetworkAddr && *NetworkAddr) {
542 data = escape_string_binding_componentW(data, NetworkAddr);
543 }
544 if ((Endpoint && *Endpoint) ||
545 (Options && *Options)) {
546 *data++ = '[';
547 if (Endpoint && *Endpoint) {
548 data = escape_string_binding_componentW(data, Endpoint);
549 if (Options && *Options) *data++ = ',';
550 }
551 if (Options && *Options) {
552 data = escape_string_binding_componentW(data, Options);
553 }
554 *data++ = ']';
555 }
556 *data = 0;
557
558 return RPC_S_OK;
559 }
560
561
562 /***********************************************************************
563 * RpcStringBindingParseA (RPCRT4.@)
564 */
565 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
566 RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
567 RPC_CSTR *Endpoint, RPC_CSTR *Options)
568 {
569 const unsigned char *data, *next;
570 static const char ep_opt[] = "endpoint=";
571 BOOL endpoint_already_found = FALSE;
572
573 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
574 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
575
576 if (ObjUuid) *ObjUuid = NULL;
577 if (Protseq) *Protseq = NULL;
578 if (NetworkAddr) *NetworkAddr = NULL;
579 if (Endpoint) *Endpoint = NULL;
580 if (Options) *Options = NULL;
581
582 data = StringBinding;
583
584 next = string_binding_find_delimiter(data, '@');
585 if (next) {
586 UUID uuid;
587 RPC_STATUS status;
588 RPC_CSTR str_uuid = unescape_string_binding_component(data, next - data);
589 status = UuidFromStringA(str_uuid, &uuid);
590 if (status != RPC_S_OK) {
591 HeapFree(GetProcessHeap(), 0, str_uuid);
592 return status;
593 }
594 if (ObjUuid)
595 *ObjUuid = str_uuid;
596 else
597 HeapFree(GetProcessHeap(), 0, str_uuid);
598 data = next+1;
599 }
600
601 next = string_binding_find_delimiter(data, ':');
602 if (next) {
603 if (Protseq) *Protseq = unescape_string_binding_component(data, next - data);
604 data = next+1;
605 }
606
607 next = string_binding_find_delimiter(data, '[');
608 if (next) {
609 const unsigned char *close;
610 RPC_CSTR opt;
611
612 if (NetworkAddr) *NetworkAddr = unescape_string_binding_component(data, next - data);
613 data = next+1;
614 close = string_binding_find_delimiter(data, ']');
615 if (!close) goto fail;
616
617 /* tokenize options */
618 while (data < close) {
619 next = string_binding_find_delimiter(data, ',');
620 if (!next || next > close) next = close;
621 /* FIXME: this is kind of inefficient */
622 opt = unescape_string_binding_component(data, next - data);
623 data = next+1;
624
625 /* parse option */
626 next = string_binding_find_delimiter(opt, '=');
627 if (!next) {
628 /* not an option, must be an endpoint */
629 if (endpoint_already_found) goto fail;
630 if (Endpoint) *Endpoint = opt;
631 else HeapFree(GetProcessHeap(), 0, opt);
632 endpoint_already_found = TRUE;
633 } else {
634 if (strncmp((const char *)opt, ep_opt, strlen(ep_opt)) == 0) {
635 /* endpoint option */
636 if (endpoint_already_found) goto fail;
637 if (Endpoint) *Endpoint = unescape_string_binding_component(next+1, -1);
638 HeapFree(GetProcessHeap(), 0, opt);
639 endpoint_already_found = TRUE;
640 } else {
641 /* network option */
642 if (Options) {
643 if (*Options) {
644 /* FIXME: this is kind of inefficient */
645 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, (char *)opt);
646 HeapFree(GetProcessHeap(), 0, opt);
647 } else
648 *Options = opt;
649 } else
650 HeapFree(GetProcessHeap(), 0, opt);
651 }
652 }
653 }
654
655 data = close+1;
656 if (*data) goto fail;
657 }
658 else if (NetworkAddr)
659 *NetworkAddr = unescape_string_binding_component(data, -1);
660
661 return RPC_S_OK;
662
663 fail:
664 if (ObjUuid) RpcStringFreeA(ObjUuid);
665 if (Protseq) RpcStringFreeA(Protseq);
666 if (NetworkAddr) RpcStringFreeA(NetworkAddr);
667 if (Endpoint) RpcStringFreeA(Endpoint);
668 if (Options) RpcStringFreeA(Options);
669 return RPC_S_INVALID_STRING_BINDING;
670 }
671
672 /***********************************************************************
673 * RpcStringBindingParseW (RPCRT4.@)
674 */
675 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
676 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
677 RPC_WSTR *Endpoint, RPC_WSTR *Options)
678 {
679 const WCHAR *data, *next;
680 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
681 BOOL endpoint_already_found = FALSE;
682
683 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
684 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
685
686 if (ObjUuid) *ObjUuid = NULL;
687 if (Protseq) *Protseq = NULL;
688 if (NetworkAddr) *NetworkAddr = NULL;
689 if (Endpoint) *Endpoint = NULL;
690 if (Options) *Options = NULL;
691
692 data = StringBinding;
693
694 next = string_binding_find_delimiterW(data, '@');
695 if (next) {
696 UUID uuid;
697 RPC_STATUS status;
698 RPC_WSTR str_uuid = unescape_string_binding_componentW(data, next - data);
699 status = UuidFromStringW(str_uuid, &uuid);
700 if (status != RPC_S_OK) {
701 HeapFree(GetProcessHeap(), 0, str_uuid);
702 return status;
703 }
704 if (ObjUuid)
705 *ObjUuid = str_uuid;
706 else
707 HeapFree(GetProcessHeap(), 0, str_uuid);
708 data = next+1;
709 }
710
711 next = string_binding_find_delimiterW(data, ':');
712 if (next) {
713 if (Protseq) *Protseq = unescape_string_binding_componentW(data, next - data);
714 data = next+1;
715 }
716
717 next = string_binding_find_delimiterW(data, '[');
718 if (next) {
719 const WCHAR *close;
720 RPC_WSTR opt;
721
722 if (NetworkAddr) *NetworkAddr = unescape_string_binding_componentW(data, next - data);
723 data = next+1;
724 close = string_binding_find_delimiterW(data, ']');
725 if (!close) goto fail;
726
727 /* tokenize options */
728 while (data < close) {
729 next = string_binding_find_delimiterW(data, ',');
730 if (!next || next > close) next = close;
731 /* FIXME: this is kind of inefficient */
732 opt = unescape_string_binding_componentW(data, next - data);
733 data = next+1;
734
735 /* parse option */
736 next = string_binding_find_delimiterW(opt, '=');
737 if (!next) {
738 /* not an option, must be an endpoint */
739 if (endpoint_already_found) goto fail;
740 if (Endpoint) *Endpoint = opt;
741 else HeapFree(GetProcessHeap(), 0, opt);
742 endpoint_already_found = TRUE;
743 } else {
744 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
745 /* endpoint option */
746 if (endpoint_already_found) goto fail;
747 if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1);
748 HeapFree(GetProcessHeap(), 0, opt);
749 endpoint_already_found = TRUE;
750 } else {
751 /* network option */
752 if (Options) {
753 if (*Options) {
754 /* FIXME: this is kind of inefficient */
755 *Options = RPCRT4_strconcatW(*Options, opt);
756 HeapFree(GetProcessHeap(), 0, opt);
757 } else
758 *Options = opt;
759 } else
760 HeapFree(GetProcessHeap(), 0, opt);
761 }
762 }
763 }
764
765 data = close+1;
766 if (*data) goto fail;
767 } else if (NetworkAddr)
768 *NetworkAddr = unescape_string_binding_componentW(data, -1);
769
770 return RPC_S_OK;
771
772 fail:
773 if (ObjUuid) RpcStringFreeW(ObjUuid);
774 if (Protseq) RpcStringFreeW(Protseq);
775 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
776 if (Endpoint) RpcStringFreeW(Endpoint);
777 if (Options) RpcStringFreeW(Options);
778 return RPC_S_INVALID_STRING_BINDING;
779 }
780
781 /***********************************************************************
782 * RpcBindingFree (RPCRT4.@)
783 */
784 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
785 {
786 RPC_STATUS status;
787 TRACE("(%p) = %p\n", Binding, *Binding);
788 if (*Binding)
789 status = RPCRT4_ReleaseBinding(*Binding);
790 else
791 status = RPC_S_INVALID_BINDING;
792 if (status == RPC_S_OK) *Binding = NULL;
793 return status;
794 }
795
796 /***********************************************************************
797 * RpcBindingVectorFree (RPCRT4.@)
798 */
799 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
800 {
801 ULONG c;
802
803 TRACE("(%p)\n", BindingVector);
804 for (c=0; c<(*BindingVector)->Count; c++) RpcBindingFree(&(*BindingVector)->BindingH[c]);
805 HeapFree(GetProcessHeap(), 0, *BindingVector);
806 *BindingVector = NULL;
807 return RPC_S_OK;
808 }
809
810 /***********************************************************************
811 * RpcBindingInqObject (RPCRT4.@)
812 */
813 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
814 {
815 RpcBinding* bind = Binding;
816
817 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
818 *ObjectUuid = bind->ObjectUuid;
819 return RPC_S_OK;
820 }
821
822 /***********************************************************************
823 * RpcBindingSetObject (RPCRT4.@)
824 */
825 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
826 {
827 RpcBinding* bind = Binding;
828
829 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
830 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
831 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
832 }
833
834 /***********************************************************************
835 * RpcBindingFromStringBindingA (RPCRT4.@)
836 */
837 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
838 {
839 RPC_STATUS ret;
840 RpcBinding* bind = NULL;
841 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
842 UUID Uuid;
843
844 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
845
846 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
847 &NetworkAddr, &Endpoint, &Options);
848 if (ret != RPC_S_OK) return ret;
849
850 ret = UuidFromStringA(ObjectUuid, &Uuid);
851
852 if (ret == RPC_S_OK)
853 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
854 if (ret != RPC_S_OK) return ret;
855 ret = RPCRT4_SetBindingObject(bind, &Uuid);
856 if (ret == RPC_S_OK)
857 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
858
859 RpcStringFreeA(&Options);
860 RpcStringFreeA(&Endpoint);
861 RpcStringFreeA(&NetworkAddr);
862 RpcStringFreeA(&Protseq);
863 RpcStringFreeA(&ObjectUuid);
864
865 if (ret == RPC_S_OK)
866 *Binding = (RPC_BINDING_HANDLE)bind;
867 else
868 RPCRT4_ReleaseBinding(bind);
869
870 return ret;
871 }
872
873 /***********************************************************************
874 * RpcBindingFromStringBindingW (RPCRT4.@)
875 */
876 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
877 {
878 RPC_STATUS ret;
879 RpcBinding* bind = NULL;
880 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
881 UUID Uuid;
882
883 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
884
885 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
886 &NetworkAddr, &Endpoint, &Options);
887 if (ret != RPC_S_OK) return ret;
888
889 ret = UuidFromStringW(ObjectUuid, &Uuid);
890
891 if (ret == RPC_S_OK)
892 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
893 if (ret != RPC_S_OK) return ret;
894 ret = RPCRT4_SetBindingObject(bind, &Uuid);
895 if (ret == RPC_S_OK)
896 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
897
898 RpcStringFreeW(&Options);
899 RpcStringFreeW(&Endpoint);
900 RpcStringFreeW(&NetworkAddr);
901 RpcStringFreeW(&Protseq);
902 RpcStringFreeW(&ObjectUuid);
903
904 if (ret == RPC_S_OK)
905 *Binding = (RPC_BINDING_HANDLE)bind;
906 else
907 RPCRT4_ReleaseBinding(bind);
908
909 return ret;
910 }
911
912 /***********************************************************************
913 * RpcBindingToStringBindingA (RPCRT4.@)
914 */
915 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
916 {
917 RPC_STATUS ret;
918 RpcBinding* bind = Binding;
919 RPC_CSTR ObjectUuid;
920
921 TRACE("(%p,%p)\n", Binding, StringBinding);
922
923 if (UuidIsNil(&bind->ObjectUuid, &ret))
924 ObjectUuid = NULL;
925 else
926 {
927 ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
928 if (ret != RPC_S_OK) return ret;
929 }
930
931 ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
932 (unsigned char*) bind->Endpoint, NULL, StringBinding);
933
934 RpcStringFreeA(&ObjectUuid);
935
936 return ret;
937 }
938
939 /***********************************************************************
940 * RpcBindingToStringBindingW (RPCRT4.@)
941 */
942 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
943 {
944 RPC_STATUS ret;
945 unsigned char *str = NULL;
946 TRACE("(%p,%p)\n", Binding, StringBinding);
947 ret = RpcBindingToStringBindingA(Binding, &str);
948 *StringBinding = RPCRT4_strdupAtoW((char*)str);
949 RpcStringFreeA(&str);
950 return ret;
951 }
952
953 /***********************************************************************
954 * I_RpcBindingInqTransportType (RPCRT4.@)
955 */
956 RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int * Type )
957 {
958
959 FIXME( "(%p,%p): stub\n", Binding, Type);
960 *Type = TRANSPORT_TYPE_LPC;
961 return RPC_S_OK;
962 }
963
964 /***********************************************************************
965 * I_RpcBindingSetAsync (RPCRT4.@)
966 * NOTES
967 * Exists in win9x and winNT, but with different number of arguments
968 * (9x version has 3 arguments, NT has 2).
969 */
970 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
971 {
972 RpcBinding* bind = Binding;
973
974 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
975
976 bind->BlockingFn = BlockingFn;
977
978 return RPC_S_OK;
979 }
980
981 /***********************************************************************
982 * RpcBindingCopy (RPCRT4.@)
983 */
984 RPC_STATUS RPC_ENTRY RpcBindingCopy(
985 RPC_BINDING_HANDLE SourceBinding,
986 RPC_BINDING_HANDLE* DestinationBinding)
987 {
988 RpcBinding *DestBinding;
989 RpcBinding *SrcBinding = SourceBinding;
990 RPC_STATUS status;
991
992 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
993
994 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
995 if (status != RPC_S_OK) return status;
996
997 DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
998 DestBinding->BlockingFn = SrcBinding->BlockingFn;
999 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
1000 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
1001 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
1002 DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
1003 if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
1004 DestBinding->Assoc = SrcBinding->Assoc;
1005
1006 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
1007 DestBinding->AuthInfo = SrcBinding->AuthInfo;
1008 if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
1009 DestBinding->QOS = SrcBinding->QOS;
1010
1011 *DestinationBinding = DestBinding;
1012 return RPC_S_OK;
1013 }
1014
1015 /***********************************************************************
1016 * RpcBindingReset (RPCRT4.@)
1017 */
1018 RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding)
1019 {
1020 RpcBinding *bind = Binding;
1021
1022 TRACE("(%p)\n", Binding);
1023
1024 RPCRT4_strfree(bind->Endpoint);
1025 bind->Endpoint = NULL;
1026 if (bind->Assoc) RpcAssoc_Release(bind->Assoc);
1027 bind->Assoc = NULL;
1028
1029 return RPC_S_OK;
1030 }
1031
1032 /***********************************************************************
1033 * RpcImpersonateClient (RPCRT4.@)
1034 *
1035 * Impersonates the client connected via a binding handle so that security
1036 * checks are done in the context of the client.
1037 *
1038 * PARAMS
1039 * BindingHandle [I] Handle to the binding to the client.
1040 *
1041 * RETURNS
1042 * Success: RPS_S_OK.
1043 * Failure: RPC_STATUS value.
1044 *
1045 * NOTES
1046 *
1047 * If BindingHandle is NULL then the function impersonates the client
1048 * connected to the binding handle of the current thread.
1049 */
1050 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
1051 {
1052 RpcBinding *bind;
1053
1054 TRACE("(%p)\n", BindingHandle);
1055
1056 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
1057 if (!BindingHandle) return RPC_S_INVALID_BINDING;
1058
1059 bind = BindingHandle;
1060 if (bind->FromConn)
1061 return rpcrt4_conn_impersonate_client(bind->FromConn);
1062 return RPC_S_WRONG_KIND_OF_BINDING;
1063 }
1064
1065 /***********************************************************************
1066 * RpcRevertToSelfEx (RPCRT4.@)
1067 *
1068 * Stops impersonating the client connected to the binding handle so that security
1069 * checks are no longer done in the context of the client.
1070 *
1071 * PARAMS
1072 * BindingHandle [I] Handle to the binding to the client.
1073 *
1074 * RETURNS
1075 * Success: RPS_S_OK.
1076 * Failure: RPC_STATUS value.
1077 *
1078 * NOTES
1079 *
1080 * If BindingHandle is NULL then the function stops impersonating the client
1081 * connected to the binding handle of the current thread.
1082 */
1083 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
1084 {
1085 RpcBinding *bind;
1086
1087 TRACE("(%p)\n", BindingHandle);
1088
1089 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
1090 if (!BindingHandle) return RPC_S_INVALID_BINDING;
1091
1092 bind = BindingHandle;
1093 if (bind->FromConn)
1094 return rpcrt4_conn_revert_to_self(bind->FromConn);
1095 return RPC_S_WRONG_KIND_OF_BINDING;
1096 }
1097
1098 static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
1099 {
1100 switch (AuthnLevel)
1101 {
1102 case RPC_C_AUTHN_GSS_NEGOTIATE:
1103 case RPC_C_AUTHN_WINNT:
1104 case RPC_C_AUTHN_GSS_KERBEROS:
1105 return TRUE;
1106 default:
1107 return FALSE;
1108 }
1109 }
1110
1111 RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
1112 CredHandle cred, TimeStamp exp,
1113 ULONG cbMaxToken,
1114 RPC_AUTH_IDENTITY_HANDLE identity,
1115 RpcAuthInfo **ret)
1116 {
1117 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
1118 if (!AuthInfo)
1119 return ERROR_OUTOFMEMORY;
1120
1121 AuthInfo->refs = 1;
1122 AuthInfo->AuthnLevel = AuthnLevel;
1123 AuthInfo->AuthnSvc = AuthnSvc;
1124 AuthInfo->cred = cred;
1125 AuthInfo->exp = exp;
1126 AuthInfo->cbMaxToken = cbMaxToken;
1127 AuthInfo->identity = identity;
1128 AuthInfo->server_principal_name = NULL;
1129
1130 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1131 * enable better matching in RpcAuthInfo_IsEqual */
1132 if (identity && has_nt_auth_identity(AuthnSvc))
1133 {
1134 const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity;
1135 AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity));
1136 if (!AuthInfo->nt_identity)
1137 {
1138 HeapFree(GetProcessHeap(), 0, AuthInfo);
1139 return ERROR_OUTOFMEMORY;
1140 }
1141
1142 AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1143 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1144 AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength);
1145 else
1146 AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength);
1147 AuthInfo->nt_identity->UserLength = nt_identity->UserLength;
1148 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1149 AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength);
1150 else
1151 AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength);
1152 AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength;
1153 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1154 AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength);
1155 else
1156 AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength);
1157 AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength;
1158
1159 if ((nt_identity->User && !AuthInfo->nt_identity->User) ||
1160 (nt_identity->Domain && !AuthInfo->nt_identity->Domain) ||
1161 (nt_identity->Password && !AuthInfo->nt_identity->Password))
1162 {
1163 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1164 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1165 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1166 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1167 HeapFree(GetProcessHeap(), 0, AuthInfo);
1168 return ERROR_OUTOFMEMORY;
1169 }
1170 }
1171 else
1172 AuthInfo->nt_identity = NULL;
1173 *ret = AuthInfo;
1174 return RPC_S_OK;
1175 }
1176
1177 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
1178 {
1179 return InterlockedIncrement(&AuthInfo->refs);
1180 }
1181
1182 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
1183 {
1184 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
1185
1186 if (!refs)
1187 {
1188 FreeCredentialsHandle(&AuthInfo->cred);
1189 if (AuthInfo->nt_identity)
1190 {
1191 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1192 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1193 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1194 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1195 }
1196 HeapFree(GetProcessHeap(), 0, AuthInfo->server_principal_name);
1197 HeapFree(GetProcessHeap(), 0, AuthInfo);
1198 }
1199
1200 return refs;
1201 }
1202
1203 BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2)
1204 {
1205 if (AuthInfo1 == AuthInfo2)
1206 return TRUE;
1207
1208 if (!AuthInfo1 || !AuthInfo2)
1209 return FALSE;
1210
1211 if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) ||
1212 (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc))
1213 return FALSE;
1214
1215 if (AuthInfo1->identity == AuthInfo2->identity)
1216 return TRUE;
1217
1218 if (!AuthInfo1->identity || !AuthInfo2->identity)
1219 return FALSE;
1220
1221 if (has_nt_auth_identity(AuthInfo1->AuthnSvc))
1222 {
1223 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity;
1224 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity;
1225 /* compare user names */
1226 if (identity1->UserLength != identity2->UserLength ||
1227 memcmp(identity1->User, identity2->User, identity1->UserLength))
1228 return FALSE;
1229 /* compare domain names */
1230 if (identity1->DomainLength != identity2->DomainLength ||
1231 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1232 return FALSE;
1233 /* compare passwords */
1234 if (identity1->PasswordLength != identity2->PasswordLength ||
1235 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1236 return FALSE;
1237 }
1238 else
1239 return FALSE;
1240
1241 return TRUE;
1242 }
1243
1244 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
1245 {
1246 RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
1247
1248 if (!qos)
1249 return RPC_S_OUT_OF_RESOURCES;
1250
1251 qos->refs = 1;
1252 qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
1253 if (!qos->qos) goto error;
1254 qos->qos->Version = qos_src->Version;
1255 qos->qos->Capabilities = qos_src->Capabilities;
1256 qos->qos->IdentityTracking = qos_src->IdentityTracking;
1257 qos->qos->ImpersonationType = qos_src->ImpersonationType;
1258 qos->qos->AdditionalSecurityInfoType = 0;
1259
1260 if (qos_src->Version >= 2)
1261 {
1262 const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
1263 qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
1264 if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1265 {
1266 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
1267 RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
1268
1269 http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
1270 qos->qos->u.HttpCredentials = http_credentials_dst;
1271 if (!http_credentials_dst) goto error;
1272 http_credentials_dst->TransportCredentials = NULL;
1273 http_credentials_dst->Flags = http_credentials_src->Flags;
1274 http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
1275 http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
1276 http_credentials_dst->AuthnSchemes = NULL;
1277 http_credentials_dst->ServerCertificateSubject = NULL;
1278 if (http_credentials_src->TransportCredentials)
1279 {
1280 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
1281 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst));
1282 if (!cred_dst) goto error;
1283 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1284 if (unicode)
1285 {
1286 const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
1287 cred_dst->UserLength = cred_src->UserLength;
1288 cred_dst->PasswordLength = cred_src->PasswordLength;
1289 cred_dst->DomainLength = cred_src->DomainLength;
1290 cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
1291 cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
1292 cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
1293 }
1294 else
1295 {
1296 const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
1297 cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
1298 cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
1299 cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
1300 cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
1301 cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
1302 cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
1303 if (!cred_dst->Password || !cred_dst->Domain) goto error;
1304 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
1305 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
1306 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
1307 }
1308 }
1309 if (http_credentials_src->NumberOfAuthnSchemes)
1310 {
1311 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1312 if (!http_credentials_dst->AuthnSchemes) goto error;
1313 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1314 }
1315 if (http_credentials_src->ServerCertificateSubject)
1316 {
1317 if (unicode)
1318 http_credentials_dst->ServerCertificateSubject =
1319 RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
1320 strlenW(http_credentials_src->ServerCertificateSubject));
1321 else
1322 http_credentials_dst->ServerCertificateSubject =
1323 RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
1324 if (!http_credentials_dst->ServerCertificateSubject) goto error;
1325 }
1326 }
1327 }
1328 *qos_dst = qos;
1329 return RPC_S_OK;
1330
1331 error:
1332 if (qos->qos)
1333 {
1334 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
1335 qos->qos->u.HttpCredentials)
1336 {
1337 if (qos->qos->u.HttpCredentials->TransportCredentials)
1338 {
1339 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1340 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1341 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1342 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1343 }
1344 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1345 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1346 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1347 }
1348 HeapFree(GetProcessHeap(), 0, qos->qos);
1349 }
1350 HeapFree(GetProcessHeap(), 0, qos);
1351 return RPC_S_OUT_OF_RESOURCES;
1352 }
1353
1354 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
1355 {
1356 return InterlockedIncrement(&qos->refs);
1357 }
1358
1359 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
1360 {
1361 ULONG refs = InterlockedDecrement(&qos->refs);
1362
1363 if (!refs)
1364 {
1365 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1366 {
1367 if (qos->qos->u.HttpCredentials->TransportCredentials)
1368 {
1369 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1370 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1371 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1372 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1373 }
1374 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1375 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1376 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1377 }
1378 HeapFree(GetProcessHeap(), 0, qos->qos);
1379 HeapFree(GetProcessHeap(), 0, qos);
1380 }
1381 return refs;
1382 }
1383
1384 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2)
1385 {
1386 if (qos1 == qos2)
1387 return TRUE;
1388
1389 if (!qos1 || !qos2)
1390 return FALSE;
1391
1392 TRACE("qos1 = { %d %d %d %d }, qos2 = { %d %d %d %d }\n",
1393 qos1->qos->Capabilities, qos1->qos->IdentityTracking,
1394 qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType,
1395 qos2->qos->Capabilities, qos2->qos->IdentityTracking,
1396 qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType);
1397
1398 if ((qos1->qos->Capabilities != qos2->qos->Capabilities) ||
1399 (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) ||
1400 (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) ||
1401 (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType))
1402 return FALSE;
1403
1404 if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1405 {
1406 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials;
1407 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials;
1408
1409 if (http_credentials1->Flags != http_credentials2->Flags)
1410 return FALSE;
1411
1412 if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget)
1413 return FALSE;
1414
1415 /* authentication schemes and server certificate subject not currently used */
1416
1417 if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials)
1418 {
1419 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials;
1420 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials;
1421
1422 if (!identity1 || !identity2)
1423 return FALSE;
1424
1425 /* compare user names */
1426 if (identity1->UserLength != identity2->UserLength ||
1427 memcmp(identity1->User, identity2->User, identity1->UserLength))
1428 return FALSE;
1429 /* compare domain names */
1430 if (identity1->DomainLength != identity2->DomainLength ||
1431 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1432 return FALSE;
1433 /* compare passwords */
1434 if (identity1->PasswordLength != identity2->PasswordLength ||
1435 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1436 return FALSE;
1437 }
1438 }
1439
1440 return TRUE;
1441 }
1442
1443 /***********************************************************************
1444 * RpcRevertToSelf (RPCRT4.@)
1445 */
1446 RPC_STATUS WINAPI RpcRevertToSelf(void)
1447 {
1448 TRACE("\n");
1449 return RpcRevertToSelfEx(NULL);
1450 }
1451
1452 /***********************************************************************
1453 * RpcMgmtSetComTimeout (RPCRT4.@)
1454 */
1455 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
1456 {
1457 FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
1458 return RPC_S_OK;
1459 }
1460
1461 /***********************************************************************
1462 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1463 */
1464 RPCRTAPI RPC_STATUS RPC_ENTRY
1465 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1466 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1467 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1468 {
1469 RPC_STATUS status;
1470 RPC_WSTR principal;
1471
1472 TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1473 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1474
1475 status = RpcBindingInqAuthInfoExW(Binding, ServerPrincName ? &principal : NULL, AuthnLevel,
1476 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1477 if (status == RPC_S_OK && ServerPrincName)
1478 {
1479 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
1480 RpcStringFreeW(&principal);
1481 if (!*ServerPrincName) return ERROR_OUTOFMEMORY;
1482 }
1483
1484 return status;
1485 }
1486
1487 /***********************************************************************
1488 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1489 */
1490 RPCRTAPI RPC_STATUS RPC_ENTRY
1491 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1492 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1493 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1494 {
1495 RpcBinding *bind = Binding;
1496
1497 TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1498 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1499
1500 if (!bind->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH;
1501
1502 if (SecurityQOS)
1503 {
1504 FIXME("QOS not implemented\n");
1505 return RPC_S_INVALID_BINDING;
1506 }
1507
1508 if (ServerPrincName)
1509 {
1510 if (bind->AuthInfo->server_principal_name)
1511 {
1512 *ServerPrincName = RPCRT4_strdupW(bind->AuthInfo->server_principal_name);
1513 if (!*ServerPrincName) return ERROR_OUTOFMEMORY;
1514 }
1515 else *ServerPrincName = NULL;
1516 }
1517 if (AuthnLevel) *AuthnLevel = bind->AuthInfo->AuthnLevel;
1518 if (AuthnSvc) *AuthnSvc = bind->AuthInfo->AuthnSvc;
1519 if (AuthIdentity) *AuthIdentity = bind->AuthInfo->identity;
1520 if (AuthzSvc)
1521 {
1522 FIXME("authorization service not implemented\n");
1523 *AuthzSvc = RPC_C_AUTHZ_NONE;
1524 }
1525
1526 return RPC_S_OK;
1527 }
1528
1529 /***********************************************************************
1530 * RpcBindingInqAuthInfoA (RPCRT4.@)
1531 */
1532 RPCRTAPI RPC_STATUS RPC_ENTRY
1533 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1534 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1535 {
1536 return RpcBindingInqAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
1537 AuthzSvc, 0, NULL);
1538 }
1539
1540 /***********************************************************************
1541 * RpcBindingInqAuthInfoW (RPCRT4.@)
1542 */
1543 RPCRTAPI RPC_STATUS RPC_ENTRY
1544 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1545 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1546 {
1547 return RpcBindingInqAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
1548 AuthzSvc, 0, NULL);
1549 }
1550
1551 /***********************************************************************
1552 * RpcBindingInqAuthClientA (RPCRT4.@)
1553 */
1554 RPCRTAPI RPC_STATUS RPC_ENTRY
1555 RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1556 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1557 ULONG *AuthzSvc )
1558 {
1559 return RpcBindingInqAuthClientExA(ClientBinding, Privs, ServerPrincName, AuthnLevel,
1560 AuthnSvc, AuthzSvc, 0);
1561 }
1562
1563 /***********************************************************************
1564 * RpcBindingInqAuthClientW (RPCRT4.@)
1565 */
1566 RPCRTAPI RPC_STATUS RPC_ENTRY
1567 RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1568 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1569 ULONG *AuthzSvc )
1570 {
1571 return RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName, AuthnLevel,
1572 AuthnSvc, AuthzSvc, 0);
1573 }
1574
1575 /***********************************************************************
1576 * RpcBindingInqAuthClientExA (RPCRT4.@)
1577 */
1578 RPCRTAPI RPC_STATUS RPC_ENTRY
1579 RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1580 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1581 ULONG *AuthzSvc, ULONG Flags )
1582 {
1583 RPC_STATUS status;
1584 RPC_WSTR principal;
1585
1586 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
1587 AuthnSvc, AuthzSvc, Flags);
1588
1589 status = RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName ? &principal : NULL,
1590 AuthnLevel, AuthnSvc, AuthzSvc, Flags);
1591 if (status == RPC_S_OK && ServerPrincName)
1592 {
1593 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
1594 if (!*ServerPrincName && principal) status = ERROR_OUTOFMEMORY;
1595 RpcStringFreeW(&principal);
1596 }
1597
1598 return status;
1599 }
1600
1601 /***********************************************************************
1602 * RpcBindingInqAuthClientExW (RPCRT4.@)
1603 */
1604 RPCRTAPI RPC_STATUS RPC_ENTRY
1605 RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1606 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1607 ULONG *AuthzSvc, ULONG Flags )
1608 {
1609 RpcBinding *bind = ClientBinding;
1610
1611 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
1612 AuthnSvc, AuthzSvc, Flags);
1613
1614 if (!bind->FromConn) return RPC_S_INVALID_BINDING;
1615
1616 return rpcrt4_conn_inquire_auth_client(bind->FromConn, Privs,
1617 ServerPrincName, AuthnLevel,
1618 AuthnSvc, AuthzSvc, Flags);
1619 }
1620
1621 /***********************************************************************
1622 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1623 */
1624 RPCRTAPI RPC_STATUS RPC_ENTRY
1625 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1626 ULONG AuthnLevel, ULONG AuthnSvc,
1627 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1628 RPC_SECURITY_QOS *SecurityQos )
1629 {
1630 RpcBinding* bind = Binding;
1631 SECURITY_STATUS r;
1632 CredHandle cred;
1633 TimeStamp exp;
1634 ULONG package_count;
1635 ULONG i;
1636 PSecPkgInfoA packages;
1637 ULONG cbMaxToken;
1638
1639 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1640 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1641
1642 if (SecurityQos)
1643 {
1644 RPC_STATUS status;
1645
1646 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1647 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1648 if (SecurityQos->Version >= 2)
1649 {
1650 const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
1651 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2->AdditionalSecurityInfoType);
1652 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1653 TRACE(", { %p, 0x%x, %d, %d, %p, %s }",
1654 SecurityQos2->u.HttpCredentials->TransportCredentials,
1655 SecurityQos2->u.HttpCredentials->Flags,
1656 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1657 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1658 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1659 SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
1660 }
1661 TRACE("}\n");
1662 status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
1663 if (status != RPC_S_OK)
1664 return status;
1665 }
1666 else
1667 {
1668 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1669 bind->QOS = NULL;
1670 }
1671
1672 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1673 AuthnSvc = RPC_C_AUTHN_WINNT;
1674
1675 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1676 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1677 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1678
1679 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1680 {
1681 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1682 bind->AuthInfo = NULL;
1683 return RPC_S_OK;
1684 }
1685
1686 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1687 {
1688 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1689 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1690 }
1691
1692 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1693 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1694 {
1695 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1696 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1697 }
1698
1699 r = EnumerateSecurityPackagesA(&package_count, &packages);
1700 if (r != SEC_E_OK)
1701 {
1702 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1703 return RPC_S_SEC_PKG_ERROR;
1704 }
1705
1706 for (i = 0; i < package_count; i++)
1707 if (packages[i].wRPCID == AuthnSvc)
1708 break;
1709
1710 if (i == package_count)
1711 {
1712 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1713 FreeContextBuffer(packages);
1714 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1715 }
1716
1717 TRACE("found package %s for service %u\n", packages[i].Name, AuthnSvc);
1718 r = AcquireCredentialsHandleA(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1719 AuthIdentity, NULL, NULL, &cred, &exp);
1720 cbMaxToken = packages[i].cbMaxToken;
1721 FreeContextBuffer(packages);
1722 if (r == ERROR_SUCCESS)
1723 {
1724 RpcAuthInfo *new_auth_info;
1725 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1726 AuthIdentity, &new_auth_info);
1727 if (r == RPC_S_OK)
1728 {
1729 new_auth_info->server_principal_name = RPCRT4_strdupAtoW((char *)ServerPrincName);
1730 if (new_auth_info->server_principal_name)
1731 {
1732 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1733 bind->AuthInfo = new_auth_info;
1734 }
1735 else
1736 {
1737 RpcAuthInfo_Release(new_auth_info);
1738 r = ERROR_OUTOFMEMORY;
1739 }
1740 }
1741 else
1742 FreeCredentialsHandle(&cred);
1743 return r;
1744 }
1745 else
1746 {
1747 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1748 return RPC_S_SEC_PKG_ERROR;
1749 }
1750 }
1751
1752 /***********************************************************************
1753 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1754 */
1755 RPCRTAPI RPC_STATUS RPC_ENTRY
1756 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1757 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1758 RPC_SECURITY_QOS *SecurityQos )
1759 {
1760 RpcBinding* bind = Binding;
1761 SECURITY_STATUS r;
1762 CredHandle cred;
1763 TimeStamp exp;
1764 ULONG package_count;
1765 ULONG i;
1766 PSecPkgInfoW packages;
1767 ULONG cbMaxToken;
1768
1769 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w(ServerPrincName),
1770 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1771
1772 if (SecurityQos)
1773 {
1774 RPC_STATUS status;
1775
1776 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1777 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1778 if (SecurityQos->Version >= 2)
1779 {
1780 const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
1781 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2->AdditionalSecurityInfoType);
1782 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1783 TRACE(", { %p, 0x%x, %d, %d, %p, %s }",
1784 SecurityQos2->u.HttpCredentials->TransportCredentials,
1785 SecurityQos2->u.HttpCredentials->Flags,
1786 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1787 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1788 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1789 debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
1790 }
1791 TRACE("}\n");
1792 status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
1793 if (status != RPC_S_OK)
1794 return status;
1795 }
1796 else
1797 {
1798 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1799 bind->QOS = NULL;
1800 }
1801
1802 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1803 AuthnSvc = RPC_C_AUTHN_WINNT;
1804
1805 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1806 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1807 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1808
1809 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1810 {
1811 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1812 bind->AuthInfo = NULL;
1813 return RPC_S_OK;
1814 }
1815
1816 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1817 {
1818 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1819 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1820 }
1821
1822 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1823 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1824 {
1825 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1826 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1827 }
1828
1829 r = EnumerateSecurityPackagesW(&package_count, &packages);
1830 if (r != SEC_E_OK)
1831 {
1832 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r);
1833 return RPC_S_SEC_PKG_ERROR;
1834 }
1835
1836 for (i = 0; i < package_count; i++)
1837 if (packages[i].wRPCID == AuthnSvc)
1838 break;
1839
1840 if (i == package_count)
1841 {
1842 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1843 FreeContextBuffer(packages);
1844 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1845 }
1846
1847 TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), AuthnSvc);
1848 r = AcquireCredentialsHandleW(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1849 AuthIdentity, NULL, NULL, &cred, &exp);
1850 cbMaxToken = packages[i].cbMaxToken;
1851 FreeContextBuffer(packages);
1852 if (r == ERROR_SUCCESS)
1853 {
1854 RpcAuthInfo *new_auth_info;
1855 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1856 AuthIdentity, &new_auth_info);
1857 if (r == RPC_S_OK)
1858 {
1859 new_auth_info->server_principal_name = RPCRT4_strdupW(ServerPrincName);
1860 if (!ServerPrincName || new_auth_info->server_principal_name)
1861 {
1862 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1863 bind->AuthInfo = new_auth_info;
1864 }
1865 else
1866 {
1867 RpcAuthInfo_Release(new_auth_info);
1868 r = ERROR_OUTOFMEMORY;
1869 }
1870 }
1871 else
1872 FreeCredentialsHandle(&cred);
1873 return r;
1874 }
1875 else
1876 {
1877 ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r);
1878 return RPC_S_SEC_PKG_ERROR;
1879 }
1880 }
1881
1882 /***********************************************************************
1883 * RpcBindingSetAuthInfoA (RPCRT4.@)
1884 */
1885 RPCRTAPI RPC_STATUS RPC_ENTRY
1886 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
1887 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1888 {
1889 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName),
1890 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1891 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1892 }
1893
1894 /***********************************************************************
1895 * RpcBindingSetAuthInfoW (RPCRT4.@)
1896 */
1897 RPCRTAPI RPC_STATUS RPC_ENTRY
1898 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1899 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1900 {
1901 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w(ServerPrincName),
1902 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1903 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1904 }
1905
1906 /***********************************************************************
1907 * RpcBindingSetOption (RPCRT4.@)
1908 */
1909 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG_PTR OptionValue)
1910 {
1911 FIXME("(%p, %d, %ld): stub\n", BindingHandle, Option, OptionValue);
1912 return RPC_S_OK;
1913 }