passdb/lookup_sid.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    uid/user handling
00004    Copyright (C) Andrew Tridgell         1992-1998
00005    Copyright (C) Gerald (Jerry) Carter   2003
00006    Copyright (C) Volker Lendecke         2005
00007    
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012    
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017    
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021 */
00022 
00023 #include "includes.h"
00024 
00025 /*****************************************************************
00026  Dissect a user-provided name into domain, name, sid and type.
00027 
00028  If an explicit domain name was given in the form domain\user, it
00029  has to try that. If no explicit domain name was given, we have
00030  to do guesswork.
00031 *****************************************************************/  
00032 
00033 BOOL lookup_name(TALLOC_CTX *mem_ctx,
00034                  const char *full_name, int flags,
00035                  const char **ret_domain, const char **ret_name,
00036                  DOM_SID *ret_sid, enum lsa_SidType *ret_type)
00037 {
00038         char *p;
00039         const char *tmp;
00040         const char *domain = NULL;
00041         const char *name = NULL;
00042         uint32 rid;
00043         DOM_SID sid;
00044         enum lsa_SidType type;
00045         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
00046 
00047         if (tmp_ctx == NULL) {
00048                 DEBUG(0, ("talloc_new failed\n"));
00049                 return False;
00050         }
00051 
00052         p = strchr_m(full_name, '\\');
00053 
00054         if (p != NULL) {
00055                 domain = talloc_strndup(tmp_ctx, full_name,
00056                                         PTR_DIFF(p, full_name));
00057                 name = talloc_strdup(tmp_ctx, p+1);
00058         } else {
00059                 domain = talloc_strdup(tmp_ctx, "");
00060                 name = talloc_strdup(tmp_ctx, full_name);
00061         }
00062 
00063         if ((domain == NULL) || (name == NULL)) {
00064                 DEBUG(0, ("talloc failed\n"));
00065                 TALLOC_FREE(tmp_ctx);
00066                 return False;
00067         }
00068 
00069         DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
00070                 full_name, domain, name));
00071         DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
00072 
00073         if ((flags & LOOKUP_NAME_DOMAIN) &&
00074             strequal(domain, get_global_sam_name()))
00075         {
00076 
00077                 /* It's our own domain, lookup the name in passdb */
00078                 if (lookup_global_sam_name(name, flags, &rid, &type)) {
00079                         sid_copy(&sid, get_global_sam_sid());
00080                         sid_append_rid(&sid, rid);
00081                         goto ok;
00082                 }
00083                 TALLOC_FREE(tmp_ctx);
00084                 return False;
00085         }
00086 
00087         if ((flags & LOOKUP_NAME_BUILTIN) &&
00088             strequal(domain, builtin_domain_name()))
00089         {
00090                 /* Explicit request for a name in BUILTIN */
00091                 if (lookup_builtin_name(name, &rid)) {
00092                         sid_copy(&sid, &global_sid_Builtin);
00093                         sid_append_rid(&sid, rid);
00094                         type = SID_NAME_ALIAS;
00095                         goto ok;
00096                 }
00097                 TALLOC_FREE(tmp_ctx);
00098                 return False;
00099         }
00100 
00101         /* Try the explicit winbind lookup first, don't let it guess the
00102          * domain yet at this point yet. This comes later. */
00103 
00104         if ((domain[0] != '\0') &&
00105             (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
00106             (winbind_lookup_name(domain, name, &sid, &type))) {
00107                         goto ok;
00108         }
00109 
00110         if (strequal(domain, unix_users_domain_name())) {
00111                 if (lookup_unix_user_name(name, &sid)) {
00112                         type = SID_NAME_USER;
00113                         goto ok;
00114                 }
00115                 TALLOC_FREE(tmp_ctx);
00116                 return False;
00117         }
00118 
00119         if (strequal(domain, unix_groups_domain_name())) {
00120                 if (lookup_unix_group_name(name, &sid)) {
00121                         type = SID_NAME_DOM_GRP;
00122                         goto ok;
00123                 }
00124                 TALLOC_FREE(tmp_ctx);
00125                 return False;
00126         }
00127 
00128         if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
00129                 TALLOC_FREE(tmp_ctx);
00130                 return False;
00131         }
00132 
00133         /* Now the guesswork begins, we haven't been given an explicit
00134          * domain. Try the sequence as documented on
00135          * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
00136          * November 27, 2005 */
00137 
00138         /* 1. well-known names */
00139 
00140         if ((flags & LOOKUP_NAME_WKN) &&
00141             lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
00142         {
00143                 type = SID_NAME_WKN_GRP;
00144                 goto ok;
00145         }
00146 
00147         /* 2. Builtin domain as such */
00148 
00149         if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
00150             strequal(name, builtin_domain_name()))
00151         {
00152                 /* Swap domain and name */
00153                 tmp = name; name = domain; domain = tmp;
00154                 sid_copy(&sid, &global_sid_Builtin);
00155                 type = SID_NAME_DOMAIN;
00156                 goto ok;
00157         }
00158 
00159         /* 3. Account domain */
00160 
00161         if ((flags & LOOKUP_NAME_DOMAIN) &&
00162             strequal(name, get_global_sam_name()))
00163         {
00164                 if (!secrets_fetch_domain_sid(name, &sid)) {
00165                         DEBUG(3, ("Could not fetch my SID\n"));
00166                         TALLOC_FREE(tmp_ctx);
00167                         return False;
00168                 }
00169                 /* Swap domain and name */
00170                 tmp = name; name = domain; domain = tmp;
00171                 type = SID_NAME_DOMAIN;
00172                 goto ok;
00173         }
00174 
00175         /* 4. Primary domain */
00176 
00177         if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
00178             strequal(name, lp_workgroup()))
00179         {
00180                 if (!secrets_fetch_domain_sid(name, &sid)) {
00181                         DEBUG(3, ("Could not fetch the domain SID\n"));
00182                         TALLOC_FREE(tmp_ctx);
00183                         return False;
00184                 }
00185                 /* Swap domain and name */
00186                 tmp = name; name = domain; domain = tmp;
00187                 type = SID_NAME_DOMAIN;
00188                 goto ok;
00189         }
00190 
00191         /* 5. Trusted domains as such, to me it looks as if members don't do
00192               this, tested an XP workstation in a NT domain -- vl */
00193 
00194         if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
00195             (secrets_fetch_trusted_domain_password(name, NULL, &sid, NULL)))
00196         {
00197                 /* Swap domain and name */
00198                 tmp = name; name = domain; domain = tmp;
00199                 type = SID_NAME_DOMAIN;
00200                 goto ok;
00201         }
00202 
00203         /* 6. Builtin aliases */        
00204 
00205         if ((flags & LOOKUP_NAME_BUILTIN) &&
00206             lookup_builtin_name(name, &rid))
00207         {
00208                 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
00209                 sid_copy(&sid, &global_sid_Builtin);
00210                 sid_append_rid(&sid, rid);
00211                 type = SID_NAME_ALIAS;
00212                 goto ok;
00213         }
00214 
00215         /* 7. Local systems' SAM (DCs don't have a local SAM) */
00216         /* 8. Primary SAM (On members, this is the domain) */
00217 
00218         /* Both cases are done by looking at our passdb */
00219 
00220         if ((flags & LOOKUP_NAME_DOMAIN) &&
00221             lookup_global_sam_name(name, flags, &rid, &type))
00222         {
00223                 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
00224                 sid_copy(&sid, get_global_sam_sid());
00225                 sid_append_rid(&sid, rid);
00226                 goto ok;
00227         }
00228 
00229         /* Now our local possibilities are exhausted. */
00230 
00231         if (!(flags & LOOKUP_NAME_REMOTE)) {
00232                 TALLOC_FREE(tmp_ctx);
00233                 return False;
00234         }
00235 
00236         /* If we are not a DC, we have to ask in our primary domain. Let
00237          * winbind do that. */
00238 
00239         if (!IS_DC &&
00240             (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
00241                 domain = talloc_strdup(tmp_ctx, lp_workgroup());
00242                 goto ok;
00243         }
00244 
00245         /* 9. Trusted domains */
00246 
00247         /* If we're a DC we have to ask all trusted DC's. Winbind does not do
00248          * that (yet), but give it a chance. */
00249 
00250         if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
00251                 DOM_SID dom_sid;
00252                 uint32 tmp_rid;
00253                 enum lsa_SidType domain_type;
00254                 
00255                 if (type == SID_NAME_DOMAIN) {
00256                         /* Swap name and type */
00257                         tmp = name; name = domain; domain = tmp;
00258                         goto ok;
00259                 }
00260 
00261                 /* Here we have to cope with a little deficiency in the
00262                  * winbind API: We have to ask it again for the name of the
00263                  * domain it figured out itself. Maybe fix that later... */
00264 
00265                 sid_copy(&dom_sid, &sid);
00266                 sid_split_rid(&dom_sid, &tmp_rid);
00267 
00268                 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
00269                                         &domain_type) ||
00270                     (domain_type != SID_NAME_DOMAIN)) {
00271                         DEBUG(2, ("winbind could not find the domain's name "
00272                                   "it just looked up for us\n"));
00273                         TALLOC_FREE(tmp_ctx);
00274                         return False;
00275                 }
00276                 goto ok;
00277         }
00278 
00279         /* 10. Don't translate */
00280 
00281         /* 11. Ok, windows would end here. Samba has two more options:
00282                Unmapped users and unmapped groups */
00283 
00284         if (lookup_unix_user_name(name, &sid)) {
00285                 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
00286                 type = SID_NAME_USER;
00287                 goto ok;
00288         }
00289 
00290         if (lookup_unix_group_name(name, &sid)) {
00291                 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
00292                 type = SID_NAME_DOM_GRP;
00293                 goto ok;
00294         }
00295 
00296         /*
00297          * Ok, all possibilities tried. Fail.
00298          */
00299 
00300         TALLOC_FREE(tmp_ctx);
00301         return False;
00302 
00303  ok:
00304         if ((domain == NULL) || (name == NULL)) {
00305                 DEBUG(0, ("talloc failed\n"));
00306                 TALLOC_FREE(tmp_ctx);
00307                 return False;
00308         }
00309 
00310         /*
00311          * Hand over the results to the talloc context we've been given.
00312          */
00313 
00314         if ((ret_name != NULL) &&
00315             !(*ret_name = talloc_strdup(mem_ctx, name))) {
00316                 DEBUG(0, ("talloc failed\n"));
00317                 TALLOC_FREE(tmp_ctx);
00318                 return False;
00319         }
00320 
00321         if (ret_domain != NULL) {
00322                 char *tmp_dom;
00323                 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
00324                         DEBUG(0, ("talloc failed\n"));
00325                         TALLOC_FREE(tmp_ctx);
00326                         return False;
00327                 }
00328                 strupper_m(tmp_dom);
00329                 *ret_domain = tmp_dom;
00330         }
00331 
00332         if (ret_sid != NULL) {
00333                 sid_copy(ret_sid, &sid);
00334         }
00335 
00336         if (ret_type != NULL) {
00337                 *ret_type = type;
00338         }
00339 
00340         TALLOC_FREE(tmp_ctx);
00341         return True;
00342 }
00343 
00344 /************************************************************************
00345  Names from smb.conf can be unqualified. eg. valid users = foo
00346  These names should never map to a remote name. Try global_sam_name()\foo,
00347  and then "Unix Users"\foo (or "Unix Groups"\foo).
00348 ************************************************************************/
00349 
00350 BOOL lookup_name_smbconf(TALLOC_CTX *mem_ctx,
00351                  const char *full_name, int flags,
00352                  const char **ret_domain, const char **ret_name,
00353                  DOM_SID *ret_sid, enum lsa_SidType *ret_type)
00354 {
00355         char *qualified_name;
00356         const char *p;
00357 
00358         /* NB. No winbindd_separator here as lookup_name needs \\' */
00359         if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
00360 
00361                 /* The name is already qualified with a domain. */
00362 
00363                 if (*lp_winbind_separator() != '\\') {
00364                         char *tmp;
00365 
00366                         /* lookup_name() needs '\\' as a separator */
00367 
00368                         tmp = talloc_strdup(mem_ctx, full_name);
00369                         if (!tmp) {
00370                                 return False;
00371                         }
00372                         tmp[p - full_name] = '\\';
00373                         full_name = tmp;
00374                 }
00375 
00376                 return lookup_name(mem_ctx, full_name, flags,
00377                                 ret_domain, ret_name,
00378                                 ret_sid, ret_type);
00379         }
00380 
00381         /* Try with our own SAM name. */
00382         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
00383                                 get_global_sam_name(),
00384                                 full_name );
00385         if (!qualified_name) {
00386                 return False;
00387         }
00388 
00389         if (lookup_name(mem_ctx, qualified_name, flags,
00390                                 ret_domain, ret_name,
00391                                 ret_sid, ret_type)) {
00392                 return True;
00393         }
00394         
00395         /* Finally try with "Unix Users" or "Unix Group" */
00396         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
00397                                 flags & LOOKUP_NAME_GROUP ?
00398                                         unix_groups_domain_name() :
00399                                         unix_users_domain_name(),
00400                                 full_name );
00401         if (!qualified_name) {
00402                 return False;
00403         }
00404 
00405         return lookup_name(mem_ctx, qualified_name, flags,
00406                                 ret_domain, ret_name,
00407                                 ret_sid, ret_type);
00408 }
00409 
00410 static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx,
00411                            const DOM_SID *domain_sid,
00412                            int num_rids, uint32 *rids,
00413                            const char **domain_name,
00414                            const char **names, enum lsa_SidType *types)
00415 {
00416         int i;
00417         const char **my_names;
00418         enum lsa_SidType *my_types;
00419         TALLOC_CTX *tmp_ctx;
00420 
00421         if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
00422                 return False;
00423         }
00424 
00425         if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
00426                                  domain_name, &my_names, &my_types)) {
00427                 *domain_name = "";
00428                 for (i=0; i<num_rids; i++) {
00429                         names[i] = "";
00430                         types[i] = SID_NAME_UNKNOWN;
00431                 }
00432                 TALLOC_FREE(tmp_ctx);
00433                 return True;
00434         }
00435 
00436         if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
00437                 TALLOC_FREE(tmp_ctx);
00438                 return False;
00439         }
00440 
00441         /*
00442          * winbind_lookup_rids allocates its own array. We've been given the
00443          * array, so copy it over
00444          */
00445 
00446         for (i=0; i<num_rids; i++) {
00447                 if (my_names[i] == NULL) {
00448                         TALLOC_FREE(tmp_ctx);
00449                         return False;
00450                 }
00451                 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
00452                         TALLOC_FREE(tmp_ctx);
00453                         return False;
00454                 }
00455                 types[i] = my_types[i];
00456         }
00457         TALLOC_FREE(tmp_ctx);
00458         return True;
00459 }
00460 
00461 static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
00462                         int num_rids, uint32_t *rids,
00463                         const char **domain_name,
00464                         const char ***names, enum lsa_SidType **types)
00465 {
00466         int i;
00467 
00468         if (num_rids) {
00469                 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
00470                 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
00471 
00472                 if ((*names == NULL) || (*types == NULL)) {
00473                         return False;
00474                 }
00475         } else {
00476                 *names = NULL;
00477                 *types = NULL;
00478         }
00479 
00480         if (sid_check_is_domain(domain_sid)) {
00481                 NTSTATUS result;
00482 
00483                 if (*domain_name == NULL) {
00484                         *domain_name = talloc_strdup(
00485                                 mem_ctx, get_global_sam_name());
00486                 }
00487 
00488                 if (*domain_name == NULL) {
00489                         return False;
00490                 }
00491 
00492                 become_root();
00493                 result = pdb_lookup_rids(domain_sid, num_rids, rids,
00494                                          *names, *types);
00495                 unbecome_root();
00496 
00497                 return (NT_STATUS_IS_OK(result) ||
00498                         NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
00499                         NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
00500         }
00501 
00502         if (sid_check_is_builtin(domain_sid)) {
00503 
00504                 if (*domain_name == NULL) {
00505                         *domain_name = talloc_strdup(
00506                                 mem_ctx, builtin_domain_name());
00507                 }
00508 
00509                 if (*domain_name == NULL) {
00510                         return False;
00511                 }
00512 
00513                 for (i=0; i<num_rids; i++) {
00514                         if (lookup_builtin_rid(*names, rids[i],
00515                                                &(*names)[i])) {
00516                                 if ((*names)[i] == NULL) {
00517                                         return False;
00518                                 }
00519                                 (*types)[i] = SID_NAME_ALIAS;
00520                         } else {
00521                                 (*types)[i] = SID_NAME_UNKNOWN;
00522                         }
00523                 }
00524                 return True;
00525         }
00526 
00527         if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
00528                 for (i=0; i<num_rids; i++) {
00529                         DOM_SID sid;
00530                         sid_copy(&sid, domain_sid);
00531                         sid_append_rid(&sid, rids[i]);
00532                         if (lookup_wellknown_sid(mem_ctx, &sid,
00533                                                  domain_name, &(*names)[i])) {
00534                                 if ((*names)[i] == NULL) {
00535                                         return False;
00536                                 }
00537                                 (*types)[i] = SID_NAME_WKN_GRP;
00538                         } else {
00539                                 (*types)[i] = SID_NAME_UNKNOWN;
00540                         }
00541                 }
00542                 return True;
00543         }
00544 
00545         if (sid_check_is_unix_users(domain_sid)) {
00546                 if (*domain_name == NULL) {
00547                         *domain_name = talloc_strdup(
00548                                 mem_ctx, unix_users_domain_name());
00549                 }
00550                 for (i=0; i<num_rids; i++) {
00551                         (*names)[i] = talloc_strdup(
00552                                 (*names), uidtoname(rids[i]));
00553                         (*types)[i] = SID_NAME_USER;
00554                 }
00555                 return True;
00556         }
00557 
00558         if (sid_check_is_unix_groups(domain_sid)) {
00559                 if (*domain_name == NULL) {
00560                         *domain_name = talloc_strdup(
00561                                 mem_ctx, unix_groups_domain_name());
00562                 }
00563                 for (i=0; i<num_rids; i++) {
00564                         (*names)[i] = talloc_strdup(
00565                                 (*names), gidtoname(rids[i]));
00566                         (*types)[i] = SID_NAME_DOM_GRP;
00567                 }
00568                 return True;
00569         }
00570 
00571         return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
00572                               domain_name, *names, *types);
00573 }
00574 
00575 /*
00576  * Is the SID a domain as such? If yes, lookup its name.
00577  */
00578 
00579 static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
00580                              const char **name)
00581 {
00582         const char *tmp;
00583         enum lsa_SidType type;
00584 
00585         if (sid_check_is_domain(sid)) {
00586                 *name = talloc_strdup(mem_ctx, get_global_sam_name());
00587                 return True;
00588         }
00589 
00590         if (sid_check_is_builtin(sid)) {
00591                 *name = talloc_strdup(mem_ctx, builtin_domain_name());
00592                 return True;
00593         }
00594 
00595         if (sid_check_is_wellknown_domain(sid, &tmp)) {
00596                 *name = talloc_strdup(mem_ctx, tmp);
00597                 return True;
00598         }
00599 
00600         if (sid->num_auths != 4) {
00601                 /* This can't be a domain */
00602                 return False;
00603         }
00604 
00605         if (IS_DC) {
00606                 uint32 i, num_domains;
00607                 struct trustdom_info **domains;
00608 
00609                 /* This is relatively expensive, but it happens only on DCs
00610                  * and for SIDs that have 4 sub-authorities and thus look like
00611                  * domains */
00612 
00613                 if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
00614                                                              &num_domains,
00615                                                              &domains))) {
00616                         return False;
00617                 }
00618 
00619                 for (i=0; i<num_domains; i++) {
00620                         if (sid_equal(sid, &domains[i]->sid)) {
00621                                 *name = talloc_strdup(mem_ctx,
00622                                                       domains[i]->name);
00623                                 return True;
00624                         }
00625                 }
00626                 return False;
00627         }
00628 
00629         if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
00630             (type == SID_NAME_DOMAIN)) {
00631                 *name = tmp;
00632                 return True;
00633         }
00634 
00635         return False;
00636 }
00637 
00638 /*
00639  * This tries to implement the rather weird rules for the lsa_lookup level
00640  * parameter.
00641  *
00642  * This is as close as we can get to what W2k3 does. With this we survive the
00643  * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
00644  * different, but I assume that's just being too liberal. For example, W2k3
00645  * replies to everything else but the levels 1-6 with INVALID_PARAMETER
00646  * whereas NT4 does the same as level 1 (I think). I did not fully test that
00647  * with NT4, this is what w2k3 does.
00648  *
00649  * Level 1: Ask everywhere
00650  * Level 2: Ask domain and trusted domains, no builtin and wkn
00651  * Level 3: Only ask domain
00652  * Level 4: W2k3ad: Only ask AD trusts
00653  * Level 5: Don't lookup anything
00654  * Level 6: Like 4
00655  */
00656 
00657 static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
00658 {
00659         int ret = False;
00660 
00661         switch(level) {
00662         case 1:
00663                 ret = True;
00664                 break;
00665         case 2:
00666                 ret = (!sid_check_is_builtin(sid) &&
00667                        !sid_check_is_wellknown_domain(sid, NULL));
00668                 break;
00669         case 3:
00670         case 4:
00671         case 6:
00672                 ret = sid_check_is_domain(sid);
00673                 break;
00674         case 5:
00675                 ret = False;
00676                 break;
00677         }
00678 
00679         DEBUG(10, ("%s SID %s in level %d\n",
00680                    ret ? "Accepting" : "Rejecting",
00681                    sid_string_static(sid), level));
00682         return ret;
00683 }
00684 
00685 /*
00686  * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
00687  * references to domains, it is explicitly made for this.
00688  *
00689  * This attempts to be as efficient as possible: It collects all SIDs
00690  * belonging to a domain and hands them in bulk to the appropriate lookup
00691  * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
00692  * *hugely* from this. Winbind is going to be extended with a lookup_rids
00693  * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
00694  * appropriate DC.
00695  */
00696 
00697 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
00698                      const DOM_SID **sids, int level,
00699                      struct lsa_dom_info **ret_domains,
00700                      struct lsa_name_info **ret_names)
00701 {
00702         TALLOC_CTX *tmp_ctx;
00703         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00704         struct lsa_name_info *name_infos;
00705         struct lsa_dom_info *dom_infos = NULL;
00706 
00707         int i, j;
00708 
00709         if (!(tmp_ctx = talloc_new(mem_ctx))) {
00710                 DEBUG(0, ("talloc_new failed\n"));
00711                 return NT_STATUS_NO_MEMORY;
00712         }
00713 
00714         if (num_sids) {
00715                 name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
00716                 if (name_infos == NULL) {
00717                         result = NT_STATUS_NO_MEMORY;
00718                         goto fail;
00719                 }
00720         } else {
00721                 name_infos = NULL;
00722         }
00723 
00724         dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
00725                                       MAX_REF_DOMAINS);
00726         if (dom_infos == NULL) {
00727                 result = NT_STATUS_NO_MEMORY;
00728                 goto fail;
00729         }
00730 
00731         /* First build up the data structures:
00732          * 
00733          * dom_infos is a list of domains referenced in the list of
00734          * SIDs. Later we will walk the list of domains and look up the RIDs
00735          * in bulk.
00736          *
00737          * name_infos is a shadow-copy of the SIDs array to collect the real
00738          * data.
00739          *
00740          * dom_info->idxs is an index into the name_infos array. The
00741          * difficulty we have here is that we need to keep the SIDs the client
00742          * asked for in the same order for the reply
00743          */
00744 
00745         for (i=0; i<num_sids; i++) {
00746                 DOM_SID sid;
00747                 uint32 rid;
00748                 const char *domain_name = NULL;
00749 
00750                 sid_copy(&sid, sids[i]);
00751                 name_infos[i].type = SID_NAME_USE_NONE;
00752 
00753                 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
00754                         /* We can't push that through the normal lookup
00755                          * process, as this would reference illegal
00756                          * domains.
00757                          *
00758                          * For example S-1-5-32 would end up referencing
00759                          * domain S-1-5- with RID 32 which is clearly wrong.
00760                          */
00761                         if (domain_name == NULL) {
00762                                 result = NT_STATUS_NO_MEMORY;
00763                                 goto fail;
00764                         }
00765                                 
00766                         name_infos[i].rid = 0;
00767                         name_infos[i].type = SID_NAME_DOMAIN;
00768                         name_infos[i].name = NULL;
00769 
00770                         if (sid_check_is_builtin(&sid)) {
00771                                 /* Yes, W2k3 returns "BUILTIN" both as domain
00772                                  * and name here */
00773                                 name_infos[i].name = talloc_strdup(
00774                                         name_infos, builtin_domain_name());
00775                                 if (name_infos[i].name == NULL) {
00776                                         result = NT_STATUS_NO_MEMORY;
00777                                         goto fail;
00778                                 }
00779                         }
00780                 } else {
00781                         /* This is a normal SID with rid component */
00782                         if (!sid_split_rid(&sid, &rid)) {
00783                                 result = NT_STATUS_INVALID_PARAMETER;
00784                                 goto fail;
00785                         }
00786                 }
00787 
00788                 if (!check_dom_sid_to_level(&sid, level)) {
00789                         name_infos[i].rid = 0;
00790                         name_infos[i].type = SID_NAME_UNKNOWN;
00791                         name_infos[i].name = NULL;
00792                         continue;
00793                 }
00794 
00795                 for (j=0; j<MAX_REF_DOMAINS; j++) {
00796                         if (!dom_infos[j].valid) {
00797                                 break;
00798                         }
00799                         if (sid_equal(&sid, &dom_infos[j].sid)) {
00800                                 break;
00801                         }
00802                 }
00803 
00804                 if (j == MAX_REF_DOMAINS) {
00805                         /* TODO: What's the right error message here? */
00806                         result = NT_STATUS_NONE_MAPPED;
00807                         goto fail;
00808                 }
00809 
00810                 if (!dom_infos[j].valid) {
00811                         /* We found a domain not yet referenced, create a new
00812                          * ref. */
00813                         dom_infos[j].valid = True;
00814                         sid_copy(&dom_infos[j].sid, &sid);
00815 
00816                         if (domain_name != NULL) {
00817                                 /* This name was being found above in the case
00818                                  * when we found a domain SID */
00819                                 dom_infos[j].name =
00820                                         talloc_strdup(dom_infos, domain_name);
00821                                 if (dom_infos[j].name == NULL) {
00822                                         result = NT_STATUS_NO_MEMORY;
00823                                         goto fail;
00824                                 }
00825                         } else {
00826                                 /* lookup_rids will take care of this */
00827                                 dom_infos[j].name = NULL;
00828                         }
00829                 }
00830 
00831                 name_infos[i].dom_idx = j;
00832 
00833                 if (name_infos[i].type == SID_NAME_USE_NONE) {
00834                         name_infos[i].rid = rid;
00835 
00836                         ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
00837                                      &dom_infos[j].num_idxs);
00838 
00839                         if (dom_infos[j].idxs == NULL) {
00840                                 result = NT_STATUS_NO_MEMORY;
00841                                 goto fail;
00842                         }
00843                 }
00844         }
00845 
00846         /* Iterate over the domains found */
00847 
00848         for (i=0; i<MAX_REF_DOMAINS; i++) {
00849                 uint32_t *rids;
00850                 const char *domain_name = NULL;
00851                 const char **names;
00852                 enum lsa_SidType *types;
00853                 struct lsa_dom_info *dom = &dom_infos[i];
00854 
00855                 if (!dom->valid) {
00856                         /* No domains left, we're done */
00857                         break;
00858                 }
00859 
00860                 if (dom->num_idxs) {
00861                         if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
00862                                 result = NT_STATUS_NO_MEMORY;
00863                                 goto fail;
00864                         }
00865                 } else {
00866                         rids = NULL;
00867                 }
00868 
00869                 for (j=0; j<dom->num_idxs; j++) {
00870                         rids[j] = name_infos[dom->idxs[j]].rid;
00871                 }
00872 
00873                 if (!lookup_rids(tmp_ctx, &dom->sid,
00874                                  dom->num_idxs, rids, &domain_name,
00875                                  &names, &types)) {
00876                         result = NT_STATUS_NO_MEMORY;
00877                         goto fail;
00878                 }
00879 
00880                 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
00881                         result = NT_STATUS_NO_MEMORY;
00882                         goto fail;
00883                 }
00884                         
00885                 for (j=0; j<dom->num_idxs; j++) {
00886                         int idx = dom->idxs[j];
00887                         name_infos[idx].type = types[j];
00888                         if (types[j] != SID_NAME_UNKNOWN) {
00889                                 name_infos[idx].name =
00890                                         talloc_strdup(name_infos, names[j]);
00891                                 if (name_infos[idx].name == NULL) {
00892                                         result = NT_STATUS_NO_MEMORY;
00893                                         goto fail;
00894                                 }
00895                         } else {
00896                                 name_infos[idx].name = NULL;
00897                         }
00898                 }
00899         }
00900 
00901         *ret_domains = dom_infos;
00902         *ret_names = name_infos;
00903         return NT_STATUS_OK;
00904 
00905  fail:
00906         TALLOC_FREE(dom_infos);
00907         TALLOC_FREE(name_infos);
00908         TALLOC_FREE(tmp_ctx);
00909         return result;
00910 }
00911 
00912 /*****************************************************************
00913  *THE CANONICAL* convert SID to name function.
00914 *****************************************************************/  
00915 
00916 BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
00917                 const char **ret_domain, const char **ret_name,
00918                 enum lsa_SidType *ret_type)
00919 {
00920         struct lsa_dom_info *domain;
00921         struct lsa_name_info *name;
00922         TALLOC_CTX *tmp_ctx;
00923         BOOL ret = False;
00924 
00925         if (!(tmp_ctx = talloc_new(mem_ctx))) {
00926                 DEBUG(0, ("talloc_new failed\n"));
00927                 return False;
00928         }
00929 
00930         if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
00931                                          &domain, &name))) {
00932                 goto done;
00933         }
00934 
00935         if (name->type == SID_NAME_UNKNOWN) {
00936                 goto done;
00937         }
00938 
00939         if ((ret_domain != NULL) &&
00940             !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
00941                 goto done;
00942         }
00943 
00944         if ((ret_name != NULL) && 
00945             !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
00946                 goto done;
00947         }
00948 
00949         if (ret_type != NULL) {
00950                 *ret_type = name->type;
00951         }
00952 
00953         ret = True;
00954 
00955  done:
00956         if (ret) {
00957                 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
00958                            sid_string_static(sid), domain->name,
00959                            name->name, name->type));
00960         } else {
00961                 DEBUG(10, ("failed to lookup sid %s\n",
00962                            sid_string_static(sid)));
00963         }
00964         TALLOC_FREE(tmp_ctx);
00965         return ret;
00966 }
00967 
00968 /*****************************************************************
00969  Id mapping cache.  This is to avoid Winbind mappings already
00970  seen by smbd to be queried too frequently, keeping winbindd
00971  busy, and blocking smbd while winbindd is busy with other
00972  stuff. Written by Michael Steffens <michael.steffens@hp.com>,
00973  modified to use linked lists by jra.
00974 *****************************************************************/  
00975 
00976 #define MAX_UID_SID_CACHE_SIZE 100
00977 #define TURNOVER_UID_SID_CACHE_SIZE 10
00978 #define MAX_GID_SID_CACHE_SIZE 100
00979 #define TURNOVER_GID_SID_CACHE_SIZE 10
00980 
00981 static size_t n_uid_sid_cache = 0;
00982 static size_t n_gid_sid_cache = 0;
00983 
00984 static struct uid_sid_cache {
00985         struct uid_sid_cache *next, *prev;
00986         uid_t uid;
00987         DOM_SID sid;
00988         enum lsa_SidType sidtype;
00989 } *uid_sid_cache_head;
00990 
00991 static struct gid_sid_cache {
00992         struct gid_sid_cache *next, *prev;
00993         gid_t gid;
00994         DOM_SID sid;
00995         enum lsa_SidType sidtype;
00996 } *gid_sid_cache_head;
00997 
00998 /*****************************************************************
00999   Find a SID given a uid.
01000 *****************************************************************/  
01001 
01002 static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
01003 {
01004         struct uid_sid_cache *pc;
01005 
01006         for (pc = uid_sid_cache_head; pc; pc = pc->next) {
01007                 if (pc->uid == uid) {
01008                         *psid = pc->sid;
01009                         DEBUG(3,("fetch sid from uid cache %u -> %s\n",
01010                                  (unsigned int)uid, sid_string_static(psid)));
01011                         DLIST_PROMOTE(uid_sid_cache_head, pc);
01012                         return True;
01013                 }
01014         }
01015         return False;
01016 }
01017 
01018 /*****************************************************************
01019   Find a uid given a SID.
01020 *****************************************************************/  
01021 
01022 static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
01023 {
01024         struct uid_sid_cache *pc;
01025 
01026         for (pc = uid_sid_cache_head; pc; pc = pc->next) {
01027                 if (sid_compare(&pc->sid, psid) == 0) {
01028                         *puid = pc->uid;
01029                         DEBUG(3,("fetch uid from cache %u -> %s\n",
01030                                  (unsigned int)*puid, sid_string_static(psid)));
01031                         DLIST_PROMOTE(uid_sid_cache_head, pc);
01032                         return True;
01033                 }
01034         }
01035         return False;
01036 }
01037 
01038 /*****************************************************************
01039  Store uid to SID mapping in cache.
01040 *****************************************************************/  
01041 
01042 void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
01043 {
01044         struct uid_sid_cache *pc;
01045 
01046         /* do not store SIDs in the "Unix Group" domain */
01047         
01048         if ( sid_check_is_in_unix_users( psid ) )
01049                 return;
01050 
01051         if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
01052                 /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
01053                 struct uid_sid_cache *pc_next;
01054                 size_t i;
01055 
01056                 for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
01057                         ;
01058                 for(; pc; pc = pc_next) {
01059                         pc_next = pc->next;
01060                         DLIST_REMOVE(uid_sid_cache_head,pc);
01061                         SAFE_FREE(pc);
01062                         n_uid_sid_cache--;
01063                 }
01064         }
01065 
01066         pc = SMB_MALLOC_P(struct uid_sid_cache);
01067         if (!pc)
01068                 return;
01069         pc->uid = uid;
01070         sid_copy(&pc->sid, psid);
01071         DLIST_ADD(uid_sid_cache_head, pc);
01072         n_uid_sid_cache++;
01073 }
01074 
01075 /*****************************************************************
01076   Find a SID given a gid.
01077 *****************************************************************/  
01078 
01079 static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
01080 {
01081         struct gid_sid_cache *pc;
01082 
01083         for (pc = gid_sid_cache_head; pc; pc = pc->next) {
01084                 if (pc->gid == gid) {
01085                         *psid = pc->sid;
01086                         DEBUG(3,("fetch sid from gid cache %u -> %s\n",
01087                                  (unsigned int)gid, sid_string_static(psid)));
01088                         DLIST_PROMOTE(gid_sid_cache_head, pc);
01089                         return True;
01090                 }
01091         }
01092         return False;
01093 }
01094 
01095 /*****************************************************************
01096   Find a gid given a SID.
01097 *****************************************************************/  
01098 
01099 static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
01100 {
01101         struct gid_sid_cache *pc;
01102 
01103         for (pc = gid_sid_cache_head; pc; pc = pc->next) {
01104                 if (sid_compare(&pc->sid, psid) == 0) {
01105                         *pgid = pc->gid;
01106                         DEBUG(3,("fetch gid from cache %u -> %s\n",
01107                                  (unsigned int)*pgid, sid_string_static(psid)));
01108                         DLIST_PROMOTE(gid_sid_cache_head, pc);
01109                         return True;
01110                 }
01111         }
01112         return False;
01113 }
01114 
01115 /*****************************************************************
01116  Store gid to SID mapping in cache.
01117 *****************************************************************/  
01118 
01119 void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
01120 {
01121         struct gid_sid_cache *pc;
01122         
01123         /* do not store SIDs in the "Unix Group" domain */
01124         
01125         if ( sid_check_is_in_unix_groups( psid ) )
01126                 return;
01127 
01128         if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
01129                 /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
01130                 struct gid_sid_cache *pc_next;
01131                 size_t i;
01132 
01133                 for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
01134                         ;
01135                 for(; pc; pc = pc_next) {
01136                         pc_next = pc->next;
01137                         DLIST_REMOVE(gid_sid_cache_head,pc);
01138                         SAFE_FREE(pc);
01139                         n_gid_sid_cache--;
01140                 }
01141         }
01142 
01143         pc = SMB_MALLOC_P(struct gid_sid_cache);
01144         if (!pc)
01145                 return;
01146         pc->gid = gid;
01147         sid_copy(&pc->sid, psid);
01148         DLIST_ADD(gid_sid_cache_head, pc);
01149 
01150         DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid,
01151                 sid_string_static(psid)));
01152 
01153         n_gid_sid_cache++;
01154 }
01155 
01156 /*****************************************************************
01157  *THE LEGACY* convert uid_t to SID function.
01158 *****************************************************************/  
01159 
01160 static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
01161 {
01162         uint32 rid;
01163         BOOL ret;
01164 
01165         ZERO_STRUCTP(psid);
01166 
01167         become_root();
01168         ret = pdb_uid_to_rid(uid, &rid);
01169         unbecome_root();
01170 
01171         if (ret) {
01172                 /* This is a mapped user */
01173                 sid_copy(psid, get_global_sam_sid());
01174                 sid_append_rid(psid, rid);
01175                 goto done;
01176         }
01177 
01178         /* This is an unmapped user */
01179 
01180         uid_to_unix_users_sid(uid, psid);
01181 
01182  done:
01183         DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
01184                   sid_string_static(psid)));
01185 
01186         store_uid_sid_cache(psid, uid);
01187         return;
01188 }
01189 
01190 /*****************************************************************
01191  *THE LEGACY* convert gid_t to SID function.
01192 *****************************************************************/  
01193 
01194 static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
01195 {
01196         BOOL ret;
01197 
01198         ZERO_STRUCTP(psid);
01199 
01200         become_root();
01201         ret = pdb_gid_to_sid(gid, psid);
01202         unbecome_root();
01203 
01204         if (ret) {
01205                 /* This is a mapped group */
01206                 goto done;
01207         }
01208         
01209         /* This is an unmapped group */
01210 
01211         gid_to_unix_groups_sid(gid, psid);
01212 
01213  done:
01214         DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
01215                   sid_string_static(psid)));
01216 
01217         store_gid_sid_cache(psid, gid);
01218         return;
01219 }
01220 
01221 /*****************************************************************
01222  *THE LEGACY* convert SID to uid function.
01223 *****************************************************************/  
01224 
01225 static BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
01226 {
01227         enum lsa_SidType type;
01228         uint32 rid;
01229 
01230         if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
01231                 union unid_t id;
01232                 BOOL ret;
01233 
01234                 become_root();
01235                 ret = pdb_sid_to_id(psid, &id, &type);
01236                 unbecome_root();
01237 
01238                 if (ret) {
01239                         if (type != SID_NAME_USER) {
01240                                 DEBUG(5, ("sid %s is a %s, expected a user\n",
01241                                           sid_string_static(psid),
01242                                           sid_type_lookup(type)));
01243                                 return False;
01244                         }
01245                         *puid = id.uid;
01246                         goto done;
01247                 }
01248 
01249                 /* This was ours, but it was not mapped.  Fail */
01250                 }
01251 
01252         DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
01253         return False;
01254 
01255 done:
01256         DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_static(psid),
01257                 (unsigned int)*puid ));
01258 
01259         store_uid_sid_cache(psid, *puid);
01260         return True;
01261 }
01262 
01263 /*****************************************************************
01264  *THE LEGACY* convert SID to gid function.
01265  Group mapping is used for gids that maps to Wellknown SIDs
01266 *****************************************************************/  
01267 
01268 static BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
01269 {
01270         uint32 rid;
01271         GROUP_MAP map;
01272         union unid_t id;
01273         enum lsa_SidType type;
01274 
01275         if ((sid_check_is_in_builtin(psid) ||
01276              sid_check_is_in_wellknown_domain(psid))) {
01277                 BOOL ret;
01278 
01279                 become_root();
01280                 ret = pdb_getgrsid(&map, *psid);
01281                 unbecome_root();
01282 
01283                 if (ret) {
01284                         *pgid = map.gid;
01285                         goto done;
01286                 }
01287                 DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
01288                 return False;
01289         }
01290 
01291         if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
01292                 BOOL ret;
01293 
01294                 become_root();
01295                 ret = pdb_sid_to_id(psid, &id, &type);
01296                 unbecome_root();
01297 
01298                 if (ret) {
01299                         if ((type != SID_NAME_DOM_GRP) &&
01300                             (type != SID_NAME_ALIAS)) {
01301                                 DEBUG(5, ("LEGACY: sid %s is a %s, expected a group\n",
01302                                           sid_string_static(psid),
01303                                           sid_type_lookup(type)));
01304                                 return False;
01305                         }
01306                         *pgid = id.gid;
01307                         goto done;
01308                 }
01309 
01310                 /* This was ours, but it was not mapped.  Fail */
01311         }
01312 
01313         DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
01314                 return False;
01315         
01316  done:
01317         DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_static(psid),
01318                   (unsigned int)*pgid ));
01319 
01320         store_gid_sid_cache(psid, *pgid);
01321 
01322         return True;
01323 }
01324 
01325 /*****************************************************************
01326  *THE CANONICAL* convert uid_t to SID function.
01327 *****************************************************************/  
01328 
01329 void uid_to_sid(DOM_SID *psid, uid_t uid)
01330 {
01331         ZERO_STRUCTP(psid);
01332 
01333         if (fetch_sid_from_uid_cache(psid, uid))
01334                 return;
01335 
01336         if (!winbind_uid_to_sid(psid, uid)) {
01337                 if (!winbind_ping()) {
01338                         legacy_uid_to_sid(psid, uid);
01339                         return;
01340                 }
01341 
01342                 DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
01343                         uid));
01344                 return;
01345         }
01346         
01347         DEBUG(10,("uid %u -> sid %s\n",
01348                   (unsigned int)uid, sid_string_static(psid)));
01349 
01350         store_uid_sid_cache(psid, uid);
01351         return;
01352 }
01353 
01354 /*****************************************************************
01355  *THE CANONICAL* convert gid_t to SID function.
01356 *****************************************************************/  
01357 
01358 void gid_to_sid(DOM_SID *psid, gid_t gid)
01359 {
01360         ZERO_STRUCTP(psid);
01361                 
01362         if (fetch_sid_from_gid_cache(psid, gid))
01363                 return;
01364 
01365         if (!winbind_gid_to_sid(psid, gid)) {
01366                 if (!winbind_ping()) {
01367                         legacy_gid_to_sid(psid, gid);
01368                         return;
01369                 }
01370 
01371                 DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
01372                         gid));
01373                 return;
01374         }
01375 
01376         DEBUG(10,("gid %u -> sid %s\n",
01377                   (unsigned int)gid, sid_string_static(psid)));
01378         
01379         store_gid_sid_cache(psid, gid);
01380         return;
01381 }
01382 
01383 /*****************************************************************
01384  *THE CANONICAL* convert SID to uid function.
01385 *****************************************************************/  
01386 
01387 BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
01388 {
01389         uint32 rid;
01390         gid_t gid;
01391 
01392         if (fetch_uid_from_cache(puid, psid))
01393                 return True;
01394 
01395         if (fetch_gid_from_cache(&gid, psid)) {
01396                 return False;
01397         }
01398 
01399         /* Optimize for the Unix Users Domain
01400          * as the conversion is straightforward */
01401         if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
01402                 uid_t uid = rid;
01403                 *puid = uid;
01404 
01405                 /* return here, don't cache */
01406                 DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid),
01407                         (unsigned int)*puid ));
01408                 return True;
01409         }
01410 
01411         if (!winbind_sid_to_uid(puid, psid)) {
01412                 if (!winbind_ping()) {
01413                         return legacy_sid_to_uid(psid, puid);
01414                 }
01415 
01416                 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
01417                           sid_string_static(psid)));
01418                 return False;
01419         }
01420         
01421         /* TODO: Here would be the place to allocate both a gid and a uid for
01422          * the SID in question */
01423 
01424         DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid),
01425                 (unsigned int)*puid ));
01426 
01427         store_uid_sid_cache(psid, *puid);
01428         return True;
01429 }
01430 
01431 /*****************************************************************
01432  *THE CANONICAL* convert SID to gid function.
01433  Group mapping is used for gids that maps to Wellknown SIDs
01434 *****************************************************************/  
01435 
01436 BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
01437 {
01438         uint32 rid;
01439         uid_t uid;
01440 
01441         if (fetch_gid_from_cache(pgid, psid))
01442                 return True;
01443 
01444         if (fetch_uid_from_cache(&uid, psid))
01445                 return False;
01446 
01447         /* Optimize for the Unix Groups Domain
01448          * as the conversion is straightforward */
01449         if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
01450                 gid_t gid = rid;
01451                 *pgid = gid;
01452 
01453                 /* return here, don't cache */
01454                 DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
01455                         (unsigned int)*pgid ));
01456                 return True;
01457         }
01458 
01459         /* Ask winbindd if it can map this sid to a gid.
01460          * (Idmap will check it is a valid SID and of the right type) */
01461 
01462         if ( !winbind_sid_to_gid(pgid, psid) ) {
01463                 if (!winbind_ping()) {
01464                         return legacy_sid_to_gid(psid, pgid);
01465                 }
01466 
01467                 DEBUG(10,("winbind failed to find a gid for sid %s\n",
01468                                         sid_string_static(psid)));
01469                 return False;
01470         }
01471 
01472         DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
01473                   (unsigned int)*pgid ));
01474 
01475         store_gid_sid_cache(psid, *pgid);
01476         
01477         return True;
01478 }
01479 

Sambaに対してSat Aug 29 21:23:12 2009に生成されました。  doxygen 1.4.7