source: vendor/current/source3/winbindd/idmap_ldap.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

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