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