s3:idmap_ldap: fix a few typos in a comment
[kai/samba.git] / source3 / winbindd / idmap_ldap.c
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    Copyright (C) Michael Adam           2010
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27 #include "winbindd.h"
28 #include "secrets.h"
29 #include "idmap.h"
30 #include "idmap_rw.h"
31 #include "../libcli/security/security.h"
32
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_IDMAP
35
36 #include <lber.h>
37 #include <ldap.h>
38
39 #include "smbldap.h"
40
41 static char *idmap_fetch_secret(const char *backend,
42                                 const char *domain, const char *identity)
43 {
44         char *tmp, *ret;
45         int r;
46
47         r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
48
49         if (r < 0)
50                 return NULL;
51
52         strupper_m(tmp); /* make sure the key is case insensitive */
53         ret = secrets_fetch_generic(tmp, identity);
54
55         SAFE_FREE(tmp);
56
57         return ret;
58 }
59
60 struct idmap_ldap_context {
61         struct smbldap_state *smbldap_state;
62         char *url;
63         char *suffix;
64         char *user_dn;
65         bool anon;
66         struct idmap_rw_ops *rw_ops;
67 };
68
69 #define CHECK_ALLOC_DONE(mem) do { \
70         if (!mem) { \
71                 DEBUG(0, ("Out of memory!\n")); \
72                 ret = NT_STATUS_NO_MEMORY; \
73                 goto done; \
74         } } while (0)
75
76 /**********************************************************************
77  IDMAP ALLOC TDB BACKEND
78 **********************************************************************/
79
80 /*********************************************************************
81  ********************************************************************/
82
83 static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx,
84                                  struct smbldap_state *ldap_state,
85                                  const char *config_option,
86                                  struct idmap_domain *dom,
87                                  char **dn )
88 {
89         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
90         char *secret = NULL;
91         const char *tmp = NULL;
92         char *user_dn = NULL;
93         bool anon = False;
94
95         /* assume anonymous if we don't have a specified user */
96
97         tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
98
99         if ( tmp ) {
100                 if (!dom) {
101                         DEBUG(0, ("get_credentials: Invalid domain 'NULL' "
102                                   "encountered for user DN %s\n",
103                                   tmp));
104                         ret = NT_STATUS_UNSUCCESSFUL;
105                         goto done;
106                 } else {
107                         secret = idmap_fetch_secret("ldap", dom->name, tmp);
108                 }
109
110                 if (!secret) {
111                         DEBUG(0, ("get_credentials: Unable to fetch "
112                                   "auth credentials for %s in %s\n",
113                                   tmp, (dom==NULL)?"ALLOC":dom->name));
114                         ret = NT_STATUS_ACCESS_DENIED;
115                         goto done;
116                 }
117                 *dn = talloc_strdup(mem_ctx, tmp);
118                 CHECK_ALLOC_DONE(*dn);
119         } else {
120                 if (!fetch_ldap_pw(&user_dn, &secret)) {
121                         DEBUG(2, ("get_credentials: Failed to lookup ldap "
122                                   "bind creds. Using anonymous connection.\n"));
123                         anon = True;
124                         *dn = NULL;
125                 } else {
126                         *dn = talloc_strdup(mem_ctx, user_dn);
127                         SAFE_FREE( user_dn );
128                         CHECK_ALLOC_DONE(*dn);
129                 }
130         }
131
132         smbldap_set_creds(ldap_state, anon, *dn, secret);
133         ret = NT_STATUS_OK;
134
135 done:
136         SAFE_FREE(secret);
137
138         return ret;
139 }
140
141
142 /**********************************************************************
143  Verify the sambaUnixIdPool entry in the directory.
144 **********************************************************************/
145
146 static NTSTATUS verify_idpool(struct idmap_domain *dom)
147 {
148         NTSTATUS ret;
149         TALLOC_CTX *mem_ctx;
150         LDAPMessage *result = NULL;
151         LDAPMod **mods = NULL;
152         const char **attr_list;
153         char *filter;
154         int count;
155         int rc;
156         struct idmap_ldap_context *ctx;
157
158         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
159
160         mem_ctx = talloc_new(ctx);
161         if (mem_ctx == NULL) {
162                 DEBUG(0, ("Out of memory!\n"));
163                 return NT_STATUS_NO_MEMORY;
164         }
165
166         filter = talloc_asprintf(mem_ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
167         CHECK_ALLOC_DONE(filter);
168
169         attr_list = get_attr_list(mem_ctx, idpool_attr_list);
170         CHECK_ALLOC_DONE(attr_list);
171
172         rc = smbldap_search(ctx->smbldap_state,
173                                 ctx->suffix,
174                                 LDAP_SCOPE_SUBTREE,
175                                 filter,
176                                 attr_list,
177                                 0,
178                                 &result);
179
180         if (rc != LDAP_SUCCESS) {
181                 DEBUG(1, ("Unable to verify the idpool, "
182                           "cannot continue initialization!\n"));
183                 return NT_STATUS_UNSUCCESSFUL;
184         }
185
186         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
187
188         ldap_msgfree(result);
189
190         if ( count > 1 ) {
191                 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
192                         filter, ctx->suffix));
193                 ret = NT_STATUS_UNSUCCESSFUL;
194                 goto done;
195         }
196         else if (count == 0) {
197                 char *uid_str, *gid_str;
198
199                 uid_str = talloc_asprintf(mem_ctx, "%lu",
200                                 (unsigned long)dom->low_id);
201                 gid_str = talloc_asprintf(mem_ctx, "%lu",
202                                 (unsigned long)dom->low_id);
203
204                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
205                                 "objectClass", LDAP_OBJ_IDPOOL);
206                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
207                                 get_attr_key2string(idpool_attr_list,
208                                                     LDAP_ATTR_UIDNUMBER),
209                                 uid_str);
210                 smbldap_set_mod(&mods, LDAP_MOD_ADD,
211                                 get_attr_key2string(idpool_attr_list,
212                                                     LDAP_ATTR_GIDNUMBER),
213                                 gid_str);
214                 if (mods) {
215                         rc = smbldap_modify(ctx->smbldap_state,
216                                                 ctx->suffix,
217                                                 mods);
218                         ldap_mods_free(mods, True);
219                 } else {
220                         ret = NT_STATUS_UNSUCCESSFUL;
221                         goto done;
222                 }
223         }
224
225         ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
226 done:
227         talloc_free(mem_ctx);
228         return ret;
229 }
230
231 /********************************
232  Allocate a new uid or gid
233 ********************************/
234
235 static NTSTATUS idmap_ldap_allocate_id(struct idmap_domain *dom,
236                                        struct unixid *xid)
237 {
238         TALLOC_CTX *mem_ctx;
239         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
240         int rc = LDAP_SERVER_DOWN;
241         int count = 0;
242         LDAPMessage *result = NULL;
243         LDAPMessage *entry = NULL;
244         LDAPMod **mods = NULL;
245         char *id_str;
246         char *new_id_str;
247         char *filter = NULL;
248         const char *dn = NULL;
249         const char **attr_list;
250         const char *type;
251         struct idmap_ldap_context *ctx;
252
253         /* Only do query if we are online */
254         if (idmap_is_offline()) {
255                 return NT_STATUS_FILE_IS_OFFLINE;
256         }
257
258         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
259
260         mem_ctx = talloc_new(ctx);
261         if (!mem_ctx) {
262                 DEBUG(0, ("Out of memory!\n"));
263                 return NT_STATUS_NO_MEMORY;
264         }
265
266         /* get type */
267         switch (xid->type) {
268
269         case ID_TYPE_UID:
270                 type = get_attr_key2string(idpool_attr_list,
271                                            LDAP_ATTR_UIDNUMBER);
272                 break;
273
274         case ID_TYPE_GID:
275                 type = get_attr_key2string(idpool_attr_list,
276                                            LDAP_ATTR_GIDNUMBER);
277                 break;
278
279         default:
280                 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
281                 return NT_STATUS_INVALID_PARAMETER;
282         }
283
284         filter = talloc_asprintf(mem_ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
285         CHECK_ALLOC_DONE(filter);
286
287         attr_list = get_attr_list(mem_ctx, idpool_attr_list);
288         CHECK_ALLOC_DONE(attr_list);
289
290         DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
291
292         rc = smbldap_search(ctx->smbldap_state,
293                            ctx->suffix,
294                            LDAP_SCOPE_SUBTREE, filter,
295                            attr_list, 0, &result);
296
297         if (rc != LDAP_SUCCESS) {
298                 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
299                 goto done;
300         }
301
302         talloc_autofree_ldapmsg(mem_ctx, result);
303
304         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
305         if (count != 1) {
306                 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
307                 goto done;
308         }
309
310         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result);
311
312         dn = smbldap_talloc_dn(mem_ctx,
313                                ctx->smbldap_state->ldap_struct,
314                                entry);
315         if ( ! dn) {
316                 goto done;
317         }
318
319         id_str = smbldap_talloc_single_attribute(
320                                 ctx->smbldap_state->ldap_struct,
321                                 entry, type, mem_ctx);
322         if (id_str == NULL) {
323                 DEBUG(0,("%s attribute not found\n", type));
324                 ret = NT_STATUS_UNSUCCESSFUL;
325                 goto done;
326         }
327
328         xid->id = strtoul(id_str, NULL, 10);
329
330         /* make sure we still have room to grow */
331
332         switch (xid->type) {
333         case ID_TYPE_UID:
334                 if (xid->id > dom->high_id) {
335                         DEBUG(0,("Cannot allocate uid above %lu!\n",
336                                  (unsigned long)dom->high_id));
337                         goto done;
338                 }
339                 break;
340
341         case ID_TYPE_GID:
342                 if (xid->id > dom->high_id) {
343                         DEBUG(0,("Cannot allocate gid above %lu!\n",
344                                  (unsigned long)dom->high_id));
345                         goto done;
346                 }
347                 break;
348
349         default:
350                 /* impossible */
351                 goto done;
352         }
353
354         new_id_str = talloc_asprintf(mem_ctx, "%lu", (unsigned long)xid->id + 1);
355         if ( ! new_id_str) {
356                 DEBUG(0,("Out of memory\n"));
357                 ret = NT_STATUS_NO_MEMORY;
358                 goto done;
359         }
360
361         smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
362         smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
363
364         if (mods == NULL) {
365                 DEBUG(0,("smbldap_set_mod() failed.\n"));
366                 goto done;
367         }
368
369         DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
370                    id_str, new_id_str));
371
372         rc = smbldap_modify(ctx->smbldap_state, dn, mods);
373
374         ldap_mods_free(mods, True);
375
376         if (rc != LDAP_SUCCESS) {
377                 DEBUG(1,("Failed to allocate new %s. "
378                          "smbldap_modify() failed.\n", type));
379                 goto done;
380         }
381
382         ret = NT_STATUS_OK;
383
384 done:
385         talloc_free(mem_ctx);
386         return ret;
387 }
388
389 /**
390  * Allocate a new unix-ID.
391  * For now this is for the default idmap domain only.
392  * Should be extended later on.
393  */
394 static NTSTATUS idmap_ldap_get_new_id(struct idmap_domain *dom,
395                                       struct unixid *id)
396 {
397         NTSTATUS ret;
398
399         if (!strequal(dom->name, "*")) {
400                 DEBUG(3, ("idmap_ldap_get_new_id: "
401                           "Refusing allocation of a new unixid for domain'%s'. "
402                           "Currently only supported for the default "
403                           "domain \"*\".\n",
404                            dom->name));
405                 return NT_STATUS_NOT_IMPLEMENTED;
406         }
407
408         ret = idmap_ldap_allocate_id(dom, id);
409
410         return ret;
411 }
412
413
414 /**********************************************************************
415  IDMAP MAPPING LDAP BACKEND
416 **********************************************************************/
417
418 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
419 {
420         smbldap_free_struct(&ctx->smbldap_state);
421         DEBUG(5,("The connection to the LDAP server was closed\n"));
422         /* maybe free the results here --metze */
423
424         return 0;
425 }
426
427 /********************************
428  Initialise idmap database.
429 ********************************/
430
431 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
432                                        const struct id_map *map);
433
434 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
435                                    const char *params)
436 {
437         NTSTATUS ret;
438         struct idmap_ldap_context *ctx = NULL;
439         char *config_option = NULL;
440         const char *tmp = NULL;
441
442         /* Only do init if we are online */
443         if (idmap_is_offline()) {
444                 return NT_STATUS_FILE_IS_OFFLINE;
445         }
446
447         ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
448         if ( ! ctx) {
449                 DEBUG(0, ("Out of memory!\n"));
450                 return NT_STATUS_NO_MEMORY;
451         }
452
453         if (strequal(dom->name, "*")) {
454                 /* more specific configuration can go here */
455         } else {
456                 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
457                 if ( ! config_option) {
458                         DEBUG(0, ("Out of memory!\n"));
459                         ret = NT_STATUS_NO_MEMORY;
460                         goto done;
461                 }
462         }
463
464         if (params != NULL) {
465                 /* assume location is the only parameter */
466                 ctx->url = talloc_strdup(ctx, params);
467         } else {
468                 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
469
470                 if ( ! tmp) {
471                         DEBUG(1, ("ERROR: missing idmap ldap url\n"));
472                         ret = NT_STATUS_UNSUCCESSFUL;
473                         goto done;
474                 }
475
476                 ctx->url = talloc_strdup(ctx, tmp);
477         }
478         CHECK_ALLOC_DONE(ctx->url);
479
480         trim_char(ctx->url, '\"', '\"');
481
482         tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
483         if ( ! tmp || ! *tmp) {
484                 tmp = lp_ldap_idmap_suffix();
485                 if ( ! tmp) {
486                         DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
487                         ret = NT_STATUS_UNSUCCESSFUL;
488                         goto done;
489                 }
490         }
491
492         ctx->suffix = talloc_strdup(ctx, tmp);
493         CHECK_ALLOC_DONE(ctx->suffix);
494
495         ctx->rw_ops = talloc_zero(ctx, struct idmap_rw_ops);
496         CHECK_ALLOC_DONE(ctx->rw_ops);
497
498         ctx->rw_ops->get_new_id = idmap_ldap_get_new_id;
499         ctx->rw_ops->set_mapping = idmap_ldap_set_mapping;
500
501         ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
502                            &ctx->smbldap_state);
503         if (!NT_STATUS_IS_OK(ret)) {
504                 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
505                 goto done;
506         }
507
508         ret = get_credentials( ctx, ctx->smbldap_state, config_option,
509                                dom, &ctx->user_dn );
510         if ( !NT_STATUS_IS_OK(ret) ) {
511                 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
512                          "credentials (%s)\n", nt_errstr(ret)));
513                 goto done;
514         }
515
516         /*
517          * Set the destructor on the context, so that resources are
518          * properly freed when the context is released.
519          */
520         talloc_set_destructor(ctx, idmap_ldap_close_destructor);
521
522         dom->private_data = ctx;
523
524         ret = verify_idpool(dom);
525         if (!NT_STATUS_IS_OK(ret)) {
526                 DEBUG(1, ("idmap_ldap_db_init: failed to verify ID pool (%s)\n",
527                          nt_errstr(ret)));
528                 goto done;
529         }
530
531         talloc_free(config_option);
532         return NT_STATUS_OK;
533
534 /*failed */
535 done:
536         talloc_free(ctx);
537         return ret;
538 }
539
540 /**
541  * set a mapping.
542  */
543
544 /* TODO: change this:  This function cannot be called to modify a mapping,
545  * only set a new one */
546
547 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
548                                        const struct id_map *map)
549 {
550         NTSTATUS ret;
551         TALLOC_CTX *memctx;
552         struct idmap_ldap_context *ctx;
553         LDAPMessage *entry = NULL;
554         LDAPMod **mods = NULL;
555         const char *type;
556         char *id_str;
557         char *sid;
558         char *dn;
559         int rc = -1;
560
561         /* Only do query if we are online */
562         if (idmap_is_offline()) {
563                 return NT_STATUS_FILE_IS_OFFLINE;
564         }
565
566         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
567
568         switch(map->xid.type) {
569         case ID_TYPE_UID:
570                 type = get_attr_key2string(sidmap_attr_list,
571                                            LDAP_ATTR_UIDNUMBER);
572                 break;
573
574         case ID_TYPE_GID:
575                 type = get_attr_key2string(sidmap_attr_list,
576                                            LDAP_ATTR_GIDNUMBER);
577                 break;
578
579         default:
580                 return NT_STATUS_INVALID_PARAMETER;
581         }
582
583         memctx = talloc_new(ctx);
584         if ( ! memctx) {
585                 DEBUG(0, ("Out of memory!\n"));
586                 return NT_STATUS_NO_MEMORY;
587         }
588
589         id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
590         CHECK_ALLOC_DONE(id_str);
591
592         sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
593         CHECK_ALLOC_DONE(sid);
594
595         dn = talloc_asprintf(memctx, "%s=%s,%s",
596                         get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
597                         sid,
598                         ctx->suffix);
599         CHECK_ALLOC_DONE(dn);
600
601         smbldap_set_mod(&mods, LDAP_MOD_ADD,
602                         "objectClass", LDAP_OBJ_IDMAP_ENTRY);
603
604         smbldap_make_mod(ctx->smbldap_state->ldap_struct,
605                          entry, &mods, type, id_str);
606
607         smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
608                          get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
609                          sid);
610
611         if ( ! mods) {
612                 DEBUG(2, ("ERROR: No mods?\n"));
613                 ret = NT_STATUS_UNSUCCESSFUL;
614                 goto done;
615         }
616
617         /* TODO: remove conflicting mappings! */
618
619         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
620
621         DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
622
623         rc = smbldap_add(ctx->smbldap_state, dn, mods);
624         ldap_mods_free(mods, True);
625
626         if (rc != LDAP_SUCCESS) {
627                 char *ld_error = NULL;
628                 ldap_get_option(ctx->smbldap_state->ldap_struct,
629                                 LDAP_OPT_ERROR_STRING, &ld_error);
630                 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
631                          "mapping [%s]\n", sid,
632                          (unsigned long)map->xid.id, type));
633                 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
634                         ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
635                 if (ld_error) {
636                         ldap_memfree(ld_error);
637                 }
638                 ret = NT_STATUS_UNSUCCESSFUL;
639                 goto done;
640         }
641
642         DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
643                   "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
644
645         ret = NT_STATUS_OK;
646
647 done:
648         talloc_free(memctx);
649         return ret;
650 }
651
652 /**
653  * Create a new mapping for an unmapped SID, also allocating a new ID.
654  * If possible, this should be run inside a transaction to make the
655  * action atomic.
656  */
657 static NTSTATUS idmap_ldap_new_mapping(struct idmap_domain *dom, struct id_map *map)
658 {
659         NTSTATUS ret;
660         struct idmap_ldap_context *ctx;
661
662         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
663
664         ret = idmap_rw_new_mapping(dom, ctx->rw_ops, map);
665
666         return ret;
667 }
668
669
670 /* max number of ids requested per batch query */
671 #define IDMAP_LDAP_MAX_IDS 30
672
673 /**********************************
674  lookup a set of unix ids.
675 **********************************/
676
677 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
678  * in maps for a match */
679 static struct id_map *find_map_by_id(struct id_map **maps,
680                                      enum id_type type,
681                                      uint32_t id)
682 {
683         int i;
684
685         for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
686                 if (maps[i] == NULL) { /* end of the run */
687                         return NULL;
688                 }
689                 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
690                         return maps[i];
691                 }
692         }
693
694         return NULL;
695 }
696
697 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
698                                            struct id_map **ids)
699 {
700         NTSTATUS ret;
701         TALLOC_CTX *memctx;
702         struct idmap_ldap_context *ctx;
703         LDAPMessage *result = NULL;
704         LDAPMessage *entry = NULL;
705         const char *uidNumber;
706         const char *gidNumber;
707         const char **attr_list;
708         char *filter = NULL;
709         bool multi = False;
710         int idx = 0;
711         int bidx = 0;
712         int count;
713         int rc;
714         int i;
715
716         /* Only do query if we are online */
717         if (idmap_is_offline()) {
718                 return NT_STATUS_FILE_IS_OFFLINE;
719         }
720
721         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
722
723         memctx = talloc_new(ctx);
724         if ( ! memctx) {
725                 DEBUG(0, ("Out of memory!\n"));
726                 return NT_STATUS_NO_MEMORY;
727         }
728
729         uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
730         gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
731
732         attr_list = get_attr_list(memctx, sidmap_attr_list);
733
734         if ( ! ids[1]) {
735                 /* if we are requested just one mapping use the simple filter */
736
737                 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
738                                 LDAP_OBJ_IDMAP_ENTRY,
739                                 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
740                                 (unsigned long)ids[0]->xid.id);
741                 CHECK_ALLOC_DONE(filter);
742                 DEBUG(10, ("Filter: [%s]\n", filter));
743         } else {
744                 /* multiple mappings */
745                 multi = True;
746         }
747
748         for (i = 0; ids[i]; i++) {
749                 ids[i]->status = ID_UNKNOWN;
750         }
751
752 again:
753         if (multi) {
754
755                 talloc_free(filter);
756                 filter = talloc_asprintf(memctx,
757                                          "(&(objectClass=%s)(|",
758                                          LDAP_OBJ_IDMAP_ENTRY);
759                 CHECK_ALLOC_DONE(filter);
760
761                 bidx = idx;
762                 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
763                         filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
764                                         (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
765                                         (unsigned long)ids[idx]->xid.id);
766                         CHECK_ALLOC_DONE(filter);
767                 }
768                 filter = talloc_asprintf_append_buffer(filter, "))");
769                 CHECK_ALLOC_DONE(filter);
770                 DEBUG(10, ("Filter: [%s]\n", filter));
771         } else {
772                 bidx = 0;
773                 idx = 1;
774         }
775
776         rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
777                 filter, attr_list, 0, &result);
778
779         if (rc != LDAP_SUCCESS) {
780                 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
781                 ret = NT_STATUS_UNSUCCESSFUL;
782                 goto done;
783         }
784
785         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
786
787         if (count == 0) {
788                 DEBUG(10, ("NO SIDs found\n"));
789         }
790
791         for (i = 0; i < count; i++) {
792                 char *sidstr = NULL;
793                 char *tmp = NULL;
794                 enum id_type type;
795                 struct id_map *map;
796                 uint32_t id;
797
798                 if (i == 0) { /* first entry */
799                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
800                                                  result);
801                 } else { /* following ones */
802                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
803                                                 entry);
804                 }
805                 if ( ! entry) {
806                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
807                                   "from results\n"));
808                         break;
809                 }
810
811                 /* first check if the SID is present */
812                 sidstr = smbldap_talloc_single_attribute(
813                                 ctx->smbldap_state->ldap_struct,
814                                 entry, LDAP_ATTRIBUTE_SID, memctx);
815                 if ( ! sidstr) { /* no sid, skip entry */
816                         DEBUG(2, ("WARNING SID not found on entry\n"));
817                         continue;
818                 }
819
820                 /* now try to see if it is a uid, if not try with a gid
821                  * (gid is more common, but in case both uidNumber and
822                  * gidNumber are returned the SID is mapped to the uid
823                  *not the gid) */
824                 type = ID_TYPE_UID;
825                 tmp = smbldap_talloc_single_attribute(
826                                 ctx->smbldap_state->ldap_struct,
827                                 entry, uidNumber, memctx);
828                 if ( ! tmp) {
829                         type = ID_TYPE_GID;
830                         tmp = smbldap_talloc_single_attribute(
831                                         ctx->smbldap_state->ldap_struct,
832                                         entry, gidNumber, memctx);
833                 }
834                 if ( ! tmp) { /* wow very strange entry, how did it match ? */
835                         DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
836                                   "nor gidNumber returned\n", sidstr));
837                         TALLOC_FREE(sidstr);
838                         continue;
839                 }
840
841                 id = strtoul(tmp, NULL, 10);
842                 if (!idmap_unix_id_is_in_range(id, dom)) {
843                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
844                                   "Filtered!\n", id,
845                                   dom->low_id, dom->high_id));
846                         TALLOC_FREE(sidstr);
847                         TALLOC_FREE(tmp);
848                         continue;
849                 }
850                 TALLOC_FREE(tmp);
851
852                 map = find_map_by_id(&ids[bidx], type, id);
853                 if (!map) {
854                         DEBUG(2, ("WARNING: couldn't match sid (%s) "
855                                   "with requested ids\n", sidstr));
856                         TALLOC_FREE(sidstr);
857                         continue;
858                 }
859
860                 if ( ! string_to_sid(map->sid, sidstr)) {
861                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
862                         TALLOC_FREE(sidstr);
863                         continue;
864                 }
865
866                 if (map->status == ID_MAPPED) {
867                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
868                               "overwriting mapping %u -> %s with %u -> %s\n",
869                               (type == ID_TYPE_UID) ? "UID" : "GID",
870                               id, sid_string_dbg(map->sid), id, sidstr));
871                 }
872
873                 TALLOC_FREE(sidstr);
874
875                 /* mapped */
876                 map->status = ID_MAPPED;
877
878                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
879                            (unsigned long)map->xid.id, map->xid.type));
880         }
881
882         /* free the ldap results */
883         if (result) {
884                 ldap_msgfree(result);
885                 result = NULL;
886         }
887
888         if (multi && ids[idx]) { /* still some values to map */
889                 goto again;
890         }
891
892         ret = NT_STATUS_OK;
893
894         /* mark all unknwon/expired ones as unmapped */
895         for (i = 0; ids[i]; i++) {
896                 if (ids[i]->status != ID_MAPPED)
897                         ids[i]->status = ID_UNMAPPED;
898         }
899
900 done:
901         talloc_free(memctx);
902         return ret;
903 }
904
905 /**********************************
906  lookup a set of sids.
907 **********************************/
908
909 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
910  * in maps for a match */
911 static struct id_map *find_map_by_sid(struct id_map **maps, struct dom_sid *sid)
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 (dom_sid_equal(maps[i]->sid, sid)) {
920                         return maps[i];
921                 }
922         }
923
924         return NULL;
925 }
926
927 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
928                                            struct id_map **ids)
929 {
930         LDAPMessage *entry = NULL;
931         NTSTATUS ret;
932         TALLOC_CTX *memctx;
933         struct idmap_ldap_context *ctx;
934         LDAPMessage *result = 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=%s))",
968                                 LDAP_OBJ_IDMAP_ENTRY,
969                                 LDAP_ATTRIBUTE_SID,
970                                 sid_string_talloc(memctx, ids[0]->sid));
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=%s)",
994                                         LDAP_ATTRIBUTE_SID,
995                                         sid_string_talloc(memctx,
996                                                           ids[idx]->sid));
997                         CHECK_ALLOC_DONE(filter);
998                 }
999                 filter = talloc_asprintf_append_buffer(filter, "))");
1000                 CHECK_ALLOC_DONE(filter);
1001                 DEBUG(10, ("Filter: [%s]", filter));
1002         } else {
1003                 bidx = 0;
1004                 idx = 1;
1005         }
1006
1007         rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1008                 filter, attr_list, 0, &result);
1009
1010         if (rc != LDAP_SUCCESS) {
1011                 DEBUG(3,("Failure looking up sids (%s)\n",
1012                          ldap_err2string(rc)));
1013                 ret = NT_STATUS_UNSUCCESSFUL;
1014                 goto done;
1015         }
1016
1017         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1018
1019         if (count == 0) {
1020                 DEBUG(10, ("NO SIDs found\n"));
1021         }
1022
1023         for (i = 0; i < count; i++) {
1024                 char *sidstr = NULL;
1025                 char *tmp = NULL;
1026                 enum id_type type;
1027                 struct id_map *map;
1028                 struct dom_sid sid;
1029                 uint32_t id;
1030
1031                 if (i == 0) { /* first entry */
1032                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1033                                                  result);
1034                 } else { /* following ones */
1035                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1036                                                 entry);
1037                 }
1038                 if ( ! entry) {
1039                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1040                                   "from results\n"));
1041                         break;
1042                 }
1043
1044                 /* first check if the SID is present */
1045                 sidstr = smbldap_talloc_single_attribute(
1046                                 ctx->smbldap_state->ldap_struct,
1047                                 entry, LDAP_ATTRIBUTE_SID, memctx);
1048                 if ( ! sidstr) { /* no sid ??, skip entry */
1049                         DEBUG(2, ("WARNING SID not found on entry\n"));
1050                         continue;
1051                 }
1052
1053                 if ( ! string_to_sid(&sid, sidstr)) {
1054                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1055                         TALLOC_FREE(sidstr);
1056                         continue;
1057                 }
1058
1059                 map = find_map_by_sid(&ids[bidx], &sid);
1060                 if (!map) {
1061                         DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1062                                   "in ids", sidstr));
1063                         TALLOC_FREE(sidstr);
1064                         continue;
1065                 }
1066
1067                 /* now try to see if it is a uid, if not try with a gid
1068                  * (gid is more common, but in case both uidNumber and
1069                  * gidNumber are returned the SID is mapped to the uid
1070                  * not the gid) */
1071                 type = ID_TYPE_UID;
1072                 tmp = smbldap_talloc_single_attribute(
1073                                 ctx->smbldap_state->ldap_struct,
1074                                 entry, uidNumber, memctx);
1075                 if ( ! tmp) {
1076                         type = ID_TYPE_GID;
1077                         tmp = smbldap_talloc_single_attribute(
1078                                         ctx->smbldap_state->ldap_struct,
1079                                         entry, gidNumber, memctx);
1080                 }
1081                 if ( ! tmp) { /* no ids ?? */
1082                         DEBUG(5, ("no uidNumber, "
1083                                   "nor gidNumber attributes found\n"));
1084                         TALLOC_FREE(sidstr);
1085                         continue;
1086                 }
1087
1088                 id = strtoul(tmp, NULL, 10);
1089                 if (!idmap_unix_id_is_in_range(id, dom)) {
1090                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1091                                   "Filtered!\n", id,
1092                                   dom->low_id, dom->high_id));
1093                         TALLOC_FREE(sidstr);
1094                         TALLOC_FREE(tmp);
1095                         continue;
1096                 }
1097                 TALLOC_FREE(tmp);
1098
1099                 if (map->status == ID_MAPPED) {
1100                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1101                               "overwriting mapping %s -> %u with %s -> %u\n",
1102                               (type == ID_TYPE_UID) ? "UID" : "GID",
1103                               sidstr, map->xid.id, sidstr, id));
1104                 }
1105
1106                 TALLOC_FREE(sidstr);
1107
1108                 /* mapped */
1109                 map->xid.type = type;
1110                 map->xid.id = id;
1111                 map->status = ID_MAPPED;
1112
1113                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1114                            (unsigned long)map->xid.id, map->xid.type));
1115         }
1116
1117         /* free the ldap results */
1118         if (result) {
1119                 ldap_msgfree(result);
1120                 result = NULL;
1121         }
1122
1123         if (multi && ids[idx]) { /* still some values to map */
1124                 goto again;
1125         }
1126
1127         /*
1128          *  try to create new mappings for unmapped sids
1129          */
1130         for (i = 0; ids[i]; i++) {
1131                 if (ids[i]->status != ID_MAPPED) {
1132                         ids[i]->status = ID_UNMAPPED;
1133                         if (ids[i]->sid != NULL) {
1134                                 ret = idmap_ldap_new_mapping(dom, ids[i]);
1135                                 if (!NT_STATUS_IS_OK(ret)) {
1136                                         goto done;
1137                                 }
1138                         }
1139                 }
1140         }
1141
1142         ret = NT_STATUS_OK;
1143
1144 done:
1145         talloc_free(memctx);
1146         return ret;
1147 }
1148
1149 /**********************************
1150  Close the idmap ldap instance
1151 **********************************/
1152
1153 static struct idmap_methods idmap_ldap_methods = {
1154
1155         .init = idmap_ldap_db_init,
1156         .unixids_to_sids = idmap_ldap_unixids_to_sids,
1157         .sids_to_unixids = idmap_ldap_sids_to_unixids,
1158         .allocate_id = idmap_ldap_get_new_id,
1159 };
1160
1161 NTSTATUS idmap_ldap_init(void);
1162 NTSTATUS idmap_ldap_init(void)
1163 {
1164         return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1165                                   &idmap_ldap_methods);
1166 }
1167