root/source3/passdb/lookup_sid.c

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

DEFINITIONS

This source file includes following definitions.
  1. lookup_name
  2. lookup_name_smbconf
  3. wb_lookup_rids
  4. lookup_rids
  5. lookup_as_domain
  6. check_dom_sid_to_level
  7. lookup_sids
  8. lookup_sid
  9. fetch_sid_from_uid_cache
  10. fetch_uid_from_cache
  11. store_uid_sid_cache
  12. fetch_sid_from_gid_cache
  13. fetch_gid_from_cache
  14. store_gid_sid_cache
  15. legacy_uid_to_sid
  16. legacy_gid_to_sid
  17. legacy_sid_to_uid
  18. legacy_sid_to_gid
  19. uid_to_sid
  20. gid_to_sid
  21. sid_to_uid
  22. sid_to_gid

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    uid/user handling
   4    Copyright (C) Andrew Tridgell         1992-1998
   5    Copyright (C) Gerald (Jerry) Carter   2003
   6    Copyright (C) Volker Lendecke         2005
   7    
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 
  24 /*****************************************************************
  25  Dissect a user-provided name into domain, name, sid and type.
  26 
  27  If an explicit domain name was given in the form domain\user, it
  28  has to try that. If no explicit domain name was given, we have
  29  to do guesswork.
  30 *****************************************************************/  
  31 
  32 bool lookup_name(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  33                  const char *full_name, int flags,
  34                  const char **ret_domain, const char **ret_name,
  35                  DOM_SID *ret_sid, enum lsa_SidType *ret_type)
  36 {
  37         char *p;
  38         const char *tmp;
  39         const char *domain = NULL;
  40         const char *name = NULL;
  41         uint32 rid;
  42         DOM_SID sid;
  43         enum lsa_SidType type;
  44         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
  45 
  46         if (tmp_ctx == NULL) {
  47                 DEBUG(0, ("talloc_new failed\n"));
  48                 return false;
  49         }
  50 
  51         p = strchr_m(full_name, '\\');
  52 
  53         if (p != NULL) {
  54                 domain = talloc_strndup(tmp_ctx, full_name,
  55                                         PTR_DIFF(p, full_name));
  56                 name = talloc_strdup(tmp_ctx, p+1);
  57         } else {
  58                 domain = talloc_strdup(tmp_ctx, "");
  59                 name = talloc_strdup(tmp_ctx, full_name);
  60         }
  61 
  62         if ((domain == NULL) || (name == NULL)) {
  63                 DEBUG(0, ("talloc failed\n"));
  64                 TALLOC_FREE(tmp_ctx);
  65                 return false;
  66         }
  67 
  68         DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
  69                 full_name, domain, name));
  70         DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
  71 
  72         if ((flags & LOOKUP_NAME_DOMAIN) &&
  73             strequal(domain, get_global_sam_name()))
  74         {
  75 
  76                 /* It's our own domain, lookup the name in passdb */
  77                 if (lookup_global_sam_name(name, flags, &rid, &type)) {
  78                         sid_copy(&sid, get_global_sam_sid());
  79                         sid_append_rid(&sid, rid);
  80                         goto ok;
  81                 }
  82                 TALLOC_FREE(tmp_ctx);
  83                 return false;
  84         }
  85 
  86         if ((flags & LOOKUP_NAME_BUILTIN) &&
  87             strequal(domain, builtin_domain_name()))
  88         {
  89                 /* Explicit request for a name in BUILTIN */
  90                 if (lookup_builtin_name(name, &rid)) {
  91                         sid_copy(&sid, &global_sid_Builtin);
  92                         sid_append_rid(&sid, rid);
  93                         type = SID_NAME_ALIAS;
  94                         goto ok;
  95                 }
  96                 TALLOC_FREE(tmp_ctx);
  97                 return false;
  98         }
  99 
 100         /* Try the explicit winbind lookup first, don't let it guess the
 101          * domain yet at this point yet. This comes later. */
 102 
 103         if ((domain[0] != '\0') &&
 104             (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
 105             (winbind_lookup_name(domain, name, &sid, &type))) {
 106                         goto ok;
 107         }
 108 
 109         if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_users_domain_name())) {
 110                 if (lookup_unix_user_name(name, &sid)) {
 111                         type = SID_NAME_USER;
 112                         goto ok;
 113                 }
 114                 TALLOC_FREE(tmp_ctx);
 115                 return false;
 116         }
 117 
 118         if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_groups_domain_name())) {
 119                 if (lookup_unix_group_name(name, &sid)) {
 120                         type = SID_NAME_DOM_GRP;
 121                         goto ok;
 122                 }
 123                 TALLOC_FREE(tmp_ctx);
 124                 return false;
 125         }
 126 
 127         if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
 128                 TALLOC_FREE(tmp_ctx);
 129                 return false;
 130         }
 131 
 132         /* Now the guesswork begins, we haven't been given an explicit
 133          * domain. Try the sequence as documented on
 134          * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
 135          * November 27, 2005 */
 136 
 137         /* 1. well-known names */
 138 
 139         if ((flags & LOOKUP_NAME_WKN) &&
 140             lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
 141         {
 142                 type = SID_NAME_WKN_GRP;
 143                 goto ok;
 144         }
 145 
 146         /* 2. Builtin domain as such */
 147 
 148         if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
 149             strequal(name, builtin_domain_name()))
 150         {
 151                 /* Swap domain and name */
 152                 tmp = name; name = domain; domain = tmp;
 153                 sid_copy(&sid, &global_sid_Builtin);
 154                 type = SID_NAME_DOMAIN;
 155                 goto ok;
 156         }
 157 
 158         /* 3. Account domain */
 159 
 160         if ((flags & LOOKUP_NAME_DOMAIN) &&
 161             strequal(name, get_global_sam_name()))
 162         {
 163                 if (!secrets_fetch_domain_sid(name, &sid)) {
 164                         DEBUG(3, ("Could not fetch my SID\n"));
 165                         TALLOC_FREE(tmp_ctx);
 166                         return false;
 167                 }
 168                 /* Swap domain and name */
 169                 tmp = name; name = domain; domain = tmp;
 170                 type = SID_NAME_DOMAIN;
 171                 goto ok;
 172         }
 173 
 174         /* 4. Primary domain */
 175 
 176         if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
 177             strequal(name, lp_workgroup()))
 178         {
 179                 if (!secrets_fetch_domain_sid(name, &sid)) {
 180                         DEBUG(3, ("Could not fetch the domain SID\n"));
 181                         TALLOC_FREE(tmp_ctx);
 182                         return false;
 183                 }
 184                 /* Swap domain and name */
 185                 tmp = name; name = domain; domain = tmp;
 186                 type = SID_NAME_DOMAIN;
 187                 goto ok;
 188         }
 189 
 190         /* 5. Trusted domains as such, to me it looks as if members don't do
 191               this, tested an XP workstation in a NT domain -- vl */
 192 
 193         if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
 194             (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
 195         {
 196                 /* Swap domain and name */
 197                 tmp = name; name = domain; domain = tmp;
 198                 type = SID_NAME_DOMAIN;
 199                 goto ok;
 200         }
 201 
 202         /* 6. Builtin aliases */        
 203 
 204         if ((flags & LOOKUP_NAME_BUILTIN) &&
 205             lookup_builtin_name(name, &rid))
 206         {
 207                 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
 208                 sid_copy(&sid, &global_sid_Builtin);
 209                 sid_append_rid(&sid, rid);
 210                 type = SID_NAME_ALIAS;
 211                 goto ok;
 212         }
 213 
 214         /* 7. Local systems' SAM (DCs don't have a local SAM) */
 215         /* 8. Primary SAM (On members, this is the domain) */
 216 
 217         /* Both cases are done by looking at our passdb */
 218 
 219         if ((flags & LOOKUP_NAME_DOMAIN) &&
 220             lookup_global_sam_name(name, flags, &rid, &type))
 221         {
 222                 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
 223                 sid_copy(&sid, get_global_sam_sid());
 224                 sid_append_rid(&sid, rid);
 225                 goto ok;
 226         }
 227 
 228         /* Now our local possibilities are exhausted. */
 229 
 230         if (!(flags & LOOKUP_NAME_REMOTE)) {
 231                 TALLOC_FREE(tmp_ctx);
 232                 return false;
 233         }
 234 
 235         /* If we are not a DC, we have to ask in our primary domain. Let
 236          * winbind do that. */
 237 
 238         if (!IS_DC &&
 239             (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
 240                 domain = talloc_strdup(tmp_ctx, lp_workgroup());
 241                 goto ok;
 242         }
 243 
 244         /* 9. Trusted domains */
 245 
 246         /* If we're a DC we have to ask all trusted DC's. Winbind does not do
 247          * that (yet), but give it a chance. */
 248 
 249         if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
 250                 DOM_SID dom_sid;
 251                 uint32 tmp_rid;
 252                 enum lsa_SidType domain_type;
 253                 
 254                 if (type == SID_NAME_DOMAIN) {
 255                         /* Swap name and type */
 256                         tmp = name; name = domain; domain = tmp;
 257                         goto ok;
 258                 }
 259 
 260                 /* Here we have to cope with a little deficiency in the
 261                  * winbind API: We have to ask it again for the name of the
 262                  * domain it figured out itself. Maybe fix that later... */
 263 
 264                 sid_copy(&dom_sid, &sid);
 265                 sid_split_rid(&dom_sid, &tmp_rid);
 266 
 267                 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
 268                                         &domain_type) ||
 269                     (domain_type != SID_NAME_DOMAIN)) {
 270                         DEBUG(2, ("winbind could not find the domain's name "
 271                                   "it just looked up for us\n"));
 272                         TALLOC_FREE(tmp_ctx);
 273                         return false;
 274                 }
 275                 goto ok;
 276         }
 277 
 278         /* 10. Don't translate */
 279 
 280         /* 11. Ok, windows would end here. Samba has two more options:
 281                Unmapped users and unmapped groups */
 282 
 283         if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) {
 284                 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
 285                 type = SID_NAME_USER;
 286                 goto ok;
 287         }
 288 
 289         if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) {
 290                 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
 291                 type = SID_NAME_DOM_GRP;
 292                 goto ok;
 293         }
 294 
 295         /*
 296          * Ok, all possibilities tried. Fail.
 297          */
 298 
 299         TALLOC_FREE(tmp_ctx);
 300         return false;
 301 
 302  ok:
 303         if ((domain == NULL) || (name == NULL)) {
 304                 DEBUG(0, ("talloc failed\n"));
 305                 TALLOC_FREE(tmp_ctx);
 306                 return false;
 307         }
 308 
 309         /*
 310          * Hand over the results to the talloc context we've been given.
 311          */
 312 
 313         if ((ret_name != NULL) &&
 314             !(*ret_name = talloc_strdup(mem_ctx, name))) {
 315                 DEBUG(0, ("talloc failed\n"));
 316                 TALLOC_FREE(tmp_ctx);
 317                 return false;
 318         }
 319 
 320         if (ret_domain != NULL) {
 321                 char *tmp_dom;
 322                 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
 323                         DEBUG(0, ("talloc failed\n"));
 324                         TALLOC_FREE(tmp_ctx);
 325                         return false;
 326                 }
 327                 strupper_m(tmp_dom);
 328                 *ret_domain = tmp_dom;
 329         }
 330 
 331         if (ret_sid != NULL) {
 332                 sid_copy(ret_sid, &sid);
 333         }
 334 
 335         if (ret_type != NULL) {
 336                 *ret_type = type;
 337         }
 338 
 339         TALLOC_FREE(tmp_ctx);
 340         return true;
 341 }
 342 
 343 /************************************************************************
 344  Names from smb.conf can be unqualified. eg. valid users = foo
 345  These names should never map to a remote name. Try global_sam_name()\foo,
 346  and then "Unix Users"\foo (or "Unix Groups"\foo).
 347 ************************************************************************/
 348 
 349 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 350                  const char *full_name, int flags,
 351                  const char **ret_domain, const char **ret_name,
 352                  DOM_SID *ret_sid, enum lsa_SidType *ret_type)
 353 {
 354         char *qualified_name;
 355         const char *p;
 356 
 357         /* NB. No winbindd_separator here as lookup_name needs \\' */
 358         if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
 359 
 360                 /* The name is already qualified with a domain. */
 361 
 362                 if (*lp_winbind_separator() != '\\') {
 363                         char *tmp;
 364 
 365                         /* lookup_name() needs '\\' as a separator */
 366 
 367                         tmp = talloc_strdup(mem_ctx, full_name);
 368                         if (!tmp) {
 369                                 return false;
 370                         }
 371                         tmp[p - full_name] = '\\';
 372                         full_name = tmp;
 373                 }
 374 
 375                 return lookup_name(mem_ctx, full_name, flags,
 376                                 ret_domain, ret_name,
 377                                 ret_sid, ret_type);
 378         }
 379 
 380         /* Try with our own SAM name. */
 381         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
 382                                 get_global_sam_name(),
 383                                 full_name );
 384         if (!qualified_name) {
 385                 return false;
 386         }
 387 
 388         if (lookup_name(mem_ctx, qualified_name, flags,
 389                                 ret_domain, ret_name,
 390                                 ret_sid, ret_type)) {
 391                 return true;
 392         }
 393         
 394         /* Finally try with "Unix Users" or "Unix Group" */
 395         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
 396                                 flags & LOOKUP_NAME_GROUP ?
 397                                         unix_groups_domain_name() :
 398                                         unix_users_domain_name(),
 399                                 full_name );
 400         if (!qualified_name) {
 401                 return false;
 402         }
 403 
 404         return lookup_name(mem_ctx, qualified_name, flags,
 405                                 ret_domain, ret_name,
 406                                 ret_sid, ret_type);
 407 }
 408 
 409 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 410                            const DOM_SID *domain_sid,
 411                            int num_rids, uint32 *rids,
 412                            const char **domain_name,
 413                            const char **names, enum lsa_SidType *types)
 414 {
 415         int i;
 416         const char **my_names;
 417         enum lsa_SidType *my_types;
 418         TALLOC_CTX *tmp_ctx;
 419 
 420         if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
 421                 return false;
 422         }
 423 
 424         if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
 425                                  domain_name, &my_names, &my_types)) {
 426                 *domain_name = talloc_strdup(mem_ctx, "");
 427                 if (!(*domain_name)) {
 428                         TALLOC_FREE(tmp_ctx);
 429                         return False;
 430                 }
 431                 for (i=0; i<num_rids; i++) {
 432                         names[i] = talloc_strdup(names, "");
 433                         if (!names[i]) {
 434                                 TALLOC_FREE(tmp_ctx);
 435                                 return False;
 436                         }
 437                         types[i] = SID_NAME_UNKNOWN;
 438                 }
 439                 TALLOC_FREE(tmp_ctx);
 440                 return true;
 441         }
 442 
 443         if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
 444                 TALLOC_FREE(tmp_ctx);
 445                 return false;
 446         }
 447 
 448         /*
 449          * winbind_lookup_rids allocates its own array. We've been given the
 450          * array, so copy it over
 451          */
 452 
 453         for (i=0; i<num_rids; i++) {
 454                 if (my_names[i] == NULL) {
 455                         TALLOC_FREE(tmp_ctx);
 456                         return false;
 457                 }
 458                 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
 459                         TALLOC_FREE(tmp_ctx);
 460                         return false;
 461                 }
 462                 types[i] = my_types[i];
 463         }
 464         TALLOC_FREE(tmp_ctx);
 465         return true;
 466 }
 467 
 468 static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
     /* [<][>][^][v][top][bottom][index][help] */
 469                         int num_rids, uint32_t *rids,
 470                         const char **domain_name,
 471                         const char ***names, enum lsa_SidType **types)
 472 {
 473         int i;
 474 
 475         DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
 476                    sid_string_dbg(domain_sid)));
 477 
 478         if (num_rids) {
 479                 *names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
 480                 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
 481 
 482                 if ((*names == NULL) || (*types == NULL)) {
 483                         return false;
 484                 }
 485 
 486                 for (i = 0; i < num_rids; i++)
 487                         (*types)[i] = SID_NAME_UNKNOWN;
 488         } else {
 489                 *names = NULL;
 490                 *types = NULL;
 491         }
 492 
 493         if (sid_check_is_domain(domain_sid)) {
 494                 NTSTATUS result;
 495 
 496                 if (*domain_name == NULL) {
 497                         *domain_name = talloc_strdup(
 498                                 mem_ctx, get_global_sam_name());
 499                 }
 500 
 501                 if (*domain_name == NULL) {
 502                         return false;
 503                 }
 504 
 505                 become_root();
 506                 result = pdb_lookup_rids(domain_sid, num_rids, rids,
 507                                          *names, *types);
 508                 unbecome_root();
 509 
 510                 return (NT_STATUS_IS_OK(result) ||
 511                         NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
 512                         NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
 513         }
 514 
 515         if (sid_check_is_builtin(domain_sid)) {
 516 
 517                 if (*domain_name == NULL) {
 518                         *domain_name = talloc_strdup(
 519                                 mem_ctx, builtin_domain_name());
 520                 }
 521 
 522                 if (*domain_name == NULL) {
 523                         return false;
 524                 }
 525 
 526                 for (i=0; i<num_rids; i++) {
 527                         if (lookup_builtin_rid(*names, rids[i],
 528                                                &(*names)[i])) {
 529                                 if ((*names)[i] == NULL) {
 530                                         return false;
 531                                 }
 532                                 (*types)[i] = SID_NAME_ALIAS;
 533                         } else {
 534                                 (*types)[i] = SID_NAME_UNKNOWN;
 535                         }
 536                 }
 537                 return true;
 538         }
 539 
 540         if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
 541                 for (i=0; i<num_rids; i++) {
 542                         DOM_SID sid;
 543                         sid_copy(&sid, domain_sid);
 544                         sid_append_rid(&sid, rids[i]);
 545                         if (lookup_wellknown_sid(mem_ctx, &sid,
 546                                                  domain_name, &(*names)[i])) {
 547                                 if ((*names)[i] == NULL) {
 548                                         return false;
 549                                 }
 550                                 (*types)[i] = SID_NAME_WKN_GRP;
 551                         } else {
 552                                 (*types)[i] = SID_NAME_UNKNOWN;
 553                         }
 554                 }
 555                 return true;
 556         }
 557 
 558         if (sid_check_is_unix_users(domain_sid)) {
 559                 if (*domain_name == NULL) {
 560                         *domain_name = talloc_strdup(
 561                                 mem_ctx, unix_users_domain_name());
 562                         if (*domain_name == NULL) {
 563                                 return false;
 564                         }
 565                 }
 566                 for (i=0; i<num_rids; i++) {
 567                         (*names)[i] = talloc_strdup(
 568                                 (*names), uidtoname(rids[i]));
 569                         if ((*names)[i] == NULL) {
 570                                 return false;
 571                         }
 572                         (*types)[i] = SID_NAME_USER;
 573                 }
 574                 return true;
 575         }
 576 
 577         if (sid_check_is_unix_groups(domain_sid)) {
 578                 if (*domain_name == NULL) {
 579                         *domain_name = talloc_strdup(
 580                                 mem_ctx, unix_groups_domain_name());
 581                         if (*domain_name == NULL) {
 582                                 return false;
 583                         }
 584                 }
 585                 for (i=0; i<num_rids; i++) {
 586                         (*names)[i] = talloc_strdup(
 587                                 (*names), gidtoname(rids[i]));
 588                         if ((*names)[i] == NULL) {
 589                                 return false;
 590                         }
 591                         (*types)[i] = SID_NAME_DOM_GRP;
 592                 }
 593                 return true;
 594         }
 595 
 596         return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
 597                               domain_name, *names, *types);
 598 }
 599 
 600 /*
 601  * Is the SID a domain as such? If yes, lookup its name.
 602  */
 603 
 604 static bool lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 605                              const char **name)
 606 {
 607         const char *tmp;
 608         enum lsa_SidType type;
 609 
 610         if (sid_check_is_domain(sid)) {
 611                 *name = talloc_strdup(mem_ctx, get_global_sam_name());
 612                 return true;
 613         }
 614 
 615         if (sid_check_is_builtin(sid)) {
 616                 *name = talloc_strdup(mem_ctx, builtin_domain_name());
 617                 return true;
 618         }
 619 
 620         if (sid_check_is_wellknown_domain(sid, &tmp)) {
 621                 *name = talloc_strdup(mem_ctx, tmp);
 622                 return true;
 623         }
 624 
 625         if (sid_check_is_unix_users(sid)) {
 626                 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
 627                 return true;
 628         }
 629 
 630         if (sid_check_is_unix_groups(sid)) {
 631                 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
 632                 return true;
 633         }
 634 
 635         if (sid->num_auths != 4) {
 636                 /* This can't be a domain */
 637                 return false;
 638         }
 639 
 640         if (IS_DC) {
 641                 uint32 i, num_domains;
 642                 struct trustdom_info **domains;
 643 
 644                 /* This is relatively expensive, but it happens only on DCs
 645                  * and for SIDs that have 4 sub-authorities and thus look like
 646                  * domains */
 647 
 648                 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
 649                                                           &num_domains,
 650                                                           &domains))) {
 651                         return false;
 652                 }
 653 
 654                 for (i=0; i<num_domains; i++) {
 655                         if (sid_equal(sid, &domains[i]->sid)) {
 656                                 *name = talloc_strdup(mem_ctx,
 657                                                       domains[i]->name);
 658                                 return true;
 659                         }
 660                 }
 661                 return false;
 662         }
 663 
 664         if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
 665             (type == SID_NAME_DOMAIN)) {
 666                 *name = tmp;
 667                 return true;
 668         }
 669 
 670         return false;
 671 }
 672 
 673 /*
 674  * This tries to implement the rather weird rules for the lsa_lookup level
 675  * parameter.
 676  *
 677  * This is as close as we can get to what W2k3 does. With this we survive the
 678  * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
 679  * different, but I assume that's just being too liberal. For example, W2k3
 680  * replies to everything else but the levels 1-6 with INVALID_PARAMETER
 681  * whereas NT4 does the same as level 1 (I think). I did not fully test that
 682  * with NT4, this is what w2k3 does.
 683  *
 684  * Level 1: Ask everywhere
 685  * Level 2: Ask domain and trusted domains, no builtin and wkn
 686  * Level 3: Only ask domain
 687  * Level 4: W2k3ad: Only ask AD trusts
 688  * Level 5: Only ask transitive forest trusts
 689  * Level 6: Like 4
 690  */
 691 
 692 static bool check_dom_sid_to_level(const DOM_SID *sid, int level)
     /* [<][>][^][v][top][bottom][index][help] */
 693 {
 694         int ret = false;
 695 
 696         switch(level) {
 697         case 1:
 698                 ret = true;
 699                 break;
 700         case 2:
 701                 ret = (!sid_check_is_builtin(sid) &&
 702                        !sid_check_is_wellknown_domain(sid, NULL));
 703                 break;
 704         case 3:
 705         case 4:
 706         case 6:
 707                 ret = sid_check_is_domain(sid);
 708                 break;
 709         case 5:
 710                 ret = false;
 711                 break;
 712         }
 713 
 714         DEBUG(10, ("%s SID %s in level %d\n",
 715                    ret ? "Accepting" : "Rejecting",
 716                    sid_string_dbg(sid), level));
 717         return ret;
 718 }
 719 
 720 /*
 721  * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
 722  * references to domains, it is explicitly made for this.
 723  *
 724  * This attempts to be as efficient as possible: It collects all SIDs
 725  * belonging to a domain and hands them in bulk to the appropriate lookup
 726  * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
 727  * *hugely* from this. Winbind is going to be extended with a lookup_rids
 728  * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
 729  * appropriate DC.
 730  */
 731 
 732 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
     /* [<][>][^][v][top][bottom][index][help] */
 733                      const DOM_SID **sids, int level,
 734                      struct lsa_dom_info **ret_domains,
 735                      struct lsa_name_info **ret_names)
 736 {
 737         TALLOC_CTX *tmp_ctx;
 738         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 739         struct lsa_name_info *name_infos;
 740         struct lsa_dom_info *dom_infos = NULL;
 741 
 742         int i, j;
 743 
 744         if (!(tmp_ctx = talloc_new(mem_ctx))) {
 745                 DEBUG(0, ("talloc_new failed\n"));
 746                 return NT_STATUS_NO_MEMORY;
 747         }
 748 
 749         if (num_sids) {
 750                 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
 751                 if (name_infos == NULL) {
 752                         result = NT_STATUS_NO_MEMORY;
 753                         goto fail;
 754                 }
 755         } else {
 756                 name_infos = NULL;
 757         }
 758 
 759         dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
 760                                       LSA_REF_DOMAIN_LIST_MULTIPLIER);
 761         if (dom_infos == NULL) {
 762                 result = NT_STATUS_NO_MEMORY;
 763                 goto fail;
 764         }
 765 
 766         /* First build up the data structures:
 767          * 
 768          * dom_infos is a list of domains referenced in the list of
 769          * SIDs. Later we will walk the list of domains and look up the RIDs
 770          * in bulk.
 771          *
 772          * name_infos is a shadow-copy of the SIDs array to collect the real
 773          * data.
 774          *
 775          * dom_info->idxs is an index into the name_infos array. The
 776          * difficulty we have here is that we need to keep the SIDs the client
 777          * asked for in the same order for the reply
 778          */
 779 
 780         for (i=0; i<num_sids; i++) {
 781                 DOM_SID sid;
 782                 uint32 rid;
 783                 const char *domain_name = NULL;
 784 
 785                 sid_copy(&sid, sids[i]);
 786                 name_infos[i].type = SID_NAME_USE_NONE;
 787 
 788                 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
 789                         /* We can't push that through the normal lookup
 790                          * process, as this would reference illegal
 791                          * domains.
 792                          *
 793                          * For example S-1-5-32 would end up referencing
 794                          * domain S-1-5- with RID 32 which is clearly wrong.
 795                          */
 796                         if (domain_name == NULL) {
 797                                 result = NT_STATUS_NO_MEMORY;
 798                                 goto fail;
 799                         }
 800                                 
 801                         name_infos[i].rid = 0;
 802                         name_infos[i].type = SID_NAME_DOMAIN;
 803                         name_infos[i].name = NULL;
 804 
 805                         if (sid_check_is_builtin(&sid)) {
 806                                 /* Yes, W2k3 returns "BUILTIN" both as domain
 807                                  * and name here */
 808                                 name_infos[i].name = talloc_strdup(
 809                                         name_infos, builtin_domain_name());
 810                                 if (name_infos[i].name == NULL) {
 811                                         result = NT_STATUS_NO_MEMORY;
 812                                         goto fail;
 813                                 }
 814                         }
 815                 } else {
 816                         /* This is a normal SID with rid component */
 817                         if (!sid_split_rid(&sid, &rid)) {
 818                                 result = NT_STATUS_INVALID_SID;
 819                                 goto fail;
 820                         }
 821                 }
 822 
 823                 if (!check_dom_sid_to_level(&sid, level)) {
 824                         name_infos[i].rid = 0;
 825                         name_infos[i].type = SID_NAME_UNKNOWN;
 826                         name_infos[i].name = NULL;
 827                         continue;
 828                 }
 829 
 830                 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
 831                         if (!dom_infos[j].valid) {
 832                                 break;
 833                         }
 834                         if (sid_equal(&sid, &dom_infos[j].sid)) {
 835                                 break;
 836                         }
 837                 }
 838 
 839                 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
 840                         /* TODO: What's the right error message here? */
 841                         result = NT_STATUS_NONE_MAPPED;
 842                         goto fail;
 843                 }
 844 
 845                 if (!dom_infos[j].valid) {
 846                         /* We found a domain not yet referenced, create a new
 847                          * ref. */
 848                         dom_infos[j].valid = true;
 849                         sid_copy(&dom_infos[j].sid, &sid);
 850 
 851                         if (domain_name != NULL) {
 852                                 /* This name was being found above in the case
 853                                  * when we found a domain SID */
 854                                 dom_infos[j].name =
 855                                         talloc_strdup(dom_infos, domain_name);
 856                                 if (dom_infos[j].name == NULL) {
 857                                         result = NT_STATUS_NO_MEMORY;
 858                                         goto fail;
 859                                 }
 860                         } else {
 861                                 /* lookup_rids will take care of this */
 862                                 dom_infos[j].name = NULL;
 863                         }
 864                 }
 865 
 866                 name_infos[i].dom_idx = j;
 867 
 868                 if (name_infos[i].type == SID_NAME_USE_NONE) {
 869                         name_infos[i].rid = rid;
 870 
 871                         ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
 872                                      &dom_infos[j].num_idxs);
 873 
 874                         if (dom_infos[j].idxs == NULL) {
 875                                 result = NT_STATUS_NO_MEMORY;
 876                                 goto fail;
 877                         }
 878                 }
 879         }
 880 
 881         /* Iterate over the domains found */
 882 
 883         for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
 884                 uint32_t *rids;
 885                 const char *domain_name = NULL;
 886                 const char **names;
 887                 enum lsa_SidType *types;
 888                 struct lsa_dom_info *dom = &dom_infos[i];
 889 
 890                 if (!dom->valid) {
 891                         /* No domains left, we're done */
 892                         break;
 893                 }
 894 
 895                 if (dom->num_idxs) {
 896                         if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
 897                                 result = NT_STATUS_NO_MEMORY;
 898                                 goto fail;
 899                         }
 900                 } else {
 901                         rids = NULL;
 902                 }
 903 
 904                 for (j=0; j<dom->num_idxs; j++) {
 905                         rids[j] = name_infos[dom->idxs[j]].rid;
 906                 }
 907 
 908                 if (!lookup_rids(tmp_ctx, &dom->sid,
 909                                  dom->num_idxs, rids, &domain_name,
 910                                  &names, &types)) {
 911                         result = NT_STATUS_NO_MEMORY;
 912                         goto fail;
 913                 }
 914 
 915                 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
 916                         result = NT_STATUS_NO_MEMORY;
 917                         goto fail;
 918                 }
 919                         
 920                 for (j=0; j<dom->num_idxs; j++) {
 921                         int idx = dom->idxs[j];
 922                         name_infos[idx].type = types[j];
 923                         if (types[j] != SID_NAME_UNKNOWN) {
 924                                 name_infos[idx].name =
 925                                         talloc_strdup(name_infos, names[j]);
 926                                 if (name_infos[idx].name == NULL) {
 927                                         result = NT_STATUS_NO_MEMORY;
 928                                         goto fail;
 929                                 }
 930                         } else {
 931                                 name_infos[idx].name = NULL;
 932                         }
 933                 }
 934         }
 935 
 936         *ret_domains = dom_infos;
 937         *ret_names = name_infos;
 938         TALLOC_FREE(tmp_ctx);
 939         return NT_STATUS_OK;
 940 
 941  fail:
 942         TALLOC_FREE(dom_infos);
 943         TALLOC_FREE(name_infos);
 944         TALLOC_FREE(tmp_ctx);
 945         return result;
 946 }
 947 
 948 /*****************************************************************
 949  *THE CANONICAL* convert SID to name function.
 950 *****************************************************************/  
 951 
 952 bool lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
     /* [<][>][^][v][top][bottom][index][help] */
 953                 const char **ret_domain, const char **ret_name,
 954                 enum lsa_SidType *ret_type)
 955 {
 956         struct lsa_dom_info *domain;
 957         struct lsa_name_info *name;
 958         TALLOC_CTX *tmp_ctx;
 959         bool ret = false;
 960 
 961         DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
 962 
 963         if (!(tmp_ctx = talloc_new(mem_ctx))) {
 964                 DEBUG(0, ("talloc_new failed\n"));
 965                 return false;
 966         }
 967 
 968         if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
 969                                          &domain, &name))) {
 970                 goto done;
 971         }
 972 
 973         if (name->type == SID_NAME_UNKNOWN) {
 974                 goto done;
 975         }
 976 
 977         if ((ret_domain != NULL) &&
 978             !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
 979                 goto done;
 980         }
 981 
 982         if ((ret_name != NULL) && 
 983             !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
 984                 goto done;
 985         }
 986 
 987         if (ret_type != NULL) {
 988                 *ret_type = name->type;
 989         }
 990 
 991         ret = true;
 992 
 993  done:
 994         if (ret) {
 995                 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
 996                            domain->name, name->name, name->type));
 997         } else {
 998                 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
 999         }
