1/* 2 Unix SMB/CIFS implementation. 3 RPC pipe client 4 Copyright (C) Tim Potter 2000-2001, 5 Copyright (C) Andrew Tridgell 1992-1997,2000, 6 Copyright (C) Rafal Szczesniak 2002 7 Copyright (C) Jeremy Allison 2005. 8 Copyright (C) Michael Adam 2007. 9 Copyright (C) Guenther Deschner 2008. 10 11 This program is free software; you can redistribute it and/or modify 12 it under the terms of the GNU General Public License as published by 13 the Free Software Foundation; either version 3 of the License, or 14 (at your option) any later version. 15 16 This program is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU General Public License for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with this program. If not, see <http://www.gnu.org/licenses/>. 23*/ 24 25#include "includes.h" 26#include "../librpc/gen_ndr/cli_lsa.h" 27 28/** @defgroup lsa LSA - Local Security Architecture 29 * @ingroup rpc_client 30 * 31 * @{ 32 **/ 33 34/** 35 * @file cli_lsarpc.c 36 * 37 * RPC client routines for the LSA RPC pipe. LSA means "local 38 * security authority", which is half of a password database. 39 **/ 40 41/** Open a LSA policy handle 42 * 43 * @param cli Handle on an initialised SMB connection */ 44 45NTSTATUS rpccli_lsa_open_policy(struct rpc_pipe_client *cli, 46 TALLOC_CTX *mem_ctx, 47 bool sec_qos, uint32 des_access, 48 struct policy_handle *pol) 49{ 50 struct lsa_ObjectAttribute attr; 51 struct lsa_QosInfo qos; 52 uint16_t system_name = '\\'; 53 54 ZERO_STRUCT(attr); 55 56 attr.len = 0x18; 57 58 if (sec_qos) { 59 qos.len = 0xc; 60 qos.impersonation_level = 2; 61 qos.context_mode = 1; 62 qos.effective_only = 0; 63 64 attr.sec_qos = &qos; 65 } 66 67 return rpccli_lsa_OpenPolicy(cli, mem_ctx, 68 &system_name, 69 &attr, 70 des_access, 71 pol); 72} 73 74/** Open a LSA policy handle 75 * 76 * @param cli Handle on an initialised SMB connection 77 */ 78 79NTSTATUS rpccli_lsa_open_policy2(struct rpc_pipe_client *cli, 80 TALLOC_CTX *mem_ctx, bool sec_qos, 81 uint32 des_access, struct policy_handle *pol) 82{ 83 struct lsa_ObjectAttribute attr; 84 struct lsa_QosInfo qos; 85 86 ZERO_STRUCT(attr); 87 88 attr.len = 0x18; 89 90 if (sec_qos) { 91 qos.len = 0xc; 92 qos.impersonation_level = 2; 93 qos.context_mode = 1; 94 qos.effective_only = 0; 95 96 attr.sec_qos = &qos; 97 } 98 99 return rpccli_lsa_OpenPolicy2(cli, mem_ctx, 100 cli->srv_name_slash, 101 &attr, 102 des_access, 103 pol); 104} 105 106/* Lookup a list of sids 107 * 108 * internal version withOUT memory allocation of the target arrays. 109 * this assumes suffciently sized arrays to store domains, names and types. */ 110 111static NTSTATUS rpccli_lsa_lookup_sids_noalloc(struct rpc_pipe_client *cli, 112 TALLOC_CTX *mem_ctx, 113 struct policy_handle *pol, 114 int num_sids, 115 const DOM_SID *sids, 116 char **domains, 117 char **names, 118 enum lsa_SidType *types, 119 bool use_lookupsids3) 120{ 121 NTSTATUS result = NT_STATUS_OK; 122 TALLOC_CTX *tmp_ctx = NULL; 123 int i; 124 struct lsa_SidArray sid_array; 125 struct lsa_RefDomainList *ref_domains = NULL; 126 struct lsa_TransNameArray lsa_names; 127 uint32_t count = 0; 128 uint16_t level = 1; 129 130 ZERO_STRUCT(lsa_names); 131 132 tmp_ctx = talloc_new(mem_ctx); 133 if (!tmp_ctx) { 134 DEBUG(0, ("rpccli_lsa_lookup_sids_noalloc: out of memory!\n")); 135 result = NT_STATUS_UNSUCCESSFUL; 136 goto done; 137 } 138 139 sid_array.num_sids = num_sids; 140 sid_array.sids = TALLOC_ARRAY(mem_ctx, struct lsa_SidPtr, num_sids); 141 if (!sid_array.sids) { 142 return NT_STATUS_NO_MEMORY; 143 } 144 145 for (i = 0; i<num_sids; i++) { 146 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[i]); 147 if (!sid_array.sids[i].sid) { 148 return NT_STATUS_NO_MEMORY; 149 } 150 } 151 152 if (use_lookupsids3) { 153 struct lsa_TransNameArray2 lsa_names2; 154 uint32_t n; 155 156 ZERO_STRUCT(lsa_names2); 157 158 result = rpccli_lsa_LookupSids3(cli, mem_ctx, 159 &sid_array, 160 &ref_domains, 161 &lsa_names2, 162 level, 163 &count, 164 0, 165 0); 166 167 if (!NT_STATUS_IS_ERR(result)) { 168 lsa_names.count = lsa_names2.count; 169 lsa_names.names = talloc_array(mem_ctx, struct lsa_TranslatedName, lsa_names.count); 170 if (!lsa_names.names) { 171 return NT_STATUS_NO_MEMORY; 172 } 173 for (n=0; n < lsa_names.count; n++) { 174 lsa_names.names[n].sid_type = lsa_names2.names[n].sid_type; 175 lsa_names.names[n].name = lsa_names2.names[n].name; 176 lsa_names.names[n].sid_index = lsa_names2.names[n].sid_index; 177 } 178 } 179 180 } else { 181 result = rpccli_lsa_LookupSids(cli, mem_ctx, 182 pol, 183 &sid_array, 184 &ref_domains, 185 &lsa_names, 186 level, 187 &count); 188 } 189 190 DEBUG(10, ("LSA_LOOKUPSIDS returned '%s', mapped count = %d'\n", 191 nt_errstr(result), count)); 192 193 if (!NT_STATUS_IS_OK(result) && 194 !NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) && 195 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) 196 { 197 /* An actual error occured */ 198 goto done; 199 } 200 201 /* Return output parameters */ 202 203 if (NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) || 204 (count == 0)) 205 { 206 for (i = 0; i < num_sids; i++) { 207 (names)[i] = NULL; 208 (domains)[i] = NULL; 209 (types)[i] = SID_NAME_UNKNOWN; 210 } 211 result = NT_STATUS_NONE_MAPPED; 212 goto done; 213 } 214 215 for (i = 0; i < num_sids; i++) { 216 const char *name, *dom_name; 217 uint32_t dom_idx = lsa_names.names[i].sid_index; 218 219 /* Translate optimised name through domain index array */ 220 221 if (dom_idx != 0xffffffff) { 222 223 dom_name = ref_domains->domains[dom_idx].name.string; 224 name = lsa_names.names[i].name.string; 225 226 if (name) { 227 (names)[i] = talloc_strdup(mem_ctx, name); 228 if ((names)[i] == NULL) { 229 DEBUG(0, ("cli_lsa_lookup_sids_noalloc(): out of memory\n")); 230 result = NT_STATUS_UNSUCCESSFUL; 231 goto done; 232 } 233 } else { 234 (names)[i] = NULL; 235 } 236 domains[i] = talloc_strdup( 237 mem_ctx, dom_name ? dom_name : ""); 238 (types)[i] = lsa_names.names[i].sid_type; 239 if (((domains)[i] == NULL)) { 240 DEBUG(0, ("cli_lsa_lookup_sids_noalloc(): out of memory\n")); 241 result = NT_STATUS_UNSUCCESSFUL; 242 goto done; 243 } 244 245 } else { 246 (names)[i] = NULL; 247 (domains)[i] = NULL; 248 (types)[i] = SID_NAME_UNKNOWN; 249 } 250 } 251 252done: 253 TALLOC_FREE(tmp_ctx); 254 return result; 255} 256 257/* Lookup a list of sids 258 * 259 * do it the right way: there is a limit (of 20480 for w2k3) entries 260 * returned by this call. when the sids list contains more entries, 261 * empty lists are returned. This version of lsa_lookup_sids passes 262 * the list of sids in hunks of LOOKUP_SIDS_HUNK_SIZE to the lsa call. */ 263 264/* This constant defines the limit of how many sids to look up 265 * in one call (maximum). the limit from the server side is 266 * at 20480 for win2k3, but we keep it at a save 1000 for now. */ 267#define LOOKUP_SIDS_HUNK_SIZE 1000 268 269static NTSTATUS rpccli_lsa_lookup_sids_generic(struct rpc_pipe_client *cli, 270 TALLOC_CTX *mem_ctx, 271 struct policy_handle *pol, 272 int num_sids, 273 const DOM_SID *sids, 274 char ***pdomains, 275 char ***pnames, 276 enum lsa_SidType **ptypes, 277 bool use_lookupsids3) 278{ 279 NTSTATUS result = NT_STATUS_OK; 280 int sids_left = 0; 281 int sids_processed = 0; 282 const DOM_SID *hunk_sids = sids; 283 char **hunk_domains; 284 char **hunk_names; 285 enum lsa_SidType *hunk_types; 286 char **domains = NULL; 287 char **names = NULL; 288 enum lsa_SidType *types = NULL; 289 290 if (num_sids) { 291 if (!(domains = TALLOC_ARRAY(mem_ctx, char *, num_sids))) { 292 DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n")); 293 result = NT_STATUS_NO_MEMORY; 294 goto fail; 295 } 296 297 if (!(names = TALLOC_ARRAY(mem_ctx, char *, num_sids))) { 298 DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n")); 299 result = NT_STATUS_NO_MEMORY; 300 goto fail; 301 } 302 303 if (!(types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_sids))) { 304 DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n")); 305 result = NT_STATUS_NO_MEMORY; 306 goto fail; 307 } 308 } 309 310 sids_left = num_sids; 311 hunk_domains = domains; 312 hunk_names = names; 313 hunk_types = types; 314 315 while (sids_left > 0) { 316 int hunk_num_sids; 317 NTSTATUS hunk_result = NT_STATUS_OK; 318 319 hunk_num_sids = ((sids_left > LOOKUP_SIDS_HUNK_SIZE) 320 ? LOOKUP_SIDS_HUNK_SIZE 321 : sids_left); 322 323 DEBUG(10, ("rpccli_lsa_lookup_sids: processing items " 324 "%d -- %d of %d.\n", 325 sids_processed, 326 sids_processed + hunk_num_sids - 1, 327 num_sids)); 328 329 hunk_result = rpccli_lsa_lookup_sids_noalloc(cli, 330 mem_ctx, 331 pol, 332 hunk_num_sids, 333 hunk_sids, 334 hunk_domains, 335 hunk_names, 336 hunk_types, 337 use_lookupsids3); 338 339 if (!NT_STATUS_IS_OK(hunk_result) && 340 !NT_STATUS_EQUAL(hunk_result, STATUS_SOME_UNMAPPED) && 341 !NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED)) 342 { 343 /* An actual error occured */ 344 result = hunk_result; 345 goto fail; 346 } 347 348 /* adapt overall result */ 349 if (( NT_STATUS_IS_OK(result) && 350 !NT_STATUS_IS_OK(hunk_result)) 351 || 352 ( NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) && 353 !NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED))) 354 { 355 result = STATUS_SOME_UNMAPPED; 356 } 357 358 sids_left -= hunk_num_sids; 359 sids_processed += hunk_num_sids; /* only used in DEBUG */ 360 hunk_sids += hunk_num_sids; 361 hunk_domains += hunk_num_sids; 362 hunk_names += hunk_num_sids; 363 hunk_types += hunk_num_sids; 364 } 365 366 *pdomains = domains; 367 *pnames = names; 368 *ptypes = types; 369 return result; 370 371fail: 372 TALLOC_FREE(domains); 373 TALLOC_FREE(names); 374 TALLOC_FREE(types); 375 return result; 376} 377 378NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli, 379 TALLOC_CTX *mem_ctx, 380 struct policy_handle *pol, 381 int num_sids, 382 const DOM_SID *sids, 383 char ***pdomains, 384 char ***pnames, 385 enum lsa_SidType **ptypes) 386{ 387 return rpccli_lsa_lookup_sids_generic(cli, mem_ctx, pol, num_sids, sids, 388 pdomains, pnames, ptypes, false); 389} 390 391NTSTATUS rpccli_lsa_lookup_sids3(struct rpc_pipe_client *cli, 392 TALLOC_CTX *mem_ctx, 393 struct policy_handle *pol, 394 int num_sids, 395 const DOM_SID *sids, 396 char ***pdomains, 397 char ***pnames, 398 enum lsa_SidType **ptypes) 399{ 400 return rpccli_lsa_lookup_sids_generic(cli, mem_ctx, pol, num_sids, sids, 401 pdomains, pnames, ptypes, true); 402} 403 404/** Lookup a list of names */ 405 406static NTSTATUS rpccli_lsa_lookup_names_generic(struct rpc_pipe_client *cli, 407 TALLOC_CTX *mem_ctx, 408 struct policy_handle *pol, int num_names, 409 const char **names, 410 const char ***dom_names, 411 int level, 412 DOM_SID **sids, 413 enum lsa_SidType **types, 414 bool use_lookupnames4) 415{ 416 NTSTATUS result; 417 int i; 418 struct lsa_String *lsa_names = NULL; 419 struct lsa_RefDomainList *domains = NULL; 420 struct lsa_TransSidArray sid_array; 421 struct lsa_TransSidArray3 sid_array3; 422 uint32_t count = 0; 423 424 ZERO_STRUCT(sid_array); 425 ZERO_STRUCT(sid_array3); 426 427 lsa_names = TALLOC_ARRAY(mem_ctx, struct lsa_String, num_names); 428 if (!lsa_names) { 429 return NT_STATUS_NO_MEMORY; 430 } 431 432 for (i=0; i<num_names; i++) { 433 init_lsa_String(&lsa_names[i], names[i]); 434 } 435 436 if (use_lookupnames4) { 437 result = rpccli_lsa_LookupNames4(cli, mem_ctx, 438 num_names, 439 lsa_names, 440 &domains, 441 &sid_array3, 442 level, 443 &count, 444 0, 445 0); 446 } else { 447 result = rpccli_lsa_LookupNames(cli, mem_ctx, 448 pol, 449 num_names, 450 lsa_names, 451 &domains, 452 &sid_array, 453 level, 454 &count); 455 } 456 457 if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != 458 NT_STATUS_V(STATUS_SOME_UNMAPPED)) { 459 460 /* An actual error occured */ 461 462 goto done; 463 } 464 465 /* Return output parameters */ 466 467 if (count == 0) { 468 result = NT_STATUS_NONE_MAPPED; 469 goto done; 470 } 471 472 if (num_names) { 473 if (!((*sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_names)))) { 474 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n")); 475 result = NT_STATUS_NO_MEMORY; 476 goto done; 477 } 478 479 if (!((*types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_names)))) { 480 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n")); 481 result = NT_STATUS_NO_MEMORY; 482 goto done; 483 } 484 485 if (dom_names != NULL) { 486 *dom_names = TALLOC_ARRAY(mem_ctx, const char *, num_names); 487 if (*dom_names == NULL) { 488 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n")); 489 result = NT_STATUS_NO_MEMORY; 490 goto done; 491 } 492 } 493 } else { 494 *sids = NULL; 495 *types = NULL; 496 if (dom_names != NULL) { 497 *dom_names = NULL; 498 } 499 } 500 501 for (i = 0; i < num_names; i++) { 502 uint32_t dom_idx; 503 DOM_SID *sid = &(*sids)[i]; 504 505 if (use_lookupnames4) { 506 dom_idx = sid_array3.sids[i].sid_index; 507 (*types)[i] = sid_array3.sids[i].sid_type; 508 } else { 509 dom_idx = sid_array.sids[i].sid_index; 510 (*types)[i] = sid_array.sids[i].sid_type; 511 } 512 513 /* Translate optimised sid through domain index array */ 514 515 if (dom_idx == 0xffffffff) { 516 /* Nothing to do, this is unknown */ 517 ZERO_STRUCTP(sid); 518 (*types)[i] = SID_NAME_UNKNOWN; 519 continue; 520 } 521 522 if (use_lookupnames4) { 523 sid_copy(sid, sid_array3.sids[i].sid); 524 } else { 525 sid_copy(sid, domains->domains[dom_idx].sid); 526 527 if (sid_array.sids[i].rid != 0xffffffff) { 528 sid_append_rid(sid, sid_array.sids[i].rid); 529 } 530 } 531 532 if (dom_names == NULL) { 533 continue; 534 } 535 536 (*dom_names)[i] = domains->domains[dom_idx].name.string; 537 } 538 539 done: 540 541 return result; 542} 543 544NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli, 545 TALLOC_CTX *mem_ctx, 546 struct policy_handle *pol, int num_names, 547 const char **names, 548 const char ***dom_names, 549 int level, 550 DOM_SID **sids, 551 enum lsa_SidType **types) 552{ 553 return rpccli_lsa_lookup_names_generic(cli, mem_ctx, pol, num_names, 554 names, dom_names, level, sids, 555 types, false); 556} 557 558NTSTATUS rpccli_lsa_lookup_names4(struct rpc_pipe_client *cli, 559 TALLOC_CTX *mem_ctx, 560 struct policy_handle *pol, int num_names, 561 const char **names, 562 const char ***dom_names, 563 int level, 564 DOM_SID **sids, 565 enum lsa_SidType **types) 566{ 567 return rpccli_lsa_lookup_names_generic(cli, mem_ctx, pol, num_names, 568 names, dom_names, level, sids, 569 types, true); 570} 571