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