s3:idmap_ldap: create mappings for unmapped sids in idmap_ldap_sids_to_unixids()
[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                 ret = NT_STATUS_UNSUCCESSFUL;
434                 goto done;
435         }
436
437         xid->id = strtoul(id_str, NULL, 10);
438
439         /* make sure we still have room to grow */
440
441         switch (xid->type) {
442         case ID_TYPE_UID:
443                 if (xid->id > dom->high_id) {
444                         DEBUG(0,("Cannot allocate uid above %lu!\n",
445                                  (unsigned long)dom->high_id));
446                         goto done;
447                 }
448                 break;
449
450         case ID_TYPE_GID:
451                 if (xid->id > dom->high_id) {
452                         DEBUG(0,("Cannot allocate gid above %lu!\n",
453                                  (unsigned long)dom->high_id));
454                         goto done;
455                 }
456                 break;
457
458         default:
459                 /* impossible */
460                 goto done;
461         }
462
463         new_id_str = talloc_asprintf(mem_ctx, "%lu", (unsigned long)xid->id + 1);
464         if ( ! new_id_str) {
465                 DEBUG(0,("Out of memory\n"));
466                 ret = NT_STATUS_NO_MEMORY;
467                 goto done;
468         }
469
470         smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
471         smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
472
473         if (mods == NULL) {
474                 DEBUG(0,("smbldap_set_mod() failed.\n"));
475                 goto done;
476         }
477
478         DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
479                    id_str, new_id_str));
480
481         rc = smbldap_modify(ctx->alloc->smbldap_state, dn, mods);
482
483         ldap_mods_free(mods, True);
484
485         if (rc != LDAP_SUCCESS) {
486                 DEBUG(1,("Failed to allocate new %s. "
487                          "smbldap_modify() failed.\n", type));
488                 goto done;
489         }
490
491         ret = NT_STATUS_OK;
492
493 done:
494         talloc_free(mem_ctx);
495         return ret;
496 }
497
498 /**
499  * Allocate a new unix-ID.
500  * For now this is for the default idmap domain only.
501  * Should be extended later on.
502  */
503 static NTSTATUS idmap_ldap_get_new_id(struct idmap_domain *dom,
504                                       struct unixid *id)
505 {
506         NTSTATUS ret;
507
508         if (!strequal(dom->name, "*")) {
509                 DEBUG(3, ("idmap_ldap_get_new_id: "
510                           "Refusing allocation of a new unixid for domain'%s'. "
511                           "Currently only supported for the default "
512                           "domain \"*\".\n",
513                            dom->name));
514                 return NT_STATUS_NOT_IMPLEMENTED;
515         }
516
517         ret = idmap_ldap_allocate_id(dom, id);
518
519         return ret;
520 }
521
522
523 /**********************************************************************
524  IDMAP MAPPING LDAP BACKEND
525 **********************************************************************/
526
527 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
528 {
529         smbldap_free_struct(&ctx->smbldap_state);
530         DEBUG(5,("The connection to the LDAP server was closed\n"));
531         /* maybe free the results here --metze */
532
533         return 0;
534 }
535
536 /********************************
537  Initialise idmap database.
538 ********************************/
539
540 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
541                                    const char *params)
542 {
543         NTSTATUS ret;
544         struct idmap_ldap_context *ctx = NULL;
545         char *config_option = NULL;
546         const char *tmp = NULL;
547
548         /* Only do init if we are online */
549         if (idmap_is_offline()) {
550                 return NT_STATUS_FILE_IS_OFFLINE;
551         }
552
553         ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
554         if ( ! ctx) {
555                 DEBUG(0, ("Out of memory!\n"));
556                 return NT_STATUS_NO_MEMORY;
557         }
558
559         if (strequal(dom->name, "*")) {
560                 /* more specific configuration can go here */
561         } else {
562                 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
563                 if ( ! config_option) {
564                         DEBUG(0, ("Out of memory!\n"));
565                         ret = NT_STATUS_NO_MEMORY;
566                         goto done;
567                 }
568         }
569
570         if (params != NULL) {
571                 /* assume location is the only parameter */
572                 ctx->url = talloc_strdup(ctx, params);
573         } else {
574                 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
575
576                 if ( ! tmp) {
577                         DEBUG(1, ("ERROR: missing idmap ldap url\n"));
578                         ret = NT_STATUS_UNSUCCESSFUL;
579                         goto done;
580                 }
581
582                 ctx->url = talloc_strdup(ctx, tmp);
583         }
584         CHECK_ALLOC_DONE(ctx->url);
585
586         trim_char(ctx->url, '\"', '\"');
587
588         tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
589         if ( ! tmp || ! *tmp) {
590                 tmp = lp_ldap_idmap_suffix();
591                 if ( ! tmp) {
592                         DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
593                         ret = NT_STATUS_UNSUCCESSFUL;
594                         goto done;
595                 }
596         }
597
598         ctx->suffix = talloc_strdup(ctx, tmp);
599         CHECK_ALLOC_DONE(ctx->suffix);
600
601         ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
602                            &ctx->smbldap_state);
603         if (!NT_STATUS_IS_OK(ret)) {
604                 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
605                 goto done;
606         }
607
608         ret = get_credentials( ctx, ctx->smbldap_state, config_option,
609                                dom, &ctx->user_dn );
610         if ( !NT_STATUS_IS_OK(ret) ) {
611                 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
612                          "credentials (%s)\n", nt_errstr(ret)));
613                 goto done;
614         }
615
616         /* set the destructor on the context, so that resource are properly
617            freed if the contexts is released */
618
619         talloc_set_destructor(ctx, idmap_ldap_close_destructor);
620
621         dom->private_data = ctx;
622
623         ret = idmap_ldap_alloc_init(dom, params);
624         if (!NT_STATUS_IS_OK(ret)) {
625                 DEBUG(1, ("idmap_ldap_db_init: Failed to initialize alloc "
626                           "subsystem: %s\n", nt_errstr(ret)));
627                 goto done;
628         }
629
630         talloc_free(config_option);
631         return NT_STATUS_OK;
632
633 /*failed */
634 done:
635         talloc_free(ctx);
636         return ret;
637 }
638
639 /**
640  * set a mapping.
641  */
642
643 /* TODO: change this:  This function cannot be called to modify a mapping,
644  * only set a new one */
645
646 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
647                                        const struct id_map *map)
648 {
649         NTSTATUS ret;
650         TALLOC_CTX *memctx;
651         struct idmap_ldap_context *ctx;
652         LDAPMessage *entry = NULL;
653         LDAPMod **mods = NULL;
654         const char *type;
655         char *id_str;
656         char *sid;
657         char *dn;
658         int rc = -1;
659
660         /* Only do query if we are online */
661         if (idmap_is_offline()) {
662                 return NT_STATUS_FILE_IS_OFFLINE;
663         }
664
665         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
666
667         switch(map->xid.type) {
668         case ID_TYPE_UID:
669                 type = get_attr_key2string(sidmap_attr_list,
670                                            LDAP_ATTR_UIDNUMBER);
671                 break;
672
673         case ID_TYPE_GID:
674                 type = get_attr_key2string(sidmap_attr_list,
675                                            LDAP_ATTR_GIDNUMBER);
676                 break;
677
678         default:
679                 return NT_STATUS_INVALID_PARAMETER;
680         }
681
682         memctx = talloc_new(ctx);
683         if ( ! memctx) {
684                 DEBUG(0, ("Out of memory!\n"));
685                 return NT_STATUS_NO_MEMORY;
686         }
687
688         id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
689         CHECK_ALLOC_DONE(id_str);
690
691         sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
692         CHECK_ALLOC_DONE(sid);
693
694         dn = talloc_asprintf(memctx, "%s=%s,%s",
695                         get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
696                         sid,
697                         ctx->suffix);
698         CHECK_ALLOC_DONE(dn);
699
700         smbldap_set_mod(&mods, LDAP_MOD_ADD,
701                         "objectClass", LDAP_OBJ_IDMAP_ENTRY);
702
703         smbldap_make_mod(ctx->smbldap_state->ldap_struct,
704                          entry, &mods, type, id_str);
705
706         smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
707                          get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
708                          sid);
709
710         if ( ! mods) {
711                 DEBUG(2, ("ERROR: No mods?\n"));
712                 ret = NT_STATUS_UNSUCCESSFUL;
713                 goto done;
714         }
715
716         /* TODO: remove conflicting mappings! */
717
718         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
719
720         DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
721
722         rc = smbldap_add(ctx->smbldap_state, dn, mods);
723         ldap_mods_free(mods, True);
724
725         if (rc != LDAP_SUCCESS) {
726                 char *ld_error = NULL;
727                 ldap_get_option(ctx->smbldap_state->ldap_struct,
728                                 LDAP_OPT_ERROR_STRING, &ld_error);
729                 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
730                          "mapping [%s]\n", sid,
731                          (unsigned long)map->xid.id, type));
732                 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
733                         ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
734                 if (ld_error) {
735                         ldap_memfree(ld_error);
736                 }
737                 ret = NT_STATUS_UNSUCCESSFUL;
738                 goto done;
739         }
740
741         DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
742                   "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
743
744         ret = NT_STATUS_OK;
745
746 done:
747         talloc_free(memctx);
748         return ret;
749 }
750
751 /**
752  * Create a new mapping for an unmapped SID, also allocating a new ID.
753  * If possible, this should be run inside a transaction to make the
754  * action atomic.
755  */
756 static NTSTATUS idmap_ldap_new_mapping(struct idmap_domain *dom, struct id_map *map)
757 {
758         NTSTATUS ret;
759
760         if (map == NULL) {
761                 ret = NT_STATUS_INVALID_PARAMETER;
762                 goto done;
763         }
764
765         if ((map->xid.type != ID_TYPE_UID) && (map->xid.type != ID_TYPE_GID)) {
766                 ret = NT_STATUS_INVALID_PARAMETER;
767                 goto done;
768         }
769
770         if (map->sid == NULL) {
771                 ret = NT_STATUS_INVALID_PARAMETER;
772                 goto done;
773         }
774
775         ret = idmap_ldap_get_new_id(dom, &map->xid);
776         if (!NT_STATUS_IS_OK(ret)) {
777                 DEBUG(3, ("Could not allocate id: %s\n", nt_errstr(ret)));
778                 goto done;
779         }
780
781         DEBUG(10, ("Setting mapping: %s <-> %s %lu\n",
782                    sid_string_dbg(map->sid),
783                    (map->xid.type == ID_TYPE_UID) ? "UID" : "GID",
784                    (unsigned long)map->xid.id));
785
786         map->status = ID_MAPPED;
787
788         /* store the mapping */
789         ret = idmap_ldap_set_mapping(dom, map);
790         if (!NT_STATUS_IS_OK(ret)) {
791                 DEBUG(3, ("Could not store the new mapping: %s\n",
792                           nt_errstr(ret)));
793         }
794
795 done:
796         return ret;
797 }
798
799
800 /* max number of ids requested per batch query */
801 #define IDMAP_LDAP_MAX_IDS 30
802
803 /**********************************
804  lookup a set of unix ids.
805 **********************************/
806
807 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
808  * in maps for a match */
809 static struct id_map *find_map_by_id(struct id_map **maps,
810                                      enum id_type type,
811                                      uint32_t id)
812 {
813         int i;
814
815         for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
816                 if (maps[i] == NULL) { /* end of the run */
817                         return NULL;
818                 }
819                 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
820                         return maps[i];
821                 }
822         }
823
824         return NULL;
825 }
826
827 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
828                                            struct id_map **ids)
829 {
830         NTSTATUS ret;
831         TALLOC_CTX *memctx;
832         struct idmap_ldap_context *ctx;
833         LDAPMessage *result = NULL;
834         LDAPMessage *entry = NULL;
835         const char *uidNumber;
836         const char *gidNumber;
837         const char **attr_list;
838         char *filter = NULL;
839         bool multi = False;
840         int idx = 0;
841         int bidx = 0;
842         int count;
843         int rc;
844         int i;
845
846         /* Only do query if we are online */
847         if (idmap_is_offline()) {
848                 return NT_STATUS_FILE_IS_OFFLINE;
849         }
850
851         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
852
853         memctx = talloc_new(ctx);
854         if ( ! memctx) {
855                 DEBUG(0, ("Out of memory!\n"));
856                 return NT_STATUS_NO_MEMORY;
857         }
858
859         uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
860         gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
861
862         attr_list = get_attr_list(memctx, sidmap_attr_list);
863
864         if ( ! ids[1]) {
865                 /* if we are requested just one mapping use the simple filter */
866
867                 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
868                                 LDAP_OBJ_IDMAP_ENTRY,
869                                 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
870                                 (unsigned long)ids[0]->xid.id);
871                 CHECK_ALLOC_DONE(filter);
872                 DEBUG(10, ("Filter: [%s]\n", filter));
873         } else {
874                 /* multiple mappings */
875                 multi = True;
876         }
877
878         for (i = 0; ids[i]; i++) {
879                 ids[i]->status = ID_UNKNOWN;
880         }
881
882 again:
883         if (multi) {
884
885                 talloc_free(filter);
886                 filter = talloc_asprintf(memctx,
887                                          "(&(objectClass=%s)(|",
888                                          LDAP_OBJ_IDMAP_ENTRY);
889                 CHECK_ALLOC_DONE(filter);
890
891                 bidx = idx;
892                 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
893                         filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
894                                         (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
895                                         (unsigned long)ids[idx]->xid.id);
896                         CHECK_ALLOC_DONE(filter);
897                 }
898                 filter = talloc_asprintf_append_buffer(filter, "))");
899                 CHECK_ALLOC_DONE(filter);
900                 DEBUG(10, ("Filter: [%s]\n", filter));
901         } else {
902                 bidx = 0;
903                 idx = 1;
904         }
905
906         rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
907                 filter, attr_list, 0, &result);
908
909         if (rc != LDAP_SUCCESS) {
910                 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
911                 ret = NT_STATUS_UNSUCCESSFUL;
912                 goto done;
913         }
914
915         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
916
917         if (count == 0) {
918                 DEBUG(10, ("NO SIDs found\n"));
919         }
920
921         for (i = 0; i < count; i++) {
922                 char *sidstr = NULL;
923                 char *tmp = NULL;
924                 enum id_type type;
925                 struct id_map *map;
926                 uint32_t id;
927
928                 if (i == 0) { /* first entry */
929                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
930                                                  result);
931                 } else { /* following ones */
932                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
933                                                 entry);
934                 }
935                 if ( ! entry) {
936                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
937                                   "from results\n"));
938                         break;
939                 }
940
941                 /* first check if the SID is present */
942                 sidstr = smbldap_talloc_single_attribute(
943                                 ctx->smbldap_state->ldap_struct,
944                                 entry, LDAP_ATTRIBUTE_SID, memctx);
945                 if ( ! sidstr) { /* no sid, skip entry */
946                         DEBUG(2, ("WARNING SID not found on entry\n"));
947                         continue;
948                 }
949
950                 /* now try to see if it is a uid, if not try with a gid
951                  * (gid is more common, but in case both uidNumber and
952                  * gidNumber are returned the SID is mapped to the uid
953                  *not the gid) */
954                 type = ID_TYPE_UID;
955                 tmp = smbldap_talloc_single_attribute(
956                                 ctx->smbldap_state->ldap_struct,
957                                 entry, uidNumber, memctx);
958                 if ( ! tmp) {
959                         type = ID_TYPE_GID;
960                         tmp = smbldap_talloc_single_attribute(
961                                         ctx->smbldap_state->ldap_struct,
962                                         entry, gidNumber, memctx);
963                 }
964                 if ( ! tmp) { /* wow very strange entry, how did it match ? */
965                         DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
966                                   "nor gidNumber returned\n", sidstr));
967                         TALLOC_FREE(sidstr);
968                         continue;
969                 }
970
971                 id = strtoul(tmp, NULL, 10);
972                 if (!idmap_unix_id_is_in_range(id, dom)) {
973                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
974                                   "Filtered!\n", id,
975                                   dom->low_id, dom->high_id));
976                         TALLOC_FREE(sidstr);
977                         TALLOC_FREE(tmp);
978                         continue;
979                 }
980                 TALLOC_FREE(tmp);
981
982                 map = find_map_by_id(&ids[bidx], type, id);
983                 if (!map) {
984                         DEBUG(2, ("WARNING: couldn't match sid (%s) "
985                                   "with requested ids\n", sidstr));
986                         TALLOC_FREE(sidstr);
987                         continue;
988                 }
989
990                 if ( ! string_to_sid(map->sid, sidstr)) {
991                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
992                         TALLOC_FREE(sidstr);
993                         continue;
994                 }
995
996                 if (map->status == ID_MAPPED) {
997                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
998                               "overwriting mapping %u -> %s with %u -> %s\n",
999                               (type == ID_TYPE_UID) ? "UID" : "GID",
1000                               id, sid_string_dbg(map->sid), id, sidstr));
1001                 }
1002
1003                 TALLOC_FREE(sidstr);
1004
1005                 /* mapped */
1006                 map->status = ID_MAPPED;
1007
1008                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1009                            (unsigned long)map->xid.id, map->xid.type));
1010         }
1011
1012         /* free the ldap results */
1013         if (result) {
1014                 ldap_msgfree(result);
1015                 result = NULL;
1016         }
1017
1018         if (multi && ids[idx]) { /* still some values to map */
1019                 goto again;
1020         }
1021
1022         ret = NT_STATUS_OK;
1023
1024         /* mark all unknwon/expired ones as unmapped */
1025         for (i = 0; ids[i]; i++) {
1026                 if (ids[i]->status != ID_MAPPED)
1027                         ids[i]->status = ID_UNMAPPED;
1028         }
1029
1030 done:
1031         talloc_free(memctx);
1032         return ret;
1033 }
1034
1035 /**********************************
1036  lookup a set of sids.
1037 **********************************/
1038
1039 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
1040  * in maps for a match */
1041 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
1042 {
1043         int i;
1044
1045         for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
1046                 if (maps[i] == NULL) { /* end of the run */
1047                         return NULL;
1048                 }
1049                 if (sid_equal(maps[i]->sid, sid)) {
1050                         return maps[i];
1051                 }
1052         }
1053
1054         return NULL;
1055 }
1056
1057 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
1058                                            struct id_map **ids)
1059 {
1060         LDAPMessage *entry = NULL;
1061         NTSTATUS ret;
1062         TALLOC_CTX *memctx;
1063         struct idmap_ldap_context *ctx;
1064         LDAPMessage *result = NULL;
1065         const char *uidNumber;
1066         const char *gidNumber;
1067         const char **attr_list;
1068         char *filter = NULL;
1069         bool multi = False;
1070         int idx = 0;
1071         int bidx = 0;
1072         int count;
1073         int rc;
1074         int i;
1075
1076         /* Only do query if we are online */
1077         if (idmap_is_offline()) {
1078                 return NT_STATUS_FILE_IS_OFFLINE;
1079         }
1080
1081         ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1082
1083         memctx = talloc_new(ctx);
1084         if ( ! memctx) {
1085                 DEBUG(0, ("Out of memory!\n"));
1086                 return NT_STATUS_NO_MEMORY;
1087         }
1088
1089         uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
1090         gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
1091
1092         attr_list = get_attr_list(memctx, sidmap_attr_list);
1093
1094         if ( ! ids[1]) {
1095                 /* if we are requested just one mapping use the simple filter */
1096
1097                 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
1098                                 LDAP_OBJ_IDMAP_ENTRY,
1099                                 LDAP_ATTRIBUTE_SID,
1100                                 sid_string_talloc(memctx, ids[0]->sid));
1101                 CHECK_ALLOC_DONE(filter);
1102                 DEBUG(10, ("Filter: [%s]\n", filter));
1103         } else {
1104                 /* multiple mappings */
1105                 multi = True;
1106         }
1107
1108         for (i = 0; ids[i]; i++) {
1109                 ids[i]->status = ID_UNKNOWN;
1110         }
1111
1112 again:
1113         if (multi) {
1114
1115                 TALLOC_FREE(filter);
1116                 filter = talloc_asprintf(memctx,
1117                                          "(&(objectClass=%s)(|",
1118                                          LDAP_OBJ_IDMAP_ENTRY);
1119                 CHECK_ALLOC_DONE(filter);
1120
1121                 bidx = idx;
1122                 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
1123                         filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
1124                                         LDAP_ATTRIBUTE_SID,
1125                                         sid_string_talloc(memctx,
1126                                                           ids[idx]->sid));
1127                         CHECK_ALLOC_DONE(filter);
1128                 }
1129                 filter = talloc_asprintf_append_buffer(filter, "))");
1130                 CHECK_ALLOC_DONE(filter);
1131                 DEBUG(10, ("Filter: [%s]", filter));
1132         } else {
1133                 bidx = 0;
1134                 idx = 1;
1135         }
1136
1137         rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1138                 filter, attr_list, 0, &result);
1139
1140         if (rc != LDAP_SUCCESS) {
1141                 DEBUG(3,("Failure looking up sids (%s)\n",
1142                          ldap_err2string(rc)));
1143                 ret = NT_STATUS_UNSUCCESSFUL;
1144                 goto done;
1145         }
1146
1147         count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1148
1149         if (count == 0) {
1150                 DEBUG(10, ("NO SIDs found\n"));
1151         }
1152
1153         for (i = 0; i < count; i++) {
1154                 char *sidstr = NULL;
1155                 char *tmp = NULL;
1156                 enum id_type type;
1157                 struct id_map *map;
1158                 DOM_SID sid;
1159                 uint32_t id;
1160
1161                 if (i == 0) { /* first entry */
1162                         entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1163                                                  result);
1164                 } else { /* following ones */
1165                         entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1166                                                 entry);
1167                 }
1168                 if ( ! entry) {
1169                         DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1170                                   "from results\n"));
1171                         break;
1172                 }
1173
1174                 /* first check if the SID is present */
1175                 sidstr = smbldap_talloc_single_attribute(
1176                                 ctx->smbldap_state->ldap_struct,
1177                                 entry, LDAP_ATTRIBUTE_SID, memctx);
1178                 if ( ! sidstr) { /* no sid ??, skip entry */
1179                         DEBUG(2, ("WARNING SID not found on entry\n"));
1180                         continue;
1181                 }
1182
1183                 if ( ! string_to_sid(&sid, sidstr)) {
1184                         DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1185                         TALLOC_FREE(sidstr);
1186                         continue;
1187                 }
1188
1189                 map = find_map_by_sid(&ids[bidx], &sid);
1190                 if (!map) {
1191                         DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1192                                   "in ids", sidstr));
1193                         TALLOC_FREE(sidstr);
1194                         continue;
1195                 }
1196
1197                 /* now try to see if it is a uid, if not try with a gid
1198                  * (gid is more common, but in case both uidNumber and
1199                  * gidNumber are returned the SID is mapped to the uid
1200                  * not the gid) */
1201                 type = ID_TYPE_UID;
1202                 tmp = smbldap_talloc_single_attribute(
1203                                 ctx->smbldap_state->ldap_struct,
1204                                 entry, uidNumber, memctx);
1205                 if ( ! tmp) {
1206                         type = ID_TYPE_GID;
1207                         tmp = smbldap_talloc_single_attribute(
1208                                         ctx->smbldap_state->ldap_struct,
1209                                         entry, gidNumber, memctx);
1210                 }
1211                 if ( ! tmp) { /* no ids ?? */
1212                         DEBUG(5, ("no uidNumber, "
1213                                   "nor gidNumber attributes found\n"));
1214                         TALLOC_FREE(sidstr);
1215                         continue;
1216                 }
1217
1218                 id = strtoul(tmp, NULL, 10);
1219                 if (!idmap_unix_id_is_in_range(id, dom)) {
1220                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1221                                   "Filtered!\n", id,
1222                                   dom->low_id, dom->high_id));
1223                         TALLOC_FREE(sidstr);
1224                         TALLOC_FREE(tmp);
1225                         continue;
1226                 }
1227                 TALLOC_FREE(tmp);
1228
1229                 if (map->status == ID_MAPPED) {
1230                         DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1231                               "overwriting mapping %s -> %u with %s -> %u\n",
1232                               (type == ID_TYPE_UID) ? "UID" : "GID",
1233                               sidstr, map->xid.id, sidstr, id));
1234                 }
1235
1236                 TALLOC_FREE(sidstr);
1237
1238                 /* mapped */
1239                 map->xid.type = type;
1240                 map->xid.id = id;
1241                 map->status = ID_MAPPED;
1242
1243                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1244                            (unsigned long)map->xid.id, map->xid.type));
1245         }
1246
1247         /* free the ldap results */
1248         if (result) {
1249                 ldap_msgfree(result);
1250                 result = NULL;
1251         }
1252
1253         if (multi && ids[idx]) { /* still some values to map */
1254                 goto again;
1255         }
1256
1257         /*
1258          *  try to create new mappings for unmapped sids
1259          */
1260         for (i = 0; ids[i]; i++) {
1261                 if (ids[i]->status != ID_MAPPED) {
1262                         ids[i]->status = ID_UNMAPPED;
1263                         if (ids[i]->sid != NULL) {
1264                                 ret = idmap_ldap_new_mapping(dom, ids[i]);
1265                                 if (!NT_STATUS_IS_OK(ret)) {
1266                                         goto done;
1267                                 }
1268                         }
1269                 }
1270         }
1271
1272         ret = NT_STATUS_OK;
1273
1274 done:
1275         talloc_free(memctx);
1276         return ret;
1277 }
1278
1279 /**********************************
1280  Close the idmap ldap instance
1281 **********************************/
1282
1283 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1284 {
1285         struct idmap_ldap_context *ctx;
1286
1287         if (dom->private_data) {
1288                 ctx = talloc_get_type(dom->private_data,
1289                                       struct idmap_ldap_context);
1290
1291                 talloc_free(ctx);
1292                 dom->private_data = NULL;
1293         }
1294
1295         return NT_STATUS_OK;
1296 }
1297
1298 static struct idmap_methods idmap_ldap_methods = {
1299
1300         .init = idmap_ldap_db_init,
1301         .unixids_to_sids = idmap_ldap_unixids_to_sids,
1302         .sids_to_unixids = idmap_ldap_sids_to_unixids,
1303         .allocate_id = idmap_ldap_get_new_id,
1304         .close_fn = idmap_ldap_close
1305 };
1306
1307 NTSTATUS idmap_ldap_init(void);
1308 NTSTATUS idmap_ldap_init(void)
1309 {
1310         return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1311                                   &idmap_ldap_methods);
1312 }
1313