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