root/source3/winbindd/idmap_ldap.c

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

DEFINITIONS

This source file includes following definitions.
  1. idmap_fetch_secret
  2. get_credentials
  3. verify_idpool
  4. idmap_ldap_alloc_init
  5. idmap_ldap_allocate_id
  6. idmap_ldap_get_hwm
  7. idmap_ldap_set_hwm
  8. idmap_ldap_alloc_close
  9. idmap_ldap_close_destructor
  10. idmap_ldap_db_init
  11. find_map_by_id
  12. idmap_ldap_unixids_to_sids
  13. find_map_by_sid
  14. idmap_ldap_sids_to_unixids
  15. idmap_ldap_set_mapping
  16. idmap_ldap_close
  17. idmap_alloc_ldap_init
  18. idmap_ldap_init

   1 /*
   2    Unix SMB/CIFS implementation.
   3 
   4    idmap LDAP backend
   5 
   6    Copyright (C) Tim Potter             2000
   7    Copyright (C) Jim McDonough <jmcd@us.ibm.com>        2003
   8    Copyright (C) Gerald Carter          2003
   9    Copyright (C) Simo Sorce             2003-2007
  10 
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; either version 3 of the License, or
  14    (at your option) any later version.
  15 
  16    This program is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19    GNU General Public License for more details.
  20 
  21    You should have received a copy of the GNU General Public License
  22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23 */
  24 
  25 #include "includes.h"
  26 #include "winbindd.h"
  27 
  28 #undef DBGC_CLASS
  29 #define DBGC_CLASS DBGC_IDMAP
  30 
  31 #include <lber.h>
  32 #include <ldap.h>
  33 
  34 #include "smbldap.h"
  35 
  36 static char *idmap_fetch_secret(const char *backend, bool alloc,
     /* [<][>][^][v][top][bottom][index][help] */
  37                                 const char *domain, const char *identity)
  38 {
  39         char *tmp, *ret;
  40         int r;
  41 
  42         if (alloc) {
  43                 r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
  44         } else {
  45                 r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
  46         }
  47 
  48         if (r < 0)
  49                 return NULL;
  50 
  51         strupper_m(tmp); /* make sure the key is case insensitive */
  52         ret = secrets_fetch_generic(tmp, identity);
  53 
  54         SAFE_FREE(tmp);
  55 
  56         return ret;
  57 }
  58 
  59 struct idmap_ldap_context {
  60         struct smbldap_state *smbldap_state;
  61         char *url;
  62         char *suffix;
  63         char *user_dn;
  64         uint32_t filter_low_id, filter_high_id;         /* Filter range */
  65         bool anon;
  66 };
  67 
  68 struct idmap_ldap_alloc_context {
  69         struct smbldap_state *smbldap_state;
  70         char *url;
  71         char *suffix;
  72         char *user_dn;
  73         uid_t low_uid, high_uid;      /* Range of uids */
  74         gid_t low_gid, high_gid;      /* Range of gids */
  75 
  76 };
  77 
  78 #define CHECK_ALLOC_DONE(mem) do { \
  79         if (!mem) { \
  80                 DEBUG(0, ("Out of memory!\n")); \
  81                 ret = NT_STATUS_NO_MEMORY; \
  82                 goto done; \
  83         } } while (0)
  84 
  85 /**********************************************************************
  86  IDMAP ALLOC TDB BACKEND
  87 **********************************************************************/
  88 
  89 static struct idmap_ldap_alloc_context *idmap_alloc_ldap;
  90 
  91 /*********************************************************************
  92  ********************************************************************/
  93 
  94 static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  95                                  struct smbldap_state *ldap_state,
  96                                  const char *config_option,
  97                                  struct idmap_domain *dom,
  98                                  char **dn )
  99 {
 100         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 101         char *secret = NULL;
 102         const char *tmp = NULL;
 103         char *user_dn = NULL;
 104         bool anon = False;
 105 
 106         /* assume anonymous if we don't have a specified user */
 107 
 108         tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
 109 
 110         if ( tmp ) {
 111                 if (!dom) {
 112                         /* only the alloc backend can pass in a NULL dom */
 113                         secret = idmap_fetch_secret("ldap", True,
 114                                                     NULL, tmp);
 115                 } else {
 116                         secret = idmap_fetch_secret("ldap", False,
 117                                                     dom->name, tmp);
 118                 }
 119 
 120                 if (!secret) {
 121                         DEBUG(0, ("get_credentials: Unable to fetch "
 122                                   "auth credentials for %s in %s\n",
 123                                   tmp, (dom==NULL)?"ALLOC":dom->name));
 124                         ret = NT_STATUS_ACCESS_DENIED;
 125                         goto done;
 126                 }
 127                 *dn = talloc_strdup(mem_ctx, tmp);
 128                 CHECK_ALLOC_DONE(*dn);
 129         } else {
 130                 if (!fetch_ldap_pw(&user_dn, &secret)) {
 131                         DEBUG(2, ("get_credentials: Failed to lookup ldap "
 132                                   "bind creds. Using anonymous connection.\n"));
 133                         anon = True;
 134                 } else {
 135                         *dn = talloc_strdup(mem_ctx, user_dn);
 136                         SAFE_FREE( user_dn );
 137                         CHECK_ALLOC_DONE(*dn);
 138                 }
 139         }
 140 
 141         smbldap_set_creds(ldap_state, anon, *dn, secret);
 142         ret = NT_STATUS_OK;
 143 
 144 done:
 145         SAFE_FREE(secret);
 146 
 147         return ret;
 148 }
 149 
 150 
 151 /**********************************************************************
 152  Verify the sambaUnixIdPool entry in the directory.
 153 **********************************************************************/
 154 
 155 static NTSTATUS verify_idpool(void)
     /* [<][>][^][v][top][bottom][index][help] */
 156 {
 157         NTSTATUS ret;
 158         TALLOC_CTX *ctx;
 159         LDAPMessage *result = NULL;
 160         LDAPMod **mods = NULL;
 161         const char **attr_list;
 162         char *filter;
 163         int count;
 164         int rc;
 165 
 166         if ( ! idmap_alloc_ldap) {
 167                 return NT_STATUS_UNSUCCESSFUL;
 168         }
 169 
 170         ctx = talloc_new(idmap_alloc_ldap);
 171         if ( ! ctx) {
 172                 DEBUG(0, ("Out of memory!\n"));
 173                 return NT_STATUS_NO_MEMORY;
 174         }
 175 
 176         filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
 177         CHECK_ALLOC_DONE(filter);
 178 
 179         attr_list = get_attr_list(ctx, idpool_attr_list);
 180         CHECK_ALLOC_DONE(attr_list);
 181 
 182         rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
 183                                 idmap_alloc_ldap->suffix,
 184                                 LDAP_SCOPE_SUBTREE,
 185                                 filter,
 186                                 attr_list,
 187                                 0,
 188                                 &result);
 189 
 190         if (rc != LDAP_SUCCESS) {
 191                 DEBUG(1, ("Unable to verify the idpool, "
 192                           "cannot continue initialization!\n"));
 193                 return NT_STATUS_UNSUCCESSFUL;
 194         }
 195 
 196         count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
 197                                    result);
 198 
 199         ldap_msgfree(result);
 200 
 201         if ( count > 1 ) {
 202                 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
 203                         filter, idmap_alloc_ldap->suffix));
 204                 ret = NT_STATUS_UNSUCCESSFUL;
 205                 goto done;
 206         }
 207         else if (count == 0) {
 208                 char *uid_str, *gid_str;
 209 
 210                 uid_str = talloc_asprintf(ctx, "%lu",
 211                                 (unsigned long)idmap_alloc_ldap->low_uid);
 212                 gid_str = talloc_asprintf(ctx, "%lu",
 213                                 (unsigned long)idmap_alloc_ldap->low_gid);
 214 
 215                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
 216                                 "objectClass", LDAP_OBJ_IDPOOL);
 217                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
 218                                 get_attr_key2string(idpool_attr_list,
 219                                                     LDAP_ATTR_UIDNUMBER),
 220                                 uid_str);
 221                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
 222                                 get_attr_key2string(idpool_attr_list,
 223                                                     LDAP_ATTR_GIDNUMBER),
 224                                 gid_str);
 225                 if (mods) {
 226                         rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
 227                                                 idmap_alloc_ldap->suffix,
 228                                                 mods);
 229                         ldap_mods_free(mods, True);
 230                 } else {
 231                         ret = NT_STATUS_UNSUCCESSFUL;
 232                         goto done;
 233                 }
 234         }
 235 
 236         ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
 237 done:
 238         talloc_free(ctx);
 239         return ret;
 240 }
 241 
 242 /*****************************************************************************
 243  Initialise idmap database.
 244 *****************************************************************************/
 245 
 246 static NTSTATUS idmap_ldap_alloc_init(const char *params)
     /* [<][>][^][v][top][bottom][index][help] */
 247 {
 248         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 249         const char *tmp;
 250         uid_t low_uid = 0;
 251         uid_t high_uid = 0;
 252         gid_t low_gid = 0;
 253         gid_t high_gid = 0;
 254 
 255         /* Only do init if we are online */
 256         if (idmap_is_offline()) {
 257                 return NT_STATUS_FILE_IS_OFFLINE;
 258         }
 259 
 260         idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context);
 261         CHECK_ALLOC_DONE( idmap_alloc_ldap );
 262 
 263         /* load ranges */
 264 
 265         if (!lp_idmap_uid(&low_uid, &high_uid)
 266             || !lp_idmap_gid(&low_gid, &high_gid)) {
 267                 DEBUG(1, ("idmap uid or idmap gid missing\n"));
 268                 ret = NT_STATUS_UNSUCCESSFUL;
 269                 goto done;
 270         }
 271 
 272         idmap_alloc_ldap->low_uid = low_uid;
 273         idmap_alloc_ldap->high_uid = high_uid;
 274         idmap_alloc_ldap->low_gid = low_gid;
 275         idmap_alloc_ldap->high_gid= high_gid;
 276 
 277         if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) {
 278                 DEBUG(1, ("idmap uid range invalid\n"));
 279                 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
 280                 ret = NT_STATUS_UNSUCCESSFUL;
 281                 goto done;
 282         }
 283 
 284         if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) {
 285                 DEBUG(1, ("idmap gid range invalid\n"));
 286                 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
 287                 ret = NT_STATUS_UNSUCCESSFUL;
 288                 goto done;
 289         }
 290 
 291         if (params && *params) {
 292                 /* assume location is the only parameter */
 293                 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
 294         } else {
 295                 tmp = lp_parm_const_string(-1, "idmap alloc config",
 296                                            "ldap_url", NULL);
 297 
 298                 if ( ! tmp) {
 299                         DEBUG(1, ("ERROR: missing idmap ldap url\n"));
 300                         ret = NT_STATUS_UNSUCCESSFUL;
 301                         goto done;
 302                 }
 303 
 304                 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
 305         }
 306         CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
 307 
 308         tmp = lp_parm_const_string(-1, "idmap alloc config",
 309                                    "ldap_base_dn", NULL);
 310         if ( ! tmp || ! *tmp) {
 311                 tmp = lp_ldap_idmap_suffix();
 312                 if ( ! tmp) {
 313                         DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
 314                         ret = NT_STATUS_UNSUCCESSFUL;
 315                         goto done;
 316                 }
 317         }
 318 
 319         idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
 320         CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
 321 
 322         ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(),
 323                            idmap_alloc_ldap->url,
 324                            &idmap_alloc_ldap->smbldap_state);
 325         if (!NT_STATUS_IS_OK(ret)) {
 326                 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
 327                           idmap_alloc_ldap->url));
 328                 goto done;
 329         }
 330 
 331         ret = get_credentials( idmap_alloc_ldap,
 332                                idmap_alloc_ldap->smbldap_state,
 333                                "idmap alloc config", NULL,
 334                                &idmap_alloc_ldap->user_dn );
 335         if ( !NT_STATUS_IS_OK(ret) ) {
 336                 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
 337                          "credentials (%s)\n", nt_errstr(ret)));
 338                 goto done;
 339         }
 340 
 341         /* see if the idmap suffix and sub entries exists */
 342 
 343         ret = verify_idpool();
 344 
 345  done:
 346         if ( !NT_STATUS_IS_OK( ret ) )
 347                 TALLOC_FREE( idmap_alloc_ldap );
 348 
 349         return ret;
 350 }
 351 
 352 /********************************
 353  Allocate a new uid or gid
 354 ********************************/
 355 
 356 static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
     /* [<][>][^][v][top][bottom][index][help] */
 357 {
 358         TALLOC_CTX *ctx;
 359         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 360         int rc = LDAP_SERVER_DOWN;
 361         int count = 0;
 362         LDAPMessage *result = NULL;
 363         LDAPMessage *entry = NULL;
 364         LDAPMod **mods = NULL;
 365         char *id_str;
 366         char *new_id_str;
 367         char *filter = NULL;
 368         const char *dn = NULL;
 369         const char **attr_list;
 370         const char *type;
 371 
 372         /* Only do query if we are online */
 373         if (idmap_is_offline()) {
 374                 return NT_STATUS_FILE_IS_OFFLINE;
 375         }
 376 
 377         if ( ! idmap_alloc_ldap) {
 378                 return NT_STATUS_UNSUCCESSFUL;
 379         }
 380 
 381         ctx = talloc_new(idmap_alloc_ldap);
 382         if ( ! ctx) {
 383                 DEBUG(0, ("Out of memory!\n"));
 384                 return NT_STATUS_NO_MEMORY;
 385         }
 386 
 387         /* get type */
 388         switch (xid->type) {
 389 
 390         case ID_TYPE_UID:
 391                 type = get_attr_key2string(idpool_attr_list,
 392                                            LDAP_ATTR_UIDNUMBER);
 393                 break;
 394 
 395         case ID_TYPE_GID:
 396                 type = get_attr_key2string(idpool_attr_list,
 397                                            LDAP_ATTR_GIDNUMBER);
 398                 break;
 399 
 400         default:
 401                 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
 402                 return NT_STATUS_INVALID_PARAMETER;
 403         }
 404 
 405         filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
 406         CHECK_ALLOC_DONE(filter);
 407 
 408         attr_list = get_attr_list(ctx, idpool_attr_list);
 409         CHECK_ALLOC_DONE(attr_list);
 410 
 411         DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
 412 
 413         rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
 414                                 idmap_alloc_ldap->suffix,
 415                                LDAP_SCOPE_SUBTREE, filter,
 416                                attr_list, 0, &result);
 417 
 418         if (rc != LDAP_SUCCESS) {
 419                 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
 420                 goto done;
 421         }
 422 
 423         talloc_autofree_ldapmsg(ctx, result);
 424 
 425         count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
 426                                    result);
 427         if (count != 1) {
 428                 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
 429                 goto done;
 430         }
 431 
 432         entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
 433                                  result);
 434 
 435         dn = smbldap_talloc_dn(ctx,
 436                                idmap_alloc_ldap->smbldap_state->ldap_struct,
 437                                entry);
 438         if ( ! dn) {
 439                 goto done;
 440         }
 441 
 442         if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
 443                                 entry, type, ctx))) {
 444                 DEBUG(0,("%s attribute not found\n", type));
 445                 goto done;
 446         }
 447         if ( ! id_str) {
 448                 DEBUG(0,("Out of memory\n"));
 449                 ret = NT_STATUS_NO_MEMORY;
 450                 goto done;
 451         }
 452 
 453         xid->id = strtoul(id_str, NULL, 10);
 454 
 455         /* make sure we still have room to grow */
 456 
 457         switch (xid->type) {
 458         case ID_TYPE_UID:
 459                 if (xid->id > idmap_alloc_ldap->high_uid) {
 460                         DEBUG(0,("Cannot allocate uid above %lu!\n",
 461                                  (unsigned long)idmap_alloc_ldap->high_uid));
 462                         goto done;
 463                 }
 464                 break;
 465 
 466         case ID_TYPE_GID:
 467                 if (xid->id > idmap_alloc_ldap->high_gid) {
 468                         DEBUG(0,("Cannot allocate gid above %lu!\n",
 469                                  (unsigned long)idmap_alloc_ldap->high_uid));
 470                         goto done;
 471                 }
 472                 break;
 473 
 474         default:
 475                 /* impossible */
 476                 goto done;
 477         }
 478 
 479         new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
 480         if ( ! new_id_str) {
 481                 DEBUG(0,("Out of memory\n"));
 482                 ret = NT_STATUS_NO_MEMORY;
 483                 goto done;
 484         }
 485 
 486         smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
 487         smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
 488 
 489         if (mods == NULL) {
 490                 DEBUG(0,("smbldap_set_mod() failed.\n"));
 491                 goto done;
 492         }
 493 
 494         DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
 495                    id_str, new_id_str));
 496 
 497         rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
 498 
 499         ldap_mods_free(mods, True);
 500 
 501         if (rc != LDAP_SUCCESS) {
 502                 DEBUG(1,("Failed to allocate new %s. "
 503                          "smbldap_modify() failed.\n", type));
 504                 goto done;
 505         }
 506 
 507         ret = NT_STATUS_OK;
 508 
 509 done:
 510         talloc_free(ctx);
 511         return ret;
 512 }
 513 
 514 /**********************************
 515  Get current highest id.
 516 **********************************/
 517 
 518 static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
     /* [<][>][^][v][top][bottom][index][help] */
 519 {
 520         TALLOC_CTX *memctx;
 521         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 522         int rc = LDAP_SERVER_DOWN;
 523         int count = 0;
 524         LDAPMessage *result = NULL;
 525         LDAPMessage *entry = NULL;
 526         char *id_str;
 527         char *filter = NULL;
 528         const char **attr_list;
 529         const char *type;
 530 
 531         /* Only do query if we are online */
 532         if (idmap_is_offline()) {
 533                 return NT_STATUS_FILE_IS_OFFLINE;
 534         }
 535 
 536         if ( ! idmap_alloc_ldap) {
 537                 return NT_STATUS_UNSUCCESSFUL;
 538         }
 539 
 540         memctx = talloc_new(idmap_alloc_ldap);
 541         if ( ! memctx) {
 542                 DEBUG(0, ("Out of memory!\n"));
 543                 return NT_STATUS_NO_MEMORY;
 544         }
 545 
 546         /* get type */
 547         switch (xid->type) {
 548 
 549         case ID_TYPE_UID:
 550                 type = get_attr_key2string(idpool_attr_list,
 551                                            LDAP_ATTR_UIDNUMBER);
 552                 break;
 553 
 554         case ID_TYPE_GID:
 555                 type = get_attr_key2string(idpool_attr_list,
 556                                            LDAP_ATTR_GIDNUMBER);
 557                 break;
 558 
 559         default:
 560                 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
 561                 return NT_STATUS_INVALID_PARAMETER;
 562         }
 563 
 564         filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
 565         CHECK_ALLOC_DONE(filter);
 566 
 567         attr_list = get_attr_list(memctx, idpool_attr_list);
 568         CHECK_ALLOC_DONE(attr_list);
 569 
 570         rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
 571                                 idmap_alloc_ldap->suffix,
 572                                LDAP_SCOPE_SUBTREE, filter,
 573                                attr_list, 0, &result);
 574 
 575         if (rc != LDAP_SUCCESS) {
 576                 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
 577                 goto done;
 578         }
 579 
 580         talloc_autofree_ldapmsg(memctx, result);
 581 
 582         count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
 583                                    result);
 584         if (count != 1) {
 585                 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
 586                 goto done;
 587         }
 588 
 589         entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
 590                                  result);
 591 
 592         id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
 593                         entry, type, memctx);
 594         if ( ! id_str) {
 595                 DEBUG(0,("%s attribute not found\n", type));
 596                 goto done;
 597         }
 598         if ( ! id_str) {
 599                 DEBUG(0,("Out of memory\n"));
 600                 ret = NT_STATUS_NO_MEMORY;
 601                 goto done;
 602         }
 603 
 604         xid->id = strtoul(id_str, NULL, 10);
 605 
 606         ret = NT_STATUS_OK;
 607 done:
 608         talloc_free(memctx);
 609         return ret;
 610 }
 611 /**********************************
 612  Set highest id.
 613 **********************************/
 614 
 615 static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
     /* [<][>][^][v][top][bottom][index][help] */
 616 {
 617         TALLOC_CTX *ctx;
 618         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 619         int rc = LDAP_SERVER_DOWN;
 620         int count = 0;
 621         LDAPMessage *result = NULL;
 622         LDAPMessage *entry = NULL;
 623         LDAPMod **mods = NULL;
 624         char *new_id_str;
 625         char *filter = NULL;
 626         const char *dn = NULL;
 627         const char **attr_list;
 628         const char *type;
 629 
 630         /* Only do query if we are online */
 631         if (idmap_is_offline()) {
 632                 return NT_STATUS_FILE_IS_OFFLINE;
 633         }
 634 
 635         if ( ! idmap_alloc_ldap) {
 636                 return NT_STATUS_UNSUCCESSFUL;
 637         }
 638 
 639         ctx = talloc_new(idmap_alloc_ldap);
 640         if ( ! ctx) {
 641                 DEBUG(0, ("Out of memory!\n"));
 642                 return NT_STATUS_NO_MEMORY;
 643         }
 644 
 645         /* get type */
 646         switch (xid->type) {
 647 
 648         case ID_TYPE_UID:
 649                 type = get_attr_key2string(idpool_attr_list,
 650                                            LDAP_ATTR_UIDNUMBER);
 651                 break;
 652 
 653         case ID_TYPE_GID:
 654                 type = get_attr_key2string(idpool_attr_list,
 655                                            LDAP_ATTR_GIDNUMBER);
 656                 break;
 657 
 658         default:
 659                 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
 660                 return NT_STATUS_INVALID_PARAMETER;
 661         }
 662 
 663         filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
 664         CHECK_ALLOC_DONE(filter);
 665 
 666         attr_list = get_attr_list(ctx, idpool_attr_list);
 667         CHECK_ALLOC_DONE(attr_list);
 668 
 669         rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
 670                                 idmap_alloc_ldap->suffix,
 671                                LDAP_SCOPE_SUBTREE, filter,
 672                                attr_list, 0, &result);
 673 
 674         if (rc != LDAP_SUCCESS) {
 675                 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
 676                 goto done;
 677         }
 678 
 679         talloc_autofree_ldapmsg(ctx, result);
 680 
 681         count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
 682                                    result);
 683         if (count != 1) {
 684                 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
 685                 goto done;
 686         }
 687 
 688         entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
 689                                  result);
 690 
 691         dn = smbldap_talloc_dn(ctx,
 692                                 idmap_alloc_ldap->smbldap_state->ldap_struct,
 693                                 entry);
 694         if ( ! dn) {
 695                 goto done;
 696         }
 697 
 698         new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id);
 699         if ( ! new_id_str) {
 700                 DEBUG(0,("Out of memory\n"));
 701                 ret = NT_STATUS_NO_MEMORY;
 702                 goto done;
 703         }
 704 
 705         smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str);
 706 
 707         if (mods == NULL) {
 708                 DEBUG(0,("smbldap_set_mod() failed.\n"));
 709                 goto done;
 710         }
 711 
 712         rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
 713 
 714         ldap_mods_free(mods, True);
 715 
 716         if (rc != LDAP_SUCCESS) {
 717                 DEBUG(1,("Failed to allocate new %s. "
 718                          "smbldap_modify() failed.\n", type));
 719                 goto done;
 720         }
 721 
 722         ret = NT_STATUS_OK;
 723 
 724 done:
 725         talloc_free(ctx);
 726         return ret;
 727 }
 728 
 729 /**********************************
 730  Close idmap ldap alloc
 731 **********************************/
 732 
 733 static NTSTATUS idmap_ldap_alloc_close(void)
     /* [<][>][^][v][top][bottom][index][help] */
 734 {
 735         if (idmap_alloc_ldap) {
 736                 smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
 737                 DEBUG(5,("The connection to the LDAP server was closed\n"));
 738                 /* maybe free the results here --metze */
 739                 TALLOC_FREE(idmap_alloc_ldap);
 740         }
 741         return NT_STATUS_OK;
 742 }
 743 
 744 
 745 /**********************************************************************
 746  IDMAP MAPPING LDAP BACKEND
 747 **********************************************************************/
 748 
 749 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 750 {
 751         smbldap_free_struct(&ctx->smbldap_state);
 752         DEBUG(5,("The connection to the LDAP server was closed\n"));
 753         /* maybe free the results here --metze */
 754 
 755         return 0;
 756 }
 757 
 758 /********************************
 759  Initialise idmap database.
 760 ********************************/
 761 
 762 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
     /* [<][>][^][v][top][bottom][index][help] */
 763                                    const char *params)
 764 {
 765         NTSTATUS ret;
 766         struct idmap_ldap_context *ctx = NULL;
 767         char *config_option = NULL;
 768         const char *tmp = NULL;
 769 
 770         /* Only do init if we are online */
 771         if (idmap_is_offline()) {
 772                 return NT_STATUS_FILE_IS_OFFLINE;
 773         }
 774 
 775         ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
 776         if ( ! ctx) {
 777                 DEBUG(0, ("Out of memory!\n"));
 778                 return NT_STATUS_NO_MEMORY;
 779         }
 780 
 781         if (strequal(dom->name, "*")) {
 782                 uid_t low_uid = 0;
 783                 uid_t high_uid = 0;
 784                 gid_t low_gid = 0;
 785                 gid_t high_gid = 0;
 786 
 787                 ctx->filter_low_id = 0;
 788                 ctx->filter_high_id = 0;
 789 
 790                 if (lp_idmap_uid(&low_uid, &high_uid)) {
 791                         ctx->filter_low_id = low_uid;
 792                         ctx->filter_high_id = high_uid;
 793                 } else {
 794                         DEBUG(3, ("Warning: 'idmap uid' not set!\n"));
 795                 }
 796 
 797                 if (lp_idmap_gid(&low_gid, &high_gid)) {
 798                         if ((low_gid != low_uid) || (high_gid != high_uid)) {
 799                                 DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
 800                                       " ranges do not agree -- building "
 801                                       "intersection\n"));
 802                                 ctx->filter_low_id = MAX(ctx->filter_low_id,
 803                                                          low_gid);
 804                                 ctx->filter_high_id = MIN(ctx->filter_high_id,
 805                                                           high_gid);
 806                         }
 807                 } else {
 808                         DEBUG(3, ("Warning: 'idmap gid' not set!\n"));
 809                 }
 810         } else {
 811                 const char *range = NULL;
 812 
 813                 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
 814                 if ( ! config_option) {
 815                         DEBUG(0, ("Out of memory!\n"));
 816                         ret = NT_STATUS_NO_MEMORY;
 817                         goto done;
 818                 }
 819 
 820                 /* load ranges */
 821                 range = lp_parm_const_string(-1, config_option, "range", NULL);
 822                 if (range && range[0]) {
 823                         if ((sscanf(range, "%u - %u", &ctx->filter_low_id,
 824                                                         &ctx->filter_high_id) != 2))
 825                         {
 826                                 DEBUG(1, ("ERROR: invalid filter range [%s]", range));
 827                                 ctx->filter_low_id = 0;
 828                                 ctx->filter_high_id = 0;
 829                         }
 830                 }
 831         }
 832 
 833         if (ctx->filter_low_id > ctx->filter_high_id) {
 834                 DEBUG(1, ("ERROR: invalid filter range [%u-%u]",
 835                       ctx->filter_low_id, ctx->filter_high_id));
 836                 ctx->filter_low_id = 0;
 837                 ctx->filter_high_id = 0;
 838         }
 839 
 840         if (params != NULL) {
 841                 /* assume location is the only parameter */
 842                 ctx->url = talloc_strdup(ctx, params);
 843         } else {
 844                 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
 845 
 846                 if ( ! tmp) {
 847                         DEBUG(1, ("ERROR: missing idmap ldap url\n"));
 848                         ret = NT_STATUS_UNSUCCESSFUL;
 849                         goto done;
 850                 }
 851 
 852                 ctx->url = talloc_strdup(ctx, tmp);
 853         }
 854         CHECK_ALLOC_DONE(ctx->url);
 855 
 856         tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
 857         if ( ! tmp || ! *tmp) {
 858                 tmp = lp_ldap_idmap_suffix();
 859                 if ( ! tmp) {
 860                         DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
 861                         ret = NT_STATUS_UNSUCCESSFUL;
 862                         goto done;
 863                 }
 864         }
 865 
 866         ctx->suffix = talloc_strdup(ctx, tmp);
 867         CHECK_ALLOC_DONE(ctx->suffix);
 868 
 869         ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
 870                            &ctx->smbldap_state);
 871         if (!NT_STATUS_IS_OK(ret)) {
 872                 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
 873                 goto done;
 874         }
 875 
 876         ret = get_credentials( ctx, ctx->smbldap_state, config_option,
 877                                dom, &ctx->user_dn );
 878         if ( !NT_STATUS_IS_OK(ret) ) {
 879                 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
 880                          "credentials (%s)\n", nt_errstr(ret)));
 881                 goto done;
 882         }
 883 
 884         /* set the destructor on the context, so that resource are properly
 885            freed if the contexts is released */
 886 
 887         talloc_set_destructor(ctx, idmap_ldap_close_destructor);
 888 
 889         dom->private_data = ctx;
 890 
 891         talloc_free(config_option);
 892         return NT_STATUS_OK;
 893 
 894 /*failed */
 895 done:
 896         talloc_free(ctx);
 897         return ret;
 898 }
 899 
 900 /* max number of ids requested per batch query */
 901 #define IDMAP_LDAP_MAX_IDS 30
 902 
 903 /**********************************
 904  lookup a set of unix ids.
 905 **********************************/
 906 
 907 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
 908  * in maps for a match */
 909 static struct id_map *find_map_by_id(struct id_map **maps,
     /* [<][>][^][v][top][bottom][index][help] */
 910                                      enum id_type type,
 911                                      uint32_t id)
 912 {
 913         int i;
 914 
 915         for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
 916                 if (maps[i] == NULL) { /* end of the run */
 917                         return NULL;
 918                 }
 919                 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
 920                         return maps[i];
 921                 }
 922         }
 923 
 924         return NULL;
 925 }
 926 
 927 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
     /* [<][>][^][v][top][bottom][index][help] */
 928                                            struct id_map **ids)
 929 {
 930         NTSTATUS ret;
 931         TALLOC_CTX *memctx;
 932         struct idmap_ldap_context *ctx;
 933         LDAPMessage *result = NULL;
 934         LDAPMessage *entry = NULL;
 935         const char *uidNumber;
 936         const char *gidNumber;
 937         const char **attr_list;
 938         char *filter = NULL;
 939         bool multi = False;
 940         int idx = 0;
 941         int bidx = 0;
 942         int count;
 943         int rc;
 944         int i;
 945 
 946         /* Only do query if we are online */
 947         if (idmap_is_offline()) {
 948                 return NT_STATUS_FILE_IS_OFFLINE;
 949         }
 950 
 951         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
 952 
 953         memctx = talloc_new(ctx);
 954         if ( ! memctx) {
 955                 DEBUG(0, ("Out of memory!\n"));
 956                 return NT_STATUS_NO_MEMORY;
 957         }
 958 
 959         uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
 960         gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
 961 
 962         attr_list = get_attr_list(memctx, sidmap_attr_list);
 963 
 964         if ( ! ids[1]) {
 965                 /* if we are requested just one mapping use the simple filter */
 966 
 967                 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
 968                                 LDAP_OBJ_IDMAP_ENTRY,
 969                                 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
 970                                 (unsigned long)ids[0]->xid.id);
 971                 CHECK_ALLOC_DONE(filter);
 972                 DEBUG(10, ("Filter: [%s]\n", filter));
 973         } else {
 974                 /* multiple mappings */
 975                 multi = True;
 976         }
 977 
 978         for (i = 0; ids[i]; i++) {
 979                 ids[i]->status = ID_UNKNOWN;
 980         }
 981 
 982 again:
 983         if (multi) {
 984 
 985                 talloc_free(filter);
 986                 filter = talloc_asprintf(memctx,
 987                                          "(&(objectClass=%s)(|",
 988                                          LDAP_OBJ_IDMAP_ENTRY);
 989                 CHECK_ALLOC_DONE(filter);
 990 
 991                 bidx = idx;
 992                 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
 993                         filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
 994                                         (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
 995                                         (unsigned long)ids[idx]->xid.id);
 996                         CHECK_ALLOC_DONE(filter);
 997                 }
 998                 filter = talloc_asprintf_append_buffer(filter, "))");
 999                 CHECK_ALLOC_DONE(filter);
