~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/winbindd/idmap_ldap.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   idmap LDAP backend
 
5
 
 
6
   Copyright (C) Tim Potter             2000
 
7
   Copyright (C) Jim McDonough <jmcd@us.ibm.com>        2003
 
8
   Copyright (C) Gerald Carter          2003
 
9
   Copyright (C) Simo Sorce             2003-2007
 
10
 
 
11
   This program is free software; you can redistribute it and/or modify
 
12
   it under the terms of the GNU General Public License as published by
 
13
   the Free Software Foundation; either version 3 of the License, or
 
14
   (at your option) any later version.
 
15
 
 
16
   This program is distributed in the hope that it will be useful,
 
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
   GNU General Public License for more details.
 
20
 
 
21
   You should have received a copy of the GNU General Public License
 
22
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
23
*/
 
24
 
 
25
#include "includes.h"
 
26
#include "winbindd.h"
 
27
 
 
28
#undef DBGC_CLASS
 
29
#define DBGC_CLASS DBGC_IDMAP
 
30
 
 
31
#include <lber.h>
 
32
#include <ldap.h>
 
33
 
 
34
#include "smbldap.h"
 
35
 
 
36
static char *idmap_fetch_secret(const char *backend, bool alloc,
 
37
                                const char *domain, const char *identity)
 
38
{
 
39
        char *tmp, *ret;
 
40
        int r;
 
41
 
 
42
        if (alloc) {
 
43
                r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
 
44
        } else {
 
45
                r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
 
46
        }
 
47
 
 
48
        if (r < 0)
 
49
                return NULL;
 
50
 
 
51
        strupper_m(tmp); /* make sure the key is case insensitive */
 
52
        ret = secrets_fetch_generic(tmp, identity);
 
53
 
 
54
        SAFE_FREE(tmp);
 
55
 
 
56
        return ret;
 
57
}
 
58
 
 
59
struct idmap_ldap_context {
 
60
        struct smbldap_state *smbldap_state;
 
61
        char *url;
 
62
        char *suffix;
 
63
        char *user_dn;
 
64
        uint32_t filter_low_id, filter_high_id;         /* Filter range */
 
65
        bool anon;
 
66
};
 
67
 
 
68
struct idmap_ldap_alloc_context {
 
69
        struct smbldap_state *smbldap_state;
 
70
        char *url;
 
71
        char *suffix;
 
72
        char *user_dn;
 
73
        uid_t low_uid, high_uid;      /* Range of uids */
 
74
        gid_t low_gid, high_gid;      /* Range of gids */
 
75
 
 
76
};
 
77
 
 
78
#define CHECK_ALLOC_DONE(mem) do { \
 
79
        if (!mem) { \
 
80
                DEBUG(0, ("Out of memory!\n")); \
 
81
                ret = NT_STATUS_NO_MEMORY; \
 
82
                goto done; \
 
83
        } } while (0)
 
84
 
 
85
/**********************************************************************
 
86
 IDMAP ALLOC TDB BACKEND
 
87
**********************************************************************/
 
88
 
 
89
static struct idmap_ldap_alloc_context *idmap_alloc_ldap;
 
90
 
 
91
/*********************************************************************
 
92
 ********************************************************************/
 
93
 
 
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,
 
98
                                 char **dn )
 
99
{
 
100
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 
101
        char *secret = NULL;
 
102
        const char *tmp = NULL;
 
103
        char *user_dn = NULL;
 
104
        bool anon = False;
 
105
 
 
106
        /* assume anonymous if we don't have a specified user */
 
107
 
 
108
        tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
 
109
 
 
110
        if ( tmp ) {
 
111
                if (!dom) {
 
112
                        /* only the alloc backend can pass in a NULL dom */
 
113
                        secret = idmap_fetch_secret("ldap", True,
 
114
                                                    NULL, tmp);
 
115
                } else {
 
116
                        secret = idmap_fetch_secret("ldap", False,
 
117
                                                    dom->name, tmp);
 
118
                }
 
119
 
 
120
                if (!secret) {
 
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;
 
125
                        goto done;
 
126
                }
 
127
                *dn = talloc_strdup(mem_ctx, tmp);
 
128
                CHECK_ALLOC_DONE(*dn);
 
129
        } else {
 
130
                if (!fetch_ldap_pw(&user_dn, &secret)) {
 
131
                        DEBUG(2, ("get_credentials: Failed to lookup ldap "
 
132
                                  "bind creds. Using anonymous connection.\n"));
 
133
                        anon = True;
 
134
                } else {
 
135
                        *dn = talloc_strdup(mem_ctx, user_dn);
 
136
                        SAFE_FREE( user_dn );
 
137
                        CHECK_ALLOC_DONE(*dn);
 
138
                }
 
139
        }
 
140
 
 
141
        smbldap_set_creds(ldap_state, anon, *dn, secret);
 
142
        ret = NT_STATUS_OK;
 
143
 
 
144
done:
 
145
        SAFE_FREE(secret);
 
146
 
 
147
        return ret;
 
148
}
 
149
 
 
150
 
 
151
/**********************************************************************
 
152
 Verify the sambaUnixIdPool entry in the directory.
 
153
**********************************************************************/
 
154
 
 
155
static NTSTATUS verify_idpool(void)
 
156
{
 
157
        NTSTATUS ret;
 
158
        TALLOC_CTX *ctx;
 
159
        LDAPMessage *result = NULL;
 
160
        LDAPMod **mods = NULL;
 
161
        const char **attr_list;
 
162
        char *filter;
 
163
        int count;
 
164
        int rc;
 
165
 
 
166
        if ( ! idmap_alloc_ldap) {
 
167
                return NT_STATUS_UNSUCCESSFUL;
 
168
        }
 
169
 
 
170
        ctx = talloc_new(idmap_alloc_ldap);
 
171
        if ( ! ctx) {
 
172
                DEBUG(0, ("Out of memory!\n"));
 
173
                return NT_STATUS_NO_MEMORY;
 
174
        }
 
175
 
 
176
        filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
 
177
        CHECK_ALLOC_DONE(filter);
 
178
 
 
179
        attr_list = get_attr_list(ctx, idpool_attr_list);
 
180
        CHECK_ALLOC_DONE(attr_list);
 
181
 
 
182
        rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
 
183
                                idmap_alloc_ldap->suffix,
 
184
                                LDAP_SCOPE_SUBTREE,
 
185
                                filter,
 
186
                                attr_list,
 
187
                                0,
 
188
                                &result);
 
