root/source4/rpc_server/lsa/lsa_lookup.c

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

DEFINITIONS

This source file includes following definitions.
  1. lookup_well_known_names
  2. lookup_well_known_sids
  3. dcesrv_lsa_lookup_name
  4. dcesrv_lsa_authority_list
  5. dcesrv_lsa_lookup_sid
  6. dcesrv_lsa_LookupSids2
  7. dcesrv_lsa_LookupSids3
  8. dcesrv_lsa_LookupSids
  9. dcesrv_lsa_LookupNames3
  10. dcesrv_lsa_LookupNames4
  11. dcesrv_lsa_LookupNames2
  12. dcesrv_lsa_LookupNames

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    endpoint server for the lsarpc pipe
   5 
   6    Copyright (C) Andrew Tridgell 2004
   7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
   8    
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13    
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18    
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "rpc_server/lsa/lsa.h"
  24 
  25 static const struct {
  26         const char *domain;
  27         const char *name;
  28         const char *sid;
  29         int rtype;
  30 } well_known[] = {
  31         {
  32                 .name = "EVERYONE",
  33                 .sid = SID_WORLD,
  34                 .rtype = SID_NAME_WKN_GRP,
  35         },
  36         {
  37                 .name = "CREATOR OWNER",
  38                 .sid = SID_CREATOR_OWNER,
  39                 .rtype = SID_NAME_WKN_GRP,
  40         },
  41         {
  42                 .name = "CREATOR GROUP",
  43                 .sid = SID_CREATOR_GROUP,
  44                 .rtype = SID_NAME_WKN_GRP,
  45         },
  46         {
  47                 .name = "Owner Rights",
  48                 .sid = SID_OWNER_RIGHTS,
  49                 .rtype = SID_NAME_WKN_GRP,
  50         },
  51         {
  52                 .domain = "NT AUTHORITY",
  53                 .name = "Dialup",
  54                 .sid = SID_NT_DIALUP,
  55                 .rtype = SID_NAME_WKN_GRP,
  56         },
  57         {
  58                 .domain = "NT AUTHORITY",
  59                 .name = "Network",
  60                 .sid = SID_NT_NETWORK,
  61                 .rtype = SID_NAME_WKN_GRP,
  62         },
  63         {
  64                 .domain = "NT AUTHORITY",
  65                 .name = "Batch",
  66                 .sid = SID_NT_BATCH,
  67                 .rtype = SID_NAME_WKN_GRP,
  68         },
  69         {
  70                 .domain = "NT AUTHORITY",
  71                 .name = "Interactive",
  72                 .sid = SID_NT_INTERACTIVE,
  73                 .rtype = SID_NAME_WKN_GRP,
  74         },
  75         {
  76                 .domain = "NT AUTHORITY",
  77                 .name = "Service",
  78                 .sid = SID_NT_SERVICE,
  79                 .rtype = SID_NAME_WKN_GRP,
  80         },
  81         {
  82                 .domain = "NT AUTHORITY",
  83                 .name = "ANONYMOUS LOGON",
  84                 .sid = SID_NT_ANONYMOUS,
  85                 .rtype = SID_NAME_WKN_GRP,
  86         },
  87         {
  88                 .domain = "NT AUTHORITY",
  89                 .name = "Proxy",
  90                 .sid = SID_NT_PROXY,
  91                 .rtype = SID_NAME_WKN_GRP,
  92         },
  93         {
  94                 .domain = "NT AUTHORITY",
  95                 .name = "ServerLogon",
  96                 .sid = SID_NT_ENTERPRISE_DCS,
  97                 .rtype = SID_NAME_WKN_GRP,
  98         },
  99         {
 100                 .domain = "NT AUTHORITY",
 101                 .name = "Self",
 102                 .sid = SID_NT_SELF,
 103                 .rtype = SID_NAME_WKN_GRP,
 104         },
 105         {
 106                 .domain = "NT AUTHORITY",
 107                 .name = "Authenticated Users",
 108                 .sid = SID_NT_AUTHENTICATED_USERS,
 109                 .rtype = SID_NAME_WKN_GRP,
 110         },
 111         {
 112                 .domain = "NT AUTHORITY",
 113                 .name = "Restricted",
 114                 .sid = SID_NT_RESTRICTED,
 115                 .rtype = SID_NAME_WKN_GRP,
 116         },
 117         {
 118                 .domain = "NT AUTHORITY",
 119                 .name = "Terminal Server User",
 120                 .sid = SID_NT_TERMINAL_SERVER_USERS,
 121                 .rtype = SID_NAME_WKN_GRP,
 122         },
 123         {
 124                 .domain = "NT AUTHORITY",
 125                 .name = "Remote Interactive Logon",
 126                 .sid = SID_NT_REMOTE_INTERACTIVE,
 127                 .rtype = SID_NAME_WKN_GRP,
 128         },
 129         {
 130                 .domain = "NT AUTHORITY",
 131                 .name = "This Organization",
 132                 .sid = SID_NT_THIS_ORGANISATION,
 133                 .rtype = SID_NAME_WKN_GRP,
 134         },
 135         {
 136                 .domain = "NT AUTHORITY",
 137                 .name = "SYSTEM",
 138                 .sid = SID_NT_SYSTEM,
 139                 .rtype = SID_NAME_WKN_GRP,
 140         },
 141         {
 142                 .domain = "NT AUTHORITY",
 143                 .name = "Local Service",
 144                 .sid = SID_NT_LOCAL_SERVICE,
 145                 .rtype = SID_NAME_WKN_GRP,
 146         },
 147         {
 148                 .domain = "NT AUTHORITY",
 149                 .name = "Network Service",
 150                 .sid = SID_NT_NETWORK_SERVICE,
 151                 .rtype = SID_NAME_WKN_GRP,
 152         },
 153         {
 154                 .domain = "NT AUTHORITY",
 155                 .name = "Digest Authentication",
 156                 .sid = SID_NT_DIGEST_AUTHENTICATION,
 157                 .rtype = SID_NAME_WKN_GRP,
 158         },
 159         {
 160                 .domain = "NT AUTHORITY",
 161                 .name = "Enterprise Domain Controllers",
 162                 .sid = SID_NT_ENTERPRISE_DCS,
 163                 .rtype = SID_NAME_WKN_GRP,
 164         },
 165         {
 166                 .domain = "NT AUTHORITY",
 167                 .name = "NTLM Authentication",
 168                 .sid = SID_NT_NTLM_AUTHENTICATION,
 169                 .rtype = SID_NAME_WKN_GRP,
 170         },
 171         {
 172                 .domain = "NT AUTHORITY",
 173                 .name = "Other Organization",
 174                 .sid = SID_NT_OTHER_ORGANISATION,
 175                 .rtype = SID_NAME_WKN_GRP,
 176         },
 177         {
 178                 .domain = "NT AUTHORITY",
 179                 .name = "SChannel Authentication",
 180                 .sid = SID_NT_SCHANNEL_AUTHENTICATION,
 181                 .rtype = SID_NAME_WKN_GRP,
 182         },
 183         {
 184                 .domain = "NT AUTHORITY",
 185                 .name = "IUSR",
 186                 .sid = SID_NT_IUSR,
 187                 .rtype = SID_NAME_WKN_GRP,
 188         },
 189         {
 190                 .sid = NULL,
 191         }
 192 };
 193 
 194 static NTSTATUS lookup_well_known_names(TALLOC_CTX *mem_ctx, const char *domain,
     /* [<][>][^][v][top][bottom][index][help] */
 195                                         const char *name, const char **authority_name, 
 196                                         struct dom_sid **sid, uint32_t *rtype) 
 197 {
 198         int i;
 199         for (i=0; well_known[i].sid; i++) {
 200                 if (domain) {
 201                         if (strcasecmp_m(domain, well_known[i].domain) == 0
 202                             && strcasecmp_m(name, well_known[i].name) == 0) {
 203                                 *authority_name = well_known[i].domain;
 204                                 *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
 205                                 *rtype = well_known[i].rtype;
 206                                 return NT_STATUS_OK;
 207                         }
 208                 } else {
 209                         if (strcasecmp_m(name, well_known[i].name) == 0) {
 210                                 *authority_name = well_known[i].domain;
 211                                 *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
 212                                 *rtype = well_known[i].rtype;
 213                                 return NT_STATUS_OK;
 214                         }
 215                 }
 216         }
 217         return NT_STATUS_NOT_FOUND;     
 218 }
 219 
 220 static NTSTATUS lookup_well_known_sids(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 221                                        const char *sid_str, const char **authority_name, 
 222                                        const char **name, uint32_t *rtype) 
 223 {
 224         int i;
 225         for (i=0; well_known[i].sid; i++) {
 226                 if (strcasecmp_m(sid_str, well_known[i].sid) == 0) {
 227                         *authority_name = well_known[i].domain;
 228                         *name = well_known[i].name;
 229                         *rtype = well_known[i].rtype;
 230                         return NT_STATUS_OK;
 231                 }
 232         }
 233         return NT_STATUS_NOT_FOUND;     
 234 }
 235 
 236 /*
 237   lookup a SID for 1 name
 238 */
 239 static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 240                                        struct loadparm_context *lp_ctx,
 241                                        struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
 242                                 const char *name, const char **authority_name, 
 243                                 struct dom_sid **sid, enum lsa_SidType *rtype)
 244 {
 245         int ret, atype, i;
 246         struct ldb_message **res;
 247         const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
 248         const char *p;
 249         const char *domain;
 250         const char *username;
 251         struct ldb_dn *domain_dn;
 252         struct dom_sid *domain_sid;
 253         NTSTATUS status;
 254 
 255         p = strchr_m(name, '\\');
 256         if (p != NULL) {
 257                 domain = talloc_strndup(mem_ctx, name, p-name);
 258                 if (!domain) {
 259                         return NT_STATUS_NO_MEMORY;
 260                 }
 261                 username = p + 1;
 262         } else if (strchr_m(name, '@')) {
 263                 status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
 264                 if (!NT_STATUS_IS_OK(status)) {
 265                         DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status)));
 266                         return status;
 267                 }
 268         } else {
 269                 domain = NULL;
 270                 username = name;
 271         }
 272         
 273         if (!domain) {
 274                 /* Look up table of well known names */
 275                 status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
 276                 if (NT_STATUS_IS_OK(status)) {
 277                         return NT_STATUS_OK;
 278                 }
 279 
 280                 if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) { 
 281                         *authority_name = NAME_NT_AUTHORITY;
 282                         *sid =  dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
 283                         *rtype = SID_NAME_DOMAIN;
 284                         return NT_STATUS_OK;
 285                 }
 286                 if (strcasecmp_m(username, NAME_BUILTIN) == 0) { 
 287                         *authority_name = NAME_BUILTIN;
 288                         *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
 289                         *rtype = SID_NAME_DOMAIN;
 290                         return NT_STATUS_OK;
 291                 }
 292                 if (strcasecmp_m(username, state->domain_dns) == 0) { 
 293                         *authority_name = state->domain_name;
 294                         *sid =  state->domain_sid;
 295                         *rtype = SID_NAME_DOMAIN;
 296                         return NT_STATUS_OK;
 297                 }
 298                 if (strcasecmp_m(username, state->domain_name) == 0) { 
 299                         *authority_name = state->domain_name;
 300                         *sid =  state->domain_sid;
 301                         *rtype = SID_NAME_DOMAIN;
 302                         return NT_STATUS_OK;
 303                 }
 304                 
 305                 /* Perhaps this is a well known user? */
 306                 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
 307                 if (!name) {
 308                         return NT_STATUS_NO_MEMORY;
 309                 }
 310                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
 311                 if (NT_STATUS_IS_OK(status)) {
 312                         return status;
 313                 }
 314 
 315                 /* Perhaps this is a BUILTIN user? */
 316                 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
 317                 if (!name) {
 318                         return NT_STATUS_NO_MEMORY;
 319                 }
 320                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
 321                 if (NT_STATUS_IS_OK(status)) {
 322                         return status;
 323                 }
 324 
 325                 /* OK, I give up - perhaps we need to assume the user is in our domain? */
 326                 name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
 327                 if (!name) {
 328                         return NT_STATUS_NO_MEMORY;
 329                 }
 330                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
 331                 if (NT_STATUS_IS_OK(status)) {
 332                         return status;
 333                 }
 334 
 335                 return STATUS_SOME_UNMAPPED;
 336         } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
 337                 if (!*username) {
 338                         *authority_name = NAME_NT_AUTHORITY;
 339                         *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
 340                         *rtype = SID_NAME_DOMAIN;
 341                         return NT_STATUS_OK;
 342                 }
 343 
 344                 /* Look up table of well known names */
 345                 return lookup_well_known_names(mem_ctx, domain, username, authority_name, 
 346                                                sid, rtype);
 347         } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
 348                 *authority_name = NAME_BUILTIN;
 349                 domain_dn = state->builtin_dn;
 350         } else if (strcasecmp_m(domain, state->domain_dns) == 0) { 
 351                 *authority_name = state->domain_name;
 352                 domain_dn = state->domain_dn;
 353         } else if (strcasecmp_m(domain, state->domain_name) == 0) { 
 354                 *authority_name = state->domain_name;
 355                 domain_dn = state->domain_dn;
 356         } else {
 357                 /* Not local, need to ask winbind in future */
 358                 return STATUS_SOME_UNMAPPED;
 359         }
 360 
 361         ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
 362         if (ret == 1) {
 363                 domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
 364                 if (domain_sid == NULL) {
 365                         return NT_STATUS_INVALID_SID;
 366                 }
 367         } else {
 368                 return NT_STATUS_INVALID_SID;
 369         }
 370 
 371         if (!*username) {
 372                 *sid = domain_sid;
 373                 *rtype = SID_NAME_DOMAIN;
 374                 return NT_STATUS_OK;
 375         }
 376         
 377         ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
 378                            "(&(sAMAccountName=%s)(objectSid=*))", 
 379                            ldb_binary_encode_string(mem_ctx, username));
 380         if (ret == -1) {
 381                 return NT_STATUS_INVALID_SID;
 382         }
 383 
 384         for (i=0; i < ret; i++) {
 385                 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
 386                 if (*sid == NULL) {
 387                         return NT_STATUS_INVALID_SID;
 388                 }
 389 
 390                 /* Check that this is in the domain */
 391                 if (!dom_sid_in_domain(domain_sid, *sid)) {
 392                         continue;
 393                 }
 394 
 395                 atype = samdb_result_uint(res[i], "sAMAccountType", 0);
 396                         
 397                 *rtype = samdb_atype_map(atype);
 398                 if (*rtype == SID_NAME_UNKNOWN) {
 399                         return STATUS_SOME_UNMAPPED;
 400                 }
 401 
 402                 return NT_STATUS_OK;
 403         }
 404 
 405         /* need to check for an allocated sid */
 406 
 407         return NT_STATUS_INVALID_SID;
 408 }
 409 
 410 
 411 /*
 412   add to the lsa_RefDomainList for LookupSids and LookupNames
 413 */
 414 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 415                                           enum lsa_SidType rtype,
 416                                           const char *authority_name,
 417                                           struct dom_sid *sid, 
 418                                           struct lsa_RefDomainList *domains,
 419                                           uint32_t *sid_index)
 420 {
 421         struct dom_sid *authority_sid;
 422         int i;
 423 
 424         if (rtype != SID_NAME_DOMAIN) {
 425                 authority_sid = dom_sid_dup(mem_ctx, sid);
 426                 if (authority_sid == NULL) {
 427                         return NT_STATUS_NO_MEMORY;
 428                 }
 429                 authority_sid->num_auths--;
 430         } else {
 431                 authority_sid = sid;
 432         }
 433 
 434         /* see if we've already done this authority name */
 435         for (i=0;i<domains->count;i++) {
 436                 if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
 437                         *sid_index = i;
 438                         return NT_STATUS_OK;
 439                 }
 440         }
 441 
 442         domains->domains = talloc_realloc(domains, 
 443                                           domains->domains,
 444                                           struct lsa_DomainInfo,
 445                                           domains->count+1);
 446         if (domains->domains == NULL) {
 447                 return NT_STATUS_NO_MEMORY;
 448         }
 449         domains->domains[i].name.string = authority_name;
 450         domains->domains[i].sid         = authority_sid;
 451         domains->count++;
 452         domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
 453         *sid_index = i;
 454         
 455         return NT_STATUS_OK;
 456 }
 457 
 458 /*
 459   lookup a name for 1 SID
 460 */
 461 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 462                                       struct dom_sid *sid, const char *sid_str,
 463                                       const char **authority_name, 
 464                                       const char **name, enum lsa_SidType *rtype)
 465 {
 466         NTSTATUS status;
 467         int ret;
 468         uint32_t atype;
 469         struct ldb_message **res;
 470         struct ldb_dn *domain_dn;
 471         const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
 472 
 473         status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
 474         if (NT_STATUS_IS_OK(status)) {
 475                 return status;
 476         }
 477 
 478         if (dom_sid_in_domain(state->domain_sid, sid)) {
 479                 *authority_name = state->domain_name;
 480                 domain_dn = state->domain_dn;
 481         } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
 482                 *authority_name = NAME_BUILTIN;
 483                 domain_dn = state->builtin_dn;
 484         } else {
 485                 /* Not well known, our domain or built in */
 486 
 487                 /* In future, we must look at SID histories, and at trusted domains via winbind */
 488 
 489                 return NT_STATUS_NOT_FOUND;
 490         }
 491 
 492         ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
 493                            "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
 494         if (ret == 1) {
 495                 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
 496                 if (!*name) {
 497                         *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
 498                         if (!*name) {
 499                                 *name = talloc_strdup(mem_ctx, sid_str);
 500                                 NT_STATUS_HAVE_NO_MEMORY(*name);
 501                         }
 502                 }
 503 
 504                 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
 505 
 506                 *rtype = samdb_atype_map(atype);
 507 
 508                 return NT_STATUS_OK;
 509         }
 510 
 511         /* need to re-add a check for an allocated sid */
 512 
 513         return NT_STATUS_NOT_FOUND;
 514 }
 515 
 516 
 517 /*
 518   lsa_LookupSids2
 519 */
 520 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
     /* [<][>][^][v][top][bottom][index][help] */
 521                                 TALLOC_CTX *mem_ctx,
 522                                 struct lsa_LookupSids2 *r)
 523 {
 524         struct lsa_policy_state *state;
 525         struct lsa_RefDomainList *domains = NULL;
 526         int i;
 527         NTSTATUS status = NT_STATUS_OK;
 528 
 529         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
 530             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
 531                 return NT_STATUS_INVALID_PARAMETER;
 532         }
 533 
 534         *r->out.domains = NULL;
 535 
 536         /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
 537            and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as 
 538            an unknown SID. We could add a SID validator here. (tridge) 
 539            MS-DTYP 2.4.2
 540         */
 541 
 542         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
 543         if (!NT_STATUS_IS_OK(status)) {
 544                 return status;
 545         }
 546 
 547         domains = talloc_zero(r->out.domains,  struct lsa_RefDomainList);
 548         if (domains == NULL) {
 549                 return NT_STATUS_NO_MEMORY;
 550         }
 551         *r->out.domains = domains;
 552 
 553         r->out.names = talloc_zero(mem_ctx,  struct lsa_TransNameArray2);
 554         if (r->out.names == NULL) {
 555                 return NT_STATUS_NO_MEMORY;
 556         }
 557 
 558         *r->out.count = 0;
 559 
 560         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, 
 561                                              r->in.sids->num_sids);
 562         if (r->out.names->names == NULL) {
 563                 return NT_STATUS_NO_MEMORY;
 564         }
 565 
 566         for (i=0;i<r->in.sids->num_sids;i++) {
 567                 struct dom_sid *sid = r->in.sids->sids[i].sid;
 568                 char *sid_str = dom_sid_string(mem_ctx, sid);
 569                 const char *name, *authority_name;
 570                 enum lsa_SidType rtype;
 571                 uint32_t sid_index;
 572                 NTSTATUS status2;
 573 
 574                 r->out.names->count++;
 575 
 576                 r->out.names->names[i].sid_type    = SID_NAME_UNKNOWN;
 577                 r->out.names->names[i].name.string = sid_str;
 578                 r->out.names->names[i].sid_index   = 0xFFFFFFFF;
 579                 r->out.names->names[i].unknown     = 0;
 580 
 581                 if (sid_str == NULL) {
 582                         r->out.names->names[i].name.string = "(SIDERROR)";
 583                         status = STATUS_SOME_UNMAPPED;
 584                         continue;
 585                 }
 586 
 587                 status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
 588                                                 &authority_name, &name, &rtype);
 589                 if (!NT_STATUS_IS_OK(status2)) {
 590                         status = STATUS_SOME_UNMAPPED;
 591                         continue;
 592                 }
 593 
 594                 /* set up the authority table */
 595                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, 
 596                                                     authority_name, sid, 
 597                                                     domains, &sid_index);
 598                 if (!NT_STATUS_IS_OK(status2)) {
 599                         continue;
 600                 }
 601 
 602                 r->out.names->names[i].sid_type    = rtype;
 603                 r->out.names->names[i].name.string = name;
 604                 r->out.names->names[i].sid_index   = sid_index;
 605                 r->out.names->names[i].unknown     = 0;
 606 
 607                 (*r->out.count)++;
 608         }
 609 
 610         if (*r->out.count == 0) {
 611                 return NT_STATUS_NONE_MAPPED;
 612         }
 613         if (*r->out.count != r->in.sids->num_sids) {
 614                 return STATUS_SOME_UNMAPPED;
 615         }
 616 
 617         return NT_STATUS_OK;
 618 }
 619 
 620 
 621 /*
 622   lsa_LookupSids3
 623 
 624   Identical to LookupSids2, but doesn't take a policy handle
 625   
 626 */
 627 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
     /* [<][>][^][v][top][bottom][index][help] */
 628                                 TALLOC_CTX *mem_ctx,
 629                                 struct lsa_LookupSids3 *r)
 630 {
 631         struct lsa_LookupSids2 r2;
 632         struct lsa_OpenPolicy2 pol;
 633         NTSTATUS status;
 634         struct dcesrv_handle *h;
 635 
 636         ZERO_STRUCT(r2);
 637         
 638         /* No policy handle on the wire, so make one up here */
 639         r2.in.handle = talloc(mem_ctx, struct policy_handle);
 640         if (!r2.in.handle) {
 641                 return NT_STATUS_NO_MEMORY;
 642         }
 643 
 644         pol.out.handle = r2.in.handle;
 645         pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
 646         pol.in.attr = NULL;
 647         pol.in.system_name = NULL;
 648         status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
 649         if (!NT_STATUS_IS_OK(status)) {
 650                 return status;
 651         }
 652 
 653         /* ensure this handle goes away at the end of this call */
 654         DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
 655         talloc_steal(mem_ctx, h);
 656 
 657         r2.in.sids     = r->in.sids;
 658         r2.in.names    = r->in.names;
 659         r2.in.level    = r->in.level;
 660         r2.in.count    = r->in.count;
 661         r2.in.unknown1 = r->in.unknown1;
 662         r2.in.unknown2 = r->in.unknown2;
 663         r2.out.count   = r->out.count;
 664         r2.out.names   = r->out.names;
 665         r2.out.domains = r->out.domains;
 666 
 667         status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
 668 
 669         r->out.domains = r2.out.domains;
 670         r->out.names   = r2.out.names;
 671         r->out.count   = r2.out.count;
 672 
 673         return status;
 674 }
 675 
 676 
 677 /* 
 678   lsa_LookupSids 
 679 */
 680 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 681                                struct lsa_LookupSids *r)
 682 {
 683         struct lsa_LookupSids2 r2;
 684         NTSTATUS status;
 685         int i;
 686 
 687         ZERO_STRUCT(r2);
 688 
 689         r2.in.handle   = r->in.handle;
 690         r2.in.sids     = r->in.sids;
 691         r2.in.names    = NULL;
 692         r2.in.level    = r->in.level;
 693         r2.in.count    = r->in.count;
 694         r2.in.unknown1 = 0;
 695         r2.in.unknown2 = 0;
 696         r2.out.count   = r->out.count;
 697         r2.out.names   = NULL;
 698         r2.out.domains = r->out.domains;
 699 
 700         status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
 701         /* we deliberately don't check for error from the above,
 702            as even on error we are supposed to return the names  */
 703 
 704         r->out.domains = r2.out.domains;
 705         if (!r2.out.names) {
 706                 r->out.names = NULL;
 707                 return status;
 708         }
 709 
 710         r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
 711         if (r->out.names == NULL) {
 712                 return NT_STATUS_NO_MEMORY;
 713         }
 714         r->out.names->count = r2.out.names->count;
 715         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, 
 716                                              r->out.names->count);
 717         if (r->out.names->names == NULL) {
 718                 return NT_STATUS_NO_MEMORY;
 719         }
 720         for (i=0;i<r->out.names->count;i++) {
 721                 r->out.names->names[i].sid_type    = r2.out.names->names[i].sid_type;
 722                 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
 723                 r->out.names->names[i].sid_index   = r2.out.names->names[i].sid_index;
 724         }
 725 
 726         return status;
 727 }
 728 
 729 
 730 /*
 731   lsa_LookupNames3
 732 */
 733 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
     /* [<][>][^][v][top][bottom][index][help] */
 734                                  TALLOC_CTX *mem_ctx,
 735                                  struct lsa_LookupNames3 *r)
 736 {
 737         struct lsa_policy_state *policy_state;
 738         struct dcesrv_handle *policy_handle;
 739         int i;
 740         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
 741         struct lsa_RefDomainList *domains;
 742 
 743         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
 744 
 745         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
 746             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
 747                 return NT_STATUS_INVALID_PARAMETER;
 748         }
 749 
 750         policy_state = policy_handle->data;
 751 
 752         *r->out.domains = NULL;
 753 
 754         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
 755         if (domains == NULL) {
 756                 return NT_STATUS_NO_MEMORY;
 757         }
 758         *r->out.domains = domains;
 759 
 760         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
 761         if (r->out.sids == NULL) {
 762                 return NT_STATUS_NO_MEMORY;
 763         }
 764 
 765         *r->out.count = 0;
 766 
 767         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
 768                                            r->in.num_names);
 769         if (r->out.sids->sids == NULL) {
 770                 return NT_STATUS_NO_MEMORY;
 771         }
 772 
 773         for (i=0;i<r->in.num_names;i++) {
 774                 const char *name = r->in.names[i].string;
 775                 const char *authority_name;
 776                 struct dom_sid *sid;
 777                 uint32_t sid_index;
 778                 enum lsa_SidType rtype;
 779                 NTSTATUS status2;
 780 
 781                 r->out.sids->count++;
 782 
 783                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
 784                 r->out.sids->sids[i].sid         = NULL;
 785                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
 786                 r->out.sids->sids[i].flags       = 0;
 787 
 788                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name, &authority_name, &sid, &rtype);
 789                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
 790                         continue;
 791                 }
 792 
 793                 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name, 
 794                                                     sid, domains, &sid_index);
 795                 if (!NT_STATUS_IS_OK(status2)) {
 796                         continue;
 797                 }
 798 
 799                 r->out.sids->sids[i].sid_type    = rtype;
 800                 r->out.sids->sids[i].sid         = sid;
 801                 r->out.sids->sids[i].sid_index   = sid_index;
 802                 r->out.sids->sids[i].flags       = 0;
 803 
 804                 (*r->out.count)++;
 805         }
 806         
 807         if (*r->out.count == 0) {
 808                 return NT_STATUS_NONE_MAPPED;
 809         }
 810         if (*r->out.count != r->in.num_names) {
 811                 return STATUS_SOME_UNMAPPED;
 812         }
 813 
 814         return NT_STATUS_OK;
 815 }
 816 
 817 /* 
 818   lsa_LookupNames4
 819 
 820   Identical to LookupNames3, but doesn't take a policy handle
 821   
 822 */
 823 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 824                                  struct lsa_LookupNames4 *r)
 825 {
 826         struct lsa_LookupNames3 r2;
 827         struct lsa_OpenPolicy2 pol;
 828         NTSTATUS status;
 829         struct dcesrv_handle *h;
 830 
 831         ZERO_STRUCT(r2);
 832 
 833         /* No policy handle on the wire, so make one up here */
 834         r2.in.handle = talloc(mem_ctx, struct policy_handle);
 835         if (!r2.in.handle) {
 836                 return NT_STATUS_NO_MEMORY;
 837         }
 838 
 839         pol.out.handle = r2.in.handle;
 840         pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
 841         pol.in.attr = NULL;
 842         pol.in.system_name = NULL;
 843         status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
 844         if (!NT_STATUS_IS_OK(status)) {
 845                 return status;
 846         }
 847 
 848         /* ensure this handle goes away at the end of this call */
 849         DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
 850         talloc_steal(mem_ctx, h);
 851 
 852         r2.in.num_names = r->in.num_names;
 853         r2.in.names = r->in.names;
 854         r2.in.level = r->in.level;
 855         r2.in.sids = r->in.sids;
 856         r2.in.count = r->in.count;
 857         r2.in.lookup_options = r->in.lookup_options;
 858         r2.in.client_revision = r->in.client_revision;
 859         r2.out.domains = r->out.domains;
 860         r2.out.sids = r->out.sids;
 861         r2.out.count = r->out.count;
 862         
 863         status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
 864         
 865         r->out.domains = r2.out.domains;
 866         r->out.sids = r2.out.sids;
 867         r->out.count = r2.out.count;
 868         return status;
 869 }
 870 
 871 /*
 872   lsa_LookupNames2
 873 */
 874 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
     /* [<][>][^][v][top][bottom][index][help] */
 875                                  TALLOC_CTX *mem_ctx,
 876                                  struct lsa_LookupNames2 *r)
 877 {
 878         struct lsa_policy_state *state;
 879         struct dcesrv_handle *h;
 880         int i;
 881         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
 882         struct lsa_RefDomainList *domains;
 883 
 884         *r->out.domains = NULL;
 885 
 886         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
 887 
 888         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
 889             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
 890                 return NT_STATUS_INVALID_PARAMETER;
 891         }
 892 
 893         state = h->data;
 894 
 895         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
 896         if (domains == NULL) {
 897                 return NT_STATUS_NO_MEMORY;
 898         }
 899         *r->out.domains = domains;
 900 
 901         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
 902         if (r->out.sids == NULL) {
 903                 return NT_STATUS_NO_MEMORY;
 904         }
 905 
 906         *r->out.count = 0;
 907 
 908         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
 909                                            r->in.num_names);
 910         if (r->out.sids->sids == NULL) {
 911                 return NT_STATUS_NO_MEMORY;
 912         }
 913 
 914         for (i=0;i<r->in.num_names;i++) {
 915                 const char *name = r->in.names[i].string;
 916                 const char *authority_name;
 917                 struct dom_sid *sid;
 918                 uint32_t rtype, sid_index;
 919                 NTSTATUS status2;
 920 
 921                 r->out.sids->count++;
 922 
 923                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
 924                 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
 925                    to sid NULL - so we should return 0 rid for
 926                    unmapped entries */
 927                 r->out.sids->sids[i].rid         = 0;
 928                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
 929                 r->out.sids->sids[i].unknown     = 0;
 930 
 931                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name, 
 932                                                  &authority_name, &sid, &rtype);
 933                 if (!NT_STATUS_IS_OK(status2)) {
 934                         continue;
 935                 }
 936 
 937                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name, 
 938                                                     sid, domains, &sid_index);
 939                 if (!NT_STATUS_IS_OK(status2)) {
 940                         continue;
 941                 }
 942 
 943                 r->out.sids->sids[i].sid_type    = rtype;
 944                 r->out.sids->sids[i].rid         = sid->sub_auths[sid->num_auths-1];
 945                 r->out.sids->sids[i].sid_index   = sid_index;
 946                 r->out.sids->sids[i].unknown     = 0;
 947 
 948                 (*r->out.count)++;
 949         }
 950         
 951         if (*r->out.count == 0) {
 952                 return NT_STATUS_NONE_MAPPED;
 953         }
 954         if (*r->out.count != r->in.num_names) {
 955                 return STATUS_SOME_UNMAPPED;
 956         }
 957 
 958         return NT_STATUS_OK;
 959 }
 960 
 961 /* 
 962   lsa_LookupNames 
 963 */
 964 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 965                        struct lsa_LookupNames *r)
 966 {
 967         struct lsa_LookupNames2 r2;
 968         NTSTATUS status;
 969         int i;
 970 
 971         ZERO_STRUCT(r2);
 972 
 973         r2.in.handle    = r->in.handle;
 974         r2.in.num_names = r->in.num_names;
 975         r2.in.names     = r->in.names;
 976         r2.in.sids      = NULL;
 977         r2.in.level     = r->in.level;
 978         r2.in.count     = r->in.count;
 979         r2.in.lookup_options = 0;
 980         r2.in.client_revision = 0;
 981         r2.out.count    = r->out.count;
 982         r2.out.domains  = r->out.domains;
 983 
 984         status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
 985         if (r2.out.sids == NULL) {
 986                 return status;
 987         }
 988 
 989         r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
 990         if (r->out.sids == NULL) {
 991                 return NT_STATUS_NO_MEMORY;
 992         }
 993         r->out.sids->count = r2.out.sids->count;
 994         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
 995                                            r->out.sids->count);
 996         if (r->out.sids->sids == NULL) {
 997                 return NT_STATUS_NO_MEMORY;
 998         }
 999         for (i=0;i<r->out.sids->count;i++) {
1000                 r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
1001                 r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
1002                 r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
1003         }
1004 
1005         return status;
1006 }
1007 

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