1000                 DEBUG(10, ("Filter: [%s]\n", filter));
1001         } else {
1002                 bidx = 0;
1003                 idx = 1;
1004         }
1005 
1006         rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1007                 filter, attr_list, 0, &result);
1008 
1009         if (rc != LDAP_SUCCESS) {
1010                 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
1011                 ret = NT_STATUS_UNSUCCESSFUL;
1012                 goto done;
1013         }
1014 
1015         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1016 
1017         if (count == 0) {
1018                 DEBUG(10, ("NO SIDs found\n"));
1019         }
1020 
1021         for (i = 0; i < count; i++) {
1022                 char *sidstr = NULL;
1023                 char *tmp = NULL;
1024                 enum id_type type;
1025                 struct id_map *map;
1026                 uint32_t id;
1027 
1028                 if (i == 0) { /* first entry */
1029                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1030                                                  result);
1031                 } else { /* following ones */
1032                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1033                                                 entry);
1034                 }
1035                 if ( ! entry) {
1036                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1037                                   "from results\n"));
1038                         break;
1039                 }
1040 
1041                 /* first check if the SID is present */
1042                 sidstr = smbldap_talloc_single_attribute(
1043                                 ctx->smbldap_state->ldap_struct,
1044                                 entry, LDAP_ATTRIBUTE_SID, memctx);
1045                 if ( ! sidstr) { /* no sid, skip entry */
1046                         DEBUG(2, ("WARNING SID not found on entry\n"));
1047                         continue;
1048                 }
1049 
1050                 /* now try to see if it is a uid, if not try with a gid
1051                  * (gid is more common, but in case both uidNumber and
1052                  * gidNumber are returned the SID is mapped to the uid
1053                  *not the gid) */
1054                 type = ID_TYPE_UID;
1055                 tmp = smbldap_talloc_single_attribute(
1056                                 ctx->smbldap_state->ldap_struct,
1057                                 entry, uidNumber, memctx);
1058                 if ( ! tmp) {
1059                         type = ID_TYPE_GID;
1060                         tmp = smbldap_talloc_single_attribute(
1061                                         ctx->smbldap_state->ldap_struct,
1062                                         entry, gidNumber, memctx);
1063                 }
1064                 if ( ! tmp) { /* wow very strange entry, how did it match ? */
1065                         DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
1066                                   "nor gidNumber returned\n", sidstr));
1067                         TALLOC_FREE(sidstr);
1068                         continue;
1069                 }
1070 
1071                 id = strtoul(tmp, NULL, 10);
1072                 if ((id == 0) ||
1073                     (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1074                     (ctx->filter_high_id && (id > ctx->filter_high_id))) {
1075                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1076                                   "Filtered!\n", id,
1077                                   ctx->filter_low_id, ctx->filter_high_id));
1078                         TALLOC_FREE(sidstr);
1079                         TALLOC_FREE(tmp);
1080                         continue;
1081                 }
1082                 TALLOC_FREE(tmp);
1083 
1084                 map = find_map_by_id(&ids[bidx], type, id);
1085                 if (!map) {
1086                         DEBUG(2, ("WARNING: couldn't match sid (%s) "
1087                                   "with requested ids\n", sidstr));
1088                         TALLOC_FREE(sidstr);
1089                         continue;
1090                 }
1091 
1092                 if ( ! string_to_sid(map->sid, sidstr)) {
1093                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1094                         TALLOC_FREE(sidstr);
1095                         continue;
1096                 }
1097 
1098                 if (map->status == ID_MAPPED) {
1099                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1100                               "overwriting mapping %u -> %s with %u -> %s\n",
1101                               (type == ID_TYPE_UID) ? "UID" : "GID",
1102                               id, sid_string_dbg(map->sid), id, sidstr));
1103                 }
1104 
1105                 TALLOC_FREE(sidstr);
1106 
1107                 /* mapped */
1108                 map->status = ID_MAPPED;
1109 
1110                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1111                            (unsigned long)map->xid.id, map->xid.type));
1112         }
1113 
1114         /* free the ldap results */
1115         if (result) {
1116                 ldap_msgfree(result);
1117                 result = NULL;
1118         }
1119 
1120         if (multi && ids[idx]) { /* still some values to map */
1121                 goto again;
1122         }
1123 
1124         ret = NT_STATUS_OK;
1125 
1126         /* mark all unknwon/expired ones as unmapped */
1127         for (i = 0; ids[i]; i++) {
1128                 if (ids[i]->status != ID_MAPPED)
1129                         ids[i]->status = ID_UNMAPPED;
1130         }
1131 
1132 done:
1133         talloc_free(memctx);
1134         return ret;
1135 }
1136 
1137 /**********************************
1138  lookup a set of sids.
1139 **********************************/
1140 
1141 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
1142  * in maps for a match */
1143 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
     /* [<][>][^][v][top][bottom][index][help] */
