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