Merge branch 'v3-devel' of ssh://git.samba.org/data/git/samba into v3-devel
authorSimo Sorce <idra@samba.org>
Tue, 26 Aug 2008 22:56:49 +0000 (18:56 -0400)
committerSimo Sorce <idra@samba.org>
Tue, 26 Aug 2008 22:56:49 +0000 (18:56 -0400)
(This used to be commit e038f1cf9fb305fc1e7a4189208e451d30aaa1f0)

1  2 
source3/include/proto.h
source3/passdb/lookup_sid.c

diff --combined source3/include/proto.h
index 2d9734873efc18a206adcee950d65f7789539083,d3a8dbbc7fe93683ef30e26006527de476d2da51..d757b2db8077e293e925a231d35a8df0252b2db2
@@@ -623,7 -623,7 +623,7 @@@ bool is_local_net(const struct sockaddr
  void setup_linklocal_scope_id(struct sockaddr_storage *pss);
  bool is_local_net_v4(struct in_addr from);
  int iface_count(void);
- int iface_count_v4(void);
+ int iface_count_v4_nl(void);
  const struct in_addr *first_ipv4_iface(void);
  struct interface *get_interface(int n);
  const struct sockaddr_storage *iface_n_sockaddr_storage(int n);
@@@ -6049,6 -6049,7 +6049,7 @@@ int lp_directory_name_cache_size(int )
  int lp_smb_encrypt(int );
  char lp_magicchar(const struct share_params *p );
  int lp_winbind_cache_time(void);
+ int lp_winbind_reconnect_delay(void);
  const char **lp_winbind_nss_info(void);
  int lp_algorithmic_rid_base(void);
  int lp_name_cache_timeout(void);
@@@ -6201,10 -6202,6 +6202,10 @@@ bool lookup_name(TALLOC_CTX *mem_ctx
                 const char *full_name, int flags,
                 const char **ret_domain, const char **ret_name,
                 DOM_SID *ret_sid, enum lsa_SidType *ret_type);
 +bool lookup_domain_name(TALLOC_CTX *mem_ctx,
 +               const char *domain, const char *name, int flags,
 +               const char **ret_domain, const char **ret_name,
 +               DOM_SID *ret_sid, enum lsa_SidType *ret_type);
  bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
                 const char *full_name, int flags,
                 const char **ret_domain, const char **ret_name,
index 57152c34b54d5343d678112af39e9c2a2f663c37,4b2edd5d59eb658777dad6b77d75528d6f7034d8..706df48923c6f12ccbc7a72c5b3277c715b82a31
   to do guesswork.
  *****************************************************************/  
  
 +#define LN_CHECK_TALLOC(var, memctx) do { \
 +      if (var == NULL) { \
 +              DEBUG(0, ("talloc failed\n")); \
 +              TALLOC_FREE(memctx); \
 +              return false; \
 +      } \
 +} while(0)
 +
  bool lookup_name(TALLOC_CTX *mem_ctx,
                 const char *full_name, int flags,
                 const char **ret_domain, const char **ret_name,
                 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
  {
 +      char *domain, *name;
 +      bool res;
        char *p;
 -      const char *tmp;
 -      const char *domain = NULL;
 -      const char *name = NULL;
 -      uint32 rid;
 -      DOM_SID sid;
 -      enum lsa_SidType type;
 -      TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 -
 -      if (tmp_ctx == NULL) {
 -              DEBUG(0, ("talloc_new failed\n"));
 -              return false;
 -      }
  
        p = strchr_m(full_name, '\\');
  
        if (p != NULL) {
 -              domain = talloc_strndup(tmp_ctx, full_name,
 +              domain = talloc_strndup(mem_ctx, full_name,
                                        PTR_DIFF(p, full_name));
 -              name = talloc_strdup(tmp_ctx, p+1);
 +              name = talloc_strdup(mem_ctx, p+1);
        } else {
 -              domain = talloc_strdup(tmp_ctx, "");
 -              name = talloc_strdup(tmp_ctx, full_name);
 +              domain = NULL;
 +              name = talloc_strdup(mem_ctx, full_name);
        }
  
 -      if ((domain == NULL) || (name == NULL)) {
 +      if (((p != NULL) && (domain == NULL)) || (name == NULL)) {
                DEBUG(0, ("talloc failed\n"));
 -              TALLOC_FREE(tmp_ctx);
                return false;
        }
  
 -      DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
 -              full_name, domain, name));
 +      DEBUG(10,("lookup_domain_name: %s => %s (domain), %s (name)\n",
 +                full_name, domain, name));
 +
 +      res = lookup_domain_name(mem_ctx, domain, name, flags,
 +                               ret_domain, ret_name, ret_sid, ret_type);
 +
 +      talloc_free(domain);
 +      talloc_free(name);
 +
 +      return res;
 +}
 +
 +bool lookup_domain_name(TALLOC_CTX *mem_ctx,
 +               const char *domain, const char *name, int flags,
 +               const char **ret_domain, const char **ret_name,
 +               DOM_SID *ret_sid, enum lsa_SidType *ret_type)
 +{
 +      const char *tmp;
 +      const char *domain_new = NULL;
 +      uint32 rid;
 +      DOM_SID sid;
 +      enum lsa_SidType type;
 +      TALLOC_CTX *tmp_ctx;
 +
 +      tmp_ctx = talloc_new(mem_ctx);
 +      if (tmp_ctx == NULL) {
 +              DEBUG(0, ("talloc_new failed\n"));
 +              return false;
 +      }
 +
 +      if (!domain) domain = talloc_strdup(tmp_ctx, "");
 +      LN_CHECK_TALLOC(domain, tmp_ctx);
 +
        DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
  
        if ((flags & LOOKUP_NAME_DOMAIN) &&
        }
  
        /* Try the explicit winbind lookup first, don't let it guess the
 -       * domain yet at this point yet. This comes later. */
 +       * domain at this point yet. This comes later. */
  
        if ((domain[0] != '\0') &&
            (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
        /* 1. well-known names */
  
        if ((flags & LOOKUP_NAME_WKN) &&
 -          lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
 +          lookup_wellknown_name(tmp_ctx, name, &sid, &domain_new))
        {
                type = SID_NAME_WKN_GRP;
 +              LN_CHECK_TALLOC(domain_new, tmp_ctx);
                goto ok;
        }
  
                goto ok;
        }
  
 -      /* 6. Builtin aliases */        
 +      /* 6. Builtin aliases */
  
        if ((flags & LOOKUP_NAME_BUILTIN) &&
            lookup_builtin_name(name, &rid))
        {
 -              domain = talloc_strdup(tmp_ctx, builtin_domain_name());
 +              domain_new = talloc_strdup(tmp_ctx, builtin_domain_name());
 +              LN_CHECK_TALLOC(domain_new, tmp_ctx);
                sid_copy(&sid, &global_sid_Builtin);
                sid_append_rid(&sid, rid);
                type = SID_NAME_ALIAS;
        if ((flags & LOOKUP_NAME_DOMAIN) &&
            lookup_global_sam_name(name, flags, &rid, &type))
        {
 -              domain = talloc_strdup(tmp_ctx, get_global_sam_name());
 +              domain_new = talloc_strdup(tmp_ctx, get_global_sam_name());
 +              LN_CHECK_TALLOC(domain_new, tmp_ctx);
                sid_copy(&sid, get_global_sam_sid());
                sid_append_rid(&sid, rid);
                goto ok;
  
        if (!IS_DC &&
            (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
 -              domain = talloc_strdup(tmp_ctx, lp_workgroup());
 +              domain_new = talloc_strdup(tmp_ctx, lp_workgroup());
 +              LN_CHECK_TALLOC(domain_new, tmp_ctx);
                goto ok;
        }
  
                DOM_SID dom_sid;
                uint32 tmp_rid;
                enum lsa_SidType domain_type;
 -              
 +
                if (type == SID_NAME_DOMAIN) {
                        /* Swap name and type */
                        tmp = name; name = domain; domain = tmp;
                        TALLOC_FREE(tmp_ctx);
                        return false;
                }
 +              LN_CHECK_TALLOC(domain_new, tmp_ctx);
                goto ok;
        }
  
                 Unmapped users and unmapped groups */
  
        if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) {
 -              domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
 +              domain_new = talloc_strdup(tmp_ctx, unix_users_domain_name());
 +              LN_CHECK_TALLOC(domain_new, tmp_ctx);
                type = SID_NAME_USER;
                goto ok;
        }
  
        if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) {
 -              domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
 +              domain_new = talloc_strdup(tmp_ctx, unix_groups_domain_name());
 +              LN_CHECK_TALLOC(domain_new, tmp_ctx);
                type = SID_NAME_DOM_GRP;
                goto ok;
        }
        return false;
  
   ok:
 -      if ((domain == NULL) || (name == NULL)) {
 -              DEBUG(0, ("talloc failed\n"));
 -              TALLOC_FREE(tmp_ctx);
 -              return false;
 -      }
 -
        /*
         * Hand over the results to the talloc context we've been given.
         */
  
        if (ret_domain != NULL) {
                char *tmp_dom;
 -              if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
 -                      DEBUG(0, ("talloc failed\n"));
 -                      TALLOC_FREE(tmp_ctx);
 -                      return false;
 +
 +              if (domain_new) {
 +                      tmp_dom = talloc_steal(mem_ctx, (char *)domain_new);
 +              } else {
 +                      tmp_dom = talloc_strdup(mem_ctx, domain);
                }
 +              LN_CHECK_TALLOC(tmp_dom, tmp_ctx);
 +
                strupper_m(tmp_dom);
                *ret_domain = tmp_dom;
        }
@@@ -383,42 -351,59 +383,42 @@@ bool lookup_name_smbconf(TALLOC_CTX *me
                 const char **ret_domain, const char **ret_name,
                 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
  {
 -      char *qualified_name;
 -      const char *p;
 -
 -      /* NB. No winbindd_separator here as lookup_name needs \\' */
 -      if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
 -
 -              /* The name is already qualified with a domain. */
 -
 -              if (*lp_winbind_separator() != '\\') {
 -                      char *tmp;
 +      char *p;
  
 -                      /* lookup_name() needs '\\' as a separator */
 +      p = strchr_m(full_name, *lp_winbind_separator());
 +      if (p != NULL) {
 +              char *name;
 +              bool res;
  
 -                      tmp = talloc_strdup(mem_ctx, full_name);
 -                      if (!tmp) {
 -                              return false;
 -                      }
 -                      tmp[p - full_name] = '\\';
 -                      full_name = tmp;
 +              name = talloc_strdup(mem_ctx, full_name);
 +              if (!name) {
 +                      DEBUG(0, ("Out of memory!\n"));
 +                      return false;
                }
 +              name[PTR_DIFF(p, full_name)] = '\\';
  
 -              return lookup_name(mem_ctx, full_name, flags,
 -                              ret_domain, ret_name,
 -                              ret_sid, ret_type);
 +              res = lookup_name(mem_ctx, name, flags,
 +                                ret_domain, ret_name,
 +                                ret_sid, ret_type);
 +              talloc_free(name);
 +              return res;
        }
  
        /* Try with our own SAM name. */
 -      qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
 -                              get_global_sam_name(),
 -                              full_name );
 -      if (!qualified_name) {
 -              return false;
 -      }
 -
 -      if (lookup_name(mem_ctx, qualified_name, flags,
 -                              ret_domain, ret_name,
 -                              ret_sid, ret_type)) {
 +      if (lookup_domain_name(mem_ctx,
 +                              get_global_sam_name(), full_name, flags,
 +                              ret_domain, ret_name, ret_sid, ret_type)) {
                return true;
        }
 -      
 +
        /* Finally try with "Unix Users" or "Unix Group" */
 -      qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
 +      return lookup_domain_name(mem_ctx,
                                flags & LOOKUP_NAME_GROUP ?
                                        unix_groups_domain_name() :
                                        unix_users_domain_name(),
 -                              full_name );
 -      if (!qualified_name) {
 -              return false;
 -      }
 +                              full_name, flags,
 +                              ret_domain, ret_name, ret_sid, ret_type);
  
 -      return lookup_name(mem_ctx, qualified_name, flags,
 -                              ret_domain, ret_name,
 -                              ret_sid, ret_type);
  }
  
  static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
@@@ -1301,20 -1286,28 +1301,28 @@@ static bool legacy_sid_to_gid(const DOM
  
  void uid_to_sid(DOM_SID *psid, uid_t uid)
  {
+       bool expired = true;
+       bool ret;
        ZERO_STRUCTP(psid);
  
        if (fetch_sid_from_uid_cache(psid, uid))
                return;
  
-       if (!winbind_uid_to_sid(psid, uid)) {
-               if (!winbind_ping()) {
-                       legacy_uid_to_sid(psid, uid);
+       /* Check the winbindd cache directly. */
+       ret = idmap_cache_find_uid2sid(uid, psid, &expired);
+       if (!ret || expired || (ret && is_null_sid(psid))) {
+               /* Not in cache. Ask winbindd. */
+               if (!winbind_uid_to_sid(psid, uid)) {
+                       if (!winbind_ping()) {
+                               legacy_uid_to_sid(psid, uid);
+                               return;
+                       }
+                       DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
+                               uid));
                        return;
                }
-               DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
-                       uid));
-               return;
        }
  
        DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
  
  void gid_to_sid(DOM_SID *psid, gid_t gid)
  {
+       bool expired = true;
+       bool ret;
        ZERO_STRUCTP(psid);
  
        if (fetch_sid_from_gid_cache(psid, gid))
                return;
  
-       if (!winbind_gid_to_sid(psid, gid)) {
-               if (!winbind_ping()) {
-                       legacy_gid_to_sid(psid, gid);
+       /* Check the winbindd cache directly. */
+       ret = idmap_cache_find_gid2sid(gid, psid, &expired);
+       if (!ret || expired || (ret && is_null_sid(psid))) {
+               /* Not in cache. Ask winbindd. */
+               if (!winbind_gid_to_sid(psid, gid)) {
+                       if (!winbind_ping()) {
+                               legacy_gid_to_sid(psid, gid);
+                               return;
+                       }
+                       DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
+                               gid));
                        return;
                }
-               DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
-                       gid));
-               return;
        }
  
        DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
                  sid_string_dbg(psid)));
-       
        store_gid_sid_cache(psid, gid);
        return;
  }
  
  bool sid_to_uid(const DOM_SID *psid, uid_t *puid)
  {
+       bool expired = true;
+       bool ret;
        uint32 rid;
        gid_t gid;
  
                return true;
        }
  