1144 {
1145         int i;
1146 
1147         for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
1148                 if (maps[i] == NULL) { /* end of the run */
1149                         return NULL;
1150                 }
1151                 if (sid_equal(maps[i]->sid, sid)) {
1152                         return maps[i];
1153                 }
1154         }
1155 
1156         return NULL;
1157 }
1158 
1159 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
     /* [<][>][^][v][top][bottom][index][help] */
1160                                            struct id_map **ids)
1161 {
1162         LDAPMessage *entry = NULL;
1163         NTSTATUS ret;
1164         TALLOC_CTX *memctx;
1165         struct idmap_ldap_context *ctx;
1166         LDAPMessage *result = NULL;
1167         const char *uidNumber;
1168         const char *gidNumber;
1169         const char **attr_list;
1170         char *filter = NULL;
1171         bool multi = False;
1172         int idx = 0;
1173         int bidx = 0;
1174         int count;
1175         int rc;
1176         int i;
1177 
1178         /* Only do query if we are online */
1179         if (idmap_is_offline()) {
1180                 return NT_STATUS_FILE_IS_OFFLINE;
1181         }
1182 
1183         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1184 
1185         memctx = talloc_new(ctx);
1186         if ( ! memctx) {
1187                 DEBUG(0, ("Out of memory!\n"));
1188                 return NT_STATUS_NO_MEMORY;
1189         }
1190 
1191         uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
1192         gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
1193 
1194         attr_list = get_attr_list(memctx, sidmap_attr_list);
1195 
1196         if ( ! ids[1]) {
1197                 /* if we are requested just one mapping use the simple filter */
1198 
1199                 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
1200                                 LDAP_OBJ_IDMAP_ENTRY,
1201                                 LDAP_ATTRIBUTE_SID,
1202                                 sid_string_talloc(memctx, ids[0]->sid));
1203                 CHECK_ALLOC_DONE(filter);
1204                 DEBUG(10, ("Filter: [%s]\n", filter));
1205         } else {
1206                 /* multiple mappings */
1207                 multi = True;
1208         }
1209 
1210         for (i = 0; ids[i]; i++) {
1211                 ids[i]->status = ID_UNKNOWN;
1212         }
1213 
1214 again:
1215         if (multi) {
1216 
1217                 TALLOC_FREE(filter);
1218                 filter = talloc_asprintf(memctx,
1219                                          "(&(objectClass=%s)(|",
1220                                          LDAP_OBJ_IDMAP_ENTRY);
1221                 CHECK_ALLOC_DONE(filter);
1222 
1223                 bidx = idx;
1224                 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
1225                         filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
1226                                         LDAP_ATTRIBUTE_SID,
1227                                         sid_string_talloc(memctx,
1228                                                           ids[idx]->sid));
1229                         CHECK_ALLOC_DONE(filter);
1230                 }
1231                 filter = talloc_asprintf_append_buffer(filter, "))");
1232                 CHECK_ALLOC_DONE(filter);
1233                 DEBUG(10, ("Filter: [%s]", filter));
1234         } else {
1235                 bidx = 0;
1236                 idx = 1;
1237         }
1238 
1239         rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1240                 filter, attr_list, 0, &result);
1241 
1242         if (rc != LDAP_SUCCESS) {
1243                 DEBUG(3,("Failure looking up sids (%s)\n",
1244                          ldap_err2string(rc)));
1245                 ret = NT_STATUS_UNSUCCESSFUL;
1246                 goto done;
1247         }
1248 
1249         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1250 
1251         if (count == 0) {
1252                 DEBUG(10, ("NO SIDs found\n"));
1253         }
1254 
1255         for (i = 0; i < count; i++) {
1256                 char *sidstr = NULL;
1257                 char *tmp = NULL;
1258                 enum id_type type;
1259                 struct id_map *map;
1260                 DOM_SID sid;
1261                 uint32_t id;
1262 
1263                 if (i == 0) { /* first entry */
1264                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1265                                                  result);
1266                 } else { /* following ones */
1267                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1268                                                 entry);
1269                 }
1270                 if ( ! entry) {
1271                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1272                                   "from results\n"));
1273                         break;
1274                 }
1275 
1276                 /* first check if the SID is present */
1277                 sidstr = smbldap_talloc_single_attribute(
1278                                 ctx->smbldap_state->ldap_struct,
1279                                 entry, LDAP_ATTRIBUTE_SID, memctx);
1280                 if ( ! sidstr) { /* no sid ??, skip entry */
1281                         DEBUG(2, ("WARNING SID not found on entry\n"));
1282                         continue;
1283                 }
1284 
1285                 if ( ! string_to_sid(&sid, sidstr)) {
1286                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1287                         TALLOC_FREE(sidstr);
1288                         continue;
1289                 }
1290 
1291                 map = find_map_by_sid(&ids[bidx], &sid);
1292                 if (!map) {
1293                         DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1294                                   "in ids", sidstr));
1295                         TALLOC_FREE(sidstr);
1296                         continue;
1297                 }
1298 
1299                 /* now try to see if it is a uid, if not try with a gid
1300                  * (gid is more common, but in case both uidNumber and
1301                  * gidNumber are returned the SID is mapped to the uid
1302                  * not the gid) */
1303                 type = ID_TYPE_UID;
1304                 tmp = smbldap_talloc_single_attribute(
1305                                 ctx->smbldap_state->ldap_struct,
1306                                 entry, uidNumber, memctx);
1307                 if ( ! tmp) {
1308                         type = ID_TYPE_GID;
1309                         tmp = smbldap_talloc_single_attribute(
1310                                         ctx->smbldap_state->ldap_struct,
1311                                         entry, gidNumber, memctx);
1312                 }
1313                 if ( ! tmp) { /* no ids ?? */
1314                         DEBUG(5, ("no uidNumber, "
1315                                   "nor gidNumber attributes found\n"));
1316                         TALLOC_FREE(sidstr);
1317                         continue;
1318                 }
1319 
1320                 id = strtoul(tmp, NULL, 10);
1321                 if ((id == 0) ||
1322                     (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1323                     (ctx->filter_high_id && (id > ctx->filter_high_id))) {
1324                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1325                                   "Filtered!\n", id,
1326                                   ctx->filter_low_id, ctx->filter_high_id));
1327                         TALLOC_FREE(sidstr);
1328                         TALLOC_FREE(tmp);
1329                         continue;
1330                 }
1331                 TALLOC_FREE(tmp);
1332 
1333                 if (map->status == ID_MAPPED) {
1334                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1335                               "overwriting mapping %s -> %u with %s -> %u\n",
1336                               (type == ID_TYPE_UID) ? "UID" : "GID",
1337                               sidstr, map->xid.id, sidstr, id));
1338                 }
1339 
1340                 TALLOC_FREE(sidstr);
1341 
1342                 /* mapped */
1343                 map->xid.type = type;
1344                 map->xid.id = id;
1345                 map->status = ID_MAPPED;
1346 
1347                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1348                            (unsigned long)map->xid.id, map->xid.type));
1349         }
1350 
1351         /* free the ldap results */
1352         if (result) {
1353                 ldap_msgfree(result);
1354                 result = NULL;
1355         }
1356 
1357         if (multi && ids[idx]) { /* still some values to map */
1358                 goto again;
1359         }
1360 
1361         ret = NT_STATUS_OK;
1362 
1363         /* mark all unknwon/expired ones as unmapped */
1364         for (i = 0; ids[i]; i++) {
1365                 if (ids[i]->status != ID_MAPPED)
1366                         ids[i]->status = ID_UNMAPPED;
1367         }
1368 
1369 done:
1370         talloc_free(memctx);
1371         return ret;
1372 }
1373 
1374 /**********************************
1375  set a mapping.
1376 **********************************/
1377 
1378 /* TODO: change this:  This function cannot be called to modify a mapping,
1379  * only set a new one */
1380 
1381 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
     /* [<][>][^][v][top][bottom][index][help] */
