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