189
 
 
190
        if (rc != LDAP_SUCCESS) {
 
191
                DEBUG(1, ("Unable to verify the idpool, "
 
192
                          "cannot continue initialization!\n"));
 
193
                return NT_STATUS_UNSUCCESSFUL;
 
194
        }
 
195
 
 
196
        count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
 
197
                                   result);
 
198
 
 
199
        ldap_msgfree(result);
 
200
 
 
201
        if ( count > 1 ) {
 
202
                DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
 
203
                        filter, idmap_alloc_ldap->suffix));
 
204
                ret = NT_STATUS_UNSUCCESSFUL;
 
205
                goto done;
 
206
        }
 
207
        else if (count == 0) {
 
208
                char *uid_str, *gid_str;
 
209
 
 
210
                uid_str = talloc_asprintf(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);
 
214
 
 
215
                smbldap_set_mod(&mods, LDAP_MOD_ADD,
 
216
                                "objectClass", LDAP_OBJ_IDPOOL);
 
217
                smbldap_set_mod(&mods, LDAP_MOD_ADD,
 
218
                                get_attr_key2string(idpool_attr_list,
 
219
                                                    LDAP_ATTR_UIDNUMBER),
 
220
                                uid_str);
 
221
                smbldap_set_mod(&mods, LDAP_MOD_ADD,
 
222
                                get_attr_key2string(idpool_attr_list,
 
223
                                                    LDAP_ATTR_GIDNUMBER),
 
224
                                gid_str);
 
225
                if (mods) {
 
226
                        rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
 
227
                                                idmap_alloc_ldap->suffix,
 
228
                                                mods);
 
229
                        ldap_mods_free(mods, True);
 
230
                } else {
 
231
                        ret = NT_STATUS_UNSUCCESSFUL;
 
232
                        goto done;
 
233
                }
 
234
        }
 
235
 
 
236
        ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
 
237
done:
 
238
        talloc_free(ctx);
 
239
        return ret;
 
240
}
 
241
 
 
242
/*****************************************************************************
 
243
 Initialise idmap database.
 
244
*****************************************************************************/
 
245
 
 
246
static NTSTATUS idmap_ldap_alloc_init(const char *params)
 
247
{
 
248
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 
249
        const char *tmp;
 
250
        uid_t low_uid = 0;
 
251
        uid_t high_uid = 0;
 
252
        gid_t low_gid = 0;
 
253
        gid_t high_gid = 0;
 
254
 
 
255
        /* Only do init if we are online */
 
256
        if (idmap_is_offline()) {
 
257
                return NT_STATUS_FILE_IS_OFFLINE;
 
258
        }
 
259
 
 
260
        idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context);
 
261
        CHECK_ALLOC_DONE( idmap_alloc_ldap );
 
262
 
 
263
        /* load ranges */
 
264
 
 
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;
 
269
                goto done;
 
270
        }
 
271
 
 
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;
 
276
 
 
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;
 
281
                goto done;
 
282
        }
 
283
 
 
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;
 
288
                goto done;
 
289
        }
 
290
 
 
291
        if (params && *params) {
 
292
                /* assume location is the only parameter */
 
293
                idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
 
294
        } else {
 
295
                tmp = lp_parm_const_string(-1, "idmap alloc config",
 
296
                                           "ldap_url", NULL);
 
297
 
 
298
                if ( ! tmp) {
 
299
                        DEBUG(1, ("ERROR: missing idmap ldap url\n"));
 
300
                        ret = NT_STATUS_UNSUCCESSFUL;
 
301
                        goto done;
 
302
                }
 
303
 
 
304
                idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
 
305
        }
 
306
        CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
 
307
 
 
308
        trim_char(idmap_alloc_ldap->url, '\"', '\"');
 
309
 
 
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();
 
314
                if ( ! tmp) {
 
315
                        DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
 
316
                        ret = NT_STATUS_UNSUCCESSFUL;
 
317
                        goto done;
 
318
                }
 
319
        }
 
320
 
 
321
        idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
 
322
        CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
 
323
 
 
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));
 
330
                goto done;
 
331
        }
 
332
 
 
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)));
 
340
                goto done;
 
341
        }
 
342
 
 
343
        /* see if the idmap suffix and sub entries exists */
 
344
 
 
345
        ret = verify_idpool();
 
346
 
 
347
 done:
 
348
        if ( !NT_STATUS_IS_OK( ret ) )
 
349
                TALLOC_FREE( idmap_alloc_ldap );
 
350
 
 
351
        return ret;
 
352
}
 
353
 
 
354
/********************************
 
355
 Allocate a new uid or gid
 
356
********************************/
 
357
 
 
358
static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
 
