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