Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrpc_binding.c
Go to the documentation of this file.
00001 /* 00002 * RPC binding API 00003 * 00004 * Copyright 2001 Ove Kåven, TransGaming Technologies 00005 * Copyright 2003 Mike Hearn 00006 * Copyright 2004 Filip Navara 00007 * Copyright 2006 CodeWeavers 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00022 */ 00023 00024 #include <stdarg.h> 00025 #include <stdio.h> 00026 #include <string.h> 00027 #include <assert.h> 00028 00029 #include "windef.h" 00030 #include "winbase.h" 00031 #include "winnls.h" 00032 #include "winerror.h" 00033 #include "winternl.h" 00034 #include "wine/unicode.h" 00035 00036 #include "rpc.h" 00037 #include "rpcndr.h" 00038 00039 #include "wine/debug.h" 00040 00041 #include "rpc_binding.h" 00042 #include "rpc_assoc.h" 00043 00044 WINE_DEFAULT_DEBUG_CHANNEL(rpc); 00045 00046 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen) 00047 { 00048 DWORD len; 00049 LPSTR s; 00050 if (!src) return NULL; 00051 if (slen == -1) slen = strlen(src); 00052 len = slen; 00053 s = HeapAlloc(GetProcessHeap(), 0, len+1); 00054 memcpy(s, src, len); 00055 s[len] = 0; 00056 return s; 00057 } 00058 00059 LPSTR RPCRT4_strdupWtoA(LPCWSTR src) 00060 { 00061 DWORD len; 00062 LPSTR s; 00063 if (!src) return NULL; 00064 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL); 00065 s = HeapAlloc(GetProcessHeap(), 0, len); 00066 WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL); 00067 return s; 00068 } 00069 00070 LPWSTR RPCRT4_strdupAtoW(LPCSTR src) 00071 { 00072 DWORD len; 00073 LPWSTR s; 00074 if (!src) return NULL; 00075 len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); 00076 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); 00077 MultiByteToWideChar(CP_ACP, 0, src, -1, s, len); 00078 return s; 00079 } 00080 00081 static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen) 00082 { 00083 DWORD len; 00084 LPWSTR s; 00085 if (!src) return NULL; 00086 len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0); 00087 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); 00088 MultiByteToWideChar(CP_ACP, 0, src, slen, s, len); 00089 return s; 00090 } 00091 00092 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen) 00093 { 00094 DWORD len; 00095 LPWSTR s; 00096 if (!src) return NULL; 00097 if (slen == -1) slen = strlenW(src); 00098 len = slen; 00099 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); 00100 memcpy(s, src, len*sizeof(WCHAR)); 00101 s[len] = 0; 00102 return s; 00103 } 00104 00105 void RPCRT4_strfree(LPSTR src) 00106 { 00107 HeapFree(GetProcessHeap(), 0, src); 00108 } 00109 00110 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server) 00111 { 00112 RpcBinding* NewBinding; 00113 00114 NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding)); 00115 NewBinding->refs = 1; 00116 NewBinding->server = server; 00117 00118 *Binding = NewBinding; 00119 00120 return RPC_S_OK; 00121 } 00122 00123 static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq) 00124 { 00125 RpcBinding* NewBinding; 00126 00127 RPCRT4_AllocBinding(&NewBinding, server); 00128 NewBinding->Protseq = RPCRT4_strdupA(Protseq); 00129 00130 TRACE("binding: %p\n", NewBinding); 00131 *Binding = NewBinding; 00132 00133 return RPC_S_OK; 00134 } 00135 00136 static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq) 00137 { 00138 RpcBinding* NewBinding; 00139 00140 RPCRT4_AllocBinding(&NewBinding, server); 00141 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq); 00142 00143 TRACE("binding: %p\n", NewBinding); 00144 *Binding = NewBinding; 00145 00146 return RPC_S_OK; 00147 } 00148 00149 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr, 00150 LPCSTR Endpoint, LPCSTR NetworkOptions) 00151 { 00152 RPC_STATUS status; 00153 00154 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, 00155 debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions)); 00156 00157 RPCRT4_strfree(Binding->NetworkAddr); 00158 Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr); 00159 RPCRT4_strfree(Binding->Endpoint); 00160 Binding->Endpoint = RPCRT4_strdupA(Endpoint); 00161 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions); 00162 Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions); 00163 00164 /* only attempt to get an association if the binding is complete */ 00165 if (Endpoint && Endpoint[0] != '\0') 00166 { 00167 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr, 00168 Binding->Endpoint, Binding->NetworkOptions, 00169 &Binding->Assoc); 00170 if (status != RPC_S_OK) 00171 return status; 00172 } 00173 00174 return RPC_S_OK; 00175 } 00176 00177 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr, 00178 LPCWSTR Endpoint, LPCWSTR NetworkOptions) 00179 { 00180 RPC_STATUS status; 00181 00182 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, 00183 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions)); 00184 00185 RPCRT4_strfree(Binding->NetworkAddr); 00186 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr); 00187 RPCRT4_strfree(Binding->Endpoint); 00188 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint); 00189 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions); 00190 Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions); 00191 00192 /* only attempt to get an association if the binding is complete */ 00193 if (Endpoint && Endpoint[0] != '\0') 00194 { 00195 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr, 00196 Binding->Endpoint, Binding->NetworkOptions, 00197 &Binding->Assoc); 00198 if (status != RPC_S_OK) 00199 return status; 00200 } 00201 00202 return RPC_S_OK; 00203 } 00204 00205 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint) 00206 { 00207 RPC_STATUS status; 00208 00209 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint); 00210 00211 RPCRT4_strfree(Binding->Endpoint); 00212 Binding->Endpoint = RPCRT4_strdupA(Endpoint); 00213 00214 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc); 00215 Binding->Assoc = NULL; 00216 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr, 00217 Binding->Endpoint, Binding->NetworkOptions, 00218 &Binding->Assoc); 00219 if (status != RPC_S_OK) 00220 return status; 00221 00222 return RPC_S_OK; 00223 } 00224 00225 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid) 00226 { 00227 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid)); 00228 if (ObjectUuid) Binding->ObjectUuid = *ObjectUuid; 00229 else UuidCreateNil(&Binding->ObjectUuid); 00230 return RPC_S_OK; 00231 } 00232 00233 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection) 00234 { 00235 RpcBinding* NewBinding; 00236 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection); 00237 00238 RPCRT4_AllocBinding(&NewBinding, Connection->server); 00239 NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection)); 00240 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr); 00241 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint); 00242 NewBinding->FromConn = Connection; 00243 00244 TRACE("binding: %p\n", NewBinding); 00245 *Binding = NewBinding; 00246 00247 return RPC_S_OK; 00248 } 00249 00250 void RPCRT4_AddRefBinding(RpcBinding* Binding) 00251 { 00252 InterlockedIncrement(&Binding->refs); 00253 } 00254 00255 RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding) 00256 { 00257 if (InterlockedDecrement(&Binding->refs)) 00258 return RPC_S_OK; 00259 00260 TRACE("binding: %p\n", Binding); 00261 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc); 00262 RPCRT4_strfree(Binding->Endpoint); 00263 RPCRT4_strfree(Binding->NetworkAddr); 00264 RPCRT4_strfree(Binding->Protseq); 00265 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions); 00266 if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo); 00267 if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS); 00268 HeapFree(GetProcessHeap(), 0, Binding); 00269 return RPC_S_OK; 00270 } 00271 00272 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection, 00273 const RPC_SYNTAX_IDENTIFIER *TransferSyntax, 00274 const RPC_SYNTAX_IDENTIFIER *InterfaceId) 00275 { 00276 TRACE("(Binding == ^%p)\n", Binding); 00277 00278 if (!Binding->server) { 00279 return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId, 00280 TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection); 00281 } else { 00282 /* we already have a connection with acceptable binding, so use it */ 00283 if (Binding->FromConn) { 00284 *Connection = Binding->FromConn; 00285 return RPC_S_OK; 00286 } else { 00287 ERR("no connection in binding\n"); 00288 return RPC_S_INTERNAL_ERROR; 00289 } 00290 } 00291 } 00292 00293 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) 00294 { 00295 TRACE("(Binding == ^%p)\n", Binding); 00296 if (!Connection) return RPC_S_OK; 00297 if (Binding->server) { 00298 /* don't destroy a connection that is cached in the binding */ 00299 if (Binding->FromConn == Connection) 00300 return RPC_S_OK; 00301 return RPCRT4_DestroyConnection(Connection); 00302 } 00303 else { 00304 RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection); 00305 return RPC_S_OK; 00306 } 00307 } 00308 00309 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src) 00310 { 00311 DWORD len = strlen(dst), slen = strlen(src); 00312 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR)); 00313 if (!ndst) 00314 { 00315 HeapFree(GetProcessHeap(), 0, dst); 00316 return NULL; 00317 } 00318 ndst[len] = ','; 00319 memcpy(ndst+len+1, src, slen+1); 00320 return ndst; 00321 } 00322 00323 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src) 00324 { 00325 DWORD len = strlenW(dst), slen = strlenW(src); 00326 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR)); 00327 if (!ndst) 00328 { 00329 HeapFree(GetProcessHeap(), 0, dst); 00330 return NULL; 00331 } 00332 ndst[len] = ','; 00333 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR)); 00334 return ndst; 00335 } 00336 00337 /* Copies the escaped version of a component into a string binding. 00338 * Note: doesn't nul-terminate the string */ 00339 static RPC_CSTR escape_string_binding_component(RPC_CSTR string_binding, 00340 const unsigned char *component) 00341 { 00342 for (; *component; component++) { 00343 switch (*component) { 00344 case '@': 00345 case ':': 00346 case '[': 00347 case ']': 00348 case '\\': 00349 *string_binding++ = '\\'; 00350 *string_binding++ = *component; 00351 break; 00352 default: 00353 *string_binding++ = *component; 00354 break; 00355 } 00356 } 00357 return string_binding; 00358 } 00359 00360 static RPC_WSTR escape_string_binding_componentW(RPC_WSTR string_binding, 00361 const WCHAR *component) 00362 { 00363 for (; *component; component++) { 00364 switch (*component) { 00365 case '@': 00366 case ':': 00367 case '[': 00368 case ']': 00369 case '\\': 00370 *string_binding++ = '\\'; 00371 *string_binding++ = *component; 00372 break; 00373 default: 00374 *string_binding++ = *component; 00375 break; 00376 } 00377 } 00378 return string_binding; 00379 } 00380 00381 static const unsigned char *string_binding_find_delimiter( 00382 const unsigned char *string_binding, unsigned char delim) 00383 { 00384 const unsigned char *next; 00385 for (next = string_binding; *next; next++) { 00386 if (*next == '\\') { 00387 next++; 00388 continue; 00389 } 00390 if (*next == delim) 00391 return next; 00392 } 00393 return NULL; 00394 } 00395 00396 static const WCHAR *string_binding_find_delimiterW( 00397 const WCHAR *string_binding, WCHAR delim) 00398 { 00399 const WCHAR *next; 00400 for (next = string_binding; *next; next++) { 00401 if (*next == '\\') { 00402 next++; 00403 continue; 00404 } 00405 if (*next == delim) 00406 return next; 00407 } 00408 return NULL; 00409 } 00410 00411 static RPC_CSTR unescape_string_binding_component( 00412 const unsigned char *string_binding, int len) 00413 { 00414 RPC_CSTR component, p; 00415 00416 if (len == -1) len = strlen((const char *)string_binding); 00417 00418 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component)); 00419 if (!component) return NULL; 00420 for (p = component; len > 0; string_binding++, len--) { 00421 if (*string_binding == '\\') { 00422 string_binding++; 00423 len--; 00424 *p++ = *string_binding; 00425 } else { 00426 *p++ = *string_binding; 00427 } 00428 } 00429 *p = '\0'; 00430 return component; 00431 } 00432 00433 static RPC_WSTR unescape_string_binding_componentW( 00434 const WCHAR *string_binding, int len) 00435 { 00436 RPC_WSTR component, p; 00437 00438 if (len == -1) len = strlenW(string_binding); 00439 00440 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component)); 00441 if (!component) return NULL; 00442 for (p = component; len > 0; string_binding++, len--) { 00443 if (*string_binding == '\\') { 00444 string_binding++; 00445 len--; 00446 *p++ = *string_binding; 00447 } else { 00448 *p++ = *string_binding; 00449 } 00450 } 00451 *p = '\0'; 00452 return component; 00453 } 00454 00455 /*********************************************************************** 00456 * RpcStringBindingComposeA (RPCRT4.@) 00457 */ 00458 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq, 00459 RPC_CSTR NetworkAddr, RPC_CSTR Endpoint, 00460 RPC_CSTR Options, RPC_CSTR *StringBinding ) 00461 { 00462 DWORD len = 1; 00463 RPC_CSTR data; 00464 00465 TRACE( "(%s,%s,%s,%s,%s,%p)\n", 00466 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ), 00467 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ), 00468 debugstr_a( (char*)Options ), StringBinding ); 00469 00470 /* overestimate for each component for escaping of delimiters */ 00471 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) * 2 + 1; 00472 if (Protseq && *Protseq) len += strlen((char*)Protseq) * 2 + 1; 00473 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr) * 2; 00474 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) * 2 + 2; 00475 if (Options && *Options) len += strlen((char*)Options) * 2 + 2; 00476 00477 data = HeapAlloc(GetProcessHeap(), 0, len); 00478 *StringBinding = data; 00479 00480 if (ObjUuid && *ObjUuid) { 00481 data = escape_string_binding_component(data, ObjUuid); 00482 *data++ = '@'; 00483 } 00484 if (Protseq && *Protseq) { 00485 data = escape_string_binding_component(data, Protseq); 00486 *data++ = ':'; 00487 } 00488 if (NetworkAddr && *NetworkAddr) 00489 data = escape_string_binding_component(data, NetworkAddr); 00490 00491 if ((Endpoint && *Endpoint) || 00492 (Options && *Options)) { 00493 *data++ = '['; 00494 if (Endpoint && *Endpoint) { 00495 data = escape_string_binding_component(data, Endpoint); 00496 if (Options && *Options) *data++ = ','; 00497 } 00498 if (Options && *Options) { 00499 data = escape_string_binding_component(data, Options); 00500 } 00501 *data++ = ']'; 00502 } 00503 *data = 0; 00504 00505 return RPC_S_OK; 00506 } 00507 00508 /*********************************************************************** 00509 * RpcStringBindingComposeW (RPCRT4.@) 00510 */ 00511 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq, 00512 RPC_WSTR NetworkAddr, RPC_WSTR Endpoint, 00513 RPC_WSTR Options, RPC_WSTR* StringBinding ) 00514 { 00515 DWORD len = 1; 00516 RPC_WSTR data; 00517 00518 TRACE("(%s,%s,%s,%s,%s,%p)\n", 00519 debugstr_w( ObjUuid ), debugstr_w( Protseq ), 00520 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ), 00521 debugstr_w( Options ), StringBinding); 00522 00523 /* overestimate for each component for escaping of delimiters */ 00524 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) * 2 + 1; 00525 if (Protseq && *Protseq) len += strlenW(Protseq) * 2 + 1; 00526 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr) * 2; 00527 if (Endpoint && *Endpoint) len += strlenW(Endpoint) * 2 + 2; 00528 if (Options && *Options) len += strlenW(Options) * 2 + 2; 00529 00530 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); 00531 *StringBinding = data; 00532 00533 if (ObjUuid && *ObjUuid) { 00534 data = escape_string_binding_componentW(data, ObjUuid); 00535 *data++ = '@'; 00536 } 00537 if (Protseq && *Protseq) { 00538 data = escape_string_binding_componentW(data, Protseq); 00539 *data++ = ':'; 00540 } 00541 if (NetworkAddr && *NetworkAddr) { 00542 data = escape_string_binding_componentW(data, NetworkAddr); 00543 } 00544 if ((Endpoint && *Endpoint) || 00545 (Options && *Options)) { 00546 *data++ = '['; 00547 if (Endpoint && *Endpoint) { 00548 data = escape_string_binding_componentW(data, Endpoint); 00549 if (Options && *Options) *data++ = ','; 00550 } 00551 if (Options && *Options) { 00552 data = escape_string_binding_componentW(data, Options); 00553 } 00554 *data++ = ']'; 00555 } 00556 *data = 0; 00557 00558 return RPC_S_OK; 00559 } 00560 00561 00562 /*********************************************************************** 00563 * RpcStringBindingParseA (RPCRT4.@) 00564 */ 00565 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid, 00566 RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr, 00567 RPC_CSTR *Endpoint, RPC_CSTR *Options) 00568 { 00569 const unsigned char *data, *next; 00570 static const char ep_opt[] = "endpoint="; 00571 BOOL endpoint_already_found = FALSE; 00572 00573 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding), 00574 ObjUuid, Protseq, NetworkAddr, Endpoint, Options); 00575 00576 if (ObjUuid) *ObjUuid = NULL; 00577 if (Protseq) *Protseq = NULL; 00578 if (NetworkAddr) *NetworkAddr = NULL; 00579 if (Endpoint) *Endpoint = NULL; 00580 if (Options) *Options = NULL; 00581 00582 data = StringBinding; 00583 00584 next = string_binding_find_delimiter(data, '@'); 00585 if (next) { 00586 UUID uuid; 00587 RPC_STATUS status; 00588 RPC_CSTR str_uuid = unescape_string_binding_component(data, next - data); 00589 status = UuidFromStringA(str_uuid, &uuid); 00590 if (status != RPC_S_OK) { 00591 HeapFree(GetProcessHeap(), 0, str_uuid); 00592 return status; 00593 } 00594 if (ObjUuid) 00595 *ObjUuid = str_uuid; 00596 else 00597 HeapFree(GetProcessHeap(), 0, str_uuid); 00598 data = next+1; 00599 } 00600 00601 next = string_binding_find_delimiter(data, ':'); 00602 if (next) { 00603 if (Protseq) *Protseq = unescape_string_binding_component(data, next - data); 00604 data = next+1; 00605 } 00606 00607 next = string_binding_find_delimiter(data, '['); 00608 if (next) { 00609 const unsigned char *close; 00610 RPC_CSTR opt; 00611 00612 if (NetworkAddr) *NetworkAddr = unescape_string_binding_component(data, next - data); 00613 data = next+1; 00614 close = string_binding_find_delimiter(data, ']'); 00615 if (!close) goto fail; 00616 00617 /* tokenize options */ 00618 while (data < close) { 00619 next = string_binding_find_delimiter(data, ','); 00620 if (!next || next > close) next = close; 00621 /* FIXME: this is kind of inefficient */ 00622 opt = unescape_string_binding_component(data, next - data); 00623 data = next+1; 00624 00625 /* parse option */ 00626 next = string_binding_find_delimiter(opt, '='); 00627 if (!next) { 00628 /* not an option, must be an endpoint */ 00629 if (endpoint_already_found) goto fail; 00630 if (Endpoint) *Endpoint = opt; 00631 else HeapFree(GetProcessHeap(), 0, opt); 00632 endpoint_already_found = TRUE; 00633 } else { 00634 if (strncmp((const char *)opt, ep_opt, strlen(ep_opt)) == 0) { 00635 /* endpoint option */ 00636 if (endpoint_already_found) goto fail; 00637 if (Endpoint) *Endpoint = unescape_string_binding_component(next+1, -1); 00638 HeapFree(GetProcessHeap(), 0, opt); 00639 endpoint_already_found = TRUE; 00640 } else { 00641 /* network option */ 00642 if (Options) { 00643 if (*Options) { 00644 /* FIXME: this is kind of inefficient */ 00645 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, (char *)opt); 00646 HeapFree(GetProcessHeap(), 0, opt); 00647 } else 00648 *Options = opt; 00649 } else 00650 HeapFree(GetProcessHeap(), 0, opt); 00651 } 00652 } 00653 } 00654 00655 data = close+1; 00656 if (*data) goto fail; 00657 } 00658 else if (NetworkAddr) 00659 *NetworkAddr = unescape_string_binding_component(data, -1); 00660 00661 return RPC_S_OK; 00662 00663 fail: 00664 if (ObjUuid) RpcStringFreeA(ObjUuid); 00665 if (Protseq) RpcStringFreeA(Protseq); 00666 if (NetworkAddr) RpcStringFreeA(NetworkAddr); 00667 if (Endpoint) RpcStringFreeA(Endpoint); 00668 if (Options) RpcStringFreeA(Options); 00669 return RPC_S_INVALID_STRING_BINDING; 00670 } 00671 00672 /*********************************************************************** 00673 * RpcStringBindingParseW (RPCRT4.@) 00674 */ 00675 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid, 00676 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr, 00677 RPC_WSTR *Endpoint, RPC_WSTR *Options) 00678 { 00679 const WCHAR *data, *next; 00680 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0}; 00681 BOOL endpoint_already_found = FALSE; 00682 00683 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding), 00684 ObjUuid, Protseq, NetworkAddr, Endpoint, Options); 00685 00686 if (ObjUuid) *ObjUuid = NULL; 00687 if (Protseq) *Protseq = NULL; 00688 if (NetworkAddr) *NetworkAddr = NULL; 00689 if (Endpoint) *Endpoint = NULL; 00690 if (Options) *Options = NULL; 00691 00692 data = StringBinding; 00693 00694 next = string_binding_find_delimiterW(data, '@'); 00695 if (next) { 00696 UUID uuid; 00697 RPC_STATUS status; 00698 RPC_WSTR str_uuid = unescape_string_binding_componentW(data, next - data); 00699 status = UuidFromStringW(str_uuid, &uuid); 00700 if (status != RPC_S_OK) { 00701 HeapFree(GetProcessHeap(), 0, str_uuid); 00702 return status; 00703 } 00704 if (ObjUuid) 00705 *ObjUuid = str_uuid; 00706 else 00707 HeapFree(GetProcessHeap(), 0, str_uuid); 00708 data = next+1; 00709 } 00710 00711 next = string_binding_find_delimiterW(data, ':'); 00712 if (next) { 00713 if (Protseq) *Protseq = unescape_string_binding_componentW(data, next - data); 00714 data = next+1; 00715 } 00716 00717 next = string_binding_find_delimiterW(data, '['); 00718 if (next) { 00719 const WCHAR *close; 00720 RPC_WSTR opt; 00721 00722 if (NetworkAddr) *NetworkAddr = unescape_string_binding_componentW(data, next - data); 00723 data = next+1; 00724 close = string_binding_find_delimiterW(data, ']'); 00725 if (!close) goto fail; 00726 00727 /* tokenize options */ 00728 while (data < close) { 00729 next = string_binding_find_delimiterW(data, ','); 00730 if (!next || next > close) next = close; 00731 /* FIXME: this is kind of inefficient */ 00732 opt = unescape_string_binding_componentW(data, next - data); 00733 data = next+1; 00734 00735 /* parse option */ 00736 next = string_binding_find_delimiterW(opt, '='); 00737 if (!next) { 00738 /* not an option, must be an endpoint */ 00739 if (endpoint_already_found) goto fail; 00740 if (Endpoint) *Endpoint = opt; 00741 else HeapFree(GetProcessHeap(), 0, opt); 00742 endpoint_already_found = TRUE; 00743 } else { 00744 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) { 00745 /* endpoint option */ 00746 if (endpoint_already_found) goto fail; 00747 if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1); 00748 HeapFree(GetProcessHeap(), 0, opt); 00749 endpoint_already_found = TRUE; 00750 } else { 00751 /* network option */ 00752 if (Options) { 00753 if (*Options) { 00754 /* FIXME: this is kind of inefficient */ 00755 *Options = RPCRT4_strconcatW(*Options, opt); 00756 HeapFree(GetProcessHeap(), 0, opt); 00757 } else 00758 *Options = opt; 00759 } else 00760 HeapFree(GetProcessHeap(), 0, opt); 00761 } 00762 } 00763 } 00764 00765 data = close+1; 00766 if (*data) goto fail; 00767 } else if (NetworkAddr) 00768 *NetworkAddr = unescape_string_binding_componentW(data, -1); 00769 00770 return RPC_S_OK; 00771 00772 fail: 00773 if (ObjUuid) RpcStringFreeW(ObjUuid); 00774 if (Protseq) RpcStringFreeW(Protseq); 00775 if (NetworkAddr) RpcStringFreeW(NetworkAddr); 00776 if (Endpoint) RpcStringFreeW(Endpoint); 00777 if (Options) RpcStringFreeW(Options); 00778 return RPC_S_INVALID_STRING_BINDING; 00779 } 00780 00781 /*********************************************************************** 00782 * RpcBindingFree (RPCRT4.@) 00783 */ 00784 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding ) 00785 { 00786 RPC_STATUS status; 00787 TRACE("(%p) = %p\n", Binding, *Binding); 00788 if (*Binding) 00789 status = RPCRT4_ReleaseBinding(*Binding); 00790 else 00791 status = RPC_S_INVALID_BINDING; 00792 if (status == RPC_S_OK) *Binding = NULL; 00793 return status; 00794 } 00795 00796 /*********************************************************************** 00797 * RpcBindingVectorFree (RPCRT4.@) 00798 */ 00799 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ) 00800 { 00801 ULONG c; 00802 00803 TRACE("(%p)\n", BindingVector); 00804 for (c=0; c<(*BindingVector)->Count; c++) RpcBindingFree(&(*BindingVector)->BindingH[c]); 00805 HeapFree(GetProcessHeap(), 0, *BindingVector); 00806 *BindingVector = NULL; 00807 return RPC_S_OK; 00808 } 00809 00810 /*********************************************************************** 00811 * RpcBindingInqObject (RPCRT4.@) 00812 */ 00813 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) 00814 { 00815 RpcBinding* bind = Binding; 00816 00817 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid)); 00818 *ObjectUuid = bind->ObjectUuid; 00819 return RPC_S_OK; 00820 } 00821 00822 /*********************************************************************** 00823 * RpcBindingSetObject (RPCRT4.@) 00824 */ 00825 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) 00826 { 00827 RpcBinding* bind = Binding; 00828 00829 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid)); 00830 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING; 00831 return RPCRT4_SetBindingObject(Binding, ObjectUuid); 00832 } 00833 00834 /*********************************************************************** 00835 * RpcBindingFromStringBindingA (RPCRT4.@) 00836 */ 00837 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding ) 00838 { 00839 RPC_STATUS ret; 00840 RpcBinding* bind = NULL; 00841 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options; 00842 UUID Uuid; 00843 00844 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding); 00845 00846 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq, 00847 &NetworkAddr, &Endpoint, &Options); 00848 if (ret != RPC_S_OK) return ret; 00849 00850 ret = UuidFromStringA(ObjectUuid, &Uuid); 00851 00852 if (ret == RPC_S_OK) 00853 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq); 00854 if (ret != RPC_S_OK) return ret; 00855 ret = RPCRT4_SetBindingObject(bind, &Uuid); 00856 if (ret == RPC_S_OK) 00857 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options); 00858 00859 RpcStringFreeA(&Options); 00860 RpcStringFreeA(&Endpoint); 00861 RpcStringFreeA(&NetworkAddr); 00862 RpcStringFreeA(&Protseq); 00863 RpcStringFreeA(&ObjectUuid); 00864 00865 if (ret == RPC_S_OK) 00866 *Binding = (RPC_BINDING_HANDLE)bind; 00867 else 00868 RPCRT4_ReleaseBinding(bind); 00869 00870 return ret; 00871 } 00872 00873 /*********************************************************************** 00874 * RpcBindingFromStringBindingW (RPCRT4.@) 00875 */ 00876 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding ) 00877 { 00878 RPC_STATUS ret; 00879 RpcBinding* bind = NULL; 00880 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options; 00881 UUID Uuid; 00882 00883 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding); 00884 00885 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq, 00886 &NetworkAddr, &Endpoint, &Options); 00887 if (ret != RPC_S_OK) return ret; 00888 00889 ret = UuidFromStringW(ObjectUuid, &Uuid); 00890 00891 if (ret == RPC_S_OK) 00892 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq); 00893 if (ret != RPC_S_OK) return ret; 00894 ret = RPCRT4_SetBindingObject(bind, &Uuid); 00895 if (ret == RPC_S_OK) 00896 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options); 00897 00898 RpcStringFreeW(&Options); 00899 RpcStringFreeW(&Endpoint); 00900 RpcStringFreeW(&NetworkAddr); 00901 RpcStringFreeW(&Protseq); 00902 RpcStringFreeW(&ObjectUuid); 00903 00904 if (ret == RPC_S_OK) 00905 *Binding = (RPC_BINDING_HANDLE)bind; 00906 else 00907 RPCRT4_ReleaseBinding(bind); 00908 00909 return ret; 00910 } 00911 00912 /*********************************************************************** 00913 * RpcBindingToStringBindingA (RPCRT4.@) 00914 */ 00915 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding ) 00916 { 00917 RPC_STATUS ret; 00918 RpcBinding* bind = Binding; 00919 RPC_CSTR ObjectUuid; 00920 00921 TRACE("(%p,%p)\n", Binding, StringBinding); 00922 00923 if (UuidIsNil(&bind->ObjectUuid, &ret)) 00924 ObjectUuid = NULL; 00925 else 00926 { 00927 ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid); 00928 if (ret != RPC_S_OK) return ret; 00929 } 00930 00931 ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr, 00932 (unsigned char*) bind->Endpoint, NULL, StringBinding); 00933 00934 RpcStringFreeA(&ObjectUuid); 00935 00936 return ret; 00937 } 00938 00939 /*********************************************************************** 00940 * RpcBindingToStringBindingW (RPCRT4.@) 00941 */ 00942 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding ) 00943 { 00944 RPC_STATUS ret; 00945 unsigned char *str = NULL; 00946 TRACE("(%p,%p)\n", Binding, StringBinding); 00947 ret = RpcBindingToStringBindingA(Binding, &str); 00948 *StringBinding = RPCRT4_strdupAtoW((char*)str); 00949 RpcStringFreeA(&str); 00950 return ret; 00951 } 00952 00953 /*********************************************************************** 00954 * I_RpcBindingInqTransportType (RPCRT4.@) 00955 */ 00956 RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int * Type ) 00957 { 00958 00959 FIXME( "(%p,%p): stub\n", Binding, Type); 00960 *Type = TRANSPORT_TYPE_LPC; 00961 return RPC_S_OK; 00962 } 00963 00964 /*********************************************************************** 00965 * I_RpcBindingSetAsync (RPCRT4.@) 00966 * NOTES 00967 * Exists in win9x and winNT, but with different number of arguments 00968 * (9x version has 3 arguments, NT has 2). 00969 */ 00970 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn) 00971 { 00972 RpcBinding* bind = Binding; 00973 00974 TRACE( "(%p,%p): stub\n", Binding, BlockingFn ); 00975 00976 bind->BlockingFn = BlockingFn; 00977 00978 return RPC_S_OK; 00979 } 00980 00981 /*********************************************************************** 00982 * RpcBindingCopy (RPCRT4.@) 00983 */ 00984 RPC_STATUS RPC_ENTRY RpcBindingCopy( 00985 RPC_BINDING_HANDLE SourceBinding, 00986 RPC_BINDING_HANDLE* DestinationBinding) 00987 { 00988 RpcBinding *DestBinding; 00989 RpcBinding *SrcBinding = SourceBinding; 00990 RPC_STATUS status; 00991 00992 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding); 00993 00994 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server); 00995 if (status != RPC_S_OK) return status; 00996 00997 DestBinding->ObjectUuid = SrcBinding->ObjectUuid; 00998 DestBinding->BlockingFn = SrcBinding->BlockingFn; 00999 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1); 01000 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1); 01001 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1); 01002 DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions); 01003 if (SrcBinding->Assoc) SrcBinding->Assoc->refs++; 01004 DestBinding->Assoc = SrcBinding->Assoc; 01005 01006 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo); 01007 DestBinding->AuthInfo = SrcBinding->AuthInfo; 01008 if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS); 01009 DestBinding->QOS = SrcBinding->QOS; 01010 01011 *DestinationBinding = DestBinding; 01012 return RPC_S_OK; 01013 } 01014 01015 /*********************************************************************** 01016 * RpcBindingReset (RPCRT4.@) 01017 */ 01018 RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding) 01019 { 01020 RpcBinding *bind = Binding; 01021 01022 TRACE("(%p)\n", Binding); 01023 01024 RPCRT4_strfree(bind->Endpoint); 01025 bind->Endpoint = NULL; 01026 if (bind->Assoc) RpcAssoc_Release(bind->Assoc); 01027 bind->Assoc = NULL; 01028 01029 return RPC_S_OK; 01030 } 01031 01032 /*********************************************************************** 01033 * RpcImpersonateClient (RPCRT4.@) 01034 * 01035 * Impersonates the client connected via a binding handle so that security 01036 * checks are done in the context of the client. 01037 * 01038 * PARAMS 01039 * BindingHandle [I] Handle to the binding to the client. 01040 * 01041 * RETURNS 01042 * Success: RPS_S_OK. 01043 * Failure: RPC_STATUS value. 01044 * 01045 * NOTES 01046 * 01047 * If BindingHandle is NULL then the function impersonates the client 01048 * connected to the binding handle of the current thread. 01049 */ 01050 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle) 01051 { 01052 RpcBinding *bind; 01053 01054 TRACE("(%p)\n", BindingHandle); 01055 01056 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle(); 01057 if (!BindingHandle) return RPC_S_INVALID_BINDING; 01058 01059 bind = BindingHandle; 01060 if (bind->FromConn) 01061 return rpcrt4_conn_impersonate_client(bind->FromConn); 01062 return RPC_S_WRONG_KIND_OF_BINDING; 01063 } 01064 01065 /*********************************************************************** 01066 * RpcRevertToSelfEx (RPCRT4.@) 01067 * 01068 * Stops impersonating the client connected to the binding handle so that security 01069 * checks are no longer done in the context of the client. 01070 * 01071 * PARAMS 01072 * BindingHandle [I] Handle to the binding to the client. 01073 * 01074 * RETURNS 01075 * Success: RPS_S_OK. 01076 * Failure: RPC_STATUS value. 01077 * 01078 * NOTES 01079 * 01080 * If BindingHandle is NULL then the function stops impersonating the client 01081 * connected to the binding handle of the current thread. 01082 */ 01083 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle) 01084 { 01085 RpcBinding *bind; 01086 01087 TRACE("(%p)\n", BindingHandle); 01088 01089 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle(); 01090 if (!BindingHandle) return RPC_S_INVALID_BINDING; 01091 01092 bind = BindingHandle; 01093 if (bind->FromConn) 01094 return rpcrt4_conn_revert_to_self(bind->FromConn); 01095 return RPC_S_WRONG_KIND_OF_BINDING; 01096 } 01097 01098 static inline BOOL has_nt_auth_identity(ULONG AuthnLevel) 01099 { 01100 switch (AuthnLevel) 01101 { 01102 case RPC_C_AUTHN_GSS_NEGOTIATE: 01103 case RPC_C_AUTHN_WINNT: 01104 case RPC_C_AUTHN_GSS_KERBEROS: 01105 return TRUE; 01106 default: 01107 return FALSE; 01108 } 01109 } 01110 01111 RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc, 01112 CredHandle cred, TimeStamp exp, 01113 ULONG cbMaxToken, 01114 RPC_AUTH_IDENTITY_HANDLE identity, 01115 RpcAuthInfo **ret) 01116 { 01117 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo)); 01118 if (!AuthInfo) 01119 return ERROR_OUTOFMEMORY; 01120 01121 AuthInfo->refs = 1; 01122 AuthInfo->AuthnLevel = AuthnLevel; 01123 AuthInfo->AuthnSvc = AuthnSvc; 01124 AuthInfo->cred = cred; 01125 AuthInfo->exp = exp; 01126 AuthInfo->cbMaxToken = cbMaxToken; 01127 AuthInfo->identity = identity; 01128 AuthInfo->server_principal_name = NULL; 01129 01130 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to 01131 * enable better matching in RpcAuthInfo_IsEqual */ 01132 if (identity && has_nt_auth_identity(AuthnSvc)) 01133 { 01134 const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity; 01135 AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity)); 01136 if (!AuthInfo->nt_identity) 01137 { 01138 HeapFree(GetProcessHeap(), 0, AuthInfo); 01139 return ERROR_OUTOFMEMORY; 01140 } 01141 01142 AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; 01143 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) 01144 AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength); 01145 else 01146 AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength); 01147 AuthInfo->nt_identity->UserLength = nt_identity->UserLength; 01148 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) 01149 AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength); 01150 else 01151 AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength); 01152 AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength; 01153 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) 01154 AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength); 01155 else 01156 AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength); 01157 AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength; 01158 01159 if ((nt_identity->User && !AuthInfo->nt_identity->User) || 01160 (nt_identity->Domain && !AuthInfo->nt_identity->Domain) || 01161 (nt_identity->Password && !AuthInfo->nt_identity->Password)) 01162 { 01163 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User); 01164 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain); 01165 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password); 01166 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity); 01167 HeapFree(GetProcessHeap(), 0, AuthInfo); 01168 return ERROR_OUTOFMEMORY; 01169 } 01170 } 01171 else 01172 AuthInfo->nt_identity = NULL; 01173 *ret = AuthInfo; 01174 return RPC_S_OK; 01175 } 01176 01177 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo) 01178 { 01179 return InterlockedIncrement(&AuthInfo->refs); 01180 } 01181 01182 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo) 01183 { 01184 ULONG refs = InterlockedDecrement(&AuthInfo->refs); 01185 01186 if (!refs) 01187 { 01188 FreeCredentialsHandle(&AuthInfo->cred); 01189 if (AuthInfo->nt_identity) 01190 { 01191 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User); 01192 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain); 01193 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password); 01194 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity); 01195 } 01196 HeapFree(GetProcessHeap(), 0, AuthInfo->server_principal_name); 01197 HeapFree(GetProcessHeap(), 0, AuthInfo); 01198 } 01199 01200 return refs; 01201 } 01202 01203 BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2) 01204 { 01205 if (AuthInfo1 == AuthInfo2) 01206 return TRUE; 01207 01208 if (!AuthInfo1 || !AuthInfo2) 01209 return FALSE; 01210 01211 if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) || 01212 (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc)) 01213 return FALSE; 01214 01215 if (AuthInfo1->identity == AuthInfo2->identity) 01216 return TRUE; 01217 01218 if (!AuthInfo1->identity || !AuthInfo2->identity) 01219 return FALSE; 01220 01221 if (has_nt_auth_identity(AuthInfo1->AuthnSvc)) 01222 { 01223 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity; 01224 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity; 01225 /* compare user names */ 01226 if (identity1->UserLength != identity2->UserLength || 01227 memcmp(identity1->User, identity2->User, identity1->UserLength)) 01228 return FALSE; 01229 /* compare domain names */ 01230 if (identity1->DomainLength != identity2->DomainLength || 01231 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength)) 01232 return FALSE; 01233 /* compare passwords */ 01234 if (identity1->PasswordLength != identity2->PasswordLength || 01235 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength)) 01236 return FALSE; 01237 } 01238 else 01239 return FALSE; 01240 01241 return TRUE; 01242 } 01243 01244 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst) 01245 { 01246 RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos)); 01247 01248 if (!qos) 01249 return RPC_S_OUT_OF_RESOURCES; 01250 01251 qos->refs = 1; 01252 qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos)); 01253 if (!qos->qos) goto error; 01254 qos->qos->Version = qos_src->Version; 01255 qos->qos->Capabilities = qos_src->Capabilities; 01256 qos->qos->IdentityTracking = qos_src->IdentityTracking; 01257 qos->qos->ImpersonationType = qos_src->ImpersonationType; 01258 qos->qos->AdditionalSecurityInfoType = 0; 01259 01260 if (qos_src->Version >= 2) 01261 { 01262 const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src; 01263 qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType; 01264 if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) 01265 { 01266 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials; 01267 RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst; 01268 01269 http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst)); 01270 qos->qos->u.HttpCredentials = http_credentials_dst; 01271 if (!http_credentials_dst) goto error; 01272 http_credentials_dst->TransportCredentials = NULL; 01273 http_credentials_dst->Flags = http_credentials_src->Flags; 01274 http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget; 01275 http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes; 01276 http_credentials_dst->AuthnSchemes = NULL; 01277 http_credentials_dst->ServerCertificateSubject = NULL; 01278 if (http_credentials_src->TransportCredentials) 01279 { 01280 SEC_WINNT_AUTH_IDENTITY_W *cred_dst; 01281 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst)); 01282 if (!cred_dst) goto error; 01283 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; 01284 if (unicode) 01285 { 01286 const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials; 01287 cred_dst->UserLength = cred_src->UserLength; 01288 cred_dst->PasswordLength = cred_src->PasswordLength; 01289 cred_dst->DomainLength = cred_src->DomainLength; 01290 cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength); 01291 cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength); 01292 cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength); 01293 } 01294 else 01295 { 01296 const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials; 01297 cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0); 01298 cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0); 01299 cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0); 01300 cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR)); 01301 cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR)); 01302 cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR)); 01303 if (!cred_dst->Password || !cred_dst->Domain) goto error; 01304 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength); 01305 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength); 01306 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength); 01307 } 01308 } 01309 if (http_credentials_src->NumberOfAuthnSchemes) 01310 { 01311 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes)); 01312 if (!http_credentials_dst->AuthnSchemes) goto error; 01313 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes)); 01314 } 01315 if (http_credentials_src->ServerCertificateSubject) 01316 { 01317 if (unicode) 01318 http_credentials_dst->ServerCertificateSubject = 01319 RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject, 01320 strlenW(http_credentials_src->ServerCertificateSubject)); 01321 else 01322 http_credentials_dst->ServerCertificateSubject = 01323 RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject); 01324 if (!http_credentials_dst->ServerCertificateSubject) goto error; 01325 } 01326 } 01327 } 01328 *qos_dst = qos; 01329 return RPC_S_OK; 01330 01331 error: 01332 if (qos->qos) 01333 { 01334 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP && 01335 qos->qos->u.HttpCredentials) 01336 { 01337 if (qos->qos->u.HttpCredentials->TransportCredentials) 01338 { 01339 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User); 01340 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain); 01341 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password); 01342 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials); 01343 } 01344 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes); 01345 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject); 01346 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials); 01347 } 01348 HeapFree(GetProcessHeap(), 0, qos->qos); 01349 } 01350 HeapFree(GetProcessHeap(), 0, qos); 01351 return RPC_S_OUT_OF_RESOURCES; 01352 } 01353 01354 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos) 01355 { 01356 return InterlockedIncrement(&qos->refs); 01357 } 01358 01359 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos) 01360 { 01361 ULONG refs = InterlockedDecrement(&qos->refs); 01362 01363 if (!refs) 01364 { 01365 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) 01366 { 01367 if (qos->qos->u.HttpCredentials->TransportCredentials) 01368 { 01369 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User); 01370 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain); 01371 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password); 01372 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials); 01373 } 01374 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes); 01375 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject); 01376 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials); 01377 } 01378 HeapFree(GetProcessHeap(), 0, qos->qos); 01379 HeapFree(GetProcessHeap(), 0, qos); 01380 } 01381 return refs; 01382 } 01383 01384 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2) 01385 { 01386 if (qos1 == qos2) 01387 return TRUE; 01388 01389 if (!qos1 || !qos2) 01390 return FALSE; 01391 01392 TRACE("qos1 = { %d %d %d %d }, qos2 = { %d %d %d %d }\n", 01393 qos1->qos->Capabilities, qos1->qos->IdentityTracking, 01394 qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType, 01395 qos2->qos->Capabilities, qos2->qos->IdentityTracking, 01396 qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType); 01397 01398 if ((qos1->qos->Capabilities != qos2->qos->Capabilities) || 01399 (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) || 01400 (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) || 01401 (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType)) 01402 return FALSE; 01403 01404 if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) 01405 { 01406 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials; 01407 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials; 01408 01409 if (http_credentials1->Flags != http_credentials2->Flags) 01410 return FALSE; 01411 01412 if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget) 01413 return FALSE; 01414 01415 /* authentication schemes and server certificate subject not currently used */ 01416 01417 if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials) 01418 { 01419 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials; 01420 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials; 01421 01422 if (!identity1 || !identity2) 01423 return FALSE; 01424 01425 /* compare user names */ 01426 if (identity1->UserLength != identity2->UserLength || 01427 memcmp(identity1->User, identity2->User, identity1->UserLength)) 01428 return FALSE; 01429 /* compare domain names */ 01430 if (identity1->DomainLength != identity2->DomainLength || 01431 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength)) 01432 return FALSE; 01433 /* compare passwords */ 01434 if (identity1->PasswordLength != identity2->PasswordLength || 01435 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength)) 01436 return FALSE; 01437 } 01438 } 01439 01440 return TRUE; 01441 } 01442 01443 /*********************************************************************** 01444 * RpcRevertToSelf (RPCRT4.@) 01445 */ 01446 RPC_STATUS WINAPI RpcRevertToSelf(void) 01447 { 01448 TRACE("\n"); 01449 return RpcRevertToSelfEx(NULL); 01450 } 01451 01452 /*********************************************************************** 01453 * RpcMgmtSetComTimeout (RPCRT4.@) 01454 */ 01455 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout) 01456 { 01457 FIXME("(%p, %d): stub\n", BindingHandle, Timeout); 01458 return RPC_S_OK; 01459 } 01460 01461 /*********************************************************************** 01462 * RpcBindingInqAuthInfoExA (RPCRT4.@) 01463 */ 01464 RPCRTAPI RPC_STATUS RPC_ENTRY 01465 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, 01466 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc, 01467 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS ) 01468 { 01469 RPC_STATUS status; 01470 RPC_WSTR principal; 01471 01472 TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel, 01473 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); 01474 01475 status = RpcBindingInqAuthInfoExW(Binding, ServerPrincName ? &principal : NULL, AuthnLevel, 01476 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); 01477 if (status == RPC_S_OK && ServerPrincName) 01478 { 01479 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal); 01480 RpcStringFreeW(&principal); 01481 if (!*ServerPrincName) return ERROR_OUTOFMEMORY; 01482 } 01483 01484 return status; 01485 } 01486 01487 /*********************************************************************** 01488 * RpcBindingInqAuthInfoExW (RPCRT4.@) 01489 */ 01490 RPCRTAPI RPC_STATUS RPC_ENTRY 01491 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, 01492 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc, 01493 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS ) 01494 { 01495 RpcBinding *bind = Binding; 01496 01497 TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel, 01498 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); 01499 01500 if (!bind->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH; 01501 01502 if (SecurityQOS) 01503 { 01504 FIXME("QOS not implemented\n"); 01505 return RPC_S_INVALID_BINDING; 01506 } 01507 01508 if (ServerPrincName) 01509 { 01510 if (bind->AuthInfo->server_principal_name) 01511 { 01512 *ServerPrincName = RPCRT4_strdupW(bind->AuthInfo->server_principal_name); 01513 if (!*ServerPrincName) return ERROR_OUTOFMEMORY; 01514 } 01515 else *ServerPrincName = NULL; 01516 } 01517 if (AuthnLevel) *AuthnLevel = bind->AuthInfo->AuthnLevel; 01518 if (AuthnSvc) *AuthnSvc = bind->AuthInfo->AuthnSvc; 01519 if (AuthIdentity) *AuthIdentity = bind->AuthInfo->identity; 01520 if (AuthzSvc) 01521 { 01522 FIXME("authorization service not implemented\n"); 01523 *AuthzSvc = RPC_C_AUTHZ_NONE; 01524 } 01525 01526 return RPC_S_OK; 01527 } 01528 01529 /*********************************************************************** 01530 * RpcBindingInqAuthInfoA (RPCRT4.@) 01531 */ 01532 RPCRTAPI RPC_STATUS RPC_ENTRY 01533 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, 01534 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc ) 01535 { 01536 return RpcBindingInqAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, 01537 AuthzSvc, 0, NULL); 01538 } 01539 01540 /*********************************************************************** 01541 * RpcBindingInqAuthInfoW (RPCRT4.@) 01542 */ 01543 RPCRTAPI RPC_STATUS RPC_ENTRY 01544 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, 01545 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc ) 01546 { 01547 return RpcBindingInqAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, 01548 AuthzSvc, 0, NULL); 01549 } 01550 01551 /*********************************************************************** 01552 * RpcBindingInqAuthClientA (RPCRT4.@) 01553 */ 01554 RPCRTAPI RPC_STATUS RPC_ENTRY 01555 RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs, 01556 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, 01557 ULONG *AuthzSvc ) 01558 { 01559 return RpcBindingInqAuthClientExA(ClientBinding, Privs, ServerPrincName, AuthnLevel, 01560 AuthnSvc, AuthzSvc, 0); 01561 } 01562 01563 /*********************************************************************** 01564 * RpcBindingInqAuthClientW (RPCRT4.@) 01565 */ 01566 RPCRTAPI RPC_STATUS RPC_ENTRY 01567 RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs, 01568 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, 01569 ULONG *AuthzSvc ) 01570 { 01571 return RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName, AuthnLevel, 01572 AuthnSvc, AuthzSvc, 0); 01573 } 01574 01575 /*********************************************************************** 01576 * RpcBindingInqAuthClientExA (RPCRT4.@) 01577 */ 01578 RPCRTAPI RPC_STATUS RPC_ENTRY 01579 RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs, 01580 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, 01581 ULONG *AuthzSvc, ULONG Flags ) 01582 { 01583 RPC_STATUS status; 01584 RPC_WSTR principal; 01585 01586 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel, 01587 AuthnSvc, AuthzSvc, Flags); 01588 01589 status = RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName ? &principal : NULL, 01590 AuthnLevel, AuthnSvc, AuthzSvc, Flags); 01591 if (status == RPC_S_OK && ServerPrincName) 01592 { 01593 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal); 01594 if (!*ServerPrincName && principal) status = ERROR_OUTOFMEMORY; 01595 RpcStringFreeW(&principal); 01596 } 01597 01598 return status; 01599 } 01600 01601 /*********************************************************************** 01602 * RpcBindingInqAuthClientExW (RPCRT4.@) 01603 */ 01604 RPCRTAPI RPC_STATUS RPC_ENTRY 01605 RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs, 01606 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, 01607 ULONG *AuthzSvc, ULONG Flags ) 01608 { 01609 RpcBinding *bind = ClientBinding; 01610 01611 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel, 01612 AuthnSvc, AuthzSvc, Flags); 01613 01614 if (!bind->FromConn) return RPC_S_INVALID_BINDING; 01615 01616 return rpcrt4_conn_inquire_auth_client(bind->FromConn, Privs, 01617 ServerPrincName, AuthnLevel, 01618 AuthnSvc, AuthzSvc, Flags); 01619 } 01620 01621 /*********************************************************************** 01622 * RpcBindingSetAuthInfoExA (RPCRT4.@) 01623 */ 01624 RPCRTAPI RPC_STATUS RPC_ENTRY 01625 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, 01626 ULONG AuthnLevel, ULONG AuthnSvc, 01627 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, 01628 RPC_SECURITY_QOS *SecurityQos ) 01629 { 01630 RpcBinding* bind = Binding; 01631 SECURITY_STATUS r; 01632 CredHandle cred; 01633 TimeStamp exp; 01634 ULONG package_count; 01635 ULONG i; 01636 PSecPkgInfoA packages; 01637 ULONG cbMaxToken; 01638 01639 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName), 01640 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos); 01641 01642 if (SecurityQos) 01643 { 01644 RPC_STATUS status; 01645 01646 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d", 01647 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType); 01648 if (SecurityQos->Version >= 2) 01649 { 01650 const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos; 01651 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2->AdditionalSecurityInfoType); 01652 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) 01653 TRACE(", { %p, 0x%x, %d, %d, %p, %s }", 01654 SecurityQos2->u.HttpCredentials->TransportCredentials, 01655 SecurityQos2->u.HttpCredentials->Flags, 01656 SecurityQos2->u.HttpCredentials->AuthenticationTarget, 01657 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes, 01658 SecurityQos2->u.HttpCredentials->AuthnSchemes, 01659 SecurityQos2->u.HttpCredentials->ServerCertificateSubject); 01660 } 01661 TRACE("}\n"); 01662 status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS); 01663 if (status != RPC_S_OK) 01664 return status; 01665 } 01666 else 01667 { 01668 if (bind->QOS) RpcQualityOfService_Release(bind->QOS); 01669 bind->QOS = NULL; 01670 } 01671 01672 if (AuthnSvc == RPC_C_AUTHN_DEFAULT) 01673 AuthnSvc = RPC_C_AUTHN_WINNT; 01674 01675 /* FIXME: the mapping should probably be retrieved using SSPI somehow */ 01676 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT) 01677 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE; 01678 01679 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE)) 01680 { 01681 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); 01682 bind->AuthInfo = NULL; 01683 return RPC_S_OK; 01684 } 01685 01686 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY) 01687 { 01688 FIXME("unknown AuthnLevel %u\n", AuthnLevel); 01689 return RPC_S_UNKNOWN_AUTHN_LEVEL; 01690 } 01691 01692 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */ 01693 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT) 01694 { 01695 FIXME("unsupported AuthzSvr %u\n", AuthzSvr); 01696 return RPC_S_UNKNOWN_AUTHZ_SERVICE; 01697 } 01698 01699 r = EnumerateSecurityPackagesA(&package_count, &packages); 01700 if (r != SEC_E_OK) 01701 { 01702 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r); 01703 return RPC_S_SEC_PKG_ERROR; 01704 } 01705 01706 for (i = 0; i < package_count; i++) 01707 if (packages[i].wRPCID == AuthnSvc) 01708 break; 01709 01710 if (i == package_count) 01711 { 01712 FIXME("unsupported AuthnSvc %u\n", AuthnSvc); 01713 FreeContextBuffer(packages); 01714 return RPC_S_UNKNOWN_AUTHN_SERVICE; 01715 } 01716 01717 TRACE("found package %s for service %u\n", packages[i].Name, AuthnSvc); 01718 r = AcquireCredentialsHandleA(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL, 01719 AuthIdentity, NULL, NULL, &cred, &exp); 01720 cbMaxToken = packages[i].cbMaxToken; 01721 FreeContextBuffer(packages); 01722 if (r == ERROR_SUCCESS) 01723 { 01724 RpcAuthInfo *new_auth_info; 01725 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken, 01726 AuthIdentity, &new_auth_info); 01727 if (r == RPC_S_OK) 01728 { 01729 new_auth_info->server_principal_name = RPCRT4_strdupAtoW((char *)ServerPrincName); 01730 if (new_auth_info->server_principal_name) 01731 { 01732 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); 01733 bind->AuthInfo = new_auth_info; 01734 } 01735 else 01736 { 01737 RpcAuthInfo_Release(new_auth_info); 01738 r = ERROR_OUTOFMEMORY; 01739 } 01740 } 01741 else 01742 FreeCredentialsHandle(&cred); 01743 return r; 01744 } 01745 else 01746 { 01747 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r); 01748 return RPC_S_SEC_PKG_ERROR; 01749 } 01750 } 01751 01752 /*********************************************************************** 01753 * RpcBindingSetAuthInfoExW (RPCRT4.@) 01754 */ 01755 RPCRTAPI RPC_STATUS RPC_ENTRY 01756 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel, 01757 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, 01758 RPC_SECURITY_QOS *SecurityQos ) 01759 { 01760 RpcBinding* bind = Binding; 01761 SECURITY_STATUS r; 01762 CredHandle cred; 01763 TimeStamp exp; 01764 ULONG package_count; 01765 ULONG i; 01766 PSecPkgInfoW packages; 01767 ULONG cbMaxToken; 01768 01769 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w(ServerPrincName), 01770 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos); 01771 01772 if (SecurityQos) 01773 { 01774 RPC_STATUS status; 01775 01776 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d", 01777 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType); 01778 if (SecurityQos->Version >= 2) 01779 { 01780 const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos; 01781 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2->AdditionalSecurityInfoType); 01782 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) 01783 TRACE(", { %p, 0x%x, %d, %d, %p, %s }", 01784 SecurityQos2->u.HttpCredentials->TransportCredentials, 01785 SecurityQos2->u.HttpCredentials->Flags, 01786 SecurityQos2->u.HttpCredentials->AuthenticationTarget, 01787 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes, 01788 SecurityQos2->u.HttpCredentials->AuthnSchemes, 01789 debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject)); 01790 } 01791 TRACE("}\n"); 01792 status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS); 01793 if (status != RPC_S_OK) 01794 return status; 01795 } 01796 else 01797 { 01798 if (bind->QOS) RpcQualityOfService_Release(bind->QOS); 01799 bind->QOS = NULL; 01800 } 01801 01802 if (AuthnSvc == RPC_C_AUTHN_DEFAULT) 01803 AuthnSvc = RPC_C_AUTHN_WINNT; 01804 01805 /* FIXME: the mapping should probably be retrieved using SSPI somehow */ 01806 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT) 01807 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE; 01808 01809 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE)) 01810 { 01811 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); 01812 bind->AuthInfo = NULL; 01813 return RPC_S_OK; 01814 } 01815 01816 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY) 01817 { 01818 FIXME("unknown AuthnLevel %u\n", AuthnLevel); 01819 return RPC_S_UNKNOWN_AUTHN_LEVEL; 01820 } 01821 01822 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */ 01823 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT) 01824 { 01825 FIXME("unsupported AuthzSvr %u\n", AuthzSvr); 01826 return RPC_S_UNKNOWN_AUTHZ_SERVICE; 01827 } 01828 01829 r = EnumerateSecurityPackagesW(&package_count, &packages); 01830 if (r != SEC_E_OK) 01831 { 01832 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r); 01833 return RPC_S_SEC_PKG_ERROR; 01834 } 01835 01836 for (i = 0; i < package_count; i++) 01837 if (packages[i].wRPCID == AuthnSvc) 01838 break; 01839 01840 if (i == package_count) 01841 { 01842 FIXME("unsupported AuthnSvc %u\n", AuthnSvc); 01843 FreeContextBuffer(packages); 01844 return RPC_S_UNKNOWN_AUTHN_SERVICE; 01845 } 01846 01847 TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), AuthnSvc); 01848 r = AcquireCredentialsHandleW(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL, 01849 AuthIdentity, NULL, NULL, &cred, &exp); 01850 cbMaxToken = packages[i].cbMaxToken; 01851 FreeContextBuffer(packages); 01852 if (r == ERROR_SUCCESS) 01853 { 01854 RpcAuthInfo *new_auth_info; 01855 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken, 01856 AuthIdentity, &new_auth_info); 01857 if (r == RPC_S_OK) 01858 { 01859 new_auth_info->server_principal_name = RPCRT4_strdupW(ServerPrincName); 01860 if (!ServerPrincName || new_auth_info->server_principal_name) 01861 { 01862 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); 01863 bind->AuthInfo = new_auth_info; 01864 } 01865 else 01866 { 01867 RpcAuthInfo_Release(new_auth_info); 01868 r = ERROR_OUTOFMEMORY; 01869 } 01870 } 01871 else 01872 FreeCredentialsHandle(&cred); 01873 return r; 01874 } 01875 else 01876 { 01877 ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r); 01878 return RPC_S_SEC_PKG_ERROR; 01879 } 01880 } 01881 01882 /*********************************************************************** 01883 * RpcBindingSetAuthInfoA (RPCRT4.@) 01884 */ 01885 RPCRTAPI RPC_STATUS RPC_ENTRY 01886 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel, 01887 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr ) 01888 { 01889 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName), 01890 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr); 01891 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); 01892 } 01893 01894 /*********************************************************************** 01895 * RpcBindingSetAuthInfoW (RPCRT4.@) 01896 */ 01897 RPCRTAPI RPC_STATUS RPC_ENTRY 01898 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel, 01899 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr ) 01900 { 01901 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w(ServerPrincName), 01902 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr); 01903 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); 01904 } 01905 01906 /*********************************************************************** 01907 * RpcBindingSetOption (RPCRT4.@) 01908 */ 01909 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG_PTR OptionValue) 01910 { 01911 FIXME("(%p, %d, %ld): stub\n", BindingHandle, Option, OptionValue); 01912 return RPC_S_OK; 01913 } Generated on Sun May 27 2012 04:26:04 for ReactOS by
1.7.6.1
|