359
{
 
360
        TALLOC_CTX *ctx;
 
361
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 
362
        int rc = LDAP_SERVER_DOWN;
 
363
        int count = 0;
 
364
        LDAPMessage *result = NULL;
 
365
        LDAPMessage *entry = NULL;
 
366
        LDAPMod **mods = NULL;
 
367
        char *id_str;
 
368
        char *new_id_str;
 
369
        char *filter = NULL;
 
370
        const char *dn = NULL;
 
371
        const char **attr_list;
 
372
        const char *type;
 
373
 
 
374
        /* Only do query if we are online */
 
375
        if (idmap_is_offline()) {
 
376
                return NT_STATUS_FILE_IS_OFFLINE;
 
377
        }
 
378
 
 
379
        if ( ! idmap_alloc_ldap) {
 
380
                return NT_STATUS_UNSUCCESSFUL;
 
381
        }
 
382
 
 
383
        ctx = talloc_new(idmap_alloc_ldap);
 
384
        if ( ! ctx) {
 
385
                DEBUG(0, ("Out of memory!\n"));
 
386
                return NT_STATUS_NO_MEMORY;
 
387
        }
 
388
 
 
389
        /* get type */
 
390
        switch (xid->type) {
 
391
 
 
392
        case ID_TYPE_UID:
 
393
                type = get_attr_key2string(idpool_attr_list,
 
394
                                           LDAP_ATTR_UIDNUMBER);
 
395
                break;
 
396
 
 
397
        case ID_TYPE_GID:
 
398
                type = get_attr_key2string(idpool_attr_list,
 
399
                                           LDAP_ATTR_GIDNUMBER);
 
400
                break;
 
401
 
 
402
        default:
 
403
                DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
 
404
                return NT_STATUS_INVALID_PARAMETER;
 
405
        }
 
406
 
 
407
        filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
 
408
        CHECK_ALLOC_DONE(filter);
 
409
 
 
410
        attr_list = get_attr_list(ctx, idpool_attr_list);
 
411
        CHECK_ALLOC_DONE(attr_list);
 
412
 
 
413
        DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
 
414
 
 
415
        rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
 
416
                                idmap_alloc_ldap->suffix,
 
417
                               LDAP_SCOPE_SUBTREE, filter,
 
418
                               attr_list, 0, &result);
 
419
 
 
420
        if (rc != LDAP_SUCCESS) {
 
421
                DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
 
422
                goto done;
 
423
        }
 
424
 
 
425
        talloc_autofree_ldapmsg(ctx, result);
 
426
 
 
427
        count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
 
428
                                   result);
 
429
        if (count != 1) {
 
430
                DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
 
431
                goto done;
 
432
        }
 
433
 
 
434
        entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
 
435
                                 result);
 
436
 
 
437
        dn = smbldap_talloc_dn(ctx,
 
438
                               idmap_alloc_ldap->smbldap_state->ldap_struct,
 
439
                               entry);
 
440
        if ( ! dn) {
 
441
                goto done;
 
442
        }
 
443
 
 
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));
 
447
                goto done;
 
448
        }
 
449
        if ( ! id_str) {
 
450
                DEBUG(0,("Out of memory\n"));
 
451
                ret = NT_STATUS_NO_MEMORY;
 
452
                goto done;
 
453
        }
 
454
 
 
455
        xid->id = strtoul(id_str, NULL, 10);
 
456
 
 
457
        /* make sure we still have room to grow */
 
458
 
 
459
        switch (xid->type) {
 
460
        case ID_TYPE_UID:
 
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));
 
464
                        goto done;
 
465
                }
 
466
                break;
 
467
 
 
468
        case ID_TYPE_GID:
 
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));
 
472
                        goto done;
 
473
                }
 
474
                break;
 
475
 
 
476
        default:
 
477
                /* impossible */
 
478
                goto done;
 
479
        }
 
480
 
 
481
        new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
 
482
        if ( ! new_id_str) {
 
483
                DEBUG(0,("Out of memory\n"));
 
484
                ret = NT_STATUS_NO_MEMORY;
 
485
                goto done;
 
486
        }
 
487
 
 
488
        smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
 
489
        smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
 
490
 
 
491
        if (mods == NULL) {
 
492
                DEBUG(0,("smbldap_set_mod() failed.\n"));
 
493
                goto done;
 
494
        }
 
495
 
 
496
        DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
 
497
                   id_str, new_id_str));
 
498
 
 
499
        rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
 
500
 
 
501
        ldap_mods_free(mods, True);
 
502
 
 
503
        if (rc != LDAP_SUCCESS) {
 
504
                DEBUG(1,("Failed to allocate new %s. "
 
505
                         "smbldap_modify() failed.\n", type));
 
506
                goto done;
 
507
        }
 
508
 
 
509
        ret = NT_STATUS_OK;
 
510
 
 
511
done:
 
512
        talloc_free(ctx);
 
513
        return ret;
 
514
}
 
515
 
 
516
/**********************************
 
517
 Get current highest id.
 
518
**********************************/
 
519
 
 
520
static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
 
521
{
 
522
        TALLOC_CTX *memctx;
 
523
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 
524
        int rc = LDAP_SERVER_DOWN;
 
525
        int count = 0;
 
526
        LDAPMessage *result = NULL;
 
527
        LDAPMessage *entry = NULL;
 
528
        char *id_str;
 
529
        char *filter = NULL;
 
530
        const char **attr_list;
 
531
        const char *type;
 
532
 
 
533
        /* Only do query if we are online */
 
534
        if (idmap_is_offline()) {
 
535
                return NT_STATUS_FILE_IS_OFFLINE;
 
536
        }
 
537
 
 
538
        if ( ! idmap_alloc_ldap) {
 
539
                return NT_STATUS_UNSUCCESSFUL;
 
540
        }
 
541
 
 
542
        memctx = talloc_new(idmap_alloc_ldap);
 
543
        if ( ! memctx) {
 
544
                DEBUG(0, ("Out of memory!\n"));
 
545
                return NT_STATUS_NO_MEMORY;
 
546
        }
 
547
 
 
548
        /* get type */
 
549
        switch (xid->type) {
 
550
 
 
551
        case ID_TYPE_UID:
 
552
                type = get_attr_key2string(idpool_attr_list,
 
553
                                           LDAP_ATTR_UIDNUMBER);
 
554
                break;
 
555
 
 
556
        case ID_TYPE_GID:
 
557
                type = get_attr_key2string(idpool_attr_list,
 
558
                                           LDAP_ATTR_GIDNUMBER);
 
559
                break;
 
560
 
 
561
        default:
 
562
                DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
 
563
                return NT_STATUS_INVALID_PARAMETER;
 
564
        }
 
565
 
 
566
        filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
 
567
        CHECK_ALLOC_DONE(filter);
 
568
 
 
569
        attr_list = get_attr_list(memctx, idpool_attr_list);
 
570
        CHECK_ALLOC_DONE(attr_list);
 
571
 
 
572
        rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
 
573
                                idmap_alloc_ldap->suffix,
 
574
                               LDAP_SCOPE_SUBTREE, filter,
 
575
                               attr_list, 0, &result);
 
