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