LCOV - code coverage report
Current view: top level - source4/winbind - idmap.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 212 407 52.1 %
Date: 2024-06-13 04:01:37 Functions: 8 8 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         601 : static int idmap_get_bounds(struct idmap_context *idmap_ctx, uint32_t *low,
      45             :                 uint32_t *high)
      46             : {
      47         601 :         int ret = -1;
      48         601 :         struct ldb_context *ldb = idmap_ctx->ldb_ctx;
      49             :         struct ldb_dn *dn;
      50         601 :         struct ldb_result *res = NULL;
      51         601 :         TALLOC_CTX *tmp_ctx = talloc_new(idmap_ctx);
      52         601 :         uint32_t lower_bound = (uint32_t) -1;
      53         601 :         uint32_t upper_bound = (uint32_t) -1;
      54             : 
      55         601 :         dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
      56         601 :         if (dn == NULL) goto failed;
      57             : 
      58         601 :         ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
      59         601 :         if (ret != LDB_SUCCESS) goto failed;
      60             : 
      61         601 :         if (res->count != 1) {
      62           0 :                 ret = -1;
      63           0 :                 goto failed;
      64             :         }
      65             : 
      66         601 :         lower_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "lowerBound", -1);
      67         601 :         if (lower_bound != (uint32_t) -1) {
      68         601 :                 ret = LDB_SUCCESS;
      69             :         } else {
      70           0 :                 ret = -1;
      71           0 :                 goto failed;
      72             :         }
      73             : 
      74         601 :         upper_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "upperBound", -1);
      75         601 :         if (upper_bound != (uint32_t) -1) {
      76         601 :                 ret = LDB_SUCCESS;
      77             :         } else {
      78           0 :                 ret = -1;
      79             :         }
      80             : 
      81         601 : failed:
      82         601 :         talloc_free(tmp_ctx);
      83         601 :         *low  = lower_bound;
      84         601 :         *high = upper_bound;
      85         601 :         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         601 : 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         601 :         ndr_err = ndr_push_struct_blob(&val, mem_ctx, sid,
     105             :                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
     106             : 
     107         601 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     108           0 :                 return -1;
     109             :         }
     110             : 
     111         601 :         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          30 : 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          30 :         val = ldb_msg_find_ldb_val(msg, attr_name);
     130          30 :         if (val == NULL) {
     131           0 :                 return NULL;
     132             :         }
     133             : 
     134          30 :         sid = talloc(mem_ctx, struct dom_sid);
     135          30 :         if (sid == NULL) {
     136           0 :                 return NULL;
     137             :         }
     138             : 
     139          30 :         ndr_err = ndr_pull_struct_blob(val, sid, sid,
     140             :                                        (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
     141          30 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     142           0 :                 talloc_free(sid);
     143           0 :                 return NULL;
     144             :         }
     145             : 
     146          30 :         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        3923 : 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        3923 :         idmap_ctx = talloc(mem_ctx, struct idmap_context);
     164        3923 :         if (idmap_ctx == NULL) {
     165           0 :                 return NULL;
     166             :         }
     167             : 
     168        3923 :         idmap_ctx->lp_ctx = lp_ctx;
     169             : 
     170        3923 :         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        3923 :         if (idmap_ctx->ldb_ctx == NULL) {
     175           0 :                 goto fail;
     176             :         }
     177             : 
     178        3923 :         idmap_ctx->samdb = samdb_connect(idmap_ctx,
     179             :                                          ev_ctx,
     180             :                                          lp_ctx,
     181             :                                          system_session(lp_ctx),
     182             :                                          NULL,
     183             :                                          0);
     184        3923 :         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        3923 :         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         118 : 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         118 :         struct ldb_context *ldb = idmap_ctx->ldb_ctx;
     216         118 :         struct ldb_result *res = NULL;
     217             :         struct ldb_message *msg;
     218             :         const struct dom_sid *unix_sid;
     219             :         struct dom_sid *new_sid;
     220         118 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     221             :         const char *id_type;
     222             : 
     223         118 :         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         118 :         switch (unixid->type) {
     232          33 :                 case ID_TYPE_UID:
     233          33 :                         if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
     234          33 :                                 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          33 :                         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          33 :                         } 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          33 :                         } 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          33 :                         id_type = "ID_TYPE_UID";
     269          33 :                         break;
     270          85 :                 case ID_TYPE_GID:
     271          85 :                         if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
     272          85 :                                 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          85 :                         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          85 :                         } 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          85 :                         } 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          85 :                         id_type = "ID_TYPE_GID";
     306          85 :                         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         118 :         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         118 :         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         118 :         if (res->count == 1) {
     324          30 :                 const char *type = ldb_msg_find_attr_as_string(res->msgs[0],
     325             :                                                                "type", NULL);
     326             : 
     327          30 :                 *sid = idmap_msg_get_dom_sid(mem_ctx, res->msgs[0],
     328             :                                              "objectSid");
     329          30 :                 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          30 :                 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          30 :                 if (strcmp(type, "ID_TYPE_BOTH") == 0) {
     342           0 :                         unixid->type = ID_TYPE_BOTH;
     343          30 :                 } else if (strcmp(type, "ID_TYPE_UID") == 0) {
     344          30 :                         unixid->type = ID_TYPE_UID;
     345             :                 } else {
     346           0 :                         unixid->type = ID_TYPE_GID;
     347             :                 }
     348             : 
     349          30 :                 talloc_free(tmp_ctx);
     350          30 :                 return NT_STATUS_OK;
     351             :         }
     352             : 
     353          88 :         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          88 :         if (unixid->type == ID_TYPE_UID) {
     357           3 :                 unix_sid = &global_sid_Unix_Users;
     358             :         } else {
     359          85 :                 unix_sid = &global_sid_Unix_Groups;
     360             :         }
     361             : 
     362          88 :         new_sid = dom_sid_add_rid(mem_ctx, unix_sid, unixid->id);
     363          88 :         if (new_sid == NULL) {
     364           0 :                 status = NT_STATUS_NO_MEMORY;
     365           0 :                 goto failed;
     366             :         }
     367             : 
     368          88 :         *sid = new_sid;
     369          88 :         talloc_free(tmp_ctx);
     370          88 :         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       21347 : 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       21347 :         struct ldb_context *ldb = idmap_ctx->ldb_ctx;
     399             :         struct ldb_dn *dn;
     400             :         struct ldb_message *hwm_msg, *map_msg, *sam_msg;
     401       21347 :         struct ldb_result *res = NULL;
     402       21347 :         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       21347 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     408       21347 :         const char *sam_attrs[] = {"uidNumber", "gidNumber", "samAccountType", NULL};
     409             : 
     410       21347 :         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       21347 :         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       21347 :         if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
     449             :                 struct dom_sid_buf buf;
     450       21347 :                 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           0 :                 ret = LDB_ERR_NO_SUCH_OBJECT;
     463             :         }
     464             : 
     465       21347 :         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       21347 :         } 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             :                            (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       21347 :         } 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       21347 :         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       21347 :         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       21347 :         if (res->count == 1) {
     516       20746 :                 const char *type = ldb_msg_find_attr_as_string(res->msgs[0],
     517             :                                                                "type", NULL);
     518       20746 :                 new_xid = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber",
     519             :                                                     -1);
     520       20746 :                 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       20746 :                 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       20746 :                 unixid->id = new_xid;
     533             : 
     534       20746 :                 if (strcmp(type, "ID_TYPE_BOTH") == 0) {
     535       18019 :                         unixid->type = ID_TYPE_BOTH;
     536        2727 :                 } else if (strcmp(type, "ID_TYPE_UID") == 0) {
     537         432 :                         unixid->type = ID_TYPE_UID;
     538             :                 } else {
     539        2295 :                         unixid->type = ID_TYPE_GID;
     540             :                 }
     541             : 
     542       20746 :                 talloc_free(tmp_ctx);
     543       20746 :                 return NT_STATUS_OK;
     544             :         }
     545             : 
     546         601 :         DEBUG(6, ("No existing mapping found, attempting to create one.\n"));
     547             : 
     548         601 :         trans = ldb_transaction_start(ldb);
     549         601 :         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         601 :         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         601 :         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         601 :         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         601 :         ret = idmap_get_bounds(idmap_ctx, &low, &high);
     572         601 :         if (ret != LDB_SUCCESS) {
     573           0 :                 status = NT_STATUS_NONE_MAPPED;
     574           0 :                 goto failed;
     575             :         }
     576             : 
     577         601 :         dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
     578         601 :         if (dn == NULL) {
     579           0 :                 status = NT_STATUS_NO_MEMORY;
     580           0 :                 goto failed;
     581             :         }
     582             : 
     583         601 :         ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
     584         601 :         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         601 :         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         601 :         hwm = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber", -1);
     597         601 :         if (hwm == (uint32_t)-1) {
     598          56 :                 hwm = low;
     599          56 :                 hwm_entry_exists = false;
     600             :         } else {
     601         545 :                 hwm_entry_exists = true;
     602             :         }
     603             : 
     604         601 :         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         601 :         hwm_msg = ldb_msg_new(tmp_ctx);
     611         601 :         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         601 :         hwm_msg->dn = dn;
     618             : 
     619         601 :         new_xid = hwm;
     620         601 :         hwm++;
     621             : 
     622         601 :         hwm_string = talloc_asprintf(tmp_ctx, "%u", hwm);
     623         601 :         if (hwm_string == NULL) {
     624           0 :                 status = NT_STATUS_NO_MEMORY;
     625           0 :                 goto failed;
     626             :         }
     627             : 
     628         601 :         dom_sid_str_buf(sid, &sid_string);
     629             : 
     630         601 :         unixid_string = talloc_asprintf(tmp_ctx, "%u", new_xid);
     631         601 :         if (unixid_string == NULL) {
     632           0 :                 status = NT_STATUS_NO_MEMORY;
     633           0 :                 goto failed;
     634             :         }
     635             : 
     636         601 :         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         545 :                 els = talloc_array(tmp_ctx, struct ldb_message_element, 2);
     642         545 :                 if (els == NULL) {
     643           0 :                         status = NT_STATUS_NO_MEMORY;
     644           0 :                         goto failed;
     645             :                 }
     646             : 
     647         545 :                 vals = talloc_array(tmp_ctx, struct ldb_val, 2);
     648         545 :                 if (vals == NULL) {
     649           0 :                         status = NT_STATUS_NO_MEMORY;
     650           0 :                         goto failed;
     651             :                 }
     652             : 
     653         545 :                 hwm_msg->num_elements = 2;
     654         545 :                 hwm_msg->elements = els;
     655             : 
     656         545 :                 els[0].num_values = 1;
     657         545 :                 els[0].values = &vals[0];
     658         545 :                 els[0].flags = LDB_FLAG_MOD_DELETE;
     659         545 :                 els[0].name = talloc_strdup(tmp_ctx, "xidNumber");
     660         545 :                 if (els[0].name == NULL) {
     661           0 :                         status = NT_STATUS_NO_MEMORY;
     662           0 :                         goto failed;
     663             :                 }
     664             : 
     665         545 :                 els[1].num_values = 1;
     666         545 :                 els[1].values = &vals[1];
     667         545 :                 els[1].flags = LDB_FLAG_MOD_ADD;
     668         545 :                 els[1].name = els[0].name;
     669             : 
     670         545 :                 vals[0].data = (uint8_t *)unixid_string;
     671         545 :                 vals[0].length = strlen(unixid_string);
     672         545 :                 vals[1].data = (uint8_t *)hwm_string;
     673         545 :                 vals[1].length = strlen(hwm_string);
     674             :         } else {
     675          56 :                 ret = ldb_msg_append_string(hwm_msg, "xidNumber", hwm_string,
     676             :                                             LDB_FLAG_MOD_ADD);
     677          56 :                 if (ret != LDB_SUCCESS)
     678             :                 {
     679           0 :                         status = NT_STATUS_NONE_MAPPED;
     680           0 :                         goto failed;
     681             :                 }
     682             :         }
     683             : 
     684         601 :         ret = ldb_modify(ldb, hwm_msg);
     685         601 :         if (ret != LDB_SUCCESS) {
     686           0 :                 DEBUG(1, ("Updating the xid high water mark failed: %s\n",
     687             :                           ldb_errstring(ldb)));
     688           0 :                 status = NT_STATUS_NONE_MAPPED;
     689           0 :                 goto failed;
     690             :         }
     691             : 
     692         601 :         map_msg = ldb_msg_new(tmp_ctx);
     693         601 :         if (map_msg == NULL) {
     694           0 :                 status = NT_STATUS_NO_MEMORY;
     695           0 :                 goto failed;
     696             :         }
     697             : 
     698         601 :         map_msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s", sid_string.buf);
     699         601 :         if (map_msg->dn == NULL) {
     700           0 :                 status = NT_STATUS_NO_MEMORY;
     701           0 :                 goto failed;
     702             :         }
     703             : 
     704         601 :         ret = ldb_msg_add_string(map_msg, "xidNumber", unixid_string);
     705         601 :         if (ret != LDB_SUCCESS) {
     706           0 :                 status = NT_STATUS_NONE_MAPPED;
     707           0 :                 goto failed;
     708             :         }
     709             : 
     710         601 :         ret = idmap_msg_add_dom_sid(idmap_ctx, tmp_ctx, map_msg, "objectSid",
     711             :                         sid);
     712         601 :         if (ret != LDB_SUCCESS) {
     713           0 :                 status = NT_STATUS_NONE_MAPPED;
     714           0 :                 goto failed;
     715             :         }
     716             : 
     717         601 :         ret = ldb_msg_add_string(map_msg, "objectClass", "sidMap");
     718         601 :         if (ret != LDB_SUCCESS) {
     719           0 :                 status = NT_STATUS_NONE_MAPPED;
     720           0 :                 goto failed;
     721             :         }
     722             : 
     723         601 :         ret = ldb_msg_add_string(map_msg, "type", "ID_TYPE_BOTH");
     724         601 :         if (ret != LDB_SUCCESS) {
     725           0 :                 status = NT_STATUS_NONE_MAPPED;
     726           0 :                 goto failed;
     727             :         }
     728             : 
     729         601 :         ret = ldb_msg_add_string(map_msg, "cn", sid_string.buf);
     730         601 :         if (ret != LDB_SUCCESS) {
     731           0 :                 status = NT_STATUS_NONE_MAPPED;
     732           0 :                 goto failed;
     733             :         }
     734             : 
     735         601 :         ret = ldb_add(ldb, map_msg);
     736         601 :         if (ret != LDB_SUCCESS) {
     737           0 :                 DEBUG(1, ("Adding a sidmap failed: %s\n", ldb_errstring(ldb)));
     738           0 :                 status = NT_STATUS_NONE_MAPPED;
     739           0 :                 goto failed;
     740             :         }
     741             : 
     742         601 :         trans = ldb_transaction_commit(ldb);
     743         601 :         if (trans != LDB_SUCCESS) {
     744           0 :                 DEBUG(1, ("Transaction failed: %s\n", ldb_errstring(ldb)));
     745           0 :                 status = NT_STATUS_NONE_MAPPED;
     746           0 :                 goto failed;
     747             :         }
     748             : 
     749         601 :         unixid->id = new_xid;
     750         601 :         unixid->type = ID_TYPE_BOTH;
     751         601 :         talloc_free(tmp_ctx);
     752         601 :         return NT_STATUS_OK;
     753             : 
     754           0 : failed:
     755           0 :         if (trans == LDB_SUCCESS) ldb_transaction_cancel(ldb);
     756           0 :         talloc_free(tmp_ctx);
     757           0 :         return status;
     758             : }
     759             : 
     760             : /**
     761             :  * Convert an array of unixids to the corresponding array of SIDs
     762             :  *
     763             :  * \param idmap_ctx idmap context to use
     764             :  * \param mem_ctx talloc context the memory for the dom_sids is allocated
     765             :  * from.
     766             :  * \param count length of id_mapping array.
     767             :  * \param id array of id_mappings.
     768             :  * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not
     769             :  * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some
     770             :  * did not.
     771             :  */
     772             : 
     773         118 : NTSTATUS idmap_xids_to_sids(struct idmap_context *idmap_ctx,
     774             :                             TALLOC_CTX *mem_ctx,
     775             :                             struct id_map **id)
     776             : {
     777         118 :         unsigned int i, error_count = 0;
     778             :         NTSTATUS status;
     779             : 
     780         236 :         for (i = 0; id && id[i]; i++) {
     781         216 :                 status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
     782         216 :                                                 &id[i]->xid, &id[i]->sid);
     783         118 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
     784           0 :                         status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
     785           0 :                                                         &id[i]->xid,
     786           0 :                                                         &id[i]->sid);
     787             :                 }
     788         118 :                 if (!NT_STATUS_IS_OK(status)) {
     789           0 :                         DEBUG(1, ("idmapping xid_to_sid failed for id[%d]=%lu: %s\n",
     790             :                                   i, (unsigned long)id[i]->xid.id, nt_errstr(status)));
     791           0 :                         error_count++;
     792           0 :                         id[i]->status = ID_UNMAPPED;
     793             :                 } else {
     794         118 :                         id[i]->status = ID_MAPPED;
     795             :                 }
     796             :         }
     797             : 
     798         118 :         if (error_count == i) {
     799             :                 /* Mapping did not work at all. */
     800           0 :                 return NT_STATUS_NONE_MAPPED;
     801         118 :         } else if (error_count > 0) {
     802             :                 /* Some mappings worked, some did not. */
     803           0 :                 return STATUS_SOME_UNMAPPED;
     804             :         } else {
     805         118 :                 return NT_STATUS_OK;
     806             :         }
     807             : }
     808             : 
     809             : /**
     810             :  * Convert an array of SIDs to the corresponding array of unixids
     811             :  *
     812             :  * \param idmap_ctx idmap context to use
     813             :  * \param mem_ctx talloc context the memory for the unixids is allocated
     814             :  * from.
     815             :  * \param count length of id_mapping array.
     816             :  * \param id array of id_mappings.
     817             :  * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not
     818             :  * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some
     819             :  * did not.
     820             :  */
     821             : 
     822       21347 : NTSTATUS idmap_sids_to_xids(struct idmap_context *idmap_ctx,
     823             :                             TALLOC_CTX *mem_ctx,
     824             :                             struct id_map **id)
     825             : {
     826       21347 :         unsigned int i, error_count = 0;
     827             :         NTSTATUS status;
     828             : 
     829       42694 :         for (i = 0; id && id[i]; i++) {
     830       38550 :                 status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
     831       38550 :                                           id[i]->sid, &id[i]->xid);
     832       21347 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
     833           0 :                         status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
     834           0 :                                                   id[i]->sid,
     835           0 :                                                   &id[i]->xid);
     836             :                 }
     837       21347 :                 if (!NT_STATUS_IS_OK(status)) {
     838             :                         struct dom_sid_buf buf;
     839           0 :                         DEBUG(1, ("idmapping sid_to_xid failed for id[%d]=%s: %s\n",
     840             :                                   i,
     841             :                                   dom_sid_str_buf(id[i]->sid, &buf),
     842             :                                   nt_errstr(status)));
     843           0 :                         error_count++;
     844           0 :                         id[i]->status = ID_UNMAPPED;
     845             :                 } else {
     846       21347 :                         id[i]->status = ID_MAPPED;
     847             :                 }
     848             :         }
     849             : 
     850       21347 :         if (error_count == i) {
     851             :                 /* Mapping did not work at all. */
     852           0 :                 return NT_STATUS_NONE_MAPPED;
     853       21347 :         } else if (error_count > 0) {
     854             :                 /* Some mappings worked, some did not. */
     855           0 :                 return STATUS_SOME_UNMAPPED;
     856             :         } else {
     857       21347 :                 return NT_STATUS_OK;
     858             :         }
     859             : }
     860             : 

Generated by: LCOV version 1.13