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