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