root/source4/winbind/idmap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. idmap_get_bounds
  2. idmap_msg_add_dom_sid
  3. idmap_msg_get_dom_sid
  4. idmap_init
  5. idmap_xid_to_sid
  6. idmap_sid_to_xid
  7. idmap_xids_to_sids
  8. idmap_sids_to_xids

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

/* [<][>][^][v][top][bottom][index][help] */