1000         TALLOC_FREE(tmp_ctx);
1001         return ret;
1002 }
1003 
1004 /*****************************************************************
1005  Id mapping cache.  This is to avoid Winbind mappings already
1006  seen by smbd to be queried too frequently, keeping winbindd
1007  busy, and blocking smbd while winbindd is busy with other
1008  stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1009  modified to use linked lists by jra.
1010 *****************************************************************/  
1011 
1012 /*****************************************************************
1013   Find a SID given a uid.
1014 *****************************************************************/
1015 
1016 static bool fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
1017 {
1018         DATA_BLOB cache_value;
1019 
1020         if (!memcache_lookup(NULL, UID_SID_CACHE,
1021                              data_blob_const(&uid, sizeof(uid)),
1022                              &cache_value)) {
1023                 return false;
1024         }
1025 
1026         memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1027         SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1028         SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, NULL, 0));
1029 
1030         return true;
1031 }
1032 
1033 /*****************************************************************
1034   Find a uid given a SID.
1035 *****************************************************************/
1036 
1037 static bool fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
     /* [<][>][^][v][top][bottom][index][help] */
1038 {
1039         DATA_BLOB cache_value;
1040 
1041         if (!memcache_lookup(NULL, SID_UID_CACHE,
1042                              data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1043                              &cache_value)) {
1044                 return false;
1045         }
1046 
1047         SMB_ASSERT(cache_value.length == sizeof(*puid));
1048         memcpy(puid, cache_value.data, sizeof(*puid));
1049 
1050         return true;
1051 }
1052 
1053 /*****************************************************************
1054  Store uid to SID mapping in cache.
1055 *****************************************************************/
1056 
1057 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
1058 {
1059         memcache_add(NULL, SID_UID_CACHE,
1060                      data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1061                      data_blob_const(&uid, sizeof(uid)));
1062         memcache_add(NULL, UID_SID_CACHE,
1063                      data_blob_const(&uid, sizeof(uid)),
1064                      data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)));
1065 }
1066 
1067 /*****************************************************************
1068   Find a SID given a gid.
1069 *****************************************************************/
1070 
1071 static bool fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
     /* [<][>][^][v][top][bottom][index][help] */
