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