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