1072 {
1073         DATA_BLOB cache_value;
1074 
1075         if (!memcache_lookup(NULL, GID_SID_CACHE,
1076                              data_blob_const(&gid, sizeof(gid)),
1077                              &cache_value)) {
1078                 return false;
1079         }
1080 
1081         memcpy(psid, cache_value.data, MIN(sizeof(*psid), cache_value.length));
1082         SMB_ASSERT(cache_value.length >= offsetof(struct dom_sid, id_auth));
1083         SMB_ASSERT(cache_value.length == ndr_size_dom_sid(psid, NULL, 0));
1084 
1085         return true;
1086 }
1087 
1088 /*****************************************************************
1089   Find a gid given a SID.
1090 *****************************************************************/
1091 
1092 static bool fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
     /* [<][>][^][v][top][bottom][index][help] */
1093 {
1094         DATA_BLOB cache_value;
1095 
1096         if (!memcache_lookup(NULL, SID_GID_CACHE,
1097                              data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1098                              &cache_value)) {
1099                 return false;
1100         }
1101 
1102         SMB_ASSERT(cache_value.length == sizeof(*pgid));
1103         memcpy(pgid, cache_value.data, sizeof(*pgid));
1104 
1105         return true;
1106 }
1107 
1108 /*****************************************************************
1109  Store gid to SID mapping in cache.
1110 *****************************************************************/
1111 
1112 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
     /* [<][>][^][v][top][bottom][index][help] */