576
 
 
577
        if (rc != LDAP_SUCCESS) {
 
578
                DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
 
579
                goto done;
 
580
        }
 
581
 
 
582
        talloc_autofree_ldapmsg(memctx, result);
 
583
 
 
584
        count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
 
585
                                   result);
 
586
        if (count != 1) {
 
587
                DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
 
588
                goto done;
 
589
        }
 
590
 
 
591
        entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
 
592
                                 result);
 
593
 
 
594
        id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
 
595
                        entry, type, memctx);
 
596
        if ( ! id_str) {
 
597
                DEBUG(0,("%s attribute not found\n", type));
 
598
                goto done;
 
599
        }
 
600
        if ( ! id_str) {
 
601
                DEBUG(0,("Out of memory\n"));
 
602
                ret = NT_STATUS_NO_MEMORY;
 
603
                goto done;
 
604
        }
 
605
 
 
606
        xid->id = strtoul(id_str, NULL, 10);
 
607
 
 
608
        ret = NT_STATUS_OK;
 
609
done:
 
610
        talloc_free(memctx);
 
611
        return ret;
 
612
}
 
613
/**********************************
 
614
 Set highest id.
 
615
**********************************/
 
616
 
 
617
static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
 
618
{
 
619
        TALLOC_CTX *ctx;
 
620
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
 
621
        int rc = LDAP_SERVER_DOWN;
 
622
        int count = 0;
 
623
        LDAPMessage *result = NULL;
 
624
        LDAPMessage *entry = NULL;
 
625
        LDAPMod **mods = NULL;
 
626
        char *new_id_str;
 
627
        char *filter = NULL;
 
628
        const char *dn = NULL;
 
629
        const char **attr_list;
 
630
        const char *type;
 
631
 
 
632
        /* Only do query if we are online */
 
633
        if (idmap_is_offline()) {
 
634
                return NT_STATUS_FILE_IS_OFFLINE;
 
635
        }
 
636
 
 
637
        if ( ! idmap_alloc_ldap) {
 
638
                return NT_STATUS_UNSUCCESSFUL;
 
639
        }
 
640
 
 
641
        ctx = talloc_new(idmap_alloc_ldap);
 
642
        if ( ! ctx) {
 
643
                DEBUG(0, ("Out of memory!\n"));
 
644
                return NT_STATUS_NO_MEMORY;
 
645
        }
 
646
 
 
647
        /* get type */
 
648
        switch (xid->type) {
 
649
 
 
650
        case ID_TYPE_UID:
 
651
                type = get_attr_key2string(idpool_attr_list,
 
652
                                           LDAP_ATTR_UIDNUMBER);
 
653
                break;
 
654
 
 
655
        case ID_TYPE_GID:
 
656
                type = get_attr_key2string(idpool_attr_list,
 
657
                                           LDAP_ATTR_GIDNUMBER);
 
658
                break;
 
659
 
 
660
        default:
 
661
                DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
 
662
                return NT_STATUS_INVALID_PARAMETER;
 
663
        }
 
664
 
 
665
        filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
 
666
        CHECK_ALLOC_DONE(filter);
 
667
 
 
668
        attr_list = get_attr_list(ctx, idpool_attr_list);
 
669
        CHECK_ALLOC_DONE(attr_list);
 
670
 
 
671
        rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
 
672
                                idmap_alloc_ldap->suffix,
 
673
                               LDAP_SCOPE_SUBTREE, filter,
 
674
                               attr_list, 0, &result);
 
675
 
 
676
        if (rc != LDAP_SUCCESS) {
 
677
                DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
 
678
                goto done;
 
679
        }
 
680
 
 
681
        talloc_autofree_ldapmsg(ctx, result);
 
682
 
 
683
        count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
 
684
                                   result);
 
685
        if (count != 1) {
 
686
                DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
 
687
                goto done;
 
688
        }
 
689
 
 
690
        entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
 
691
                                 result);
 
692
 
 
693
        dn = smbldap_talloc_dn(ctx,
 
694
                                idmap_alloc_ldap->smbldap_state->ldap_struct,
 
695
                                entry);
 
696
        if ( ! dn) {
 
697
                goto done;
 
698
        }
 
699
 
 
700
        new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id);
 
701
        if ( ! new_id_str) {
 
702
                DEBUG(0,("Out of memory\n"));
 
703
                ret = NT_STATUS_NO_MEMORY;
 
704
                goto done;
 
705
        }
 
706
 
 
707
        smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str);
 
708
 
 
709
        if (mods == NULL) {
 
710
                DEBUG(0,("smbldap_set_mod() failed.\n"));
 
711
                goto done;
 
712
        }
 
713
 
 
714
        rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
 
715
 
 
716
        ldap_mods_free(mods, True);
 
717
 
 
718
        if (rc != LDAP_SUCCESS) {
 
719
                DEBUG(1,("Failed to allocate new %s. "
 
720
                         "smbldap_modify() failed.\n", type));
 
721
                goto done;
 
722
        }
 
723
 
 
724
        ret = NT_STATUS_OK;
 
725
 
 
726
done:
 
727
        talloc_free(ctx);
 
728
        return ret;
 
729
}
 
730
 
 
731
/**********************************
 
732
 Close idmap ldap alloc
 
733
**********************************/
 
734
 
 
735
static NTSTATUS idmap_ldap_alloc_close(void)
 
736
{
 
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);
 
742
        }
 
743
        return NT_STATUS_OK;
 
744
}
 
745
 
 
746
 
 
747
/**********************************************************************
 
748
 IDMAP MAPPING LDAP BACKEND
 
749
**********************************************************************/
 
750
 
 
751
static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
 
752
{
 
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 */
 
756
 
 
757
        return 0;
 
758
}
 
759
 
 
760
/********************************
 
761
 Initialise idmap database.
 
762
********************************/
 
763
 
 
764
static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
 
765
                                   const char *params)
 
