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