1113 {
1114         memcache_add(NULL, SID_GID_CACHE,
1115                      data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)),
1116                      data_blob_const(&gid, sizeof(gid)));
1117         memcache_add(NULL, GID_SID_CACHE,
1118                      data_blob_const(&gid, sizeof(gid)),
1119                      data_blob_const(psid, ndr_size_dom_sid(psid, NULL, 0)));
1120 }
1121 
1122 /*****************************************************************
1123  *THE LEGACY* convert uid_t to SID function.
1124 *****************************************************************/  
1125 
1126 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
1127 {
1128         uint32 rid;
1129         bool ret;
1130 
1131         ZERO_STRUCTP(psid);
1132 
1133         become_root();
1134         ret = pdb_uid_to_rid(uid, &rid);
1135         unbecome_root();
1136 
1137         if (ret) {
1138                 /* This is a mapped user */
1139                 sid_copy(psid, get_global_sam_sid());
1140                 sid_append_rid(psid, rid);
1141                 goto done;
1142         }
1143 
1144         /* This is an unmapped user */
1145 
1146         uid_to_unix_users_sid(uid, psid);
1147 
1148  done:
1149         DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1150                   sid_string_dbg(psid)));
1151 
1152         store_uid_sid_cache(psid, uid);
1153         return;
1154 }
1155 
1156 /*****************************************************************
1157  *THE LEGACY* convert gid_t to SID function.
1158 *****************************************************************/  
1159 
1160 static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
     /* [<][>][^][v][top][bottom][index][help] */