1382                                        const struct id_map *map)
1383 {
1384         NTSTATUS ret;
1385         TALLOC_CTX *memctx;
1386         struct idmap_ldap_context *ctx;
1387         LDAPMessage *entry = NULL;
1388         LDAPMod **mods = NULL;
1389         const char *type;
1390         char *id_str;
1391         char *sid;
1392         char *dn;
1393         int rc = -1;
1394 
1395         /* Only do query if we are online */
1396         if (idmap_is_offline()) {
1397                 return NT_STATUS_FILE_IS_OFFLINE;
1398         }
1399 
1400         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1401 
1402         switch(map->xid.type) {
1403         case ID_TYPE_UID:
1404                 type = get_attr_key2string(sidmap_attr_list,
1405                                            LDAP_ATTR_UIDNUMBER);
1406                 break;
1407 
1408         case ID_TYPE_GID:
1409                 type = get_attr_key2string(sidmap_attr_list,
1410                                            LDAP_ATTR_GIDNUMBER);
1411                 break;
1412 
1413         default:
1414                 return NT_STATUS_INVALID_PARAMETER;
1415         }
1416 
1417         memctx = talloc_new(ctx);
1418         if ( ! memctx) {
1419                 DEBUG(0, ("Out of memory!\n"));
1420                 return NT_STATUS_NO_MEMORY;
1421         }
1422 
1423         id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
1424         CHECK_ALLOC_DONE(id_str);
1425 
1426         sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
1427         CHECK_ALLOC_DONE(sid);
1428 
1429         dn = talloc_asprintf(memctx, "%s=%s,%s",
1430                         get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1431                         sid,
1432                         ctx->suffix);
1433         CHECK_ALLOC_DONE(dn);
1434 
1435         smbldap_set_mod(&mods, LDAP_MOD_ADD,
1436                         "objectClass", LDAP_OBJ_IDMAP_ENTRY);
1437 
1438         smbldap_make_mod(ctx->smbldap_state->ldap_struct,
1439                          entry, &mods, type, id_str);
1440 
1441         smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
1442                          get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1443                          sid);
1444 
1445         if ( ! mods) {
1446                 DEBUG(2, ("ERROR: No mods?\n"));
1447                 ret = NT_STATUS_UNSUCCESSFUL;
1448                 goto done;
1449         }
1450 
1451         /* TODO: remove conflicting mappings! */
1452 
1453         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
1454 
1455         DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
1456 
1457         rc = smbldap_add(ctx->smbldap_state, dn, mods);
1458         ldap_mods_free(mods, True);
1459 
1460         if (rc != LDAP_SUCCESS) {
1461                 char *ld_error = NULL;
1462                 ldap_get_option(ctx->smbldap_state->ldap_struct,
1463                                 LDAP_OPT_ERROR_STRING, &ld_error);
1464                 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
1465                          "mapping [%s]\n", sid,
1466                          (unsigned long)map->xid.id, type));
1467                 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1468                         ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
1469                 if (ld_error) {
1470                         ldap_memfree(ld_error);
1471                 }
1472                 ret = NT_STATUS_UNSUCCESSFUL;
1473                 goto done;
1474         }
1475 
1476         DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
1477                   "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
1478 
1479         ret = NT_STATUS_OK;
1480 
1481 done:
1482         talloc_free(memctx);
1483         return ret;
1484 }
1485 
1486 /**********************************
1487  Close the idmap ldap instance
1488 **********************************/
1489 
1490 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
     /* [<][>][^][v][top][bottom][index][help] */
