2
Unix SMB/CIFS implementation.
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
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 3 of the License, or
14
(at your option) any later version.
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
21
You should have received a copy of the GNU General Public License
22
along with this program. If not, see <http://www.gnu.org/licenses/>.
29
#define DBGC_CLASS DBGC_IDMAP
36
static char *idmap_fetch_secret(const char *backend, bool alloc,
37
const char *domain, const char *identity)
43
r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
45
r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
51
strupper_m(tmp); /* make sure the key is case insensitive */
52
ret = secrets_fetch_generic(tmp, identity);
59
struct idmap_ldap_context {
60
struct smbldap_state *smbldap_state;
64
uint32_t filter_low_id, filter_high_id; /* Filter range */
68
struct idmap_ldap_alloc_context {
69
struct smbldap_state *smbldap_state;
73
uid_t low_uid, high_uid; /* Range of uids */
74
gid_t low_gid, high_gid; /* Range of gids */
78
#define CHECK_ALLOC_DONE(mem) do { \
80
DEBUG(0, ("Out of memory!\n")); \
81
ret = NT_STATUS_NO_MEMORY; \
85
/**********************************************************************
86
IDMAP ALLOC TDB BACKEND
87
**********************************************************************/
89
static struct idmap_ldap_alloc_context *idmap_alloc_ldap;
91
/*********************************************************************
92
********************************************************************/
94
static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx,
95
struct smbldap_state *ldap_state,
96
const char *config_option,
97
struct idmap_domain *dom,
100
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
102
const char *tmp = NULL;
103
char *user_dn = NULL;
106
/* assume anonymous if we don't have a specified user */
108
tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
112
/* only the alloc backend can pass in a NULL dom */
113
secret = idmap_fetch_secret("ldap", True,
116
secret = idmap_fetch_secret("ldap", False,
121
DEBUG(0, ("get_credentials: Unable to fetch "
122
"auth credentials for %s in %s\n",
123
tmp, (dom==NULL)?"ALLOC":dom->name));
124
ret = NT_STATUS_ACCESS_DENIED;
127
*dn = talloc_strdup(mem_ctx, tmp);
128
CHECK_ALLOC_DONE(*dn);
130
if (!fetch_ldap_pw(&user_dn, &secret)) {
131
DEBUG(2, ("get_credentials: Failed to lookup ldap "
132
"bind creds. Using anonymous connection.\n"));
135
*dn = talloc_strdup(mem_ctx, user_dn);
136
SAFE_FREE( user_dn );
137
CHECK_ALLOC_DONE(*dn);
141
smbldap_set_creds(ldap_state, anon, *dn, secret);
151
/**********************************************************************
152
Verify the sambaUnixIdPool entry in the directory.
153
**********************************************************************/
155
static NTSTATUS verify_idpool(void)
159
LDAPMessage *result = NULL;
160
LDAPMod **mods = NULL;
161
const char **attr_list;
166
if ( ! idmap_alloc_ldap) {
167
return NT_STATUS_UNSUCCESSFUL;
170
ctx = talloc_new(idmap_alloc_ldap);
172
DEBUG(0, ("Out of memory!\n"));
173
return NT_STATUS_NO_MEMORY;
176
filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
177
CHECK_ALLOC_DONE(filter);
179
attr_list = get_attr_list(ctx, idpool_attr_list);
180
CHECK_ALLOC_DONE(attr_list);
182
rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
183
idmap_alloc_ldap->suffix,
190
if (rc != LDAP_SUCCESS) {
191
DEBUG(1, ("Unable to verify the idpool, "
192
"cannot continue initialization!\n"));
193
return NT_STATUS_UNSUCCESSFUL;
196
count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
199
ldap_msgfree(result);
202
DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
203
filter, idmap_alloc_ldap->suffix));
204
ret = NT_STATUS_UNSUCCESSFUL;
207
else if (count == 0) {
208
char *uid_str, *gid_str;
210
uid_str = talloc_asprintf(ctx, "%lu",
211
(unsigned long)idmap_alloc_ldap->low_uid);
212
gid_str = talloc_asprintf(ctx, "%lu",
213
(unsigned long)idmap_alloc_ldap->low_gid);
215
smbldap_set_mod(&mods, LDAP_MOD_ADD,
216
"objectClass", LDAP_OBJ_IDPOOL);
217
smbldap_set_mod(&mods, LDAP_MOD_ADD,
218
get_attr_key2string(idpool_attr_list,
219
LDAP_ATTR_UIDNUMBER),
221
smbldap_set_mod(&mods, LDAP_MOD_ADD,
222
get_attr_key2string(idpool_attr_list,
223
LDAP_ATTR_GIDNUMBER),
226
rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
227
idmap_alloc_ldap->suffix,
229
ldap_mods_free(mods, True);
231
ret = NT_STATUS_UNSUCCESSFUL;
236
ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
242
/*****************************************************************************
243
Initialise idmap database.
244
*****************************************************************************/
246
static NTSTATUS idmap_ldap_alloc_init(const char *params)
248
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
255
/* Only do init if we are online */
256
if (idmap_is_offline()) {
257
return NT_STATUS_FILE_IS_OFFLINE;
260
idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context);
261
CHECK_ALLOC_DONE( idmap_alloc_ldap );
265
if (!lp_idmap_uid(&low_uid, &high_uid)
266
|| !lp_idmap_gid(&low_gid, &high_gid)) {
267
DEBUG(1, ("idmap uid or idmap gid missing\n"));
268
ret = NT_STATUS_UNSUCCESSFUL;
272
idmap_alloc_ldap->low_uid = low_uid;
273
idmap_alloc_ldap->high_uid = high_uid;
274
idmap_alloc_ldap->low_gid = low_gid;
275
idmap_alloc_ldap->high_gid= high_gid;
277
if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) {
278
DEBUG(1, ("idmap uid range invalid\n"));
279
DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
280
ret = NT_STATUS_UNSUCCESSFUL;
284
if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) {
285
DEBUG(1, ("idmap gid range invalid\n"));
286
DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
287
ret = NT_STATUS_UNSUCCESSFUL;
291
if (params && *params) {
292
/* assume location is the only parameter */
293
idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
295
tmp = lp_parm_const_string(-1, "idmap alloc config",
299
DEBUG(1, ("ERROR: missing idmap ldap url\n"));
300
ret = NT_STATUS_UNSUCCESSFUL;
304
idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
306
CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
308
trim_char(idmap_alloc_ldap->url, '\"', '\"');
310
tmp = lp_parm_const_string(-1, "idmap alloc config",
311
"ldap_base_dn", NULL);
312
if ( ! tmp || ! *tmp) {
313
tmp = lp_ldap_idmap_suffix();
315
DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
316
ret = NT_STATUS_UNSUCCESSFUL;
321
idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
322
CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
324
ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(),
325
idmap_alloc_ldap->url,
326
&idmap_alloc_ldap->smbldap_state);
327
if (!NT_STATUS_IS_OK(ret)) {
328
DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
329
idmap_alloc_ldap->url));
333
ret = get_credentials( idmap_alloc_ldap,
334
idmap_alloc_ldap->smbldap_state,
335
"idmap alloc config", NULL,
336
&idmap_alloc_ldap->user_dn );
337
if ( !NT_STATUS_IS_OK(ret) ) {
338
DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
339
"credentials (%s)\n", nt_errstr(ret)));
343
/* see if the idmap suffix and sub entries exists */
345
ret = verify_idpool();
348
if ( !NT_STATUS_IS_OK( ret ) )
349
TALLOC_FREE( idmap_alloc_ldap );
354
/********************************
355
Allocate a new uid or gid
356
********************************/
358
static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
361
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
362
int rc = LDAP_SERVER_DOWN;
364
LDAPMessage *result = NULL;
365
LDAPMessage *entry = NULL;
366
LDAPMod **mods = NULL;
370
const char *dn = NULL;
371
const char **attr_list;
374
/* Only do query if we are online */
375
if (idmap_is_offline()) {
376
return NT_STATUS_FILE_IS_OFFLINE;
379
if ( ! idmap_alloc_ldap) {
380
return NT_STATUS_UNSUCCESSFUL;
383
ctx = talloc_new(idmap_alloc_ldap);
385
DEBUG(0, ("Out of memory!\n"));
386
return NT_STATUS_NO_MEMORY;
393
type = get_attr_key2string(idpool_attr_list,
394
LDAP_ATTR_UIDNUMBER);
398
type = get_attr_key2string(idpool_attr_list,
399
LDAP_ATTR_GIDNUMBER);
403
DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
404
return NT_STATUS_INVALID_PARAMETER;
407
filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
408
CHECK_ALLOC_DONE(filter);
410
attr_list = get_attr_list(ctx, idpool_attr_list);
411
CHECK_ALLOC_DONE(attr_list);
413
DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
415
rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
416
idmap_alloc_ldap->suffix,
417
LDAP_SCOPE_SUBTREE, filter,
418
attr_list, 0, &result);
420
if (rc != LDAP_SUCCESS) {
421
DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
425
talloc_autofree_ldapmsg(ctx, result);
427
count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
430
DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
434
entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
437
dn = smbldap_talloc_dn(ctx,
438
idmap_alloc_ldap->smbldap_state->ldap_struct,
444
if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
445
entry, type, ctx))) {
446
DEBUG(0,("%s attribute not found\n", type));
450
DEBUG(0,("Out of memory\n"));
451
ret = NT_STATUS_NO_MEMORY;
455
xid->id = strtoul(id_str, NULL, 10);
457
/* make sure we still have room to grow */
461
if (xid->id > idmap_alloc_ldap->high_uid) {
462
DEBUG(0,("Cannot allocate uid above %lu!\n",
463
(unsigned long)idmap_alloc_ldap->high_uid));
469
if (xid->id > idmap_alloc_ldap->high_gid) {
470
DEBUG(0,("Cannot allocate gid above %lu!\n",
471
(unsigned long)idmap_alloc_ldap->high_uid));
481
new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
483
DEBUG(0,("Out of memory\n"));
484
ret = NT_STATUS_NO_MEMORY;
488
smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
489
smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
492
DEBUG(0,("smbldap_set_mod() failed.\n"));
496
DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
497
id_str, new_id_str));
499
rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
501
ldap_mods_free(mods, True);
503
if (rc != LDAP_SUCCESS) {
504
DEBUG(1,("Failed to allocate new %s. "
505
"smbldap_modify() failed.\n", type));
516
/**********************************
517
Get current highest id.
518
**********************************/
520
static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
523
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
524
int rc = LDAP_SERVER_DOWN;
526
LDAPMessage *result = NULL;
527
LDAPMessage *entry = NULL;
530
const char **attr_list;
533
/* Only do query if we are online */
534
if (idmap_is_offline()) {
535
return NT_STATUS_FILE_IS_OFFLINE;
538
if ( ! idmap_alloc_ldap) {
539
return NT_STATUS_UNSUCCESSFUL;
542
memctx = talloc_new(idmap_alloc_ldap);
544
DEBUG(0, ("Out of memory!\n"));
545
return NT_STATUS_NO_MEMORY;
552
type = get_attr_key2string(idpool_attr_list,
553
LDAP_ATTR_UIDNUMBER);
557
type = get_attr_key2string(idpool_attr_list,
558
LDAP_ATTR_GIDNUMBER);
562
DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
563
return NT_STATUS_INVALID_PARAMETER;
566
filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
567
CHECK_ALLOC_DONE(filter);
569
attr_list = get_attr_list(memctx, idpool_attr_list);
570
CHECK_ALLOC_DONE(attr_list);
572
rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
573
idmap_alloc_ldap->suffix,
574
LDAP_SCOPE_SUBTREE, filter,
575
attr_list, 0, &result);
577
if (rc != LDAP_SUCCESS) {
578
DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
582
talloc_autofree_ldapmsg(memctx, result);
584
count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
587
DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
591
entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
594
id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
595
entry, type, memctx);
597
DEBUG(0,("%s attribute not found\n", type));
601
DEBUG(0,("Out of memory\n"));
602
ret = NT_STATUS_NO_MEMORY;
606
xid->id = strtoul(id_str, NULL, 10);
613
/**********************************
615
**********************************/
617
static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
620
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
621
int rc = LDAP_SERVER_DOWN;
623
LDAPMessage *result = NULL;
624
LDAPMessage *entry = NULL;
625
LDAPMod **mods = NULL;
628
const char *dn = NULL;
629
const char **attr_list;
632
/* Only do query if we are online */
633
if (idmap_is_offline()) {
634
return NT_STATUS_FILE_IS_OFFLINE;
637
if ( ! idmap_alloc_ldap) {
638
return NT_STATUS_UNSUCCESSFUL;
641
ctx = talloc_new(idmap_alloc_ldap);
643
DEBUG(0, ("Out of memory!\n"));
644
return NT_STATUS_NO_MEMORY;
651
type = get_attr_key2string(idpool_attr_list,
652
LDAP_ATTR_UIDNUMBER);
656
type = get_attr_key2string(idpool_attr_list,
657
LDAP_ATTR_GIDNUMBER);
661
DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
662
return NT_STATUS_INVALID_PARAMETER;
665
filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
666
CHECK_ALLOC_DONE(filter);
668
attr_list = get_attr_list(ctx, idpool_attr_list);
669
CHECK_ALLOC_DONE(attr_list);
671
rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
672
idmap_alloc_ldap->suffix,
673
LDAP_SCOPE_SUBTREE, filter,
674
attr_list, 0, &result);
676
if (rc != LDAP_SUCCESS) {
677
DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
681
talloc_autofree_ldapmsg(ctx, result);
683
count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
686
DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
690
entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
693
dn = smbldap_talloc_dn(ctx,
694
idmap_alloc_ldap->smbldap_state->ldap_struct,
700
new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id);
702
DEBUG(0,("Out of memory\n"));
703
ret = NT_STATUS_NO_MEMORY;
707
smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str);
710
DEBUG(0,("smbldap_set_mod() failed.\n"));
714
rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
716
ldap_mods_free(mods, True);
718
if (rc != LDAP_SUCCESS) {
719
DEBUG(1,("Failed to allocate new %s. "
720
"smbldap_modify() failed.\n", type));
731
/**********************************
732
Close idmap ldap alloc
733
**********************************/
735
static NTSTATUS idmap_ldap_alloc_close(void)
737
if (idmap_alloc_ldap) {
738
smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
739
DEBUG(5,("The connection to the LDAP server was closed\n"));
740
/* maybe free the results here --metze */
741
TALLOC_FREE(idmap_alloc_ldap);
747
/**********************************************************************
748
IDMAP MAPPING LDAP BACKEND
749
**********************************************************************/
751
static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
753
smbldap_free_struct(&ctx->smbldap_state);
754
DEBUG(5,("The connection to the LDAP server was closed\n"));
755
/* maybe free the results here --metze */
760
/********************************
761
Initialise idmap database.
762
********************************/
764
static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
768
struct idmap_ldap_context *ctx = NULL;
769
char *config_option = NULL;
770
const char *tmp = NULL;
772
/* Only do init if we are online */
773
if (idmap_is_offline()) {
774
return NT_STATUS_FILE_IS_OFFLINE;
777
ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
779
DEBUG(0, ("Out of memory!\n"));
780
return NT_STATUS_NO_MEMORY;
783
if (strequal(dom->name, "*")) {
789
ctx->filter_low_id = 0;
790
ctx->filter_high_id = 0;
792
if (lp_idmap_uid(&low_uid, &high_uid)) {
793
ctx->filter_low_id = low_uid;
794
ctx->filter_high_id = high_uid;
796
DEBUG(3, ("Warning: 'idmap uid' not set!\n"));
799
if (lp_idmap_gid(&low_gid, &high_gid)) {
800
if ((low_gid != low_uid) || (high_gid != high_uid)) {
801
DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
802
" ranges do not agree -- building "
804
ctx->filter_low_id = MAX(ctx->filter_low_id,
806
ctx->filter_high_id = MIN(ctx->filter_high_id,
810
DEBUG(3, ("Warning: 'idmap gid' not set!\n"));
813
const char *range = NULL;
815
config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
816
if ( ! config_option) {
817
DEBUG(0, ("Out of memory!\n"));
818
ret = NT_STATUS_NO_MEMORY;
823
range = lp_parm_const_string(-1, config_option, "range", NULL);
824
if (range && range[0]) {
825
if ((sscanf(range, "%u - %u", &ctx->filter_low_id,
826
&ctx->filter_high_id) != 2))
828
DEBUG(1, ("ERROR: invalid filter range [%s]", range));
829
ctx->filter_low_id = 0;
830
ctx->filter_high_id = 0;
835
if (ctx->filter_low_id > ctx->filter_high_id) {
836
DEBUG(1, ("ERROR: invalid filter range [%u-%u]",
837
ctx->filter_low_id, ctx->filter_high_id));
838
ctx->filter_low_id = 0;
839
ctx->filter_high_id = 0;
842
if (params != NULL) {
843
/* assume location is the only parameter */
844
ctx->url = talloc_strdup(ctx, params);
846
tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
849
DEBUG(1, ("ERROR: missing idmap ldap url\n"));
850
ret = NT_STATUS_UNSUCCESSFUL;
854
ctx->url = talloc_strdup(ctx, tmp);
856
CHECK_ALLOC_DONE(ctx->url);
858
trim_char(ctx->url, '\"', '\"');
860
tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
861
if ( ! tmp || ! *tmp) {
862
tmp = lp_ldap_idmap_suffix();
864
DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
865
ret = NT_STATUS_UNSUCCESSFUL;
870
ctx->suffix = talloc_strdup(ctx, tmp);
871
CHECK_ALLOC_DONE(ctx->suffix);
873
ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
874
&ctx->smbldap_state);
875
if (!NT_STATUS_IS_OK(ret)) {
876
DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
880
ret = get_credentials( ctx, ctx->smbldap_state, config_option,
881
dom, &ctx->user_dn );
882
if ( !NT_STATUS_IS_OK(ret) ) {
883
DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
884
"credentials (%s)\n", nt_errstr(ret)));
888
/* set the destructor on the context, so that resource are properly
889
freed if the contexts is released */
891
talloc_set_destructor(ctx, idmap_ldap_close_destructor);
893
dom->private_data = ctx;
895
talloc_free(config_option);
904
/* max number of ids requested per batch query */
905
#define IDMAP_LDAP_MAX_IDS 30
907
/**********************************
908
lookup a set of unix ids.
909
**********************************/
911
/* this function searches up to IDMAP_LDAP_MAX_IDS entries
912
* in maps for a match */
913
static struct id_map *find_map_by_id(struct id_map **maps,
919
for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
920
if (maps[i] == NULL) { /* end of the run */
923
if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
931
static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
936
struct idmap_ldap_context *ctx;
937
LDAPMessage *result = NULL;
938
LDAPMessage *entry = NULL;
939
const char *uidNumber;
940
const char *gidNumber;
941
const char **attr_list;
950
/* Only do query if we are online */
951
if (idmap_is_offline()) {
952
return NT_STATUS_FILE_IS_OFFLINE;
955
ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
957
memctx = talloc_new(ctx);
959
DEBUG(0, ("Out of memory!\n"));
960
return NT_STATUS_NO_MEMORY;
963
uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
964
gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
966
attr_list = get_attr_list(memctx, sidmap_attr_list);
969
/* if we are requested just one mapping use the simple filter */
971
filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
972
LDAP_OBJ_IDMAP_ENTRY,
973
(ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
974
(unsigned long)ids[0]->xid.id);
975
CHECK_ALLOC_DONE(filter);
976
DEBUG(10, ("Filter: [%s]\n", filter));
978
/* multiple mappings */
982
for (i = 0; ids[i]; i++) {
983
ids[i]->status = ID_UNKNOWN;
990
filter = talloc_asprintf(memctx,
991
"(&(objectClass=%s)(|",
992
LDAP_OBJ_IDMAP_ENTRY);
993
CHECK_ALLOC_DONE(filter);
996
for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
997
filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
998
(ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
999
(unsigned long)ids[idx]->xid.id);
1000
CHECK_ALLOC_DONE(filter);
1002
filter = talloc_asprintf_append_buffer(filter, "))");
1003
CHECK_ALLOC_DONE(filter);
1004
DEBUG(10, ("Filter: [%s]\n", filter));
1010
rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1011
filter, attr_list, 0, &result);
1013
if (rc != LDAP_SUCCESS) {
1014
DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
1015
ret = NT_STATUS_UNSUCCESSFUL;
1019
count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1022
DEBUG(10, ("NO SIDs found\n"));
1025
for (i = 0; i < count; i++) {
1026
char *sidstr = NULL;
1032
if (i == 0) { /* first entry */
1033
entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1035
} else { /* following ones */
1036
entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1040
DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1045
/* first check if the SID is present */
1046
sidstr = smbldap_talloc_single_attribute(
1047
ctx->smbldap_state->ldap_struct,
1048
entry, LDAP_ATTRIBUTE_SID, memctx);
1049
if ( ! sidstr) { /* no sid, skip entry */
1050
DEBUG(2, ("WARNING SID not found on entry\n"));
1054
/* now try to see if it is a uid, if not try with a gid
1055
* (gid is more common, but in case both uidNumber and
1056
* gidNumber are returned the SID is mapped to the uid
1059
tmp = smbldap_talloc_single_attribute(
1060
ctx->smbldap_state->ldap_struct,
1061
entry, uidNumber, memctx);
1064
tmp = smbldap_talloc_single_attribute(
1065
ctx->smbldap_state->ldap_struct,
1066
entry, gidNumber, memctx);
1068
if ( ! tmp) { /* wow very strange entry, how did it match ? */
1069
DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
1070
"nor gidNumber returned\n", sidstr));
1071
TALLOC_FREE(sidstr);
1075
id = strtoul(tmp, NULL, 10);
1077
(ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1078
(ctx->filter_high_id && (id > ctx->filter_high_id))) {
1079
DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1081
ctx->filter_low_id, ctx->filter_high_id));
1082
TALLOC_FREE(sidstr);
1088
map = find_map_by_id(&ids[bidx], type, id);
1090
DEBUG(2, ("WARNING: couldn't match sid (%s) "
1091
"with requested ids\n", sidstr));
1092
TALLOC_FREE(sidstr);
1096
if ( ! string_to_sid(map->sid, sidstr)) {
1097
DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1098
TALLOC_FREE(sidstr);
1102
if (map->status == ID_MAPPED) {
1103
DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1104
"overwriting mapping %u -> %s with %u -> %s\n",
1105
(type == ID_TYPE_UID) ? "UID" : "GID",
1106
id, sid_string_dbg(map->sid), id, sidstr));
1109
TALLOC_FREE(sidstr);
1112
map->status = ID_MAPPED;
1114
DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1115
(unsigned long)map->xid.id, map->xid.type));
1118
/* free the ldap results */
1120
ldap_msgfree(result);
1124
if (multi && ids[idx]) { /* still some values to map */
1130
/* mark all unknwon/expired ones as unmapped */
1131
for (i = 0; ids[i]; i++) {
1132
if (ids[i]->status != ID_MAPPED)
1133
ids[i]->status = ID_UNMAPPED;
1137
talloc_free(memctx);
1141
/**********************************
1142
lookup a set of sids.
1143
**********************************/
1145
/* this function searches up to IDMAP_LDAP_MAX_IDS entries
1146
* in maps for a match */
1147
static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
1151
for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
1152
if (maps[i] == NULL) { /* end of the run */
1155
if (sid_equal(maps[i]->sid, sid)) {
1163
static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
1164
struct id_map **ids)
1166
LDAPMessage *entry = NULL;
1169
struct idmap_ldap_context *ctx;
1170
LDAPMessage *result = NULL;
1171
const char *uidNumber;
1172
const char *gidNumber;
1173
const char **attr_list;
1174
char *filter = NULL;
1182
/* Only do query if we are online */
1183
if (idmap_is_offline()) {
1184
return NT_STATUS_FILE_IS_OFFLINE;
1187
ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1189
memctx = talloc_new(ctx);
1191
DEBUG(0, ("Out of memory!\n"));
1192
return NT_STATUS_NO_MEMORY;
1195
uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
1196
gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
1198
attr_list = get_attr_list(memctx, sidmap_attr_list);
1201
/* if we are requested just one mapping use the simple filter */
1203
filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
1204
LDAP_OBJ_IDMAP_ENTRY,
1206
sid_string_talloc(memctx, ids[0]->sid));
1207
CHECK_ALLOC_DONE(filter);
1208
DEBUG(10, ("Filter: [%s]\n", filter));
1210
/* multiple mappings */
1214
for (i = 0; ids[i]; i++) {
1215
ids[i]->status = ID_UNKNOWN;
1221
TALLOC_FREE(filter);
1222
filter = talloc_asprintf(memctx,
1223
"(&(objectClass=%s)(|",
1224
LDAP_OBJ_IDMAP_ENTRY);
1225
CHECK_ALLOC_DONE(filter);
1228
for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
1229
filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
1231
sid_string_talloc(memctx,
1233
CHECK_ALLOC_DONE(filter);
1235
filter = talloc_asprintf_append_buffer(filter, "))");
1236
CHECK_ALLOC_DONE(filter);
1237
DEBUG(10, ("Filter: [%s]", filter));
1243
rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1244
filter, attr_list, 0, &result);
1246
if (rc != LDAP_SUCCESS) {
1247
DEBUG(3,("Failure looking up sids (%s)\n",
1248
ldap_err2string(rc)));
1249
ret = NT_STATUS_UNSUCCESSFUL;
1253
count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1256
DEBUG(10, ("NO SIDs found\n"));
1259
for (i = 0; i < count; i++) {
1260
char *sidstr = NULL;
1267
if (i == 0) { /* first entry */
1268
entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1270
} else { /* following ones */
1271
entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1275
DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1280
/* first check if the SID is present */
1281
sidstr = smbldap_talloc_single_attribute(
1282
ctx->smbldap_state->ldap_struct,
1283
entry, LDAP_ATTRIBUTE_SID, memctx);
1284
if ( ! sidstr) { /* no sid ??, skip entry */
1285
DEBUG(2, ("WARNING SID not found on entry\n"));
1289
if ( ! string_to_sid(&sid, sidstr)) {
1290
DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1291
TALLOC_FREE(sidstr);
1295
map = find_map_by_sid(&ids[bidx], &sid);
1297
DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1299
TALLOC_FREE(sidstr);
1303
/* now try to see if it is a uid, if not try with a gid
1304
* (gid is more common, but in case both uidNumber and
1305
* gidNumber are returned the SID is mapped to the uid
1308
tmp = smbldap_talloc_single_attribute(
1309
ctx->smbldap_state->ldap_struct,
1310
entry, uidNumber, memctx);
1313
tmp = smbldap_talloc_single_attribute(
1314
ctx->smbldap_state->ldap_struct,
1315
entry, gidNumber, memctx);
1317
if ( ! tmp) { /* no ids ?? */
1318
DEBUG(5, ("no uidNumber, "
1319
"nor gidNumber attributes found\n"));
1320
TALLOC_FREE(sidstr);
1324
id = strtoul(tmp, NULL, 10);
1326
(ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1327
(ctx->filter_high_id && (id > ctx->filter_high_id))) {
1328
DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1330
ctx->filter_low_id, ctx->filter_high_id));
1331
TALLOC_FREE(sidstr);
1337
if (map->status == ID_MAPPED) {
1338
DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1339
"overwriting mapping %s -> %u with %s -> %u\n",
1340
(type == ID_TYPE_UID) ? "UID" : "GID",
1341
sidstr, map->xid.id, sidstr, id));
1344
TALLOC_FREE(sidstr);
1347
map->xid.type = type;
1349
map->status = ID_MAPPED;
1351
DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1352
(unsigned long)map->xid.id, map->xid.type));
1355
/* free the ldap results */
1357
ldap_msgfree(result);
1361
if (multi && ids[idx]) { /* still some values to map */
1367
/* mark all unknwon/expired ones as unmapped */
1368
for (i = 0; ids[i]; i++) {
1369
if (ids[i]->status != ID_MAPPED)
1370
ids[i]->status = ID_UNMAPPED;
1374
talloc_free(memctx);
1378
/**********************************
1380
**********************************/
1382
/* TODO: change this: This function cannot be called to modify a mapping,
1383
* only set a new one */
1385
static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
1386
const struct id_map *map)
1390
struct idmap_ldap_context *ctx;
1391
LDAPMessage *entry = NULL;
1392
LDAPMod **mods = NULL;
1399
/* Only do query if we are online */
1400
if (idmap_is_offline()) {
1401
return NT_STATUS_FILE_IS_OFFLINE;
1404
ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1406
switch(map->xid.type) {
1408
type = get_attr_key2string(sidmap_attr_list,
1409
LDAP_ATTR_UIDNUMBER);
1413
type = get_attr_key2string(sidmap_attr_list,
1414
LDAP_ATTR_GIDNUMBER);
1418
return NT_STATUS_INVALID_PARAMETER;
1421
memctx = talloc_new(ctx);
1423
DEBUG(0, ("Out of memory!\n"));
1424
return NT_STATUS_NO_MEMORY;
1427
id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
1428
CHECK_ALLOC_DONE(id_str);
1430
sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
1431
CHECK_ALLOC_DONE(sid);
1433
dn = talloc_asprintf(memctx, "%s=%s,%s",
1434
get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1437
CHECK_ALLOC_DONE(dn);
1439
smbldap_set_mod(&mods, LDAP_MOD_ADD,
1440
"objectClass", LDAP_OBJ_IDMAP_ENTRY);
1442
smbldap_make_mod(ctx->smbldap_state->ldap_struct,
1443
entry, &mods, type, id_str);
1445
smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
1446
get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1450
DEBUG(2, ("ERROR: No mods?\n"));
1451
ret = NT_STATUS_UNSUCCESSFUL;
1455
/* TODO: remove conflicting mappings! */
1457
smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
1459
DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
1461
rc = smbldap_add(ctx->smbldap_state, dn, mods);
1462
ldap_mods_free(mods, True);
1464
if (rc != LDAP_SUCCESS) {
1465
char *ld_error = NULL;
1466
ldap_get_option(ctx->smbldap_state->ldap_struct,
1467
LDAP_OPT_ERROR_STRING, &ld_error);
1468
DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
1469
"mapping [%s]\n", sid,
1470
(unsigned long)map->xid.id, type));
1471
DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1472
ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
1474
ldap_memfree(ld_error);
1476
ret = NT_STATUS_UNSUCCESSFUL;
1480
DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
1481
"%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
1486
talloc_free(memctx);
1490
/**********************************
1491
Close the idmap ldap instance
1492
**********************************/
1494
static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1496
struct idmap_ldap_context *ctx;
1498
if (dom->private_data) {
1499
ctx = talloc_get_type(dom->private_data,
1500
struct idmap_ldap_context);
1503
dom->private_data = NULL;
1506
return NT_STATUS_OK;
1509
static struct idmap_methods idmap_ldap_methods = {
1511
.init = idmap_ldap_db_init,
1512
.unixids_to_sids = idmap_ldap_unixids_to_sids,
1513
.sids_to_unixids = idmap_ldap_sids_to_unixids,
1514
.set_mapping = idmap_ldap_set_mapping,
1515
.close_fn = idmap_ldap_close
1518
static struct idmap_alloc_methods idmap_ldap_alloc_methods = {
1520
.init = idmap_ldap_alloc_init,
1521
.allocate_id = idmap_ldap_allocate_id,
1522
.get_id_hwm = idmap_ldap_get_hwm,
1523
.set_id_hwm = idmap_ldap_set_hwm,
1524
.close_fn = idmap_ldap_alloc_close,
1525
/* .dump_data = TODO */
1528
static NTSTATUS idmap_alloc_ldap_init(void)
1530
return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1531
&idmap_ldap_alloc_methods);
1534
NTSTATUS idmap_ldap_init(void);
1535
NTSTATUS idmap_ldap_init(void)
1539
/* FIXME: bad hack to actually register also the alloc_ldap module
1540
* without changining configure.in */
1541
ret = idmap_alloc_ldap_init();
1542
if (! NT_STATUS_IS_OK(ret)) {
1545
return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1546
&idmap_ldap_methods);