root/source3/rpc_client/cli_lsarpc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rpccli_lsa_open_policy
  2. rpccli_lsa_open_policy2
  3. rpccli_lsa_lookup_sids_noalloc
  4. rpccli_lsa_lookup_sids_generic
  5. rpccli_lsa_lookup_sids
  6. rpccli_lsa_lookup_sids3
  7. rpccli_lsa_lookup_names_generic
  8. rpccli_lsa_lookup_names
  9. rpccli_lsa_lookup_names4

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

/* [<][>][^][v][top][bottom][index][help] */