766
{
 
767
        NTSTATUS ret;
 
768
        struct idmap_ldap_context *ctx = NULL;
 
769
        char *config_option = NULL;
 
770
        const char *tmp = NULL;
 
771
 
 
772
        /* Only do init if we are online */
 
773
        if (idmap_is_offline()) {
 
774
                return NT_STATUS_FILE_IS_OFFLINE;
 
775
        }
 
776
 
 
777
        ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
 
778
        if ( ! ctx) {
 
779
                DEBUG(0, ("Out of memory!\n"));
 
780
                return NT_STATUS_NO_MEMORY;
 
781
        }
 
782
 
 
783
        if (strequal(dom->name, "*")) {
 
784
                uid_t low_uid = 0;
 
785
                uid_t high_uid = 0;
 
786
                gid_t low_gid = 0;
 
787
                gid_t high_gid = 0;
 
788
 
 
789
                ctx->filter_low_id = 0;
 
790
                ctx->filter_high_id = 0;
 
791
 
 
792
                if (lp_idmap_uid(&low_uid, &high_uid)) {
 
793
                        ctx->filter_low_id = low_uid;
 
794
                        ctx->filter_high_id = high_uid;
 
795
                } else {
 
796
                        DEBUG(3, ("Warning: 'idmap uid' not set!\n"));
 
797
                }
 
798
 
 
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 "
 
803
                                      "intersection\n"));
 
804
                                ctx->filter_low_id = MAX(ctx->filter_low_id,
 
805
                                                         low_gid);
 
806
                                ctx->filter_high_id = MIN(ctx->filter_high_id,
 
807
                                                          high_gid);
 
808
                        }
 
809
                } else {
 
810
                        DEBUG(3, ("Warning: 'idmap gid' not set!\n"));
 
811
                }
 
812
        } else {
 
813
                const char *range = NULL;
 
814
 
 
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;
 
819
                        goto done;
 
820
                }
 
821
 
 
822
                /* load ranges */
 
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))
 
827
                        {
 
828
                                DEBUG(1, ("ERROR: invalid filter range [%s]", range));
 
829
                                ctx->filter_low_id = 0;
 
830
                                ctx->filter_high_id = 0;
 
831
                        }
 
832
                }
 
833
        }
 
834
 
 
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;
 
840
        }
 
841
 
 
842
        if (params != NULL) {
 
843
                /* assume location is the only parameter */
 
844
                ctx->url = talloc_strdup(ctx, params);
 
845
        } else {
 
846
                tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
 
847
 
 
848
                if ( ! tmp) {
 
849
                        DEBUG(1, ("ERROR: missing idmap ldap url\n"));
 
850
                        ret = NT_STATUS_UNSUCCESSFUL;
 
851
                        goto done;
 
852
                }
 
853
 
 
854
                ctx->url = talloc_strdup(ctx, tmp);
 
855
        }
 
856
        CHECK_ALLOC_DONE(ctx->url);
 
857
 
 
858
        trim_char(ctx->url, '\"', '\"');
 
859
 
 
860
        tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
 
861
        if ( ! tmp || ! *tmp) {
 
862
                tmp = lp_ldap_idmap_suffix();
 
863
                if ( ! tmp) {
 
864
                        DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
 
865
                        ret = NT_STATUS_UNSUCCESSFUL;
 
866
                        goto done;
 
867
                }
 
868
        }
 
869
 
 
870
        ctx->suffix = talloc_strdup(ctx, tmp);
 
871
        CHECK_ALLOC_DONE(ctx->suffix);
 
872
 
 
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));
 
877
                goto done;
 
878
        }
 
879
 
 
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)));
 
885
                goto done;
 
886
        }
 
887
 
 
888
        /* set the destructor on the context, so that resource are properly
 
889
           freed if the contexts is released */
 
890
 
 
891
        talloc_set_destructor(ctx, idmap_ldap_close_destructor);
 
892
 
 
893
        dom->private_data = ctx;
 
894
 
 
895
        talloc_free(config_option);
 
896
        return NT_STATUS_OK;
 
897
 
 
898
/*failed */
 
899
done:
 
900
        talloc_free(ctx);
 
901
        return ret;
 
902
}
 
903
 
 
904
/* max number of ids requested per batch query */
 
905
#define IDMAP_LDAP_MAX_IDS 30
 
906
 
 
907
/**********************************
 
908
 lookup a set of unix ids.
 
909
**********************************/
 
910
 
 
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,
 
914
                                     enum id_type type,
 
915
                                     uint32_t id)
 
916
{
 
917
        int i;
 
918
 
 
919
        for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
 
920
                if (maps[i] == NULL) { /* end of the run */
 
921
                        return NULL;
 
922
                }
 
923
                if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
 
924
                        return maps[i];
 
925
                }
 
926
        }
 
927
 
 
928
        return NULL;
 
929
}
 
930
 
 
931
static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
 
932
                                           struct id_map **ids)
 
933
{
 
934
        NTSTATUS ret;
 
935
        TALLOC_CTX *memctx;
 
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;
 
942
        char *filter = NULL;
 
943
        bool multi = False;
 
944
        int idx = 0;
 
945
        int bidx = 0;
 
946
        int count;
 
947
        int rc;
 
948
        int i;
 
949
 
 
950
        /* Only do query if we are online */
 
951
        if (idmap_is_offline()) {
 
952
                return NT_STATUS_FILE_IS_OFFLINE;
 
953
        }
 
954
 
 
955
        ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
 
956
 
 
957
        memctx = talloc_new(ctx);
 
958
        if ( ! memctx) {
 
959
                DEBUG(0, ("Out of memory!\n"));
 
960
                return NT_STATUS_NO_MEMORY;
 
961
        }
 
962
 
 
963
        uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
 
964
        gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
 
965
 
 
966
        attr_list = get_attr_list(memctx, sidmap_attr_list);
 
967
 
 
968
        if ( ! ids[1]) {
 
969
                /* if we are requested just one mapping use the simple filter */
 
970
 
 
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));
 
977
        } else {
 
978
                /* multiple mappings */
 
979
                multi = True;
 
980
        }
 
981
 
 
982
        for (i = 0; ids[i]; i++) {
 
983
                ids[i]->status = ID_UNKNOWN;
 
984
        }
 
