LCOV - code coverage report
Current view: top level - db - sysdb_idmap.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 12 129 9.3 %
Date: 2015-10-19 Functions: 1 3 33.3 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Authors:
       5             :         Stephen Gallagher <sgallagh@redhat.com>
       6             : 
       7             :     Copyright (C) 2012 Red Hat
       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             : 
      24             : #include "db/sysdb.h"
      25             : #include "db/sysdb_private.h"
      26             : 
      27             : static struct ldb_dn *
      28           0 : sysdb_idmap_dn(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain,
      29             :                const char *object_sid)
      30             : {
      31             :     errno_t ret;
      32             :     char *clean_sid;
      33             :     struct ldb_dn *dn;
      34             : 
      35           0 :     ret = sysdb_dn_sanitize(NULL, object_sid, &clean_sid);
      36           0 :     if (ret != EOK) {
      37           0 :         return NULL;
      38             :     }
      39             : 
      40           0 :     DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_IDMAP"\n", clean_sid, domain->name);
      41             : 
      42           0 :     dn = ldb_dn_new_fmt(mem_ctx, domain->sysdb->ldb, SYSDB_TMPL_IDMAP,
      43             :                         clean_sid, domain->name);
      44           0 :     talloc_free(clean_sid);
      45             : 
      46           0 :     return dn;
      47             : }
      48             : 
      49             : errno_t
      50           0 : sysdb_idmap_store_mapping(struct sss_domain_info *domain,
      51             :                           const char *dom_name,
      52             :                           const char *dom_sid,
      53             :                           id_t slice_num)
      54             : {
      55             :     errno_t ret, sret;
      56             :     int lret;
      57           0 :     bool in_transaction = false;
      58             :     TALLOC_CTX *tmp_ctx;
      59             :     struct ldb_dn *dn;
      60             :     static const char *attrs[] = SYSDB_IDMAP_ATTRS;
      61             :     size_t count;
      62             :     struct ldb_message *update_msg;
      63             :     struct ldb_message **msgs;
      64             :     const char *old_name;
      65             :     id_t old_slice;
      66             : 
      67           0 :     tmp_ctx = talloc_new(NULL);
      68           0 :     if (!tmp_ctx) return ENOMEM;
      69             : 
      70           0 :     dn = sysdb_idmap_dn(tmp_ctx, domain, dom_sid);
      71           0 :     if (!dn) {
      72           0 :         ret = ENOMEM;
      73           0 :         goto done;
      74             :     }
      75             : 
      76           0 :     update_msg = ldb_msg_new(tmp_ctx);
      77           0 :     if (!update_msg) {
      78           0 :         ret = ENOMEM;
      79           0 :         goto done;
      80             :     }
      81           0 :     update_msg->dn = dn;
      82             : 
      83           0 :     ret = sysdb_transaction_start(domain->sysdb);
      84           0 :     if (ret != EOK) {
      85           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
      86           0 :         goto done;
      87             :     }
      88             : 
      89           0 :     in_transaction = true;
      90             : 
      91             : 
      92             :     /* Check for an existing mapping */
      93           0 :     ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_BASE,
      94             :                              NULL, attrs, &count, &msgs);
      95           0 :     if (ret != EOK && ret != ENOENT) goto done;
      96             : 
      97           0 :     if (ret == EOK && count != 1) {
      98             :         /* More than one reply for a base search? */
      99           0 :         ret = EIO;
     100           0 :         goto done;
     101           0 :     } else if (ret == ENOENT) {
     102             :         /* Create a new mapping */
     103           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
     104             :               "Adding new ID mapping [%s][%s][%lu]\n",
     105             :                dom_name, dom_sid, (unsigned long)slice_num);
     106             : 
     107             :         /* Add the objectClass */
     108           0 :         lret = ldb_msg_add_empty(update_msg, SYSDB_OBJECTCLASS,
     109             :                                  LDB_FLAG_MOD_ADD,
     110             :                                  NULL);
     111           0 :         if (lret != LDB_SUCCESS) {
     112           0 :             ret = sysdb_error_to_errno(lret);
     113           0 :             goto done;
     114             :         }
     115             : 
     116           0 :         lret = ldb_msg_add_string(update_msg, SYSDB_OBJECTCLASS,
     117             :                                   SYSDB_IDMAP_MAPPING_OC);
     118           0 :         if (lret != LDB_SUCCESS) {
     119           0 :             ret = sysdb_error_to_errno(lret);
     120           0 :             goto done;
     121             :         }
     122             : 
     123             :         /* Add the domain objectSID */
     124           0 :         lret = ldb_msg_add_empty(update_msg, SYSDB_IDMAP_SID_ATTR,
     125             :                                  LDB_FLAG_MOD_ADD,
     126             :                                  NULL);
     127           0 :         if (lret != LDB_SUCCESS) {
     128           0 :             ret = sysdb_error_to_errno(lret);
     129           0 :             goto done;
     130             :         }
     131             : 
     132           0 :         lret = ldb_msg_add_string(update_msg, SYSDB_IDMAP_SID_ATTR, dom_sid);
     133           0 :         if (lret != LDB_SUCCESS) {
     134           0 :             ret = sysdb_error_to_errno(lret);
     135           0 :             goto done;
     136             :         }
     137             : 
     138             :         /* Add the domain name */
     139           0 :         lret = ldb_msg_add_empty(update_msg, SYSDB_NAME,
     140             :                                  LDB_FLAG_MOD_ADD,
     141             :                                  NULL);
     142           0 :         if (lret != LDB_SUCCESS) {
     143           0 :             ret = sysdb_error_to_errno(lret);
     144           0 :             goto done;
     145             :         }
     146             : 
     147           0 :         lret = ldb_msg_add_string(update_msg, SYSDB_NAME, dom_name);
     148           0 :         if (lret != LDB_SUCCESS) {
     149           0 :             ret = sysdb_error_to_errno(lret);
     150           0 :             goto done;
     151             :         }
     152             : 
     153             :         /* Add the slice number */
     154           0 :         lret = ldb_msg_add_empty(update_msg, SYSDB_IDMAP_SLICE_ATTR,
     155             :                                  LDB_FLAG_MOD_ADD,
     156             :                                  NULL);
     157           0 :         if (lret != LDB_SUCCESS) {
     158           0 :             ret = sysdb_error_to_errno(lret);
     159           0 :             goto done;
     160             :         }
     161             : 
     162           0 :         lret = ldb_msg_add_fmt(update_msg, SYSDB_IDMAP_SLICE_ATTR,
     163             :                                "%lu", (unsigned long)slice_num);
     164           0 :         if (lret != LDB_SUCCESS) {
     165           0 :             ret = sysdb_error_to_errno(lret);
     166           0 :             goto done;
     167             :         }
     168             : 
     169           0 :         lret = ldb_add(domain->sysdb->ldb, update_msg);
     170           0 :         if (lret != LDB_SUCCESS) {
     171           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     172             :                   "Failed to add mapping: [%s]\n",
     173             :                    ldb_strerror(lret));
     174           0 :             ret = sysdb_error_to_errno(lret);
     175           0 :             goto done;
     176             :         }
     177             :     } else {
     178             :         /* Update the existing mapping */
     179             : 
     180             :         /* Check whether the slice has changed
     181             :          * This should never happen, and it's a recipe for
     182             :          * disaster. We'll throw an error if it does.
     183             :          */
     184           0 :         old_slice = ldb_msg_find_attr_as_int(msgs[0],
     185             :                                              SYSDB_IDMAP_SLICE_ATTR,
     186             :                                              -1);
     187           0 :         if (old_slice == -1) {
     188           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     189             :                   "Could not identify original slice for SID [%s]\n",
     190             :                    dom_sid);
     191           0 :             ret = ENOENT;
     192           0 :             goto done;
     193             :         }
     194             : 
     195           0 :         if (slice_num != old_slice) {
     196           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     197             :                   "Detected attempt to change slice value for sid [%s] "
     198             :                    "This will break existing users. Refusing to perform.\n",
     199             :                    dom_sid);
     200           0 :             ret = EINVAL;
     201           0 :             goto done;
     202             :         }
     203             : 
     204             :         /* Check whether the name has changed. This may happen
     205             :          * if we're told the real name of a domain and want to
     206             :          * replace the SID as placeholder.
     207             :          */
     208           0 :         old_name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
     209           0 :         if (!old_name) {
     210           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     211             :                   "Could not identify original domain name of SID [%s]\n",
     212             :                    dom_sid);
     213           0 :             ret = ENOENT;
     214           0 :             goto done;
     215             :         }
     216             : 
     217           0 :         if (strcmp(old_name, dom_name) == 0) {
     218             :             /* There's nothing to be done. We don't need to
     219             :              * make any changes here. Just return success.
     220             :              */
     221           0 :             DEBUG(SSSDBG_TRACE_LIBS,
     222             :                   "No changes needed, canceling transaction\n");
     223           0 :             ret = EOK;
     224           0 :             goto done;
     225             :         } else {
     226             :             /* The name has changed. Replace it */
     227           0 :             DEBUG(SSSDBG_CONF_SETTINGS,
     228             :                   "Changing domain name of SID [%s] from [%s] to [%s]\n",
     229             :                    dom_sid, old_name, dom_name);
     230             : 
     231             :             /* Set the new name */
     232           0 :             lret = ldb_msg_add_empty(update_msg, SYSDB_NAME,
     233             :                                      LDB_FLAG_MOD_REPLACE,
     234             :                                      NULL);
     235           0 :             if (lret != LDB_SUCCESS) {
     236           0 :                 ret = sysdb_error_to_errno(lret);
     237           0 :                 goto done;
     238             :             }
     239             : 
     240           0 :             lret = ldb_msg_add_string(update_msg, SYSDB_NAME, dom_name);
     241           0 :             if (lret != LDB_SUCCESS) {
     242           0 :                 ret = sysdb_error_to_errno(lret);
     243           0 :                 goto done;
     244             :             }
     245             :         }
     246             : 
     247           0 :         lret = ldb_modify(domain->sysdb->ldb, update_msg);
     248           0 :         if (lret != LDB_SUCCESS) {
     249           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     250             :                   "Failed to update mapping: [%s](%d)[%s]\n",
     251             :                   ldb_strerror(lret), lret, ldb_errstring(domain->sysdb->ldb));
     252           0 :             ret = sysdb_error_to_errno(lret);
     253           0 :             goto done;
     254             :         }
     255             :     }
     256             : 
     257           0 :     ret = sysdb_transaction_commit(domain->sysdb);
     258           0 :     if (ret != EOK) {
     259           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     260             :               "Could not commit transaction: [%s]\n", strerror(ret));
     261           0 :         goto done;
     262             :     }
     263           0 :     in_transaction = false;
     264             : 
     265             : done:
     266           0 :     if (in_transaction) {
     267           0 :         sret = sysdb_transaction_cancel(domain->sysdb);
     268           0 :         if (sret != EOK) {
     269           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     270             :                   "Could not cancel transaction\n");
     271             :         }
     272             :     }
     273           0 :     talloc_free(tmp_ctx);
     274           0 :     return ret;
     275             : }
     276             : 
     277             : errno_t
     278           8 : sysdb_idmap_get_mappings(TALLOC_CTX *mem_ctx,
     279             :                          struct sss_domain_info *domain,
     280             :                          struct ldb_result **_result)
     281             : {
     282             :     errno_t ret;
     283             :     struct ldb_dn *base_dn;
     284             :     TALLOC_CTX *tmp_ctx;
     285             :     struct ldb_result *res;
     286             :     static const char *attrs[] = SYSDB_IDMAP_ATTRS;
     287             : 
     288           8 :     tmp_ctx = talloc_new(NULL);
     289           8 :     if (!tmp_ctx) return ENOMEM;
     290             : 
     291           8 :     DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_IDMAP_BASE"\n", domain->name);
     292             : 
     293           8 :     base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
     294             :                              SYSDB_TMPL_IDMAP_BASE, domain->name);
     295           8 :     if (!base_dn) {
     296           0 :         ret = ENOMEM;
     297           0 :         goto done;
     298             :     }
     299             : 
     300           8 :     SSS_LDB_SEARCH(ret, domain->sysdb->ldb, tmp_ctx, &res, base_dn,
     301             :                    LDB_SCOPE_SUBTREE, attrs, SYSDB_IDMAP_FILTER);
     302           8 :     if (ret != EOK) {
     303           8 :         DEBUG(SSSDBG_MINOR_FAILURE,
     304             :               "Could not locate ID mappings: [%s]\n",
     305             :               sss_strerror(ret));
     306           8 :         goto done;
     307             :     }
     308             : 
     309           0 :     *_result = talloc_steal(mem_ctx, res);
     310             : 
     311           0 :     ret = EOK;
     312             : 
     313             : done:
     314           8 :     talloc_free(tmp_ctx);
     315           8 :     return ret;
     316             : }

Generated by: LCOV version 1.10