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