985
 
 
986
again:
 
987
        if (multi) {
 
988
 
 
989
                talloc_free(filter);
 
990
                filter = talloc_asprintf(memctx,
 
991
                                         "(&(objectClass=%s)(|",
 
992
                                         LDAP_OBJ_IDMAP_ENTRY);
 
993
                CHECK_ALLOC_DONE(filter);
 
994
 
 
995
                bidx = idx;
 
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);
 
1001
                }
 
1002
                filter = talloc_asprintf_append_buffer(filter, "))");
 
1003
                CHECK_ALLOC_DONE(filter);
 
1004
                DEBUG(10, ("Filter: [%s]\n", filter));
 
1005
        } else {
 
1006
                bidx = 0;
 
1007
                idx = 1;
 
1008
        }
 
1009
 
 
1010
        rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
 
1011
                filter, attr_list, 0, &result);
 
1012
 
 
1013
        if (rc != LDAP_SUCCESS) {
 
1014
                DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
 
1015
                ret = NT_STATUS_UNSUCCESSFUL;
 
1016
                goto done;
 
1017
        }
 
1018
 
 
1019
        count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
 
1020
 
 
1021
        if (count == 0) {
 
1022
                DEBUG(10, ("NO SIDs found\n"));
 
1023
        }
 
1024
 
 
1025
        for (i = 0; i < count; i++) {
 
1026
                char *sidstr = NULL;
 
1027
                char *tmp = NULL;
 
1028
                enum id_type type;
 
1029
                struct id_map *map;
 
1030
                uint32_t id;
 
1031
 
 
1032
                if (i == 0) { /* first entry */
 
1033
                        entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
 
1034
                                                 result);
 
1035
                } else { /* following ones */
 
1036
                        entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
 
1037
                                                entry);
 
1038
                }
 
1039
                if ( ! entry) {
 
1040
                        DEBUG(2, ("ERROR: Unable to fetch ldap entries "
 
1041
                                  "from results\n"));
 
1042
                        break;
 
1043
                }
 
1044
 
 
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"));
 
1051
                        continue;
 
1052
                }
 
1053
 
 
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
 
1057
                 *not the gid) */
 
1058
                type = ID_TYPE_UID;
 
1059
                tmp = smbldap_talloc_single_attribute(
 
1060
                                ctx->smbldap_state->ldap_struct,
 
1061
                                entry, uidNumber, memctx);
 
1062
                if ( ! tmp) {
 
1063
                        type = ID_TYPE_GID;
 
1064
                        tmp = smbldap_talloc_single_attribute(
 
1065
                                        ctx->smbldap_state->ldap_struct,
 
1066
                                        entry, gidNumber, memctx);
 
1067
                }
 
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);
 
1072
                        continue;
 
1073
                }
 
1074
 
 
1075
                id = strtoul(tmp, NULL, 10);
 
1076
                if ((id == 0) ||
 
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). "
 
1080
                                  "Filtered!\n", id,
 
1081
                                  ctx->filter_low_id, ctx->filter_high_id));
 
1082
                        TALLOC_FREE(sidstr);
 
1083
                        TALLOC_FREE(tmp);
 
1084
                        continue;
 
1085
                }
 
1086
                TALLOC_FREE(tmp);
 
1087
 
 
1088
                map = find_map_by_id(&ids[bidx], type, id);
 
1089
                if (!map) {
 
1090
                        DEBUG(2, ("WARNING: couldn't match sid (%s) "
 
1091
                                  "with requested ids\n", sidstr));
 
1092
                        TALLOC_FREE(sidstr);
 
1093
                        continue;
 
1094
                }
 
1095
 
 
1096
                if ( ! string_to_sid(map->sid, sidstr)) {
 
1097
                        DEBUG(2, ("ERROR: Invalid SID on entry\n"));
 
1098
                        TALLOC_FREE(sidstr);
 
1099
                        continue;
 
1100
                }
 
1101
 
 
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));
 
1107
                }
 
1108
 
 
1109
                TALLOC_FREE(sidstr);
 
1110
 
 
1111
                /* mapped */
 
1112
                map->status = ID_MAPPED;
 
1113
 
 
1114
                DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
 
1115
                           (unsigned long)map->xid.id, map->xid.type));
 
1116
        }
 
1117
 
 
1118
        /* free the ldap results */
 
1119
        if (result) {
 
1120
                ldap_msgfree(result);
 
1121
                result = NULL;
 
1122
        }
 
1123
 
 
1124
        if (multi && ids[idx]) { /* still some values to map */
 
1125
                goto again;
 
1126
        }
 
1127
 
 
1128
        ret = NT_STATUS_OK;
 
1129
 
 
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;
 
1134
        }
 
1135
 
 
1136
done:
 
1137
        talloc_free(memctx);
 
1138
        return ret;
 
1139
}
 
1140
 
 
1141
/**********************************
 
1142
 lookup a set of sids.
 
1143
**********************************/
 
1144
 
 
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)
 
1148
{
 
1149
        int i;
 
1150
 
 
1151
        for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
 
1152
                if (maps[i] == NULL) { /* end of the run */
 
1153
                        return NULL;
 
1154
                }
 
1155
                if (sid_equal(maps[i]->sid, sid)) {
 
1156
                        return maps[i];
 
1157
                }
 
1158
        }
 
1159
 
 
1160
        return NULL;
 
1161
}
 
1162
 
 
1163
static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
 
1164
                                           struct id_map **ids)
 