1491 {
1492         struct idmap_ldap_context *ctx;
1493 
1494         if (dom->private_data) {
1495                 ctx = talloc_get_type(dom->private_data,
1496                                       struct idmap_ldap_context);
1497 
1498                 talloc_free(ctx);
1499                 dom->private_data = NULL;
1500         }
1501 
1502         return NT_STATUS_OK;
1503 }
1504 
1505 static struct idmap_methods idmap_ldap_methods = {
1506 
1507         .init = idmap_ldap_db_init,
1508         .unixids_to_sids = idmap_ldap_unixids_to_sids,
1509         .sids_to_unixids = idmap_ldap_sids_to_unixids,
1510         .set_mapping = idmap_ldap_set_mapping,
1511         .close_fn = idmap_ldap_close
1512 };
1513 
1514 static struct idmap_alloc_methods idmap_ldap_alloc_methods = {
1515 
1516         .init = idmap_ldap_alloc_init,
1517         .allocate_id = idmap_ldap_allocate_id,
1518         .get_id_hwm = idmap_ldap_get_hwm,
1519         .set_id_hwm = idmap_ldap_set_hwm,
1520         .close_fn = idmap_ldap_alloc_close,
1521         /* .dump_data = TODO */
1522 };
1523 
1524 static NTSTATUS idmap_alloc_ldap_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
1525 {
1526         return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1527                                         &idmap_ldap_alloc_methods);
1528 }
1529 
1530 NTSTATUS idmap_ldap_init(void);
1531 NTSTATUS idmap_ldap_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
1532 {
1533         NTSTATUS ret;
1534 
1535         /* FIXME: bad hack to actually register also the alloc_ldap module
1536          * without changining configure.in */
1537         ret = idmap_alloc_ldap_init();
1538         if (! NT_STATUS_IS_OK(ret)) {
1539                 return ret;
1540         }
1541         return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1542                                   &idmap_ldap_methods);
1543 }
1544 

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