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