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