1161 {
1162         bool ret;
1163 
1164         ZERO_STRUCTP(psid);
1165 
1166         become_root();
1167         ret = pdb_gid_to_sid(gid, psid);
1168         unbecome_root();
1169 
1170         if (ret) {
1171                 /* This is a mapped group */
1172                 goto done;
1173         }
1174         
1175         /* This is an unmapped group */
1176 
1177         gid_to_unix_groups_sid(gid, psid);
1178 
1179  done:
1180         DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1181                   sid_string_dbg(psid)));
1182 
1183         store_gid_sid_cache(psid, gid);
1184         return;
1185 }
1186 
1187 /*****************************************************************
1188  *THE LEGACY* convert SID to uid function.
1189 *****************************************************************/  
1190 
1191 static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
     /* [<][>][^][v][top][bottom][index][help] */
1192 {
1193         enum lsa_SidType type;
1194         uint32 rid;
1195 
1196         if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1197                 union unid_t id;
1198                 bool ret;
1199 
1200                 become_root();
1201                 ret = pdb_sid_to_id(psid, &id, &type);
1202                 unbecome_root();
1203 
1204                 if (ret) {
1205                         if (type != SID_NAME_USER) {
1206                                 DEBUG(5, ("sid %s is a %s, expected a user\n",
1207                                           sid_string_dbg(psid),
1208                                           sid_type_lookup(type)));
1209                                 return false;
1210                         }
1211                         *puid = id.uid;
1212                         goto done;
1213                 }
1214 
1215                 /* This was ours, but it was not mapped.  Fail */
1216         }
1217 
1218         DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1219                   sid_string_dbg(psid)));
1220         return false;
1221 
1222 done:
1223         DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1224                   (unsigned int)*puid ));
1225 
1226         store_uid_sid_cache(psid, *puid);
1227         return true;
1228 }
1229 
1230 /*****************************************************************
1231  *THE LEGACY* convert SID to gid function.
1232  Group mapping is used for gids that maps to Wellknown SIDs
1233 *****************************************************************/  
1234 
1235 static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
     /* [<][>][^][v][top][bottom][index][help] */
