source: trunk/samba/source/nsswitch/idmap_ldap.c @ 39

Last change on this file since 39 was 39, checked in by Paul Smedley, 14 years ago

Upgrade source to 3.0.25a

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