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