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