LCOV - code coverage report
Current view: top level - source4/winbind - idmap.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 239 439 54.4 %
Date: 2024-04-21 15:09:00 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         720 : static int idmap_get_bounds(struct idmap_context *idmap_ctx, uint32_t *low,
      45             :                 uint32_t *high)
      46             : {
      47         720 :         int ret = -1;
      48         720 :         struct ldb_context *ldb = idmap_ctx->ldb_ctx;
      49          50 :         struct ldb_dn *dn;
      50         720 :         struct ldb_result *res = NULL;
      51         720 :         TALLOC_CTX *tmp_ctx = talloc_new(idmap_ctx);
      52         720 :         uint32_t lower_bound = (uint32_t) -1;
      53         720 :         uint32_t upper_bound = (uint32_t) -1;
      54             : 
      55         720 :         dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
      56         720 :         if (dn == NULL) goto failed;
      57             : 
      58         720 :         ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
      59         720 :         if (ret != LDB_SUCCESS) goto failed;
      60             : 
      61         720 :         if (res->count != 1) {
      62           0 :                 ret = -1;
      63           0 :                 goto failed;
      64             :         }
      65             : 
      66         720 :         lower_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "lowerBound", -1);
      67         720 :         if (lower_bound != (uint32_t) -1) {
      68         720 :                 ret = LDB_SUCCESS;
      69             :         } else {
      70           0 :                 ret = -1;
      71           0 :                 goto failed;
      72             :         }
      73             : 
      74         720 :         upper_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "upperBound", -1);
      75         720 :         if (upper_bound != (uint32_t) -1) {
      76         670 :                 ret = LDB_SUCCESS;
      77             :         } else {
      78           0 :                 ret = -1;
      79             :         }
      80             : 
      81         720 : failed:
      82         720 :         talloc_free(tmp_ctx);
      83         720 :         *low  = lower_bound;
      84         720 :         *high = upper_bound;
      85         720 :         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         720 : 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          50 :         struct ldb_val val;
     102          50 :         enum ndr_err_code ndr_err;
     103             : 
     104         720 :         ndr_err = ndr_push_struct_blob(&val, mem_ctx, sid,
     105             :                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
     106             : 
     107         720 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     108           0 :                 return -1;
     109             :         }
     110             : 
     111         720 :         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           2 :         struct dom_sid *sid;
     126           2 :         const struct ldb_val *val;
     127           2 :         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       10184 : struct idmap_context *idmap_init(TALLOC_CTX *mem_ctx,
     158             :                                  struct tevent_context *ev_ctx,
     159             :                                  struct loadparm_context *lp_ctx)
     160             : {
     161         860 :         struct idmap_context *idmap_ctx;
     162             : 
     163       10184 :         idmap_ctx = talloc(mem_ctx, struct idmap_context);
     164       10184 :         if (idmap_ctx == NULL) {
     165           0 :                 return NULL;
     166             :         }
     167             : 
     168       10184 :         idmap_ctx->lp_ctx = lp_ctx;
     169             : 
     170       10184 :         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       10184 :         if (idmap_ctx->ldb_ctx == NULL) {
     175           0 :                 goto fail;
     176             :         }
     177             : 
     178       10184 :         idmap_ctx->samdb = samdb_connect(idmap_ctx,
     179             :                                          ev_ctx,
     180             :                                          lp_ctx,
     181             :                                          system_session(lp_ctx),
     182             :                                          NULL,
     183             :                                          0);
     184       10184 :         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        9324 :         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         154 : 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           8 :         int ret;
     214           8 :         NTSTATUS status;
     215         154 :         struct ldb_context *ldb = idmap_ctx->ldb_ctx;
     216         154 :         struct ldb_result *res = NULL;
     217           8 :         struct ldb_message *msg;
     218           8 :         const struct dom_sid *unix_sid;
     219           8 :         struct dom_sid *new_sid;
     220         154 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     221           8 :         const char *id_type;
     222             : 
     223         154 :         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         154 :         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          73 :                 case ID_TYPE_GID:
     271          73 :                         if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
     272          71 :                                 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          71 :                         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          73 :                         } 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          73 :                         } 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          69 :                         id_type = "ID_TYPE_GID";
     306          69 :                         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         154 :         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         154 :         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         154 :         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          78 :         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          78 :         if (unixid->type == ID_TYPE_UID) {
     357           3 :                 unix_sid = &global_sid_Unix_Users;
     358             :         } else {
     359          73 :                 unix_sid = &global_sid_Unix_Groups;
     360             :         }
     361             : 
     362          78 :         new_sid = dom_sid_add_rid(mem_ctx, unix_sid, unixid->id);
     363          78 :         if (new_sid == NULL) {
     364           0 :                 status = NT_STATUS_NO_MEMORY;
     365           0 :                 goto failed;
     366             :         }
     367             : 
     368          78 :         *sid = new_sid;
     369          78 :         talloc_free(tmp_ctx);
     370          78 :         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       44006 : 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        2298 :         int ret;
     397        2298 :         NTSTATUS status;
     398       44006 :         struct ldb_context *ldb = idmap_ctx->ldb_ctx;
     399        2298 :         struct ldb_dn *dn;
     400        2298 :         struct ldb_message *hwm_msg, *map_msg, *sam_msg;
     401       44006 :         struct ldb_result *res = NULL;
     402       44006 :         int trans = -1;
     403        2298 :         uint32_t low, high, hwm, new_xid;
     404        2298 :         struct dom_sid_buf sid_string;
     405        2298 :         char *unixid_string, *hwm_string;
     406        2298 :         bool hwm_entry_exists;
     407       44006 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     408       44006 :         const char *sam_attrs[] = {"uidNumber", "gidNumber", "samAccountType", NULL};
     409             : 
     410       44006 :         if (sid_check_is_in_unix_users(sid)) {
     411           0 :                 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       44006 :         if (sid_check_is_in_unix_groups(sid)) {
     427           0 :                 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       44006 :         if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
     449         918 :                 struct dom_sid_buf buf;
     450       34546 :                 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       42626 :         if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
     466           0 :                 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       44006 :         } 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       44006 :         } else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
     497           0 :                 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       44006 :         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       44006 :         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       44006 :         if (res->count == 1) {
     516       43286 :                 const char *type = ldb_msg_find_attr_as_string(res->msgs[0],
     517             :                                                                "type", NULL);
     518       43286 :                 new_xid = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber",
     519             :                                                     -1);
     520       43286 :                 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       43286 :                 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       43286 :                 unixid->id = new_xid;
     533             : 
     534       43286 :                 if (strcmp(type, "ID_TYPE_BOTH") == 0) {
     535       37651 :                         unixid->type = ID_TYPE_BOTH;
     536        5635 :                 } else if (strcmp(type, "ID_TYPE_UID") == 0) {
     537         962 :                         unixid->type = ID_TYPE_UID;
     538             :                 } else {
     539        4673 :                         unixid->type = ID_TYPE_GID;
     540             :                 }
     541             : 
     542       43286 :                 talloc_free(tmp_ctx);
     543       43286 :                 return NT_STATUS_OK;
     544             :         }
     545             : 
     546         720 :         DEBUG(6, ("No existing mapping found, attempting to create one.\n"));
     547             : 
     548         720 :         trans = ldb_transaction_start(ldb);
     549         720 :         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         720 :         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         720 :         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         720 :         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         720 :         ret = idmap_get_bounds(idmap_ctx, &low, &high);
     572         720 :         if (ret != LDB_SUCCESS) {
     573           0 :                 status = NT_STATUS_NONE_MAPPED;
     574           0 :                 goto failed;
     575             :         }
     576             : 
     577         720 :         dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
     578         720 :         if (dn == NULL) {
     579           0 :                 status = NT_STATUS_NO_MEMORY;
     580           0 :                 goto failed;
     581             :         }
     582             : 
     583         720 :         ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
     584         720 :         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         720 :         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         720 :         hwm = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber", -1);
     597         720 :         if (hwm == (uint32_t)-1) {
     598          81 :                 hwm = low;
     599          81 :                 hwm_entry_exists = false;
     600             :         } else {
     601         594 :                 hwm_entry_exists = true;
     602             :         }
     603             : 
     604         720 :         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         720 :         hwm_msg = ldb_msg_new(tmp_ctx);
     611         720 :         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         720 :         hwm_msg->dn = dn;
     618             : 
     619         720 :         new_xid = hwm;
     620         720 :         hwm++;
     621             : 
     622         720 :         hwm_string = talloc_asprintf(tmp_ctx, "%u", hwm);
     623         720 :         if (hwm_string == NULL) {
     624           0 :                 status = NT_STATUS_NO_MEMORY;
     625           0 :                 goto failed;
     626             :         }
     627             : 
     628         720 :         dom_sid_str_buf(sid, &sid_string);
     629             : 
     630         720 :         unixid_string = talloc_asprintf(tmp_ctx, "%u", new_xid);
     631         720 :         if (unixid_string == NULL) {
     632           0 :                 status = NT_STATUS_NO_MEMORY;
     633           0 :                 goto failed;
     634             :         }
     635             : 
     636         720 :         if (hwm_entry_exists) {
     637          45 :                 struct ldb_message_element *els;
     638          45 :                 struct ldb_val *vals;
     639             : 
     640             :                 /* We're modifying the entry, not just adding a new one. */
     641         639 :                 els = talloc_array(tmp_ctx, struct ldb_message_element, 2);
     642         639 :                 if (els == NULL) {
     643           0 :                         status = NT_STATUS_NO_MEMORY;
     644           0 :                         goto failed;
     645             :                 }
     646             : 
     647         639 :                 vals = talloc_array(tmp_ctx, struct ldb_val, 2);
     648         639 :                 if (vals == NULL) {
     649           0 :                         status = NT_STATUS_NO_MEMORY;
     650           0 :                         goto failed;
     651             :                 }
     652             : 
     653         639 :                 hwm_msg->num_elements = 2;
     654         639 :                 hwm_msg->elements = els;
     655             : 
     656         639 :                 els[0].num_values = 1;
     657         639 :                 els[0].values = &vals[0];
     658         639 :                 els[0].flags = LDB_FLAG_MOD_DELETE;
     659         639 :                 els[0].name = talloc_strdup(tmp_ctx, "xidNumber");
     660         639 :                 if (els[0].name == NULL) {
     661           0 :                         status = NT_STATUS_NO_MEMORY;
     662           0 :                         goto failed;
     663             :                 }
     664             : 
     665         639 :                 els[1].num_values = 1;
     666         639 :                 els[1].values = &vals[1];
     667         639 :                 els[1].flags = LDB_FLAG_MOD_ADD;
     668         639 :                 els[1].name = els[0].name;
     669             : 
     670         639 :                 vals[0].data = (uint8_t *)unixid_string;
     671         639 :                 vals[0].length = strlen(unixid_string);
     672         639 :                 vals[1].data = (uint8_t *)hwm_string;
     673         639 :                 vals[1].length = strlen(hwm_string);
     674             :         } else {
     675          81 :                 ret = ldb_msg_append_string(hwm_msg, "xidNumber", hwm_string,
     676             :                                             LDB_FLAG_MOD_ADD);
     677          81 :                 if (ret != LDB_SUCCESS)
     678             :                 {
     679           0 :                         status = NT_STATUS_NONE_MAPPED;
     680           0 :                         goto failed;
     681             :                 }
     682             :         }
     683             : 
     684         720 :         ret = ldb_modify(ldb, hwm_msg);
     685         720 :         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         720 :         map_msg = ldb_msg_new(tmp_ctx);
     693         720 :         if (map_msg == NULL) {
     694           0 :                 status = NT_STATUS_NO_MEMORY;
     695           0 :                 goto failed;
     696             :         }
     697             : 
     698         720 :         map_msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s", sid_string.buf);
     699         720 :         if (map_msg->dn == NULL) {
     700           0 :                 status = NT_STATUS_NO_MEMORY;
     701           0 :                 goto failed;
     702             :         }
     703             : 
     704         720 :         ret = ldb_msg_add_string(map_msg, "xidNumber", unixid_string);
     705         720 :         if (ret != LDB_SUCCESS) {
     706           0 :                 status = NT_STATUS_NONE_MAPPED;
     707           0 :                 goto failed;
     708             :         }
     709             : 
     710         720 :         ret = idmap_msg_add_dom_sid(idmap_ctx, tmp_ctx, map_msg, "objectSid",
     711             :                         sid);
     712         720 :         if (ret != LDB_SUCCESS) {
     713           0 :                 status = NT_STATUS_NONE_MAPPED;
     714           0 :                 goto failed;
     715             :         }
     716             : 
     717         720 :         ret = ldb_msg_add_string(map_msg, "objectClass", "sidMap");
     718         720 :         if (ret != LDB_SUCCESS) {
     719           0 :                 status = NT_STATUS_NONE_MAPPED;
     720           0 :                 goto failed;
     721             :         }
     722             : 
     723         720 :         ret = ldb_msg_add_string(map_msg, "type", "ID_TYPE_BOTH");
     724         720 :         if (ret != LDB_SUCCESS) {
     725           0 :                 status = NT_STATUS_NONE_MAPPED;
     726           0 :                 goto failed;
     727             :         }
     728             : 
     729         720 :         ret = ldb_msg_add_string(map_msg, "cn", sid_string.buf);
     730         720 :         if (ret != LDB_SUCCESS) {
     731           0 :                 status = NT_STATUS_NONE_MAPPED;
     732           0 :                 goto failed;
     733             :         }
     734             : 
     735         720 :         ret = ldb_add(ldb, map_msg);
     736         720 :         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         720 :         trans = ldb_transaction_commit(ldb);
     743         720 :         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         720 :         unixid->id = new_xid;
     750         720 :         unixid->type = ID_TYPE_BOTH;
     751         720 :         talloc_free(tmp_ctx);
     752         720 :         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         154 : NTSTATUS idmap_xids_to_sids(struct idmap_context *idmap_ctx,
     774             :                             TALLOC_CTX *mem_ctx,
     775             :                             struct id_map **id)
     776             : {
     777         154 :         unsigned int i, error_count = 0;
     778           8 :         NTSTATUS status;
     779             : 
     780         308 :         for (i = 0; id && id[i]; i++) {
     781         154 :                 status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
     782         146 :                                                 &id[i]->xid, &id[i]->sid);
     783         154 :                 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         154 :                 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         154 :                         id[i]->status = ID_MAPPED;
     795             :                 }
     796             :         }
     797             : 
     798         154 :         if (error_count == i) {
     799             :                 /* Mapping did not work at all. */
     800           0 :                 return NT_STATUS_NONE_MAPPED;
     801         154 :         } else if (error_count > 0) {
     802             :                 /* Some mappings worked, some did not. */
     803           0 :                 return STATUS_SOME_UNMAPPED;
     804             :         } else {
     805         154 :                 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       44006 : NTSTATUS idmap_sids_to_xids(struct idmap_context *idmap_ctx,
     823             :                             TALLOC_CTX *mem_ctx,
     824             :                             struct id_map **id)
     825             : {
     826       44006 :         unsigned int i, error_count = 0;
     827        2298 :         NTSTATUS status;
     828             : 
     829       88012 :         for (i = 0; id && id[i]; i++) {
     830       46304 :                 status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
     831       44006 :                                           id[i]->sid, &id[i]->xid);
     832       44006 :                 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       44006 :                 if (!NT_STATUS_IS_OK(status)) {
     838           0 :                         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       44006 :                         id[i]->status = ID_MAPPED;
     847             :                 }
     848             :         }
     849             : 
     850       44006 :         if (error_count == i) {
     851             :                 /* Mapping did not work at all. */
     852           0 :                 return NT_STATUS_NONE_MAPPED;
     853       44006 :         } else if (error_count > 0) {
     854             :                 /* Some mappings worked, some did not. */
     855           0 :                 return STATUS_SOME_UNMAPPED;
     856             :         } else {
     857       44006 :                 return NT_STATUS_OK;
     858             :         }
     859             : }
     860             : 

Generated by: LCOV version 1.14