-       if (!winbind_sid_to_uid(puid, psid)) {
-               if (!winbind_ping()) {
-                       return legacy_sid_to_uid(psid, puid);
-               }
+       /* Check the winbindd cache directly. */
+       ret = idmap_cache_find_sid2uid(psid, puid, &expired);
  
-               DEBUG(5, ("winbind failed to find a uid for sid %s\n",
-                         sid_string_dbg(psid)));
-               return false;
+       if (!ret || expired || (ret && (*puid == (uid_t)-1))) {
+               /* Not in cache. Ask winbindd. */
+               if (!winbind_sid_to_uid(puid, psid)) {
+                       if (!winbind_ping()) {
+                               return legacy_sid_to_uid(psid, puid);
+                       }
+                       DEBUG(5, ("winbind failed to find a uid for sid %s\n",
+                                 sid_string_dbg(psid)));
+                       return false;
+               }
        }
  
        /* TODO: Here would be the place to allocate both a gid and a uid for
  
  bool sid_to_gid(const DOM_SID *psid, gid_t *pgid)
  {
+       bool expired = true;
+       bool ret;
        uint32 rid;
        uid_t uid;
  
                return true;
        }
  
-       /* Ask winbindd if it can map this sid to a gid.
-        * (Idmap will check it is a valid SID and of the right type) */
+       /* Check the winbindd cache directly. */
+       ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
  
-       if ( !winbind_sid_to_gid(pgid, psid) ) {
-               if (!winbind_ping()) {
-                       return legacy_sid_to_gid(psid, pgid);
-               }
+       if (!ret || expired || (ret && (*pgid == (gid_t)-1))) {
+               /* Not in cache or negative. Ask winbindd. */
+               /* Ask winbindd if it can map this sid to a gid.
+                * (Idmap will check it is a valid SID and of the right type) */
  
-               DEBUG(10,("winbind failed to find a gid for sid %s\n",
-                         sid_string_dbg(psid)));
-               return false;
+               if ( !winbind_sid_to_gid(pgid, psid) ) {
+                       if (!winbind_ping()) {
+                               return legacy_sid_to_gid(psid, pgid);
+                       }
+                       DEBUG(10,("winbind failed to find a gid for sid %s\n",
+                                 sid_string_dbg(psid)));
+                       return false;
+               }
        }
  
        DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
                  (unsigned int)*pgid ));
  
        store_gid_sid_cache(psid, *pgid);
-       
        return true;
  }