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