1236 {
1237         uint32 rid;
1238         GROUP_MAP map;
1239         union unid_t id;
1240         enum lsa_SidType type;
1241 
1242         if ((sid_check_is_in_builtin(psid) ||
1243              sid_check_is_in_wellknown_domain(psid))) {
1244                 bool ret;
1245 
1246                 become_root();
1247                 ret = pdb_getgrsid(&map, *psid);
1248                 unbecome_root();
1249 
1250                 if (ret) {
1251                         *pgid = map.gid;
1252                         goto done;
1253                 }
1254                 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1255                           sid_string_dbg(psid)));
1256                 return false;
1257         }
1258 
1259         if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
1260                 bool ret;
1261 
1262                 become_root();
1263                 ret = pdb_sid_to_id(psid, &id, &type);
1264                 unbecome_root();
1265 
1266                 if (ret) {
1267                         if ((type != SID_NAME_DOM_GRP) &&
1268                             (type != SID_NAME_ALIAS)) {
1269                                 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1270                                           "a group\n", sid_string_dbg(psid),
1271                                           sid_type_lookup(type)));
1272                                 return false;
1273                         }
1274                         *pgid = id.gid;
1275                         goto done;
1276                 }
1277         
1278                 /* This was ours, but it was not mapped.  Fail */
1279         }
1280 
1281         DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1282                   sid_string_dbg(psid)));
1283         return false;
1284         
1285  done:
1286         DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1287                   (unsigned int)*pgid ));
1288 
1289         store_gid_sid_cache(psid, *pgid);
1290 
1291         return true;
1292 }
1293 
1294 /*****************************************************************
1295  *THE CANONICAL* convert uid_t to SID function.
1296 *****************************************************************/  
1297 
1298 void uid_to_sid(DOM_SID *psid, uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
1299 {
1300         bool expired = true;
1301         bool ret;
1302         ZERO_STRUCTP(psid);
1303 
1304         if (fetch_sid_from_uid_cache(psid, uid))
1305                 return;
1306 
1307         /* Check the winbindd cache directly. */
1308         ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1309 
1310         if (ret && !expired && is_null_sid(psid)) {
1311                 /*
1312                  * Negative cache entry, we already asked.
1313                  * do legacy.
1314                  */
1315                 legacy_uid_to_sid(psid, uid);
1316                 return;
1317         }
1318 
1319         if (!ret || expired) {
1320                 /* Not in cache. Ask winbindd. */
1321                 if (!winbind_uid_to_sid(psid, uid)) {
1322                         /*
1323                          * We shouldn't return the NULL SID
1324                          * here if winbind was running and
1325                          * couldn't map, as winbind will have
1326                          * added a negative entry that will
1327                          * cause us to go though the
1328                          * legacy_uid_to_sid()
1329                          * function anyway in the case above
1330                          * the next time we ask.
1331                          */
1332                         DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1333                                   "for uid %u\n", (unsigned int)uid));
1334 
1335                         legacy_uid_to_sid(psid, uid);
1336                         return;
1337                 }
1338         }
1339 
1340         DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1341                   sid_string_dbg(psid)));
1342 
1343         store_uid_sid_cache(psid, uid);
1344         return;
1345 }
1346 
1347 /*****************************************************************
1348  *THE CANONICAL* convert gid_t to SID function.
1349 *****************************************************************/  
1350 
1351 void gid_to_sid(DOM_SID *psid, gid_t gid)
     /* [<][>][^][v][top][bottom][index][help] */
