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