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