1352 {
1353         bool expired = true;
1354         bool ret;
1355         ZERO_STRUCTP(psid);
1356 
1357         if (fetch_sid_from_gid_cache(psid, gid))
1358                 return;
1359 
1360         /* Check the winbindd cache directly. */
1361         ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1362 
1363         if (ret && !expired && is_null_sid(psid)) {
1364                 /*
1365                  * Negative cache entry, we already asked.
1366                  * do legacy.
1367                  */
1368                 legacy_gid_to_sid(psid, gid);
1369                 return;
1370         }
1371 
1372         if (!ret || expired) {
1373                 /* Not in cache. Ask winbindd. */
1374                 if (!winbind_gid_to_sid(psid, gid)) {
1375                         /*
1376                          * We shouldn't return the NULL SID
1377                          * here if winbind was running and
1378                          * couldn't map, as winbind will have
1379                          * added a negative entry that will
1380                          * cause us to go though the
1381                          * legacy_gid_to_sid()
1382                          * function anyway in the case above
1383                          * the next time we ask.
1384                          */
1385                         DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1386                                   "for gid %u\n", (unsigned int)gid));
1387 
1388                         legacy_gid_to_sid(psid, gid);
1389                         return;
1390                 }
1391         }
1392 
1393         DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1394                   sid_string_dbg(psid)));
1395 
1396         store_gid_sid_cache(psid, gid);
1397         return;
1398 }
1399 
1400 /*****************************************************************
1401  *THE CANONICAL* convert SID to uid function.
1402 *****************************************************************/  
1403 
1404 bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
     /* [<][>][^][v][top][bottom][index][help] */
