passdb: Introduce xid_to_sid
authorVolker Lendecke <vl@samba.org>
Tue, 26 Feb 2019 14:10:21 +0000 (15:10 +0100)
committerVolker Lendecke <vl@samba.org>
Thu, 28 Feb 2019 12:57:24 +0000 (12:57 +0000)
This explicitly avoids the legacy_[ug]id_to_sid calls, which create
long-term cache entries to S-1-22-x-y if anthing fails. We can't do
this, because this will turn temporary winbind communication failures
into long-term problems: A short hickup in winbind_uid_to_sid will
create a mapping to S-1-22-1-uid for a week. It should be up to the
lower layers to do the caching.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Christof Schmitt <cs@samba.org>
Bug: https://bugzilla.samba.org/show_bug.cgi?id=13813

source3/passdb/lookup_sid.c
source3/passdb/lookup_sid.h

index bf3ded6683e6fdd85cbb0f10094fc2c2fbd49e86..bdd8082afb422baf2a1fae86808ac8968d6401e8 100644 (file)
@@ -1349,6 +1349,80 @@ void gid_to_sid(struct dom_sid *psid, gid_t gid)
        return;
 }
 
+void xid_to_sid(struct dom_sid *psid, const struct unixid *xid)
+{
+       bool expired = true;
+       bool ret;
+       struct dom_sid_buf buf;
+
+       SMB_ASSERT(xid->type == ID_TYPE_UID || xid->type == ID_TYPE_GID);
+
+       *psid = (struct dom_sid) {0};
+
+       ret = idmap_cache_find_xid2sid(xid, psid, &expired);
+       if (ret && !expired) {
+               DBG_DEBUG("%cID %"PRIu32" -> %s from cache\n",
+                         xid->type == ID_TYPE_UID ? 'U' : 'G',
+                         xid->id,
+                         dom_sid_str_buf(psid, &buf));
+               goto done;
+       }
+
+       ret = winbind_xid_to_sid(psid, xid);
+       if (ret) {
+               /*
+                * winbind can return an explicit negative mapping
+                * here. It's up to winbind to prime the cache either
+                * positively or negatively, don't mess with the cache
+                * here.
+                */
+               DBG_DEBUG("%cID %"PRIu32" -> %s from cache\n",
+                         xid->type == ID_TYPE_UID ? 'U' : 'G',
+                         xid->id,
+                         dom_sid_str_buf(psid, &buf));
+               goto done;
+       }
+
+       {
+               /*
+                * Make a copy, pdb_id_to_sid might want to turn
+                * xid->type into ID_TYPE_BOTH, which we ignore here.
+                */
+               struct unixid rw_xid = *xid;
+
+               become_root();
+               ret = pdb_id_to_sid(&rw_xid, psid);
+               unbecome_root();
+       }
+
+       if (ret) {
+               DBG_DEBUG("%cID %"PRIu32" -> %s from passdb\n",
+                         xid->type == ID_TYPE_UID ? 'U' : 'G',
+                         xid->id,
+                         dom_sid_str_buf(psid, &buf));
+               goto done;
+       }
+
+done:
+       if (is_null_sid(psid)) {
+               /*
+                * Nobody found anything: Return S-1-22-xx-yy. Don't
+                * store that in caches, this is up to the layers
+                * beneath us.
+                */
+               if (xid->type == ID_TYPE_UID) {
+                       uid_to_unix_users_sid(xid->id, psid);
+               } else {
+                       gid_to_unix_groups_sid(xid->id, psid);
+               }
+
+               DBG_DEBUG("%cID %"PRIu32" -> %s fallback\n",
+                         xid->type == ID_TYPE_UID ? 'U' : 'G',
+                         xid->id,
+                         dom_sid_str_buf(psid, &buf));
+       }
+}
+
 bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
                     struct unixid *ids)
 {
index 8b5edf6bcb81796aa8b4a57f7c4706793309c34e..8a21cca2a4d034e7afe387f712aaef7c11e2232f 100644 (file)
@@ -83,6 +83,7 @@ bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
                enum lsa_SidType *ret_type);
 void uid_to_sid(struct dom_sid *psid, uid_t uid);
 void gid_to_sid(struct dom_sid *psid, gid_t gid);
+void xid_to_sid(struct dom_sid *psid, const struct unixid *xid);
 bool sid_to_uid(const struct dom_sid *psid, uid_t *puid);
 bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid);
 bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,