s3-idmap-ldap: private_data is a talloc child of dom
[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         /* set the destructor on the context, so that resource are properly
517            freed if the contexts is released */
518
519         talloc_set_destructor(ctx, idmap_ldap_close_destructor);
520
521         dom->private_data = ctx;
522
523         ret = verify_idpool(dom);
524         if (!NT_STATUS_IS_OK(ret)) {
525                 DEBUG(1, ("idmap_ldap_db_init: failed to verify ID pool (%s)\n",
526                          nt_errstr(ret)));
527                 goto done;
528         }
529
530         talloc_free(config_option);
531         return NT_STATUS_OK;
532
533 /*failed */
534 done:
535         talloc_free(ctx);
536         return ret;
537 }
538
539 /**
540  * set a mapping.
541  */
542
543 /* TODO: change this:  This function cannot be called to modify a mapping,
544  * only set a new one */
545
546 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
547                                        const struct id_map *map)
548 {
549         NTSTATUS ret;
550         TALLOC_CTX *memctx;
551         struct idmap_ldap_context *ctx;
552         LDAPMessage *entry = NULL;
553         LDAPMod **mods = NULL;
554         const char *type;
555         char *id_str;
556         char *sid;
557         char *dn;
558         int rc = -1;
559
560         /* Only do query if we are online */
561         if (idmap_is_offline()) {
562                 return NT_STATUS_FILE_IS_OFFLINE;
563         }
564
565         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
566
567         switch(map->xid.type) {
568         case ID_TYPE_UID:
569                 type = get_attr_key2string(sidmap_attr_list,
570                                            LDAP_ATTR_UIDNUMBER);
571                 break;
572
573         case ID_TYPE_GID:
574                 type = get_attr_key2string(sidmap_attr_list,
575                                            LDAP_ATTR_GIDNUMBER);
576                 break;
577
578         default:
579                 return NT_STATUS_INVALID_PARAMETER;
580         }
581
582         memctx = talloc_new(ctx);
583         if ( ! memctx) {
584                 DEBUG(0, ("Out of memory!\n"));
585                 return NT_STATUS_NO_MEMORY;
586         }
587
588         id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
589         CHECK_ALLOC_DONE(id_str);
590
591         sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
592         CHECK_ALLOC_DONE(sid);
593
594         dn = talloc_asprintf(memctx, "%s=%s,%s",
595                         get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
596                         sid,
597                         ctx->suffix);
598         CHECK_ALLOC_DONE(dn);
599
600         smbldap_set_mod(&mods, LDAP_MOD_ADD,
601                         "objectClass", LDAP_OBJ_IDMAP_ENTRY);
602
603         smbldap_make_mod(ctx->smbldap_state->ldap_struct,
604                          entry, &mods, type, id_str);
605
606         smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
607                          get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
608                          sid);
609
610         if ( ! mods) {
611                 DEBUG(2, ("ERROR: No mods?\n"));
612                 ret = NT_STATUS_UNSUCCESSFUL;
613                 goto done;
614         }
615
616         /* TODO: remove conflicting mappings! */
617
618         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
619
620         DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
621
622         rc = smbldap_add(ctx->smbldap_state, dn, mods);
623         ldap_mods_free(mods, True);
624
625         if (rc != LDAP_SUCCESS) {
626                 char *ld_error = NULL;
627                 ldap_get_option(ctx->smbldap_state->ldap_struct,
628                                 LDAP_OPT_ERROR_STRING, &ld_error);
629                 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
630                          "mapping [%s]\n", sid,
631                          (unsigned long)map->xid.id, type));
632                 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
633                         ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
634                 if (ld_error) {
635                         ldap_memfree(ld_error);
636                 }
637                 ret = NT_STATUS_UNSUCCESSFUL;
638                 goto done;
639         }
640
641         DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
642                   "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
643
644         ret = NT_STATUS_OK;
645
646 done:
647         talloc_free(memctx);
648         return ret;
649 }
650
651 /**
652  * Create a new mapping for an unmapped SID, also allocating a new ID.
653  * If possible, this should be run inside a transaction to make the
654  * action atomic.
655  */
656 static NTSTATUS idmap_ldap_new_mapping(struct idmap_domain *dom, struct id_map *map)
657 {
658         NTSTATUS ret;
659         struct idmap_ldap_context *ctx;
660
661         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
662
663         ret = idmap_rw_new_mapping(dom, ctx->rw_ops, map);
664
665         return ret;
666 }
667
668
669 /* max number of ids requested per batch query */
670 #define IDMAP_LDAP_MAX_IDS 30
671
672 /**********************************
673  lookup a set of unix ids.
674 **********************************/
675
676 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
677  * in maps for a match */
678 static struct id_map *find_map_by_id(struct id_map **maps,
679                                      enum id_type type,
680                                      uint32_t id)
681 {
682         int i;
683
684         for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
685                 if (maps[i] == NULL) { /* end of the run */
686                         return NULL;
687                 }
688                 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
689                         return maps[i];
690                 }
691         }
692
693         return NULL;
694 }
695
696 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
697                                            struct id_map **ids)
698 {
699         NTSTATUS ret;
700         TALLOC_CTX *memctx;
701         struct idmap_ldap_context *ctx;
702         LDAPMessage *result = NULL;
703         LDAPMessage *entry = NULL;
704         const char *uidNumber;
705         const char *gidNumber;
706         const char **attr_list;
707         char *filter = NULL;
708         bool multi = False;
709         int idx = 0;
710         int bidx = 0;
711         int count;
712         int rc;
713         int i;
714
715         /* Only do query if we are online */
716         if (idmap_is_offline()) {
717                 return NT_STATUS_FILE_IS_OFFLINE;
718         }
719
720         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
721
722         memctx = talloc_new(ctx);
723         if ( ! memctx) {
724                 DEBUG(0, ("Out of memory!\n"));
725                 return NT_STATUS_NO_MEMORY;
726         }
727
728         uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
729         gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
730
731         attr_list = get_attr_list(memctx, sidmap_attr_list);
732
733         if ( ! ids[1]) {
734                 /* if we are requested just one mapping use the simple filter */
735
736                 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
737                                 LDAP_OBJ_IDMAP_ENTRY,
738                                 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
739                                 (unsigned long)ids[0]->xid.id);
740                 CHECK_ALLOC_DONE(filter);
741                 DEBUG(10, ("Filter: [%s]\n", filter));
742         } else {
743                 /* multiple mappings */
744                 multi = True;
745         }
746
747         for (i = 0; ids[i]; i++) {
748                 ids[i]->status = ID_UNKNOWN;
749         }
750
751 again:
752         if (multi) {
753
754                 talloc_free(filter);
755                 filter = talloc_asprintf(memctx,
756                                          "(&(objectClass=%s)(|",
757                                          LDAP_OBJ_IDMAP_ENTRY);
758                 CHECK_ALLOC_DONE(filter);
759
760                 bidx = idx;
761                 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
762                         filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
763                                         (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
764                                         (unsigned long)ids[idx]->xid.id);
765                         CHECK_ALLOC_DONE(filter);
766                 }
767                 filter = talloc_asprintf_append_buffer(filter, "))");
768                 CHECK_ALLOC_DONE(filter);
769                 DEBUG(10, ("Filter: [%s]\n", filter));
770         } else {
771                 bidx = 0;
772                 idx = 1;
773         }
774
775         rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
776                 filter, attr_list, 0, &result);
777
778         if (rc != LDAP_SUCCESS) {
779                 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
780                 ret = NT_STATUS_UNSUCCESSFUL;
781                 goto done;
782         }
783
784         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
785
786         if (count == 0) {
787                 DEBUG(10, ("NO SIDs found\n"));
788         }
789
790         for (i = 0; i < count; i++) {
791                 char *sidstr = NULL;
792                 char *tmp = NULL;
793                 enum id_type type;
794                 struct id_map *map;
795                 uint32_t id;
796
797                 if (i == 0) { /* first entry */
798                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
799                                                  result);
800                 } else { /* following ones */
801                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
802                                                 entry);
803                 }
804                 if ( ! entry) {
805                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
806                                   "from results\n"));
807                         break;
808                 }
809
810                 /* first check if the SID is present */
811                 sidstr = smbldap_talloc_single_attribute(
812                                 ctx->smbldap_state->ldap_struct,
813                                 entry, LDAP_ATTRIBUTE_SID, memctx);
814                 if ( ! sidstr) { /* no sid, skip entry */
815                         DEBUG(2, ("WARNING SID not found on entry\n"));
816                         continue;
817                 }
818
819                 /* now try to see if it is a uid, if not try with a gid
820                  * (gid is more common, but in case both uidNumber and
821                  * gidNumber are returned the SID is mapped to the uid
822                  *not the gid) */
823                 type = ID_TYPE_UID;
824                 tmp = smbldap_talloc_single_attribute(
825                                 ctx->smbldap_state->ldap_struct,
826                                 entry, uidNumber, memctx);
827                 if ( ! tmp) {
828                         type = ID_TYPE_GID;
829                         tmp = smbldap_talloc_single_attribute(
830                                         ctx->smbldap_state->ldap_struct,
831                                         entry, gidNumber, memctx);
832                 }
833                 if ( ! tmp) { /* wow very strange entry, how did it match ? */
834                         DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
835                                   "nor gidNumber returned\n", sidstr));
836                         TALLOC_FREE(sidstr);
837                         continue;
838                 }
839
840                 id = strtoul(tmp, NULL, 10);
841                 if (!idmap_unix_id_is_in_range(id, dom)) {
842                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
843                                   "Filtered!\n", id,
844                                   dom->low_id, dom->high_id));
845                         TALLOC_FREE(sidstr);
846                         TALLOC_FREE(tmp);
847                         continue;
848                 }
849                 TALLOC_FREE(tmp);
850
851                 map = find_map_by_id(&ids[bidx], type, id);
852                 if (!map) {
853                         DEBUG(2, ("WARNING: couldn't match sid (%s) "
854                                   "with requested ids\n", sidstr));
855                         TALLOC_FREE(sidstr);
856                         continue;
857                 }
858
859                 if ( ! string_to_sid(map->sid, sidstr)) {
860                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
861                         TALLOC_FREE(sidstr);
862                         continue;
863                 }
864
865                 if (map->status == ID_MAPPED) {
866                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
867                               "overwriting mapping %u -> %s with %u -> %s\n",
868                               (type == ID_TYPE_UID) ? "UID" : "GID",
869                               id, sid_string_dbg(map->sid), id, sidstr));
870                 }
871
872                 TALLOC_FREE(sidstr);
873
874                 /* mapped */
875                 map->status = ID_MAPPED;
876
877                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
878                            (unsigned long)map->xid.id, map->xid.type));
879         }
880
881         /* free the ldap results */
882         if (result) {
883                 ldap_msgfree(result);
884                 result = NULL;
885         }
886
887         if (multi && ids[idx]) { /* still some values to map */
888                 goto again;
889         }
890
891         ret = NT_STATUS_OK;
892
893         /* mark all unknwon/expired ones as unmapped */
894         for (i = 0; ids[i]; i++) {
895                 if (ids[i]->status != ID_MAPPED)
896                         ids[i]->status = ID_UNMAPPED;
897         }
898
899 done:
900         talloc_free(memctx);
901         return ret;
902 }
903
904 /**********************************
905  lookup a set of sids.
906 **********************************/
907
908 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
909  * in maps for a match */
910 static struct id_map *find_map_by_sid(struct id_map **maps, struct dom_sid *sid)
911 {
912         int i;
913
914         for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
915                 if (maps[i] == NULL) { /* end of the run */
916                         return NULL;
917                 }
918                 if (dom_sid_equal(maps[i]->sid, sid)) {
919                         return maps[i];
920                 }
921         }
922
923         return NULL;
924 }
925
926 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
927                                            struct id_map **ids)
928 {
929         LDAPMessage *entry = NULL;
930         NTSTATUS ret;
931         TALLOC_CTX *memctx;
932         struct idmap_ldap_context *ctx;
933         LDAPMessage *result = NULL;
934         const char *uidNumber;
935         const char *gidNumber;
936         const char **attr_list;
937         char *filter = NULL;
938         bool multi = False;
939         int idx = 0;
940         int bidx = 0;
941         int count;
942         int rc;
943         int i;
944
945         /* Only do query if we are online */
946         if (idmap_is_offline()) {
947                 return NT_STATUS_FILE_IS_OFFLINE;
948         }
949
950         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
951
952         memctx = talloc_new(ctx);
953         if ( ! memctx) {
954                 DEBUG(0, ("Out of memory!\n"));
955                 return NT_STATUS_NO_MEMORY;
956         }
957
958         uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
959         gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
960
961         attr_list = get_attr_list(memctx, sidmap_attr_list);
962
963         if ( ! ids[1]) {
964                 /* if we are requested just one mapping use the simple filter */
965
966                 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
967                                 LDAP_OBJ_IDMAP_ENTRY,
968                                 LDAP_ATTRIBUTE_SID,
969                                 sid_string_talloc(memctx, ids[0]->sid));
970                 CHECK_ALLOC_DONE(filter);
971                 DEBUG(10, ("Filter: [%s]\n", filter));
972         } else {
973                 /* multiple mappings */
974                 multi = True;
975         }
976
977         for (i = 0; ids[i]; i++) {
978                 ids[i]->status = ID_UNKNOWN;
979         }
980
981 again:
982         if (multi) {
983
984                 TALLOC_FREE(filter);
985                 filter = talloc_asprintf(memctx,
986                                          "(&(objectClass=%s)(|",
987                                          LDAP_OBJ_IDMAP_ENTRY);
988                 CHECK_ALLOC_DONE(filter);
989
990                 bidx = idx;
991                 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
992                         filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
993                                         LDAP_ATTRIBUTE_SID,
994                                         sid_string_talloc(memctx,
995                                                           ids[idx]->sid));
996                         CHECK_ALLOC_DONE(filter);
997                 }
998                 filter = talloc_asprintf_append_buffer(filter, "))");
999                 CHECK_ALLOC_DONE(filter);
1000                 DEBUG(10, ("Filter: [%s]", 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 sids (%s)\n",
1011                          ldap_err2string(rc)));
1012                 ret = NT_STATUS_UNSUCCESSFUL;
1013                 goto done;
1014         }
1015
1016         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1017
1018         if (count == 0) {
1019                 DEBUG(10, ("NO SIDs found\n"));
1020         }
1021
1022         for (i = 0; i < count; i++) {
1023                 char *sidstr = NULL;
1024                 char *tmp = NULL;
1025                 enum id_type type;
1026                 struct id_map *map;
1027                 struct dom_sid sid;
1028                 uint32_t id;
1029
1030                 if (i == 0) { /* first entry */
1031                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1032                                                  result);
1033                 } else { /* following ones */
1034                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1035                                                 entry);
1036                 }
1037                 if ( ! entry) {
1038                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1039                                   "from results\n"));
1040                         break;
1041                 }
1042
1043                 /* first check if the SID is present */
1044                 sidstr = smbldap_talloc_single_attribute(
1045                                 ctx->smbldap_state->ldap_struct,
1046                                 entry, LDAP_ATTRIBUTE_SID, memctx);
1047                 if ( ! sidstr) { /* no sid ??, skip entry */
1048                         DEBUG(2, ("WARNING SID not found on entry\n"));
1049                         continue;
1050                 }
1051
1052                 if ( ! string_to_sid(&sid, sidstr)) {
1053                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1054                         TALLOC_FREE(sidstr);
1055                         continue;
1056                 }
1057
1058                 map = find_map_by_sid(&ids[bidx], &sid);
1059                 if (!map) {
1060                         DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1061                                   "in ids", sidstr));
1062                         TALLOC_FREE(sidstr);
1063                         continue;
1064                 }
1065
1066                 /* now try to see if it is a uid, if not try with a gid
1067                  * (gid is more common, but in case both uidNumber and
1068                  * gidNumber are returned the SID is mapped to the uid
1069                  * not the gid) */
1070                 type = ID_TYPE_UID;
1071                 tmp = smbldap_talloc_single_attribute(
1072                                 ctx->smbldap_state->ldap_struct,
1073                                 entry, uidNumber, memctx);
1074                 if ( ! tmp) {
1075                         type = ID_TYPE_GID;
1076                         tmp = smbldap_talloc_single_attribute(
1077                                         ctx->smbldap_state->ldap_struct,
1078                                         entry, gidNumber, memctx);
1079                 }
1080                 if ( ! tmp) { /* no ids ?? */
1081                         DEBUG(5, ("no uidNumber, "
1082                                   "nor gidNumber attributes found\n"));
1083                         TALLOC_FREE(sidstr);
1084                         continue;
1085                 }
1086
1087                 id = strtoul(tmp, NULL, 10);
1088                 if (!idmap_unix_id_is_in_range(id, dom)) {
1089                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1090                                   "Filtered!\n", id,
1091                                   dom->low_id, dom->high_id));
1092                         TALLOC_FREE(sidstr);
1093                         TALLOC_FREE(tmp);
1094                         continue;
1095                 }
1096                 TALLOC_FREE(tmp);
1097
1098                 if (map->status == ID_MAPPED) {
1099                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1100                               "overwriting mapping %s -> %u with %s -> %u\n",
1101                               (type == ID_TYPE_UID) ? "UID" : "GID",
1102                               sidstr, map->xid.id, sidstr, id));
1103                 }
1104
1105                 TALLOC_FREE(sidstr);
1106
1107                 /* mapped */
1108                 map->xid.type = type;
1109                 map->xid.id = id;
1110                 map->status = ID_MAPPED;
1111
1112                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1113                            (unsigned long)map->xid.id, map->xid.type));
1114         }
1115
1116         /* free the ldap results */
1117         if (result) {
1118                 ldap_msgfree(result);
1119                 result = NULL;
1120         }
1121
1122         if (multi && ids[idx]) { /* still some values to map */
1123                 goto again;
1124         }
1125
1126         /*
1127          *  try to create new mappings for unmapped sids
1128          */
1129         for (i = 0; ids[i]; i++) {
1130                 if (ids[i]->status != ID_MAPPED) {
1131                         ids[i]->status = ID_UNMAPPED;
1132                         if (ids[i]->sid != NULL) {
1133                                 ret = idmap_ldap_new_mapping(dom, ids[i]);
1134                                 if (!NT_STATUS_IS_OK(ret)) {
1135                                         goto done;
1136                                 }
1137                         }
1138                 }
1139         }
1140
1141         ret = NT_STATUS_OK;
1142
1143 done:
1144         talloc_free(memctx);
1145         return ret;
1146 }
1147
1148 /**********************************
1149  Close the idmap ldap instance
1150 **********************************/
1151
1152 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1153 {
1154         return NT_STATUS_OK;
1155 }
1156
1157 static struct idmap_methods idmap_ldap_methods = {
1158
1159         .init = idmap_ldap_db_init,
1160         .unixids_to_sids = idmap_ldap_unixids_to_sids,
1161         .sids_to_unixids = idmap_ldap_sids_to_unixids,
1162         .allocate_id = idmap_ldap_get_new_id,
1163         .close_fn = idmap_ldap_close
1164 };
1165
1166 NTSTATUS idmap_ldap_init(void);
1167 NTSTATUS idmap_ldap_init(void)
1168 {
1169         return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1170                                   &idmap_ldap_methods);
1171 }
1172