1405 {
1406         bool expired = true;
1407         bool ret;
1408         uint32 rid;
1409         gid_t gid;
1410 
1411         if (fetch_uid_from_cache(puid, psid))
1412                 return true;
1413 
1414         if (fetch_gid_from_cache(&gid, psid)) {
1415                 return false;
1416         }
1417 
1418         /* Optimize for the Unix Users Domain
1419          * as the conversion is straightforward */
1420         if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1421                 uid_t uid = rid;
1422                 *puid = uid;
1423 
1424                 /* return here, don't cache */
1425                 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1426                         (unsigned int)*puid ));
1427                 return true;
1428         }
1429 
1430         /* Check the winbindd cache directly. */
1431         ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1432 
1433         if (ret && !expired && (*puid == (uid_t)-1)) {
1434                 /*
1435                  * Negative cache entry, we already asked.
1436                  * do legacy.
1437                  */
1438                 return legacy_sid_to_uid(psid, puid);
1439         }
1440 
1441         if (!ret || expired) {
1442                 /* Not in cache. Ask winbindd. */
1443                 if (!winbind_sid_to_uid(puid, psid)) {
1444                         DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1445                                   sid_string_dbg(psid)));
1446                         /* winbind failed. do legacy */
1447                         return legacy_sid_to_uid(psid, puid);
1448                 }
1449         }
1450 
1451         /* TODO: Here would be the place to allocate both a gid and a uid for
1452          * the SID in question */
1453 
1454         DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1455                 (unsigned int)*puid ));
1456 
1457         store_uid_sid_cache(psid, *puid);
1458         return true;
1459 }
1460 
1461 /*****************************************************************
1462  *THE CANONICAL* convert SID to gid function.
1463  Group mapping is used for gids that maps to Wellknown SIDs
1464 *****************************************************************/  
1465 
1466 bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
     /* [<][>][^][v][top][bottom][index][help] */
1467 {
1468         bool expired = true;
1469         bool ret;
1470         uint32 rid;
1471         uid_t uid;
1472 
1473         if (fetch_gid_from_cache(pgid, psid))
1474                 return true;
1475 
1476         if (fetch_uid_from_cache(&uid, psid))
1477                 return false;
1478 
1479         /* Optimize for the Unix Groups Domain
1480          * as the conversion is straightforward */
1481         if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1482                 gid_t gid = rid;
1483                 *pgid = gid;
1484 
1485                 /* return here, don't cache */
1486                 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1487                         (unsigned int)*pgid ));
1488                 return true;
1489         }
1490 
1491         /* Check the winbindd cache directly. */
1492         ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1493 
1494         if (ret && !expired && (*pgid == (gid_t)-1)) {
1495                 /*
1496                  * Negative cache entry, we already asked.
1497                  * do legacy.
1498                  */
1499                 return legacy_sid_to_gid(psid, pgid);
1500         }
1501 
1502         if (!ret || expired) {
1503                 /* Not in cache or negative. Ask winbindd. */
1504                 /* Ask winbindd if it can map this sid to a gid.
1505                  * (Idmap will check it is a valid SID and of the right type) */
1506 
1507                 if ( !winbind_sid_to_gid(pgid, psid) ) {
1508 
1509                         DEBUG(10,("winbind failed to find a gid for sid %s\n",
1510                                   sid_string_dbg(psid)));
1511                         /* winbind failed. do legacy */
1512                         return legacy_sid_to_gid(psid, pgid);
1513                 }
1514         }
1515 
1516         DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1517                   (unsigned int)*pgid ));
1518 
1519         store_gid_sid_cache(psid, *pgid);
1520         return true;
1521 }

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