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