1165
{
 
1166
        LDAPMessage *entry = NULL;
 
1167
        NTSTATUS ret;
 
1168
        TALLOC_CTX *memctx;
 
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;
 
1175
        bool multi = False;
 
1176
        int idx = 0;
 
1177
        int bidx = 0;
 
1178
        int count;
 
1179
        int rc;
 
1180
        int i;
 
1181
 
 
1182
        /* Only do query if we are online */
 
1183
        if (idmap_is_offline()) {
 
1184
                return NT_STATUS_FILE_IS_OFFLINE;
 
1185
        }
 
1186
 
 
1187
        ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
 
1188
 
 
1189
        memctx = talloc_new(ctx);
 
1190
        if ( ! memctx) {
 
1191
                DEBUG(0, ("Out of memory!\n"));
 
1192
                return NT_STATUS_NO_MEMORY;
 
1193
        }
 
1194
 
 
1195
        uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
 
1196
        gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
 
1197
 
 
1198
        attr_list = get_attr_list(memctx, sidmap_attr_list);
 
1199
 
 
1200
        if ( ! ids[1]) {
 
1201
                /* if we are requested just one mapping use the simple filter */
 
1202
 
 
1203
                filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
 
1204
                                LDAP_OBJ_IDMAP_ENTRY,
 
1205
                                LDAP_ATTRIBUTE_SID,
 
1206
                                sid_string_talloc(memctx, ids[0]->sid));
 
1207
                CHECK_ALLOC_DONE(filter);
 
1208
                DEBUG(10, ("Filter: [%s]\n", filter));
 
1209
        } else {
 
1210
                /* multiple mappings */
 
1211
                multi = True;
 
1212
        }
 
1213
 
 
1214
        for (i = 0; ids[i]; i++) {
 
1215
                ids[i]->status = ID_UNKNOWN;
 
1216
        }
 
1217
 
 
1218
again:
 
1219
        if (multi) {
 
1220
 
 
1221
                TALLOC_FREE(filter);
 
1222
                filter = talloc_asprintf(memctx,
 
1223
                                         "(&(objectClass=%s)(|",
 
1224
                                         LDAP_OBJ_IDMAP_ENTRY);
 
1225
                CHECK_ALLOC_DONE(filter);
 
1226
 
 
1227
                bidx = idx;
 
1228
                for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
 
1229
                        filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
 
1230
                                        LDAP_ATTRIBUTE_SID,
 
1231
                                        sid_string_talloc(memctx,
 
1232
                                                          ids[idx]->sid));
 
1233
                        CHECK_ALLOC_DONE(filter);
 
1234
                }
 
1235
                filter = talloc_asprintf_append_buffer(filter, "))");
 
1236
                CHECK_ALLOC_DONE(filter);
 
1237
                DEBUG(10, ("Filter: [%s]", filter));
 
1238
        } else {
 
1239
                bidx = 0;
 
1240
                idx = 1;
 
1241
        }
 
1242
 
 
1243
        rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
 
1244
                filter, attr_list, 0, &result);
 
1245
 
 
1246
        if (rc != LDAP_SUCCESS) {
 
1247
                DEBUG(3,("Failure looking up sids (%s)\n",
 
1248
                         ldap_err2string(rc)));
 
1249
                ret = NT_STATUS_UNSUCCESSFUL;
 
1250
                goto done;
 
1251
        }
 
1252
 
 
1253
        count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
 
1254
 
 
1255
        if (count == 0) {
 
1256
                DEBUG(10, ("NO SIDs found\n"));
 
1257
        }
 
1258
 
 
1259
        for (i = 0; i < count; i++) {
 
1260
                char *sidstr = NULL;
 
1261
                char *tmp = NULL;
 
1262
                enum id_type type;
 
1263
                struct id_map *map;
 
1264
                DOM_SID sid;
 
1265
                uint32_t id;
 
1266
 
 
1267
                if (i == 0) { /* first entry */
 
1268
                        entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
 
1269
                                                 result);
 
1270
                } else { /* following ones */
 
1271
                        entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
 
1272
                                                entry);
 
1273
                }
 
1274
                if ( ! entry) {
 
1275
                        DEBUG(2, ("ERROR: Unable to fetch ldap entries "
 
1276
                                  "from results\n"));
 
1277
                        break;
 
1278
                }
 
1279
 
 
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"));
 
1286
                        continue;
 
1287
                }
 
1288
 
 
1289
                if ( ! string_to_sid(&sid, sidstr)) {
 
1290
                        DEBUG(2, ("ERROR: Invalid SID on entry\n"));
 
1291
                        TALLOC_FREE(sidstr);
 
1292
                        continue;
 
1293
                }
 
1294
 
 
1295
                map = find_map_by_sid(&ids[bidx], &sid);
 
1296
                if (!map) {
 
1297
                        DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
 
1298
                                  "in ids", sidstr));
 
1299
                        TALLOC_FREE(sidstr);
 
1300
                        continue;
 
1301
                }
 
1302
 
 
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
 
1306
                 * not the gid) */
 
1307
                type = ID_TYPE_UID;
 
1308
                tmp = smbldap_talloc_single_attribute(
 
1309
                                ctx->smbldap_state->ldap_struct,
 
1310
                                entry, uidNumber, memctx);
 
1311
                if ( ! tmp) {
 
1312
                        type = ID_TYPE_GID;
 
1313
                        tmp = smbldap_talloc_single_attribute(
 
1314
                                        ctx->smbldap_state->ldap_struct,
 
1315
                                        entry, gidNumber, memctx);
 
1316
                }
 
1317
                if ( ! tmp) { /* no ids ?? */
 
1318
                        DEBUG(5, ("no uidNumber, "
 
1319
                                  "nor gidNumber attributes found\n"));
 
1320
                        TALLOC_FREE(sidstr);
 
1321
                        continue;
 
1322
                }
 
1323
 
 
1324
                id = strtoul(tmp, NULL, 10);
 
1325
                if ((id == 0) ||
 
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). "
 
1329
                                  "Filtered!\n", id,
 
1330
                                  ctx->filter_low_id, ctx->filter_high_id));
 
1331
                        TALLOC_FREE(sidstr);
 
1332
                        TALLOC_FREE(tmp);
 
1333
                        continue;
 
1334
                }
 
1335
                TALLOC_FREE(tmp);
 
1336
 
 
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));
 
1342
                }
 
1343
 
 
1344
                TALLOC_FREE(sidstr);
 
1345
 
 
1346
                /* mapped */
 
1347
                map->xid.type = type;
 
1348
                map->xid.id = id;
 
1349
                map->status = ID_MAPPED;
 
