s3:idmap: remove special treatment of domain "*" from idmap_ldap_init.
[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(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_get_new_id(struct idmap_domain *dom,
395                                       struct unixid *id)
396 {
397         NTSTATUS ret;
398
399         if (!strequal(dom->name, "*")) {
400                 DEBUG(3, ("idmap_ldap_get_new_id: "
401                           "Refusing allocation of a new unixid for domain'%s'. "
402                           "Currently 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(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                                    const char *params)
436 {
437         NTSTATUS ret;
438         struct idmap_ldap_context *ctx = NULL;
439         char *config_option = NULL;
440         const char *tmp = NULL;
441
442         /* Only do init if we are online */
443         if (idmap_is_offline()) {
444                 return NT_STATUS_FILE_IS_OFFLINE;
445         }
446
447         ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
448         if ( ! ctx) {
449                 DEBUG(0, ("Out of memory!\n"));
450                 return NT_STATUS_NO_MEMORY;
451         }
452
453         config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
454         if (!config_option) {
455                 DEBUG(0, ("Out of memory!\n"));
456                 ret = NT_STATUS_NO_MEMORY;
457                 goto done;
458         }
459
460         tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
461
462         if ( ! tmp) {
463                 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
464                 ret = NT_STATUS_UNSUCCESSFUL;
465                 goto done;
466         }
467
468         ctx->url = talloc_strdup(ctx, tmp);
469
470         trim_char(ctx->url, '\"', '\"');
471
472         tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
473         if ( ! tmp || ! *tmp) {
474                 tmp = lp_ldap_idmap_suffix();
475                 if ( ! tmp) {
476                         DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
477                         ret = NT_STATUS_UNSUCCESSFUL;
478                         goto done;
479                 }
480         }
481
482         ctx->suffix = talloc_strdup(ctx, tmp);
483         CHECK_ALLOC_DONE(ctx->suffix);
484
485         ctx->rw_ops = talloc_zero(ctx, struct idmap_rw_ops);
486         CHECK_ALLOC_DONE(ctx->rw_ops);
487
488         ctx->rw_ops->get_new_id = idmap_ldap_get_new_id;
489         ctx->rw_ops->set_mapping = idmap_ldap_set_mapping;
490
491         ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
492                            &ctx->smbldap_state);
493         if (!NT_STATUS_IS_OK(ret)) {
494                 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
495                 goto done;
496         }
497
498         ret = get_credentials( ctx, ctx->smbldap_state, config_option,
499                                dom, &ctx->user_dn );
500         if ( !NT_STATUS_IS_OK(ret) ) {
501                 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
502                          "credentials (%s)\n", nt_errstr(ret)));
503                 goto done;
504         }
505
506         /*
507          * Set the destructor on the context, so that resources are
508          * properly freed when the context is released.
509          */
510         talloc_set_destructor(ctx, idmap_ldap_close_destructor);
511
512         dom->private_data = ctx;
513
514         ret = verify_idpool(dom);
515         if (!NT_STATUS_IS_OK(ret)) {
516                 DEBUG(1, ("idmap_ldap_db_init: failed to verify ID pool (%s)\n",
517                          nt_errstr(ret)));
518                 goto done;
519         }
520
521         talloc_free(config_option);
522         return NT_STATUS_OK;
523
524 /*failed */
525 done:
526         talloc_free(ctx);
527         return ret;
528 }
529
530 /**
531  * set a mapping.
532  */
533
534 /* TODO: change this:  This function cannot be called to modify a mapping,
535  * only set a new one */
536
537 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
538                                        const struct id_map *map)
539 {
540         NTSTATUS ret;
541         TALLOC_CTX *memctx;
542         struct idmap_ldap_context *ctx;
543         LDAPMessage *entry = NULL;
544         LDAPMod **mods = NULL;
545         const char *type;
546         char *id_str;
547         char *sid;
548         char *dn;
549         int rc = -1;
550
551         /* Only do query if we are online */
552         if (idmap_is_offline()) {
553                 return NT_STATUS_FILE_IS_OFFLINE;
554         }
555
556         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
557
558         switch(map->xid.type) {
559         case ID_TYPE_UID:
560                 type = get_attr_key2string(sidmap_attr_list,
561                                            LDAP_ATTR_UIDNUMBER);
562                 break;
563
564         case ID_TYPE_GID:
565                 type = get_attr_key2string(sidmap_attr_list,
566                                            LDAP_ATTR_GIDNUMBER);
567                 break;
568
569         default:
570                 return NT_STATUS_INVALID_PARAMETER;
571         }
572
573         memctx = talloc_new(ctx);
574         if ( ! memctx) {
575                 DEBUG(0, ("Out of memory!\n"));
576                 return NT_STATUS_NO_MEMORY;
577         }
578
579         id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
580         CHECK_ALLOC_DONE(id_str);
581
582         sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
583         CHECK_ALLOC_DONE(sid);
584
585         dn = talloc_asprintf(memctx, "%s=%s,%s",
586                         get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
587                         sid,
588                         ctx->suffix);
589         CHECK_ALLOC_DONE(dn);
590
591         smbldap_set_mod(&mods, LDAP_MOD_ADD,
592                         "objectClass", LDAP_OBJ_IDMAP_ENTRY);
593
594         smbldap_make_mod(ctx->smbldap_state->ldap_struct,
595                          entry, &mods, type, id_str);
596
597         smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
598                          get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
599                          sid);
600
601         if ( ! mods) {
602                 DEBUG(2, ("ERROR: No mods?\n"));
603                 ret = NT_STATUS_UNSUCCESSFUL;
604                 goto done;
605         }
606
607         /* TODO: remove conflicting mappings! */
608
609         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
610
611         DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
612
613         rc = smbldap_add(ctx->smbldap_state, dn, mods);
614         ldap_mods_free(mods, True);
615
616         if (rc != LDAP_SUCCESS) {
617                 char *ld_error = NULL;
618                 ldap_get_option(ctx->smbldap_state->ldap_struct,
619                                 LDAP_OPT_ERROR_STRING, &ld_error);
620                 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
621                          "mapping [%s]\n", sid,
622                          (unsigned long)map->xid.id, type));
623                 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
624                         ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
625                 if (ld_error) {
626                         ldap_memfree(ld_error);
627                 }
628                 ret = NT_STATUS_UNSUCCESSFUL;
629                 goto done;
630         }
631
632         DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
633                   "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
634
635         ret = NT_STATUS_OK;
636
637 done:
638         talloc_free(memctx);
639         return ret;
640 }
641
642 /**
643  * Create a new mapping for an unmapped SID, also allocating a new ID.
644  * If possible, this should be run inside a transaction to make the
645  * action atomic.
646  */
647 static NTSTATUS idmap_ldap_new_mapping(struct idmap_domain *dom, struct id_map *map)
648 {
649         NTSTATUS ret;
650         struct idmap_ldap_context *ctx;
651
652         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
653
654         ret = idmap_rw_new_mapping(dom, ctx->rw_ops, map);
655
656         return ret;
657 }
658
659
660 /* max number of ids requested per batch query */
661 #define IDMAP_LDAP_MAX_IDS 30
662
663 /**********************************
664  lookup a set of unix ids.
665 **********************************/
666
667 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
668  * in maps for a match */
669 static struct id_map *find_map_by_id(struct id_map **maps,
670                                      enum id_type type,
671                                      uint32_t id)
672 {
673         int i;
674
675         for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
676                 if (maps[i] == NULL) { /* end of the run */
677                         return NULL;
678                 }
679                 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
680                         return maps[i];
681                 }
682         }
683
684         return NULL;
685 }
686
687 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
688                                            struct id_map **ids)
689 {
690         NTSTATUS ret;
691         TALLOC_CTX *memctx;
692         struct idmap_ldap_context *ctx;
693         LDAPMessage *result = NULL;
694         LDAPMessage *entry = NULL;
695         const char *uidNumber;
696         const char *gidNumber;
697         const char **attr_list;
698         char *filter = NULL;
699         bool multi = False;
700         int idx = 0;
701         int bidx = 0;
702         int count;
703         int rc;
704         int i;
705
706         /* Only do query if we are online */
707         if (idmap_is_offline()) {
708                 return NT_STATUS_FILE_IS_OFFLINE;
709         }
710
711         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
712
713         memctx = talloc_new(ctx);
714         if ( ! memctx) {
715                 DEBUG(0, ("Out of memory!\n"));
716                 return NT_STATUS_NO_MEMORY;
717         }
718
719         uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
720         gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
721
722         attr_list = get_attr_list(memctx, sidmap_attr_list);
723
724         if ( ! ids[1]) {
725                 /* if we are requested just one mapping use the simple filter */
726
727                 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
728                                 LDAP_OBJ_IDMAP_ENTRY,
729                                 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
730                                 (unsigned long)ids[0]->xid.id);
731                 CHECK_ALLOC_DONE(filter);
732                 DEBUG(10, ("Filter: [%s]\n", filter));
733         } else {
734                 /* multiple mappings */
735                 multi = True;
736         }
737
738         for (i = 0; ids[i]; i++) {
739                 ids[i]->status = ID_UNKNOWN;
740         }
741
742 again:
743         if (multi) {
744
745                 talloc_free(filter);
746                 filter = talloc_asprintf(memctx,
747                                          "(&(objectClass=%s)(|",
748                                          LDAP_OBJ_IDMAP_ENTRY);
749                 CHECK_ALLOC_DONE(filter);
750
751                 bidx = idx;
752                 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
753                         filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
754                                         (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
755                                         (unsigned long)ids[idx]->xid.id);
756                         CHECK_ALLOC_DONE(filter);
757                 }
758                 filter = talloc_asprintf_append_buffer(filter, "))");
759                 CHECK_ALLOC_DONE(filter);
760                 DEBUG(10, ("Filter: [%s]\n", filter));
761         } else {
762                 bidx = 0;
763                 idx = 1;
764         }
765
766         rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
767                 filter, attr_list, 0, &result);
768
769         if (rc != LDAP_SUCCESS) {
770                 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
771                 ret = NT_STATUS_UNSUCCESSFUL;
772                 goto done;
773         }
774
775         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
776
777         if (count == 0) {
778                 DEBUG(10, ("NO SIDs found\n"));
779         }
780
781         for (i = 0; i < count; i++) {
782                 char *sidstr = NULL;
783                 char *tmp = NULL;
784                 enum id_type type;
785                 struct id_map *map;
786                 uint32_t id;
787
788                 if (i == 0) { /* first entry */
789                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
790                                                  result);
791                 } else { /* following ones */
792                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
793                                                 entry);
794                 }
795                 if ( ! entry) {
796                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
797                                   "from results\n"));
798                         break;
799                 }
800
801                 /* first check if the SID is present */
802                 sidstr = smbldap_talloc_single_attribute(
803                                 ctx->smbldap_state->ldap_struct,
804                                 entry, LDAP_ATTRIBUTE_SID, memctx);
805                 if ( ! sidstr) { /* no sid, skip entry */
806                         DEBUG(2, ("WARNING SID not found on entry\n"));
807                         continue;
808                 }
809
810                 /* now try to see if it is a uid, if not try with a gid
811                  * (gid is more common, but in case both uidNumber and
812                  * gidNumber are returned the SID is mapped to the uid
813                  *not the gid) */
814                 type = ID_TYPE_UID;
815                 tmp = smbldap_talloc_single_attribute(
816                                 ctx->smbldap_state->ldap_struct,
817                                 entry, uidNumber, memctx);
818                 if ( ! tmp) {
819                         type = ID_TYPE_GID;
820                         tmp = smbldap_talloc_single_attribute(
821                                         ctx->smbldap_state->ldap_struct,
822                                         entry, gidNumber, memctx);
823                 }
824                 if ( ! tmp) { /* wow very strange entry, how did it match ? */
825                         DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
826                                   "nor gidNumber returned\n", sidstr));
827                         TALLOC_FREE(sidstr);
828                         continue;
829                 }
830
831                 id = strtoul(tmp, NULL, 10);
832                 if (!idmap_unix_id_is_in_range(id, dom)) {
833                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
834                                   "Filtered!\n", id,
835                                   dom->low_id, dom->high_id));
836                         TALLOC_FREE(sidstr);
837                         TALLOC_FREE(tmp);
838                         continue;
839                 }
840                 TALLOC_FREE(tmp);
841
842                 map = find_map_by_id(&ids[bidx], type, id);
843                 if (!map) {
844                         DEBUG(2, ("WARNING: couldn't match sid (%s) "
845                                   "with requested ids\n", sidstr));
846                         TALLOC_FREE(sidstr);
847                         continue;
848                 }
849
850                 if ( ! string_to_sid(map->sid, sidstr)) {
851                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
852                         TALLOC_FREE(sidstr);
853                         continue;
854                 }
855
856                 if (map->status == ID_MAPPED) {
857                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
858                               "overwriting mapping %u -> %s with %u -> %s\n",
859                               (type == ID_TYPE_UID) ? "UID" : "GID",
860                               id, sid_string_dbg(map->sid), id, sidstr));
861                 }
862
863                 TALLOC_FREE(sidstr);
864
865                 /* mapped */
866                 map->status = ID_MAPPED;
867
868                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
869                            (unsigned long)map->xid.id, map->xid.type));
870         }
871
872         /* free the ldap results */
873         if (result) {
874                 ldap_msgfree(result);
875                 result = NULL;
876         }
877
878         if (multi && ids[idx]) { /* still some values to map */
879                 goto again;
880         }
881
882         ret = NT_STATUS_OK;
883
884         /* mark all unknwon/expired ones as unmapped */
885         for (i = 0; ids[i]; i++) {
886                 if (ids[i]->status != ID_MAPPED)
887                         ids[i]->status = ID_UNMAPPED;
888         }
889
890 done:
891         talloc_free(memctx);
892         return ret;
893 }
894
895 /**********************************
896  lookup a set of sids.
897 **********************************/
898
899 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
900  * in maps for a match */
901 static struct id_map *find_map_by_sid(struct id_map **maps, struct dom_sid *sid)
902 {
903         int i;
904
905         for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
906                 if (maps[i] == NULL) { /* end of the run */
907                         return NULL;
908                 }
909                 if (dom_sid_equal(maps[i]->sid, sid)) {
910                         return maps[i];
911                 }
912         }
913
914         return NULL;
915 }
916
917 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
918                                            struct id_map **ids)
919 {
920         LDAPMessage *entry = NULL;
921         NTSTATUS ret;
922         TALLOC_CTX *memctx;
923         struct idmap_ldap_context *ctx;
924         LDAPMessage *result = NULL;
925         const char *uidNumber;
926         const char *gidNumber;
927         const char **attr_list;
928         char *filter = NULL;
929         bool multi = False;
930         int idx = 0;
931         int bidx = 0;
932         int count;
933         int rc;
934         int i;
935
936         /* Only do query if we are online */
937         if (idmap_is_offline()) {
938                 return NT_STATUS_FILE_IS_OFFLINE;
939         }
940
941         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
942
943         memctx = talloc_new(ctx);
944         if ( ! memctx) {
945                 DEBUG(0, ("Out of memory!\n"));
946                 return NT_STATUS_NO_MEMORY;
947         }
948
949         uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
950         gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
951
952         attr_list = get_attr_list(memctx, sidmap_attr_list);
953
954         if ( ! ids[1]) {
955                 /* if we are requested just one mapping use the simple filter */
956
957                 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
958                                 LDAP_OBJ_IDMAP_ENTRY,
959                                 LDAP_ATTRIBUTE_SID,
960                                 sid_string_talloc(memctx, ids[0]->sid));
961                 CHECK_ALLOC_DONE(filter);
962                 DEBUG(10, ("Filter: [%s]\n", filter));
963         } else {
964                 /* multiple mappings */
965                 multi = True;
966         }
967
968         for (i = 0; ids[i]; i++) {
969                 ids[i]->status = ID_UNKNOWN;
970         }
971
972 again:
973         if (multi) {
974
975                 TALLOC_FREE(filter);
976                 filter = talloc_asprintf(memctx,
977                                          "(&(objectClass=%s)(|",
978                                          LDAP_OBJ_IDMAP_ENTRY);
979                 CHECK_ALLOC_DONE(filter);
980
981                 bidx = idx;
982                 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
983                         filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
984                                         LDAP_ATTRIBUTE_SID,
985                                         sid_string_talloc(memctx,
986                                                           ids[idx]->sid));
987                         CHECK_ALLOC_DONE(filter);
988                 }
989                 filter = talloc_asprintf_append_buffer(filter, "))");
990                 CHECK_ALLOC_DONE(filter);
991                 DEBUG(10, ("Filter: [%s]", filter));
992         } else {
993                 bidx = 0;
994                 idx = 1;
995         }
996
997         rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
998                 filter, attr_list, 0, &result);
999
1000         if (rc != LDAP_SUCCESS) {
1001                 DEBUG(3,("Failure looking up sids (%s)\n",
1002                          ldap_err2string(rc)));
1003                 ret = NT_STATUS_UNSUCCESSFUL;
1004                 goto done;
1005         }
1006
1007         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1008
1009         if (count == 0) {
1010                 DEBUG(10, ("NO SIDs found\n"));
1011         }
1012
1013         for (i = 0; i < count; i++) {
1014                 char *sidstr = NULL;
1015                 char *tmp = NULL;
1016                 enum id_type type;
1017                 struct id_map *map;
1018                 struct dom_sid sid;
1019                 uint32_t id;
1020
1021                 if (i == 0) { /* first entry */
1022                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1023                                                  result);
1024                 } else { /* following ones */
1025                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1026                                                 entry);
1027                 }
1028                 if ( ! entry) {
1029                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1030                                   "from results\n"));
1031                         break;
1032                 }
1033
1034                 /* first check if the SID is present */
1035                 sidstr = smbldap_talloc_single_attribute(
1036                                 ctx->smbldap_state->ldap_struct,
1037                                 entry, LDAP_ATTRIBUTE_SID, memctx);
1038                 if ( ! sidstr) { /* no sid ??, skip entry */
1039                         DEBUG(2, ("WARNING SID not found on entry\n"));
1040                         continue;
1041                 }
1042
1043                 if ( ! string_to_sid(&sid, sidstr)) {
1044                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1045                         TALLOC_FREE(sidstr);
1046                         continue;
1047                 }
1048
1049                 map = find_map_by_sid(&ids[bidx], &sid);
1050                 if (!map) {
1051                         DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1052                                   "in ids", sidstr));
1053                         TALLOC_FREE(sidstr);
1054                         continue;
1055                 }
1056
1057                 /* now try to see if it is a uid, if not try with a gid
1058                  * (gid is more common, but in case both uidNumber and
1059                  * gidNumber are returned the SID is mapped to the uid
1060                  * not the gid) */
1061                 type = ID_TYPE_UID;
1062                 tmp = smbldap_talloc_single_attribute(
1063                                 ctx->smbldap_state->ldap_struct,
1064                                 entry, uidNumber, memctx);
1065                 if ( ! tmp) {
1066                         type = ID_TYPE_GID;
1067                         tmp = smbldap_talloc_single_attribute(
1068                                         ctx->smbldap_state->ldap_struct,
1069                                         entry, gidNumber, memctx);
1070                 }
1071                 if ( ! tmp) { /* no ids ?? */
1072                         DEBUG(5, ("no uidNumber, "
1073                                   "nor gidNumber attributes found\n"));
1074                         TALLOC_FREE(sidstr);
1075                         continue;
1076                 }
1077
1078                 id = strtoul(tmp, NULL, 10);
1079                 if (!idmap_unix_id_is_in_range(id, dom)) {
1080                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1081                                   "Filtered!\n", id,
1082                                   dom->low_id, dom->high_id));
1083                         TALLOC_FREE(sidstr);
1084                         TALLOC_FREE(tmp);
1085                         continue;
1086                 }
1087                 TALLOC_FREE(tmp);
1088
1089                 if (map->status == ID_MAPPED) {
1090                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1091                               "overwriting mapping %s -> %u with %s -> %u\n",
1092                               (type == ID_TYPE_UID) ? "UID" : "GID",
1093                               sidstr, map->xid.id, sidstr, id));
1094                 }
1095
1096                 TALLOC_FREE(sidstr);
1097
1098                 /* mapped */
1099                 map->xid.type = type;
1100                 map->xid.id = id;
1101                 map->status = ID_MAPPED;
1102
1103                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1104                            (unsigned long)map->xid.id, map->xid.type));
1105         }
1106
1107         /* free the ldap results */
1108         if (result) {
1109                 ldap_msgfree(result);
1110                 result = NULL;
1111         }
1112
1113         if (multi && ids[idx]) { /* still some values to map */
1114                 goto again;
1115         }
1116
1117         /*
1118          *  try to create new mappings for unmapped sids
1119          */
1120         for (i = 0; ids[i]; i++) {
1121                 if (ids[i]->status != ID_MAPPED) {
1122                         ids[i]->status = ID_UNMAPPED;
1123                         if (ids[i]->sid != NULL) {
1124                                 ret = idmap_ldap_new_mapping(dom, ids[i]);
1125                                 if (!NT_STATUS_IS_OK(ret)) {
1126                                         goto done;
1127                                 }
1128                         }
1129                 }
1130         }
1131
1132         ret = NT_STATUS_OK;
1133
1134 done:
1135         talloc_free(memctx);
1136         return ret;
1137 }
1138
1139 /**********************************
1140  Close the idmap ldap instance
1141 **********************************/
1142
1143 static struct idmap_methods idmap_ldap_methods = {
1144
1145         .init = idmap_ldap_db_init,
1146         .unixids_to_sids = idmap_ldap_unixids_to_sids,
1147         .sids_to_unixids = idmap_ldap_sids_to_unixids,
1148         .allocate_id = idmap_ldap_get_new_id,
1149 };
1150
1151 NTSTATUS idmap_ldap_init(void);
1152 NTSTATUS idmap_ldap_init(void)
1153 {
1154         return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1155                                   &idmap_ldap_methods);
1156 }
1157