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