1350
 
 
1351
                DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
 
1352
                           (unsigned long)map->xid.id, map->xid.type));
 
1353
        }
 
1354
 
 
1355
        /* free the ldap results */
 
1356
        if (result) {
 
1357
                ldap_msgfree(result);
 
1358
                result = NULL;
 
1359
        }
 
1360
 
 
1361
        if (multi && ids[idx]) { /* still some values to map */
 
1362
                goto again;
 
1363
        }
 
1364
 
 
1365
        ret = NT_STATUS_OK;
 
1366
 
 
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;
 
1371
        }
 
1372
 
 
1373
done:
 
1374
        talloc_free(memctx);
 
1375
        return ret;
 
1376
}
 
1377
 
 
1378
/**********************************
 
1379
 set a mapping.
 
1380
**********************************/
 
1381
 
 
1382
/* TODO: change this:  This function cannot be called to modify a mapping,
 
1383
 * only set a new one */
 
1384
 
 
1385
static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
 
1386
                                       const struct id_map *map)
 
1387
{
 
1388
        NTSTATUS ret;
 
1389
        TALLOC_CTX *memctx;
 
1390
        struct idmap_ldap_context *ctx;
 
1391
        LDAPMessage *entry = NULL;
 
1392
        LDAPMod **mods = NULL;
 
1393
        const char *type;
 
1394
        char *id_str;
 
1395
        char *sid;
 
1396
        char *dn;
 
1397
        int rc = -1;
 
1398
 
 
1399
        /* Only do query if we are online */
 
1400
        if (idmap_is_offline()) {
 
1401
                return NT_STATUS_FILE_IS_OFFLINE;
 
1402
        }
 
1403
 
 
1404
        ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
 
1405
 
 
1406
        switch(map->xid.type) {
 
1407
        case ID_TYPE_UID:
 
1408
                type = get_attr_key2string(sidmap_attr_list,
 
1409
                                           LDAP_ATTR_UIDNUMBER);
 
1410
                break;
 
1411
 
 
1412
        case ID_TYPE_GID:
 
1413
                type = get_attr_key2string(sidmap_attr_list,
 
1414
                                           LDAP_ATTR_GIDNUMBER);
 
1415
                break;
 
1416
 
 
1417
        default:
 
1418
                return NT_STATUS_INVALID_PARAMETER;
 
1419
        }
 
1420
 
 
1421
        memctx = talloc_new(ctx);
 
1422
        if ( ! memctx) {
 
1423
                DEBUG(0, ("Out of memory!\n"));
 
1424
                return NT_STATUS_NO_MEMORY;
 
1425
        }
 
1426
 
 
1427
        id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
 
1428
        CHECK_ALLOC_DONE(id_str);
 
1429
 
 
1430
        sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
 
1431
        CHECK_ALLOC_DONE(sid);
 
1432
 
 
1433
        dn = talloc_asprintf(memctx, "%s=%s,%s",
 
1434
                        get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
 
1435
                        sid,
 
1436
                        ctx->suffix);
 
1437
        CHECK_ALLOC_DONE(dn);
 
1438
 
 
1439
        smbldap_set_mod(&mods, LDAP_MOD_ADD,
 
1440
                        "objectClass", LDAP_OBJ_IDMAP_ENTRY);
 
1441
 
 
1442
        smbldap_make_mod(ctx->smbldap_state->ldap_struct,
 
1443
                         entry, &mods, type, id_str);
 
1444
 
 
1445
        smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
 
1446
                         get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
 
1447
                         sid);
 
1448
 
 
1449
        if ( ! mods) {
 
1450
                DEBUG(2, ("ERROR: No mods?\n"));
 
1451
                ret = NT_STATUS_UNSUCCESSFUL;
 
1452
                goto done;
 
1453
        }
 
1454
 
 
1455
        /* TODO: remove conflicting mappings! */
 
1456
 
 
1457
        smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
 
1458
 
 
1459
        DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
 
1460
 
 
1461
        rc = smbldap_add(ctx->smbldap_state, dn, mods);
 
1462
        ldap_mods_free(mods, True);
 
1463
 
 
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)));
 
1473
                if (ld_error) {
 
1474
                        ldap_memfree(ld_error);
 
1475
                }
 
1476
                ret = NT_STATUS_UNSUCCESSFUL;
 
1477
                goto done;
 
1478
        }
 
1479
 
 
1480
        DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
 
1481
                  "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
 
1482
 
 
1483
        ret = NT_STATUS_OK;
 
1484
 
 
1485
done:
 
1486
        talloc_free(memctx);
 
1487
        return ret;
 
1488
}
 
1489
 
 
1490
/**********************************
 
1491
 Close the idmap ldap instance
 
1492
**********************************/
 
1493
 
 
1494
static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
 
1495
{
 
1496
        struct idmap_ldap_context *ctx;
 
1497
 
 
1498
        if (dom->private_data) {
 
1499
                ctx = talloc_get_type(dom->private_data,
 
1500
                                      struct idmap_ldap_context);
 
1501
 
 
1502
                talloc_free(ctx);
 
1503
                dom->private_data = NULL;
 
1504
        }
 
1505
 
 
1506
        return NT_STATUS_OK;
 
1507
}
 
1508
 
 
1509
static struct idmap_methods idmap_ldap_methods = {
 
1510
 
 
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
 
1516
};
 
1517
 
 
1518
static struct idmap_alloc_methods idmap_ldap_alloc_methods = {
 
1519
 
 
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 */
 
1526
};
 
1527
 
 
1528
static NTSTATUS idmap_alloc_ldap_init(void)
 
1529
{
 
1530
        return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap",
 
1531
                                        &idmap_ldap_alloc_methods);
 
1532
}
 
1533
 
 
1534
NTSTATUS idmap_ldap_init(void);
 
1535
NTSTATUS idmap_ldap_init(void)
 
1536
{
 
1537
        NTSTATUS ret;
 
1538
 
 
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)) {
 
1543
                return ret;
 
1544
        }
 
1545
        return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
 
1546
                                  &idmap_ldap_methods);
 
1547
}
 
1548