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

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

Code updated to Samba 3.0.25rc2 level

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