LCOV - code coverage report
Current view: top level - source4/winbind - idmap.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 215 412 52.2 %
Date: 2021-09-23 10:06:22 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Map SIDs to unixids and back
       5             : 
       6             :    Copyright (C) Kai Blin 2008
       7             :    Copyright (C) Andrew Bartlett 2012
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "auth/auth.h"
      25             : #include "librpc/gen_ndr/ndr_security.h"
      26             : #include "lib/util_unixsids.h"
      27             : #include <ldb.h>
      28             : #include "ldb_wrap.h"
      29             : #include "param/param.h"
      30             : #include "winbind/idmap.h"
      31             : #include "libcli/security/security.h"
      32             : #include "libcli/ldap/ldap_ndr.h"
      33             : #include "dsdb/samdb/samdb.h"
      34             : #include "../libds/common/flags.h"
      35             : 
      36             : /**
      37             :  * Get uid/gid bounds from idmap database
      38             :  *
      39             :  * \param idmap_ctx idmap context to use
      40             :  * \param low lower uid/gid bound is stored here
      41             :  * \param high upper uid/gid bound is stored here
      42             :  * \return 0 on success, nonzero on failure
      43             :  */
      44         916 : static int idmap_get_bounds(struct idmap_context *idmap_ctx, uint32_t *low,
      45             :                 uint32_t *high)
      46             : {
      47         916 :         int ret = -1;
      48         916 :         struct ldb_context *ldb = idmap_ctx->ldb_ctx;
      49             :         struct ldb_dn *dn;
      50         916 :         struct ldb_result *res = NULL;
      51         916 :         TALLOC_CTX *tmp_ctx = talloc_new(idmap_ctx);
      52         916 :         uint32_t lower_bound = (uint32_t) -1;
      53         916 :         uint32_t upper_bound = (uint32_t) -1;
      54             : 
      55         916 :         dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
      56         916 :         if (dn == NULL) goto failed;
      57             : 
      58         916 :         ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
      59         916 :         if (ret != LDB_SUCCESS) goto failed;
      60             : 
      61         916 :         if (res->count != 1) {
      62           0 :                 ret = -1;
      63           0 :                 goto failed;
      64             :         }
      65             : 
      66         916 :         lower_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "lowerBound", -1);
      67         916 :         if (lower_bound != (uint32_t) -1) {
      68         916 :                 ret = LDB_SUCCESS;
      69             :         } else {
      70           0 :                 ret = -1;
      71           0 :                 goto failed;
      72             :         }
      73             : 
      74         916 :         upper_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "upperBound", -1);
      75         916 :         if (upper_bound != (uint32_t) -1) {
      76         851 :                 ret = LDB_SUCCESS;
      77             :         } else {
      78           0 :                 ret = -1;
      79             :         }
      80             : 
      81         916 : failed:
      82         916 :         talloc_free(tmp_ctx);
      83         916 :         *low  = lower_bound;
      84         916 :         *high = upper_bound;
      85         916 :         return ret;
      86             : }
      87             : 
      88             : /**
      89             :  * Add a dom_sid structure to a ldb_message
      90             :  * \param idmap_ctx idmap context to use
      91             :  * \param mem_ctx talloc context to use
      92             :  * \param ldb_message ldb message to add dom_sid to
      93             :  * \param attr_name name of the attribute to store the dom_sid in
      94             :  * \param sid dom_sid to store
      95             :  * \return 0 on success, an ldb error code on failure.
      96             :  */
      97         916 : static int idmap_msg_add_dom_sid(struct idmap_context *idmap_ctx,
      98             :                 TALLOC_CTX *mem_ctx, struct ldb_message *msg,
      99             :                 const char *attr_name, const struct dom_sid *sid)
     100             : {
     101             :         struct ldb_val val;
     102             :         enum ndr_err_code ndr_err;
     103             : 
     104         916 :         ndr_err = ndr_push_struct_blob(&val, mem_ctx, sid,
     105             :                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
     106             : 
     107         916 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     108           0 :                 return -1;
     109             :         }
     110             : 
     111         916 :         return ldb_msg_add_value(msg, attr_name, &val, NULL);
     112             : }
     113             : 
     114             : /**
     115             :  * Get a dom_sid structure from a ldb message.
     116             :  *
     117             :  * \param mem_ctx talloc context to allocate dom_sid memory in
     118             :  * \param msg ldb_message to get dom_sid from
     119             :  * \param attr_name key that has the dom_sid as data
     120             :  * \return dom_sid structure on success, NULL on failure
     121             :  */
     122          76 : static struct dom_sid *idmap_msg_get_dom_sid(TALLOC_CTX *mem_ctx,
     123             :                 struct ldb_message *msg, const char *attr_name)
     124             : {
     125             :         struct dom_sid *sid;
     126             :         const struct ldb_val *val;
     127             :         enum ndr_err_code ndr_err;
     128             : 
     129          76 :         val = ldb_msg_find_ldb_val(msg, attr_name);
     130          76 :         if (val == NULL) {
     131           0 :                 return NULL;
     132             :         }
     133             : 
     134          76 :         sid = talloc(mem_ctx, struct dom_sid);
     135          76 :         if (sid == NULL) {
     136           0 :                 return NULL;
     137             :         }
     138             : 
     139          76 :         ndr_err = ndr_pull_struct_blob(val, sid, sid,
     140             :                                        (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
     141          76 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     142           0 :                 talloc_free(sid);
     143           0 :                 return NULL;
     144             :         }
     145             : 
     146          74 :         return sid;
     147             : }
     148             : 
     149             : /**
     150             :  * Initialize idmap context
     151             :  *
     152             :  * talloc_free to close.
     153             :  *
     154             :  * \param mem_ctx talloc context to use.
     155             :  * \return allocated idmap_context on success, NULL on error
     156             :  */
     157        8993 : struct idmap_context *idmap_init(TALLOC_CTX *mem_ctx,
     158             :                                  struct tevent_context *ev_ctx,
     159             :                                  struct loadparm_context *lp_ctx)
     160             : {
     161             :         struct idmap_context *idmap_ctx;
     162             : 
     163        8993 :         idmap_ctx = talloc(mem_ctx, struct idmap_context);
     164        8993 :         if (idmap_ctx == NULL) {
     165           0 :                 return NULL;
     166             :         }
     167             : 
     168        8993 :         idmap_ctx->lp_ctx = lp_ctx;
     169             : 
     170        8993 :         idmap_ctx->ldb_ctx = ldb_wrap_connect(idmap_ctx, ev_ctx, lp_ctx,
     171             :                                               "idmap.ldb",
     172             :                                               system_session(lp_ctx),
     173             :                                               NULL, 0);
     174        8993 :         if (idmap_ctx->ldb_ctx == NULL) {
     175           0 :                 goto fail;
     176             :         }
     177             : 
     178        8993 :         idmap_ctx->samdb = samdb_connect(idmap_ctx,
     179             :                                          ev_ctx,
     180             :                                          lp_ctx,
     181             :                                          system_session(lp_ctx),
     182             :                                          NULL,
     183             :                                          0);
     184        8993 :         if (idmap_ctx->samdb == NULL) {
     185           0 :                 DEBUG(0, ("Failed to load sam.ldb in idmap_init\n"));
     186           0 :                 goto fail;
     187             :         }
     188             : 
     189        8439 :         return idmap_ctx;
     190           0 : fail:
     191           0 :         TALLOC_FREE(idmap_ctx);
     192           0 :         return NULL;
     193             : }
     194             : 
     195             : /**
     196             :  * Convert an unixid to the corresponding SID
     197             :  *
     198             :  * \param idmap_ctx idmap context to use
     199             :  * \param mem_ctx talloc context the memory for the struct dom_sid is allocated
     200             :  * from.
     201             :  * \param unixid pointer to a unixid struct to convert
     202             :  * \param sid pointer that will take the struct dom_sid pointer if the mapping
     203             :  * succeeds.
     204             :  * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping not
     205             :  * possible or some other NTSTATUS that is more descriptive on failure.
     206             :  */
     207             : 
     208         214 : static NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx,
     209             :                                  TALLOC_CTX *mem_ctx,
     210             :                                  struct unixid *unixid,
     211             :                                  struct dom_sid **sid)
     212             : {
     213             :         int ret;
     214             :         NTSTATUS status;
     215         214 :         struct ldb_context *ldb = idmap_ctx->ldb_ctx;
     216         214 :         struct ldb_result *res = NULL;
     217             :         struct ldb_message *msg;
     218             :         const struct dom_sid *unix_sid;
     219             :         struct dom_sid *new_sid;
     220         214 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     221             :         const char *id_type;
     222             : 
     223         214 :         const char *sam_attrs[] = {"objectSid", NULL};
     224             :         
     225             :         /* 
     226             :          * First check against our local DB, to see if this user has a
     227             :          * mapping there.  This means that the Samba4 AD DC behaves
     228             :          * much like a winbindd member server running idmap_ad
     229             :          */
     230             :         
     231         214 :         switch (unixid->type) {
     232          81 :                 case ID_TYPE_UID:
     233          81 :                         if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
     234          79 :                                 ret = dsdb_search_one(idmap_ctx->samdb, tmp_ctx, &msg,
     235             :                                                       ldb_get_default_basedn(idmap_ctx->samdb),
     236             :                                                       LDB_SCOPE_SUBTREE,
     237             :                                                       sam_attrs, 0,
     238             :                                                       "(&(|(sAMaccountType=%u)(sAMaccountType=%u)(sAMaccountType=%u))"
     239             :                                                       "(uidNumber=%u)(objectSid=*))",
     240             :                                                       ATYPE_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST, unixid->id);
     241             :                         } else {
     242             :                                 /* If we are not to use the rfc2307 attributes, we just emulate a non-match */
     243           0 :                                 ret = LDB_ERR_NO_SUCH_OBJECT;
     244             :                         }
     245             : 
     246          79 :                         if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
     247           0 :                                 DEBUG(1, ("Search for uidNumber=%lu gave duplicate results, failing to map to a SID!\n",
     248             :                                           (unsigned long)unixid->id));
     249           0 :                                 status = NT_STATUS_NONE_MAPPED;
     250           0 :                                 goto failed;
     251          81 :                         } else if (ret == LDB_SUCCESS) {
     252           0 :                                 *sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid");
     253           0 :                                 if (*sid == NULL) {
     254           0 :                                         DEBUG(1, ("Search for uidNumber=%lu did not return an objectSid!\n",
     255             :                                                   (unsigned long)unixid->id));
     256           0 :                                         status = NT_STATUS_NONE_MAPPED;
     257           0 :                                         goto failed;
     258             :                                 }
     259           0 :                                 talloc_free(tmp_ctx);
     260           0 :                                 return NT_STATUS_OK;
     261          81 :                         } else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
     262           0 :                                 DEBUG(1, ("Search for uidNumber=%lu gave '%s', failing to map to a SID!\n",
     263             :                                           (unsigned long)unixid->id, ldb_errstring(idmap_ctx->samdb)));
     264           0 :                                 status = NT_STATUS_NONE_MAPPED;
     265           0 :                                 goto failed;
     266             :                         }
     267             : 
     268          77 :                         id_type = "ID_TYPE_UID";
     269          77 :                         break;
     270         133 :                 case ID_TYPE_GID:
     271         133 :                         if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
     272         131 :                                 ret = dsdb_search_one(idmap_ctx->samdb, tmp_ctx, &msg,
     273             :                                                       ldb_get_default_basedn(idmap_ctx->samdb),
     274             :                                                       LDB_SCOPE_SUBTREE,
     275             :                                                       sam_attrs, 0,
     276             :                                                       "(&(|(sAMaccountType=%u)(sAMaccountType=%u))(gidNumber=%u))",
     277             :                                                       ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP,
     278             :                                                       unixid->id);
     279             :                         } else {
     280             :                                 /* If we are not to use the rfc2307 attributes, we just emulate a non-match */
     281           0 :                                 ret = LDB_ERR_NO_SUCH_OBJECT;
     282             :                         }
     283         131 :                         if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
     284           0 :                                 DEBUG(1, ("Search for gidNumber=%lu gave duplicate results, failing to map to a SID!\n",
     285             :                                           (unsigned long)unixid->id));
     286           0 :                                 status = NT_STATUS_NONE_MAPPED;
     287           0 :                                 goto failed;
     288         133 :                         } else if (ret == LDB_SUCCESS) {
     289           0 :                                 *sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid");
     290           0 :                                 if (*sid == NULL) {
     291           0 :                                         DEBUG(1, ("Search for gidNumber=%lu did not return an objectSid!\n",
     292             :                                                   (unsigned long)unixid->id));
     293           0 :                                         status = NT_STATUS_NONE_MAPPED;
     294           0 :                                         goto failed;
     295             :                                 }
     296           0 :                                 talloc_free(tmp_ctx);
     297           0 :                                 return NT_STATUS_OK;
     298         133 :                         } else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
     299           0 :                                 DEBUG(1, ("Search for gidNumber=%lu gave '%s', failing to map to a SID!\n",
     300             :                                           (unsigned long)unixid->id, ldb_errstring(idmap_ctx->samdb)));
     301           0 :                                 status = NT_STATUS_NONE_MAPPED;
     302           0 :                                 goto failed;
     303             :                         }
     304             : 
     305         125 :                         id_type = "ID_TYPE_GID";
     306         125 :                         break;
     307           0 :                 default:
     308           0 :                         DEBUG(1, ("unixid->type must be type gid or uid (got %u) for lookup with id %lu\n",
     309             :                                   (unsigned)unixid->type, (unsigned long)unixid->id));
     310           0 :                         status = NT_STATUS_NONE_MAPPED;
     311           0 :                         goto failed;
     312             :         }
     313             : 
     314         214 :         ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
     315             :                                  NULL, "(&(|(type=ID_TYPE_BOTH)(type=%s))"
     316             :                                  "(xidNumber=%u))", id_type, unixid->id);
     317         214 :         if (ret != LDB_SUCCESS) {
     318           0 :                 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
     319           0 :                 status = NT_STATUS_NONE_MAPPED;
     320           0 :                 goto failed;
     321             :         }
     322             : 
     323         214 :         if (res->count == 1) {
     324          76 :                 const char *type = ldb_msg_find_attr_as_string(res->msgs[0],
     325             :                                                                "type", NULL);
     326             : 
     327          76 :                 *sid = idmap_msg_get_dom_sid(mem_ctx, res->msgs[0],
     328             :                                              "objectSid");
     329          76 :                 if (*sid == NULL) {
     330           0 :                         DEBUG(1, ("Failed to get sid from db: %u\n", ret));
     331           0 :                         status = NT_STATUS_NONE_MAPPED;
     332           0 :                         goto failed;
     333             :                 }
     334             : 
     335          76 :                 if (type == NULL) {
     336           0 :                         DEBUG(1, ("Invalid type for mapping entry.\n"));
     337           0 :                         talloc_free(tmp_ctx);
     338           0 :                         return NT_STATUS_NONE_MAPPED;
     339             :                 }
     340             : 
     341          76 :                 if (strcmp(type, "ID_TYPE_BOTH") == 0) {
     342           0 :                         unixid->type = ID_TYPE_BOTH;
     343          76 :                 } else if (strcmp(type, "ID_TYPE_UID") == 0) {
     344          76 :                         unixid->type = ID_TYPE_UID;
     345             :                 } else {
     346           0 :                         unixid->type = ID_TYPE_GID;
     347             :                 }
     348             : 
     349          76 :                 talloc_free(tmp_ctx);
     350          76 :                 return NT_STATUS_OK;
     351             :         }
     352             : 
     353         138 :         DEBUG(6, ("xid not found in idmap db, create S-1-22- SID.\n"));
     354             : 
     355             :         /* For local users/groups , we just create a rid = uid/gid */
     356         138 :         if (unixid->type == ID_TYPE_UID) {
     357           3 :                 unix_sid = &global_sid_Unix_Users;
     358             :         } else {
     359         133 :                 unix_sid = &global_sid_Unix_Groups;
     360             :         }
     361             : 
     362         138 :         new_sid = dom_sid_add_rid(mem_ctx, unix_sid, unixid->id);
     363         138 :         if (new_sid == NULL) {
     364           0 :                 status = NT_STATUS_NO_MEMORY;
     365           0 :                 goto failed;
     366             :         }
     367             : 
     368         138 :         *sid = new_sid;
     369         138 :         talloc_free(tmp_ctx);
     370         138 :         return NT_STATUS_OK;
     371             : 
     372           0 : failed:
     373           0 :         talloc_free(tmp_ctx);
     374           0 :         return status;
     375             : }
     376             : 
     377             : 
     378             : /**
     379             :  * Map a SID to an unixid struct.
     380             :  *
     381             :  * If no mapping exists, a new mapping will be created.
     382             :  *
     383             :  * \param idmap_ctx idmap context to use
     384             :  * \param mem_ctx talloc context to use
     385             :  * \param sid SID to map to an unixid struct
     386             :  * \param unixid pointer to a unixid struct
     387             :  * \return NT_STATUS_OK on success, NT_STATUS_INVALID_SID if the sid is not from
     388             :  * a trusted domain and idmap trusted only = true, NT_STATUS_NONE_MAPPED if the
     389             :  * mapping failed.
     390             :  */
     391       41268 : static NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx,
     392             :                                  TALLOC_CTX *mem_ctx,
     393             :                                  const struct dom_sid *sid,
     394             :                                  struct unixid *unixid)
     395             : {
     396             :         int ret;
     397             :         NTSTATUS status;
     398       41268 :         struct ldb_context *ldb = idmap_ctx->ldb_ctx;
     399             :         struct ldb_dn *dn;
     400             :         struct ldb_message *hwm_msg, *map_msg, *sam_msg;
     401       41268 :         struct ldb_result *res = NULL;
     402       41268 :         int trans = -1;
     403             :         uint32_t low, high, hwm, new_xid;
     404             :         struct dom_sid_buf sid_string;
     405             :         char *unixid_string, *hwm_string;
     406             :         bool hwm_entry_exists;
     407       41268 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     408       41268 :         const char *sam_attrs[] = {"uidNumber", "gidNumber", "samAccountType", NULL};
     409             : 
     410       41268 :         if (sid_check_is_in_unix_users(sid)) {
     411             :                 uint32_t rid;
     412           0 :                 DEBUG(6, ("This is a local unix uid, just calculate that.\n"));
     413           0 :                 status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
     414           0 :                 if (!NT_STATUS_IS_OK(status)) {
     415           0 :                         talloc_free(tmp_ctx);
     416           0 :                         return status;
     417             :                 }
     418             : 
     419           0 :                 unixid->id = rid;
     420           0 :                 unixid->type = ID_TYPE_UID;
     421             : 
     422           0 :                 talloc_free(tmp_ctx);
     423           0 :                 return NT_STATUS_OK;
     424             :         }
     425             : 
     426       41268 :         if (sid_check_is_in_unix_groups(sid)) {
     427             :                 uint32_t rid;
     428           0 :                 DEBUG(6, ("This is a local unix gid, just calculate that.\n"));
     429           0 :                 status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
     430           0 :                 if (!NT_STATUS_IS_OK(status)) {
     431           0 :                         talloc_free(tmp_ctx);
     432           0 :                         return status;
     433             :                 }
     434             : 
     435           0 :                 unixid->id = rid;
     436           0 :                 unixid->type = ID_TYPE_GID;
     437             : 
     438           0 :                 talloc_free(tmp_ctx);
     439           0 :                 return NT_STATUS_OK;
     440             :         }
     441             : 
     442             :         /* 
     443             :          * First check against our local DB, to see if this user has a
     444             :          * mapping there.  This means that the Samba4 AD DC behaves
     445             :          * much like a winbindd member server running idmap_ad
     446             :          */
     447             :         
     448       41268 :         if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
     449             :                 struct dom_sid_buf buf;
     450       31802 :                 ret = dsdb_search_one(idmap_ctx->samdb, tmp_ctx, &sam_msg,
     451             :                                       ldb_get_default_basedn(idmap_ctx->samdb),
     452             :                                       LDB_SCOPE_SUBTREE, sam_attrs, 0,
     453             :                                       "(&(objectSid=%s)"
     454             :                                       "(|(sAMaccountType=%u)(sAMaccountType=%u)(sAMaccountType=%u)"
     455             :                                       "(sAMaccountType=%u)(sAMaccountType=%u))"
     456             :                                       "(|(uidNumber=*)(gidNumber=*)))",
     457             :                                       dom_sid_str_buf(sid, &buf),
     458             :                                       ATYPE_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
     459             :                                       ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP);
     460             :         } else {
     461             :                 /* If we are not to use the rfc2307 attributes, we just emulate a non-match */
     462        8080 :                 ret = LDB_ERR_NO_SUCH_OBJECT;
     463             :         }
     464             : 
     465       39882 :         if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
     466             :                 struct dom_sid_buf buf;
     467           0 :                 DEBUG(1, ("Search for objectSid=%s gave duplicate results, failing to map to a unix ID!\n",
     468             :                           dom_sid_str_buf(sid, &buf)));
     469           0 :                 status = NT_STATUS_NONE_MAPPED;
     470           0 :                 goto failed;
     471       41268 :         } else if (ret == LDB_SUCCESS) {
     472           0 :                 uint32_t account_type = ldb_msg_find_attr_as_uint(sam_msg, "sAMaccountType", 0);
     473           0 :                 if ((account_type == ATYPE_ACCOUNT) ||
     474           0 :                     (account_type == ATYPE_WORKSTATION_TRUST ) ||
     475             :                     (account_type == ATYPE_INTERDOMAIN_TRUST ))
     476           0 :                 {
     477           0 :                         const struct ldb_val *v = ldb_msg_find_ldb_val(sam_msg, "uidNumber");
     478           0 :                         if (v) {
     479           0 :                                 unixid->type = ID_TYPE_UID;
     480           0 :                                 unixid->id = ldb_msg_find_attr_as_uint(sam_msg, "uidNumber", -1);
     481           0 :                                 talloc_free(tmp_ctx);
     482           0 :                                 return NT_STATUS_OK;
     483             :                         }
     484             : 
     485           0 :                 } else if ((account_type == ATYPE_SECURITY_GLOBAL_GROUP) ||
     486           0 :                            (account_type == ATYPE_SECURITY_LOCAL_GROUP))
     487             :                 {
     488           0 :                         const struct ldb_val *v = ldb_msg_find_ldb_val(sam_msg, "gidNumber");
     489           0 :                         if (v) {
     490           0 :                                 unixid->type = ID_TYPE_GID;
     491           0 :                                 unixid->id = ldb_msg_find_attr_as_uint(sam_msg, "gidNumber", -1);
     492           0 :                                 talloc_free(tmp_ctx);
     493           0 :                                 return NT_STATUS_OK;
     494             :                         }
     495             :                 }
     496       41268 :         } else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
     497             :                 struct dom_sid_buf buf;
     498           0 :                 DEBUG(1, ("Search for objectSid=%s gave '%s', failing to map to a SID!\n",
     499             :                           dom_sid_str_buf(sid, &buf),
     500             :                           ldb_errstring(idmap_ctx->samdb)));
     501             : 
     502           0 :                 status = NT_STATUS_NONE_MAPPED;
     503           0 :                 goto failed;
     504             :         }
     505             : 
     506       41268 :         ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
     507             :                                  NULL, "(&(objectClass=sidMap)(objectSid=%s))",
     508             :                                  ldap_encode_ndr_dom_sid(tmp_ctx, sid));
     509       41268 :         if (ret != LDB_SUCCESS) {
     510           0 :                 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
     511           0 :                 talloc_free(tmp_ctx);
     512           0 :                 return NT_STATUS_NONE_MAPPED;
     513             :         }
     514             : 
     515       41268 :         if (res->count == 1) {
     516       40352 :                 const char *type = ldb_msg_find_attr_as_string(res->msgs[0],
     517             :                                                                "type", NULL);
     518       40352 :                 new_xid = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber",
     519             :                                                     -1);
     520       40352 :                 if (new_xid == (uint32_t) -1) {
     521           0 :                         DEBUG(1, ("Invalid xid mapping.\n"));
     522           0 :                         talloc_free(tmp_ctx);
     523           0 :                         return NT_STATUS_NONE_MAPPED;
     524             :                 }
     525             : 
     526       40352 :                 if (type == NULL) {
     527           0 :                         DEBUG(1, ("Invalid type for mapping entry.\n"));
     528           0 :                         talloc_free(tmp_ctx);
     529           0 :                         return NT_STATUS_NONE_MAPPED;
     530             :                 }
     531             : 
     532       40352 :                 unixid->id = new_xid;
     533             : 
     534       40352 :                 if (strcmp(type, "ID_TYPE_BOTH") == 0) {
     535       34963 :                         unixid->type = ID_TYPE_BOTH;
     536        5389 :                 } else if (strcmp(type, "ID_TYPE_UID") == 0) {
     537         948 :                         unixid->type = ID_TYPE_UID;
     538             :                 } else {
     539        4441 :                         unixid->type = ID_TYPE_GID;
     540             :                 }
     541             : 
     542       40352 :                 talloc_free(tmp_ctx);
     543       40352 :                 return NT_STATUS_OK;
     544             :         }
     545             : 
     546         916 :         DEBUG(6, ("No existing mapping found, attempting to create one.\n"));
     547             : 
     548         916 :         trans = ldb_transaction_start(ldb);
     549         916 :         if (trans != LDB_SUCCESS) {
     550           0 :                 status = NT_STATUS_NONE_MAPPED;
     551           0 :                 goto failed;
     552             :         }
     553             : 
     554             :         /* Redo the search to make sure no one changed the mapping while we
     555             :          * weren't looking */
     556         916 :         ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
     557             :                                  NULL, "(&(objectClass=sidMap)(objectSid=%s))",
     558             :                                  ldap_encode_ndr_dom_sid(tmp_ctx, sid));
     559         916 :         if (ret != LDB_SUCCESS) {
     560           0 :                 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
     561           0 :                 status = NT_STATUS_NONE_MAPPED;
     562           0 :                 goto failed;
     563             :         }
     564             : 
     565         916 :         if (res->count > 0) {
     566           0 :                 DEBUG(1, ("Database changed while trying to add a sidmap.\n"));
     567           0 :                 status = NT_STATUS_RETRY;
     568           0 :                 goto failed;
     569             :         }
     570             : 
     571         916 :         ret = idmap_get_bounds(idmap_ctx, &low, &high);
     572         916 :         if (ret != LDB_SUCCESS) {
     573           0 :                 status = NT_STATUS_NONE_MAPPED;
     574           0 :                 goto failed;
     575             :         }
     576             : 
     577         916 :         dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
     578         916 :         if (dn == NULL) {
     579           0 :                 status = NT_STATUS_NO_MEMORY;
     580           0 :                 goto failed;
     581             :         }
     582             : 
     583         916 :         ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
     584         916 :         if (ret != LDB_SUCCESS) {
     585           0 :                 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
     586           0 :                 status = NT_STATUS_NONE_MAPPED;
     587           0 :                 goto failed;
     588             :         }
     589             : 
     590         916 :         if (res->count != 1) {
     591           0 :                 DEBUG(1, ("No CN=CONFIG record, idmap database is broken.\n"));
     592           0 :                 status = NT_STATUS_NONE_MAPPED;
     593           0 :                 goto failed;
     594             :         }
     595             : 
     596         916 :         hwm = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber", -1);
     597         916 :         if (hwm == (uint32_t)-1) {
     598          84 :                 hwm = low;
     599          84 :                 hwm_entry_exists = false;
     600             :         } else {
     601         772 :                 hwm_entry_exists = true;
     602             :         }
     603             : 
     604         916 :         if (hwm > high) {
     605           0 :                 DEBUG(1, ("Out of xids to allocate.\n"));
     606           0 :                 status = NT_STATUS_NONE_MAPPED;
     607           0 :                 goto failed;
     608             :         }
     609             : 
     610         916 :         hwm_msg = ldb_msg_new(tmp_ctx);
     611         916 :         if (hwm_msg == NULL) {
     612           0 :                 DEBUG(1, ("Out of memory when creating ldb_message\n"));
     613           0 :                 status = NT_STATUS_NO_MEMORY;
     614           0 :                 goto failed;
     615             :         }
     616             : 
     617         916 :         hwm_msg->dn = dn;
     618             : 
     619         916 :         new_xid = hwm;
     620         916 :         hwm++;
     621             : 
     622         916 :         hwm_string = talloc_asprintf(tmp_ctx, "%u", hwm);
     623         916 :         if (hwm_string == NULL) {
     624           0 :                 status = NT_STATUS_NO_MEMORY;
     625           0 :                 goto failed;
     626             :         }
     627             : 
     628         916 :         dom_sid_str_buf(sid, &sid_string);
     629             : 
     630         916 :         unixid_string = talloc_asprintf(tmp_ctx, "%u", new_xid);
     631         916 :         if (unixid_string == NULL) {
     632           0 :                 status = NT_STATUS_NO_MEMORY;
     633           0 :                 goto failed;
     634             :         }
     635             : 
     636         916 :         if (hwm_entry_exists) {
     637             :                 struct ldb_message_element *els;
     638             :                 struct ldb_val *vals;
     639             : 
     640             :                 /* We're modifying the entry, not just adding a new one. */
     641         832 :                 els = talloc_array(tmp_ctx, struct ldb_message_element, 2);
     642         832 :                 if (els == NULL) {
     643           0 :                         status = NT_STATUS_NO_MEMORY;
     644           0 :                         goto failed;
     645             :                 }
     646             : 
     647         832 :                 vals = talloc_array(tmp_ctx, struct ldb_val, 2);
     648         832 :                 if (vals == NULL) {
     649           0 :                         status = NT_STATUS_NO_MEMORY;
     650           0 :                         goto failed;
     651             :                 }
     652             : 
     653         832 :                 hwm_msg->num_elements = 2;
     654         832 :                 hwm_msg->elements = els;
     655             : 
     656         832 :                 els[0].num_values = 1;
     657         832 :                 els[0].values = &vals[0];
     658         832 :                 els[0].flags = LDB_FLAG_MOD_DELETE;
     659         832 :                 els[0].name = talloc_strdup(tmp_ctx, "xidNumber");
     660         832 :                 if (els[0].name == NULL) {
     661           0 :                         status = NT_STATUS_NO_MEMORY;
     662           0 :                         goto failed;
     663             :                 }
     664             : 
     665         832 :                 els[1].num_values = 1;
     666         832 :                 els[1].values = &vals[1];
     667         832 :                 els[1].flags = LDB_FLAG_MOD_ADD;
     668         832 :                 els[1].name = els[0].name;
     669             : 
     670         832 :                 vals[0].data = (uint8_t *)unixid_string;
     671         832 :                 vals[0].length = strlen(unixid_string);
     672         832 :                 vals[1].data = (uint8_t *)hwm_string;
     673         832 :                 vals[1].length = strlen(hwm_string);
     674             :         } else {
     675          84 :                 ret = ldb_msg_add_empty(hwm_msg, "xidNumber", LDB_FLAG_MOD_ADD,
     676             :                                         NULL);
     677          84 :                 if (ret != LDB_SUCCESS) {
     678           0 :                         status = NT_STATUS_NONE_MAPPED;
     679           0 :                         goto failed;
     680             :                 }
     681             : 
     682          84 :                 ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string);
     683          84 :                 if (ret != LDB_SUCCESS)
     684             :                 {
     685           0 :                         status = NT_STATUS_NONE_MAPPED;
     686           0 :                         goto failed;
     687             :                 }
     688             :         }
     689             : 
     690         916 :         ret = ldb_modify(ldb, hwm_msg);
     691         916 :         if (ret != LDB_SUCCESS) {
     692           0 :                 DEBUG(1, ("Updating the xid high water mark failed: %s\n",
     693             :                           ldb_errstring(ldb)));
     694           0 :                 status = NT_STATUS_NONE_MAPPED;
     695           0 :                 goto failed;
     696             :         }
     697             : 
     698         916 :         map_msg = ldb_msg_new(tmp_ctx);
     699         916 :         if (map_msg == NULL) {
     700           0 :                 status = NT_STATUS_NO_MEMORY;
     701           0 :                 goto failed;
     702             :         }
     703             : 
     704         916 :         map_msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s", sid_string.buf);
     705         916 :         if (map_msg->dn == NULL) {
     706           0 :                 status = NT_STATUS_NO_MEMORY;
     707           0 :                 goto failed;
     708             :         }
     709             : 
     710         916 :         ret = ldb_msg_add_string(map_msg, "xidNumber", unixid_string);
     711         916 :         if (ret != LDB_SUCCESS) {
     712           0 :                 status = NT_STATUS_NONE_MAPPED;
     713           0 :                 goto failed;
     714             :         }
     715             : 
     716         916 :         ret = idmap_msg_add_dom_sid(idmap_ctx, tmp_ctx, map_msg, "objectSid",
     717             :                         sid);
     718         916 :         if (ret != LDB_SUCCESS) {
     719           0 :                 status = NT_STATUS_NONE_MAPPED;
     720           0 :                 goto failed;
     721             :         }
     722             : 
     723         916 :         ret = ldb_msg_add_string(map_msg, "objectClass", "sidMap");
     724         916 :         if (ret != LDB_SUCCESS) {
     725           0 :                 status = NT_STATUS_NONE_MAPPED;
     726           0 :                 goto failed;
     727             :         }
     728             : 
     729         916 :         ret = ldb_msg_add_string(map_msg, "type", "ID_TYPE_BOTH");
     730         916 :         if (ret != LDB_SUCCESS) {
     731           0 :                 status = NT_STATUS_NONE_MAPPED;
     732           0 :                 goto failed;
     733             :         }
     734             : 
     735         916 :         ret = ldb_msg_add_string(map_msg, "cn", sid_string.buf);
     736         916 :         if (ret != LDB_SUCCESS) {
     737           0 :                 status = NT_STATUS_NONE_MAPPED;
     738           0 :                 goto failed;
     739             :         }
     740             : 
     741         916 :         ret = ldb_add(ldb, map_msg);
     742         916 :         if (ret != LDB_SUCCESS) {
     743           0 :                 DEBUG(1, ("Adding a sidmap failed: %s\n", ldb_errstring(ldb)));
     744           0 :                 status = NT_STATUS_NONE_MAPPED;
     745           0 :                 goto failed;
     746             :         }
     747             : 
     748         916 :         trans = ldb_transaction_commit(ldb);
     749         916 :         if (trans != LDB_SUCCESS) {
     750           0 :                 DEBUG(1, ("Transaction failed: %s\n", ldb_errstring(ldb)));
     751           0 :                 status = NT_STATUS_NONE_MAPPED;
     752           0 :                 goto failed;
     753             :         }
     754             : 
     755         916 :         unixid->id = new_xid;
     756         916 :         unixid->type = ID_TYPE_BOTH;
     757         916 :         talloc_free(tmp_ctx);
     758         916 :         return NT_STATUS_OK;
     759             : 
     760           0 : failed:
     761           0 :         if (trans == LDB_SUCCESS) ldb_transaction_cancel(ldb);
     762           0 :         talloc_free(tmp_ctx);
     763           0 :         return status;
     764             : }
     765             : 
     766             : /**
     767             :  * Convert an array of unixids to the corresponding array of SIDs
     768             :  *
     769             :  * \param idmap_ctx idmap context to use
     770             :  * \param mem_ctx talloc context the memory for the dom_sids is allocated
     771             :  * from.
     772             :  * \param count length of id_mapping array.
     773             :  * \param id array of id_mappings.
     774             :  * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not
     775             :  * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some
     776             :  * did not.
     777             :  */
     778             : 
     779         214 : NTSTATUS idmap_xids_to_sids(struct idmap_context *idmap_ctx,
     780             :                             TALLOC_CTX *mem_ctx,
     781             :                             struct id_map **id)
     782             : {
     783         214 :         unsigned int i, error_count = 0;
     784             :         NTSTATUS status;
     785             : 
     786         428 :         for (i = 0; id && id[i]; i++) {
     787         360 :                 status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
     788         348 :                                                 &id[i]->xid, &id[i]->sid);
     789         214 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
     790           0 :                         status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
     791           0 :                                                         &id[i]->xid,
     792           0 :                                                         &id[i]->sid);
     793             :                 }
     794         214 :                 if (!NT_STATUS_IS_OK(status)) {
     795           0 :                         DEBUG(1, ("idmapping xid_to_sid failed for id[%d]=%lu: %s\n",
     796             :                                   i, (unsigned long)id[i]->xid.id, nt_errstr(status)));
     797           0 :                         error_count++;
     798           0 :                         id[i]->status = ID_UNMAPPED;
     799             :                 } else {
     800         214 :                         id[i]->status = ID_MAPPED;
     801             :                 }
     802             :         }
     803             : 
     804         214 :         if (error_count == i) {
     805             :                 /* Mapping did not work at all. */
     806           0 :                 return NT_STATUS_NONE_MAPPED;
     807         214 :         } else if (error_count > 0) {
     808             :                 /* Some mappings worked, some did not. */
     809           0 :                 return STATUS_SOME_UNMAPPED;
     810             :         } else {
     811         214 :                 return NT_STATUS_OK;
     812             :         }
     813             : }
     814             : 
     815             : /**
     816             :  * Convert an array of SIDs to the corresponding array of unixids
     817             :  *
     818             :  * \param idmap_ctx idmap context to use
     819             :  * \param mem_ctx talloc context the memory for the unixids is allocated
     820             :  * from.
     821             :  * \param count length of id_mapping array.
     822             :  * \param id array of id_mappings.
     823             :  * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not
     824             :  * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some
     825             :  * did not.
     826             :  */
     827             : 
     828       41268 : NTSTATUS idmap_sids_to_xids(struct idmap_context *idmap_ctx,
     829             :                             TALLOC_CTX *mem_ctx,
     830             :                             struct id_map **id)
     831             : {
     832       41268 :         unsigned int i, error_count = 0;
     833             :         NTSTATUS status;
     834             : 
     835       82536 :         for (i = 0; id && id[i]; i++) {
     836       69678 :                 status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
     837       67344 :                                           id[i]->sid, &id[i]->xid);
     838       41268 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
     839           0 :                         status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
     840           0 :                                                   id[i]->sid,
     841           0 :                                                   &id[i]->xid);
     842             :                 }
     843       41268 :                 if (!NT_STATUS_IS_OK(status)) {
     844             :                         struct dom_sid_buf buf;
     845           0 :                         DEBUG(1, ("idmapping sid_to_xid failed for id[%d]=%s: %s\n",
     846             :                                   i,
     847             :                                   dom_sid_str_buf(id[i]->sid, &buf),
     848             :                                   nt_errstr(status)));
     849           0 :                         error_count++;
     850           0 :                         id[i]->status = ID_UNMAPPED;
     851             :                 } else {
     852       41268 :                         id[i]->status = ID_MAPPED;
     853             :                 }
     854             :         }
     855             : 
     856       41268 :         if (error_count == i) {
     857             :                 /* Mapping did not work at all. */
     858           0 :                 return NT_STATUS_NONE_MAPPED;
     859       41268 :         } else if (error_count > 0) {
     860             :                 /* Some mappings worked, some did not. */
     861           0 :                 return STATUS_SOME_UNMAPPED;
     862             :         } else {
     863       41268 :                 return NT_STATUS_OK;
     864             :         }
     865             : }
     866             : 

Generated by: LCOV version 1.13