~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/winbindd/idmap_adex/provider_unified.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
 * idmap_adex
 
3
 *
 
4
 * Provider for RFC2307 and SFU AD Forests
 
5
 *
 
6
 * Copyright (C) Gerald (Jerry) Carter 2006-2008
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
 */
 
22
 
 
23
#include "includes.h"
 
24
#include "idmap_adex.h"
 
25
 
 
26
#undef DBGC_CLASS
 
27
#define DBGC_CLASS DBGC_IDMAP
 
28
 
 
29
/* Information needed by the LDAP search filters */
 
30
 
 
31
enum filterType { SidFilter, IdFilter, AliasFilter };
 
32
 
 
33
struct lwcell_filter
 
34
{
 
35
        enum filterType ftype;
 
36
        bool use2307;
 
37
        union {
 
38
                DOM_SID sid;
 
39
                struct {
 
40
                        uint32_t id;
 
41
                        enum id_type type;
 
42
                } id;
 
43
                fstring alias;
 
44
        } filter;
 
45
};
 
46
 
 
47
/********************************************************************
 
48
 *******************************************************************/
 
49
 
 
50
static char* build_id_filter(uint32_t id,
 
51
                             enum id_type type,
 
52
                             uint32_t search_flags)
 
53
{
 
54
        char *filter = NULL;
 
55
        char *oc_filter, *attr_filter;
 
56
        NTSTATUS nt_status;
 
57
        TALLOC_CTX *frame = talloc_stackframe();
 
58
        bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
 
59
                        == LWCELL_FLAG_USE_RFC2307_ATTRS);
 
60
        bool use_gc = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
 
61
                       == LWCELL_FLAG_SEARCH_FOREST);
 
62
        const char *oc;
 
63
 
 
64
        /* Construct search filter for objectclass and attributes */
 
65
 
 
66
        switch (type) {
 
67
        case ID_TYPE_UID:
 
68
                oc = ADEX_OC_USER;
 
69
                if (use2307) {
 
70
                        oc = ADEX_OC_POSIX_USER;
 
71
                        if (use_gc) {
 
72
                                oc = AD_USER;
 
73
                        }
 
74
                }
 
75
                oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
 
76
                attr_filter = talloc_asprintf(frame, "%s=%u",
 
77
                                              ADEX_ATTR_UIDNUM, id);
 
78
                break;
 
79
 
 
80
        case ID_TYPE_GID:
 
81
                oc = ADEX_OC_GROUP;
 
82
                if (use2307) {
 
83
                        oc = ADEX_OC_POSIX_GROUP;
 
84
                        if (use_gc) {
 
85
                                oc = AD_GROUP;
 
86
                        }
 
87
                }
 
88
                oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
 
89
                attr_filter = talloc_asprintf(frame, "%s=%u",
 
90
                                              ADEX_ATTR_GIDNUM, id);
 
91
                break;
 
92
        default:
 
93
                return NULL;
 
94
        }
 
95
 
 
96
        BAIL_ON_PTR_ERROR(oc_filter, nt_status);
 
97
        BAIL_ON_PTR_ERROR(attr_filter, nt_status);
 
98
 
 
99
        /* Use "keywords=%s" for non-schema cells */
 
100
 
 
101
        if (use2307) {
 
102
                filter = talloc_asprintf(frame, "(&(%s)(%s))",
 
103
                                         oc_filter, attr_filter);
 
104
        } else {
 
105
                filter = talloc_asprintf(frame, "(&(keywords=%s)(keywords=%s))",
 
106
                                         oc_filter, attr_filter);
 
107
        }
 
108
 
 
109
        talloc_destroy(oc_filter);
 
110
        talloc_destroy(attr_filter);
 
111
 
 
112
done:
 
113
        /* Don't destroy the stackframe CTX since we are returning
 
114
           memory from it */
 
115
 
 
116
        return filter;
 
117
}
 
118
 
 
119
/********************************************************************
 
120
 *******************************************************************/
 
121
 
 
122
static char* build_alias_filter(const char *alias, uint32_t search_flags)
 
123
{
 
124
        char *filter = NULL;
 
125
        char *user_attr_filter, *group_attr_filter;
 
126
        NTSTATUS nt_status;
 
127
        TALLOC_CTX *frame = talloc_stackframe();
 
128
        bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
 
129
                        == LWCELL_FLAG_USE_RFC2307_ATTRS);
 
130
        bool search_forest = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
 
131
                              == LWCELL_FLAG_SEARCH_FOREST);
 
132
 
 
133
        /* Construct search filter for objectclass and attributes */
 
134
 
 
135
        user_attr_filter = talloc_asprintf(frame, "%s=%s",
 
136
                                           ADEX_ATTR_UID, alias);
 
137
        group_attr_filter = talloc_asprintf(frame, "%s=%s",
 
138
                                            ADEX_ATTR_DISPLAYNAME, alias);
 
139
        BAIL_ON_PTR_ERROR(user_attr_filter, nt_status);
 
140
        BAIL_ON_PTR_ERROR(group_attr_filter, nt_status);
 
141
 
 
142
        /* Use "keywords=%s" for non-schema cells */
 
143
 
 
144
        if (use2307) {
 
145
                filter = talloc_asprintf(frame,
 
146
                                         "(|(&(%s)(objectclass=%s))(&(%s)(objectclass=%s)))",
 
147
                                         user_attr_filter,
 
148
                                         search_forest ? AD_USER : ADEX_OC_POSIX_USER,
 
149
                                         group_attr_filter,
 
150
                                         search_forest ? AD_GROUP : ADEX_OC_POSIX_GROUP);
 
151
        } else {
 
152
                filter = talloc_asprintf(frame,
 
153
                                         "(|(keywords=%s)(keywords=%s))",
 
154
                                         user_attr_filter,
 
155
                                         group_attr_filter);
 
156
        }
 
157
 
 
158
        talloc_destroy(user_attr_filter);
 
159
        talloc_destroy(group_attr_filter);
 
160
 
 
161
done:
 
162
        /* Don't destroy the stackframe CTX since we are returning
 
163
           memory from it */
 
164
 
 
165
        return filter;
 
166
}
 
167
 
 
168
 
 
169
/********************************************************************
 
170
 *******************************************************************/
 
171
 
 
172
static NTSTATUS search_cell(struct likewise_cell *c,
 
173
                            LDAPMessage **msg,
 
174
                            const struct lwcell_filter *fdata)
 
175
{
 
176
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
177
        TALLOC_CTX* frame = talloc_stackframe();
 
178
        char *filter = NULL;
 
179
        const char *base = NULL;
 
180
        ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
 
181
        const char *attrs[] = { "*", NULL };
 
182
        int count;
 
183
        char *sid_str;
 
184
 
 
185
        /* get the filter and other search parameters */
 
186
 
 
187
        switch (fdata->ftype) {
 
188
        case SidFilter:
 
189
                sid_str = sid_string_talloc(frame, &fdata->filter.sid);
 
190
                BAIL_ON_PTR_ERROR(sid_str, nt_status);
 
191
 
 
192
                filter = talloc_asprintf(frame, "(keywords=backLink=%s)",
 
193
                                         sid_str);
 
194
                break;
 
195
        case IdFilter:
 
196
                filter = build_id_filter(fdata->filter.id.id,
 
197
                                         fdata->filter.id.type,
 
198
                                         cell_flags(c));
 
199
                break;
 
200
        case AliasFilter:
 
201
                filter = build_alias_filter(fdata->filter.alias,
 
202
                                            cell_flags(c));
 
203
                break;
 
204
        default:
 
205
                nt_status = NT_STATUS_INVALID_PARAMETER;
 
206
                break;
 
207
        }
 
208
        BAIL_ON_PTR_ERROR(filter, nt_status);
 
209
 
 
210
        base = cell_search_base(c);
 
211
        BAIL_ON_PTR_ERROR(base, nt_status);
 
212
 
 
213
        ads_status = cell_do_search(c, base, LDAP_SCOPE_SUBTREE,
 
214
                                    filter, attrs, msg);
 
215
 
 
216
        nt_status = ads_ntstatus(ads_status);
 
217
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
218
 
 
219
        /* Now check that we got only one reply */
 
220
 
 
221
        count = ads_count_replies(c->conn, *msg);
 
222
        if (count < 1) {
 
223
                nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
224
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
225
        }
 
226
 
 
227
        if ( count > 1) {
 
228
                nt_status = NT_STATUS_DUPLICATE_NAME;
 
229
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
230
        }
 
231
 
 
232
done:
 
233
        PRINT_NTSTATUS_ERROR(nt_status, "search_cell", 4);
 
234
 
 
235
        talloc_destroy(CONST_DISCARD(char*, base));
 
236
        talloc_destroy(frame);
 
237
 
 
238
        return nt_status;
 
239
}
 
240
 
 
241
/********************************************************************
 
242
 *******************************************************************/
 
243
 
 
244
static NTSTATUS search_domain(struct likewise_cell **cell,
 
245
                              LDAPMessage **msg,
 
246
                              const char *dn,
 
247
                              const DOM_SID *sid)
 
248
{
 
249
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
250
        TALLOC_CTX* frame = talloc_stackframe();
 
251
        int count;
 
252
 
 
253
        nt_status = dc_search_domains(cell, msg, dn, sid);
 
254
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
255
 
 
256
        /* Now check that we got only one reply */
 
257
 
 
258
        count = ads_count_replies(cell_connection(*cell), *msg);
 
259
        if (count < 1) {
 
260
                nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
261
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
262
        }
 
263
 
 
264
        if ( count > 1) {
 
265
                nt_status = NT_STATUS_DUPLICATE_NAME;
 
266
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
267
        }
 
268
 
 
269
done:
 
270
        PRINT_NTSTATUS_ERROR(nt_status, "search_domain", 4);
 
271
        talloc_destroy(frame);
 
272
 
 
273
        return nt_status;
 
274
}
 
275
 
 
276
 
 
277
/********************************************************************
 
278
 Check that a DN is within the forest scope.
 
279
 *******************************************************************/
 
280
 
 
281
static bool check_forest_scope(const char *dn)
 
282
{
 
283
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
284
        TALLOC_CTX *frame = talloc_stackframe();
 
285
        char *p = NULL;
 
286
        char *q = NULL;
 
287
        char *dns_domain = NULL;
 
288
        struct winbindd_tdc_domain *domain;
 
289
 
 
290
        /* If the DN does *not* contain "$LikewiseIdentityCell",
 
291
           assume this is a schema mode forest and it is in the
 
292
           forest scope by definition. */
 
293
 
 
294
        if ((p = strstr_m(dn, ADEX_CELL_RDN)) == NULL) {
 
295
                nt_status = NT_STATUS_OK;
 
296
                goto done;
 
297
        }
 
298
 
 
299
        /* If this is a non-schema forest, then make sure that the DN
 
300
           is in the form "...,cn=$LikewiseIdentityCell,DC=..." */
 
301
 
 
302
        if ((q = strchr_m(p, ',')) == NULL) {
 
303
                nt_status = NT_STATUS_OBJECT_NAME_INVALID;
 
304
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
305
        }
 
306
 
 
307
        q++;
 
308
        if (StrnCaseCmp(q, "dc=", 3) != 0) {
 
309
                nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
 
310
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
311
        }
 
312
 
 
313
 
 
314
        dns_domain = cell_dn_to_dns(q);
 
315
        BAIL_ON_PTR_ERROR(dns_domain, nt_status);
 
316
 
 
317
        domain = wcache_tdc_fetch_domain(frame, dns_domain);
 
318
        if (!domain) {
 
319
                nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
 
320
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
321
        }
 
322
 
 
323
        nt_status = NT_STATUS_OK;
 
324
 
 
325
done:
 
326
        talloc_destroy(frame);
 
327
        SAFE_FREE(dns_domain);
 
328
 
 
329
        return NT_STATUS_IS_OK(nt_status);
 
330
}
 
331
 
 
332
 
 
333
 
 
334
/********************************************************************
 
335
 Check that only one result was returned within the forest cell
 
336
 scope.
 
337
 *******************************************************************/
 
338
 
 
339
static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list,
 
340
                                           LDAPMessage **msg_list,
 
341
                                           int num_resp,
 
342
                                           char **dn,
 
343
                                           DOM_SID *user_sid)
 
344
{
 
345
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
346
        int i;
 
347
        ADS_STRUCT *ads = NULL;
 
348
        LDAPMessage *msg = NULL;
 
349
        int count = 0;
 
350
        char *entry_dn = NULL;
 
351
        TALLOC_CTX *frame = talloc_stackframe();
 
352
 
 
353
        if (!dn || !user_sid) {
 
354
                nt_status = NT_STATUS_INVALID_PARAMETER;
 
355
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
356
        }
 
357
 
 
358
        *dn = NULL;
 
359
 
 
360
        if (!ads_list || !msg_list || (num_resp == 0)) {
 
361
                nt_status = NT_STATUS_NO_SUCH_FILE;
 
362
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
363
        }
 
364
 
 
365
        /* Loop over all msgs */
 
366
 
 
367
        for (i=0; i<num_resp; i++) {
 
368
                LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]);
 
369
 
 
370
                while (e) {
 
371
                        entry_dn = ads_get_dn(ads_list[i], talloc_tos(), e);
 
372
                        BAIL_ON_PTR_ERROR(entry_dn, nt_status);
 
373
 
 
374
                        if (check_forest_scope(entry_dn)) {
 
375
                                count++;
 
376
 
 
377
                                /* If we've already broken the condition, no
 
378
                                   need to continue */
 
379
 
 
380
                                if (count > 1) {
 
381
                                        nt_status = NT_STATUS_DUPLICATE_NAME;
 
382
                                        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
383
                                }
 
384
 
 
385
                                ads = ads_list[i];
 
386
                                msg = e;
 
387
                                *dn = SMB_STRDUP(entry_dn);
 
388
                                BAIL_ON_PTR_ERROR((*dn), nt_status);
 
389
                        }
 
390
 
 
391
                        e = ads_next_entry(ads_list[i], e);
 
392
                        TALLOC_FREE(entry_dn);
 
393
                }
 
394
        }
 
395
 
 
396
        if (!ads || !msg) {
 
397
                nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
398
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
399
        }
 
400
 
 
401
        /* If we made is through the loop, then grab the user_sid and
 
402
           run home to base */
 
403
 
 
404
        /*
 
405
           Try and get the SID from either objectSid or keywords.
 
406
           We cannot use pull_sid() here since we want to try
 
407
           both methods and not only one or the other (and we
 
408
           have no full likewise_cell struct.
 
409
 
 
410
           Fail if both are unavailable
 
411
        */
 
412
 
 
413
        if (!ads_pull_sid(ads, msg, "objectSid", user_sid)) {
 
414
                char **keywords;
 
415
                char *s;
 
416
                size_t num_lines = 0;
 
417
 
 
418
                keywords = ads_pull_strings(ads, frame, msg, "keywords",
 
419
                                            &num_lines);
 
420
                BAIL_ON_PTR_ERROR(keywords, nt_status);
 
421
 
 
422
                s = find_attr_string(keywords, num_lines, "backLink");
 
423
                if (!s) {
 
424
                        nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
425
                        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
426
                }
 
427
 
 
428
                if (!string_to_sid(user_sid, s)) {
 
429
                        nt_status = NT_STATUS_INVALID_SID;
 
430
                        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
431
                }
 
432
        }
 
433
 
 
434
        nt_status = NT_STATUS_OK;
 
435
 
 
436
done:
 
437
        if (!NT_STATUS_IS_OK(nt_status)) {
 
438
                SAFE_FREE(*dn);
 
439
        }
 
440
 
 
441
        talloc_destroy(frame);
 
442
 
 
443
        return nt_status;
 
444
}
 
445
 
 
446
/********************************************************************
 
447
 Search all forests.  Each forest can have it's own forest-cell
 
448
 settings so we have to generate the filter for each search.
 
449
 We don't use gc_search_all_forests() since we may have a different
 
450
 schema model in each forest and need to construct the search
 
451
 filter for each GC search.
 
452
 *******************************************************************/
 
453
 
 
454
static NTSTATUS search_forest(struct likewise_cell *forest_cell,
 
455
                              LDAPMessage **msg,
 
456
                              const struct lwcell_filter *fdata)
 
457
{
 
458
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
459
        TALLOC_CTX *frame = talloc_stackframe();
 
460
        char *filter = NULL;
 
461
        char *dn = NULL;
 
462
        struct gc_info *gc = NULL;
 
463
        ADS_STRUCT **ads_list = NULL;
 
464
        LDAPMessage **msg_list = NULL;
 
465
        int num_resp = 0;
 
466
        LDAPMessage *m;
 
467
        DOM_SID user_sid;
 
468
        struct likewise_cell *domain_cell = NULL;
 
469
 
 
470
        if ((gc = gc_search_start()) == NULL) {
 
471
                nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
 
472
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
473
        }
 
474
 
 
475
        while (gc) {
 
476
                char *sid_binstr = NULL;
 
477
                uint32_t flags = LWCELL_FLAG_SEARCH_FOREST;
 
478
 
 
479
                m = NULL;
 
480
 
 
481
                flags |= cell_flags(gc->forest_cell);
 
482
 
 
483
                switch (fdata->ftype) {
 
484
                case SidFilter:
 
485
                        sid_binstr = sid_binstring(&fdata->filter.sid);
 
486
                        BAIL_ON_PTR_ERROR(sid_binstr, nt_status);
 
487
 
 
488
                        filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr);
 
489
                        SAFE_FREE(sid_binstr);
 
490
                        break;
 
491
                case IdFilter:
 
492
                        filter = build_id_filter(fdata->filter.id.id,
 
493
                                                 fdata->filter.id.type, flags);
 
494
                        break;
 
495
                case AliasFilter:
 
496
                        filter = build_alias_filter(fdata->filter.alias, flags);
 
497
                        break;
 
498
                }
 
499
 
 
500
                /* First find the sparse object in GC */
 
501
                nt_status = gc_search_forest(gc, &m, filter);
 
502
                if (!NT_STATUS_IS_OK(nt_status)) {
 
503
                        gc = gc->next;
 
504
                        continue;
 
505
                }
 
506
 
 
507
                nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
 
508
                                                    m, &ads_list, &msg_list,
 
509
                                                    &num_resp);
 
510
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
511
 
 
512
                gc = gc->next;
 
513
        }
 
514
 
 
515
        /* Uniqueness check across forests */
 
516
 
 
517
        nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp,
 
518
                                               &dn, &user_sid);
 
519
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
520
 
 
521
        nt_status = search_domain(&domain_cell, &m, dn, &user_sid);
 
522
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
523
 
 
524
        /* Save the connection and results in the return parameters */
 
525
 
 
526
        forest_cell->gc_search_cell = domain_cell;
 
527
        *msg = m;
 
528
 
 
529
done:
 
530
        PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4);
 
531
 
 
532
        SAFE_FREE(dn);
 
533
 
 
534
        free_result_array(ads_list, msg_list, num_resp);
 
535
        talloc_destroy(frame);
 
536
 
 
537
        return nt_status;
 
538
}
 
539
 
 
540
/********************************************************************
 
541
 *******************************************************************/
 
542
 
 
543
static NTSTATUS search_cell_list(struct likewise_cell **c,
 
544
                                 LDAPMessage **m,
 
545
                                 const struct lwcell_filter *fdata)
 
546
{
 
547
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
548
        struct likewise_cell *cell = NULL;
 
549
        LDAPMessage *msg = NULL;
 
550
        struct likewise_cell *result_cell = NULL;
 
551
 
 
552
        if ((cell = cell_list_head()) == NULL) {
 
553
                nt_status = NT_STATUS_INVALID_SERVER_STATE;
 
554
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
555
        }
 
556
 
 
557
        while (cell) {
 
558
                /* Clear any previous GC search results */
 
559
 
 
560
                cell->gc_search_cell = NULL;
 
561
 
 
562
                if (cell_search_forest(cell)) {
 
563
                        nt_status = search_forest(cell, &msg, fdata);
 
564
                } else {
 
565
                        nt_status = search_cell(cell, &msg, fdata);
 
566
                }
 
567
 
 
568
                /* Always point to the search result cell.
 
569
                   In forests this might be for another domain
 
570
                   which means the schema model may be different */
 
571
 
 
572
                result_cell = cell->gc_search_cell ?
 
573
                        cell->gc_search_cell : cell;
 
574
 
 
575
                /* Check if we are done */
 
576
 
 
577
                if (NT_STATUS_IS_OK(nt_status)) {
 
578
                        break;
 
579
                }
 
580
 
 
581
                /* No luck.  Free memory and hit the next cell.
 
582
                   Forest searches always set the gc_search_cell
 
583
                   so give preference to that connection if possible. */
 
584
 
 
585
                ads_msgfree(cell_connection(result_cell), msg);
 
586
                msg = NULL;
 
587
 
 
588
                cell = cell->next;
 
589
        }
 
590
 
 
591
        /* This might be assigning NULL but that is ok as long as we
 
592
           give back the proper error code */
 
593
 
 
594
        *c = result_cell;
 
595
        *m = msg;
 
596
 
 
597
done:
 
598
        PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3);
 
599
 
 
600
        return nt_status;
 
601
}
 
602
 
 
603
/********************************************************************
 
604
 Pull the SID from an object which is always stored in the keywords
 
605
 attribute as "backLink=S-1-5-21-..."
 
606
 *******************************************************************/
 
607
 
 
608
static NTSTATUS pull_sid(struct likewise_cell *c,
 
609
                         LDAPMessage *msg,
 
610
                         DOM_SID *sid)
 
611
{
 
612
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
613
        TALLOC_CTX *frame = talloc_stackframe();
 
614
        ADS_STRUCT *ads = NULL;
 
615
 
 
616
        ads = cell_connection(c);
 
617
 
 
618
        /*
 
619
           We have two ways of getting the sid:
 
620
           (a) from the objectSID in case of a GC search,
 
621
           (b) from backLink in the case of a cell search.
 
622
           Pull the keywords attributes and grab the backLink.
 
623
        */
 
624
 
 
625
        if (!ads_pull_sid(ads, msg, "objectSid", sid)) {
 
626
                char **keywords;
 
627
                char *s;
 
628
                size_t num_lines = 0;
 
629
 
 
630
                keywords = ads_pull_strings(ads, frame, msg,
 
631
                                            "keywords", &num_lines);
 
632
                BAIL_ON_PTR_ERROR(keywords, nt_status);
 
633
 
 
634
                s = find_attr_string(keywords, num_lines, "backLink");
 
635
                if (!s) {
 
636
                        nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
637
                        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
638
                }
 
639
 
 
640
                if (!string_to_sid(sid, s)) {
 
641
                        nt_status = NT_STATUS_INVALID_SID;
 
642
                        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
643
                }
 
644
        }
 
645
 
 
646
        nt_status = NT_STATUS_OK;
 
647
 
 
648
done:
 
649
        talloc_destroy(frame);
 
650
 
 
651
        return nt_status;
 
652
}
 
653
 
 
654
/********************************************************************
 
655
 *******************************************************************/
 
656
 
 
657
static NTSTATUS get_object_type(struct likewise_cell *c,
 
658
                                LDAPMessage *msg,
 
659
                                enum id_type *type)
 
660
{
 
661
        TALLOC_CTX *ctx = talloc_stackframe();
 
662
        char **oc_list = NULL;
 
663
        NTSTATUS nt_status = NT_STATUS_OK;
 
664
        size_t list_size = 0;
 
665
        char *s = NULL;
 
666
        ADS_STRUCT *ads = NULL;
 
667
 
 
668
        ads = cell_connection(c);
 
669
 
 
670
        /* Deal with RFC 2307 support first */
 
671
 
 
672
        if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
 
673
                oc_list = ads_pull_strings(ads, ctx, msg,
 
674
                                           "objectClass", &list_size);
 
675
                if (!oc_list) {
 
676
                        nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
677
                        goto done;
 
678
                }
 
679
 
 
680
                /* Check for posix classes and AD classes */
 
681
 
 
682
                if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER)
 
683
                    || is_object_class(oc_list, list_size, AD_USER)) {
 
684
                        *type = ID_TYPE_UID;
 
685
                } else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP)
 
686
                           || is_object_class(oc_list, list_size, AD_GROUP)) {
 
687
                        *type = ID_TYPE_GID;
 
688
                } else {
 
689
                        *type = ID_TYPE_NOT_SPECIFIED;
 
690
                        nt_status = NT_STATUS_INVALID_PARAMETER;
 
691
                }
 
692
        } else {
 
693
                /* Default to non-schema mode */
 
694
 
 
695
                oc_list = ads_pull_strings(ads, ctx, msg,
 
696
                                           "keywords", &list_size);
 
697
                if (!oc_list) {
 
698
                        nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
699
                        goto done;
 
700
                }
 
701
 
 
702
                s = find_attr_string(oc_list, list_size, "objectClass");
 
703
                if (!s) {
 
704
                        nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
705
                        goto done;
 
706
                }
 
707
 
 
708
                if (strequal(s, ADEX_OC_USER)) {
 
709
                        *type = ID_TYPE_UID;
 
710
                } else if (strequal(s, ADEX_OC_GROUP)) {
 
711
                        *type = ID_TYPE_GID;
 
712
                } else {
 
713
                        *type = ID_TYPE_NOT_SPECIFIED;
 
714
                        nt_status = NT_STATUS_INVALID_PARAMETER;
 
715
                }
 
716
        }
 
717
 
 
718
        nt_status = NT_STATUS_OK;
 
719
 
 
720
done:
 
721
        talloc_destroy(ctx);
 
722
 
 
723
        return nt_status;
 
724
}
 
725
 
 
726
/********************************************************************
 
727
 Pull an attribute uint32_t  value
 
728
 *******************************************************************/
 
729
 
 
730
static NTSTATUS get_object_uint32(struct likewise_cell *c,
 
731
                                  LDAPMessage *msg,
 
732
                                  const char *attrib,
 
733
                                  uint32_t *x)
 
734
{
 
735
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
736
        char **keywords = NULL;
 
737
        size_t list_size = 0;
 
738
        TALLOC_CTX *frame = talloc_stackframe();
 
739
        ADS_STRUCT *ads = NULL;
 
740
 
 
741
        ads = cell_connection(c);
 
742
 
 
743
        /* Deal with RFC2307 schema */
 
744
 
 
745
        if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
 
746
                if (!ads_pull_uint32(ads, msg, attrib, x)) {
 
747
                        nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
748
                        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
749
                }
 
750
        } else {
 
751
                /* Non-schema mode */
 
752
                char *s = NULL;
 
753
                uint32_t num;
 
754
 
 
755
                keywords = ads_pull_strings(ads, frame, msg, "keywords",
 
756
                                            &list_size);
 
757
                BAIL_ON_PTR_ERROR(keywords, nt_status);
 
758
 
 
759
                s = find_attr_string(keywords, list_size, attrib);
 
760
                if (!s) {
 
761
                        nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
762
                        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
763
                }
 
764
 
 
765
                num = strtoll(s, NULL, 10);
 
766
                if (errno == ERANGE) {
 
767
                        nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
768
                        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
769
                }
 
770
                *x = num;
 
771
        }
 
772
 
 
773
        nt_status = NT_STATUS_OK;
 
774
 
 
775
done:
 
776
        talloc_destroy(frame);
 
777
 
 
778
        return nt_status;
 
779
}
 
780
 
 
781
/********************************************************************
 
782
 *******************************************************************/
 
783
 
 
784
static NTSTATUS get_object_id(struct likewise_cell *c,
 
785
                              LDAPMessage *msg,
 
786
                              enum id_type type,
 
787
                              uint32_t *id)
 
788
{
 
789
        NTSTATUS nt_status = NT_STATUS_OK;
 
790
        const char *id_attr;
 
791
 
 
792
        /* Figure out which attribute we need to pull */
 
793
 
 
794
        switch (type) {
 
795
        case ID_TYPE_UID:
 
796
                id_attr = ADEX_ATTR_UIDNUM;
 
797
                break;
 
798
        case ID_TYPE_GID:
 
799
                id_attr = ADEX_ATTR_GIDNUM;
 
800
                break;
 
801
        default:
 
802
                nt_status = NT_STATUS_INVALID_PARAMETER;
 
803
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
804
                break;
 
805
        }
 
806
 
 
807
        nt_status = get_object_uint32(c, msg, id_attr, id);
 
808
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
809
 
 
810
done:
 
811
        return nt_status;
 
812
}
 
813
 
 
814
/********************************************************************
 
815
 Pull the uid/gid and type from an object.  This differs depending on
 
816
 the cell flags.
 
817
 *******************************************************************/
 
818
 
 
819
static NTSTATUS pull_id(struct likewise_cell *c,
 
820
                        LDAPMessage *msg,
 
821
                        uint32_t *id,
 
822
                        enum id_type *type)
 
823
{
 
824
        NTSTATUS nt_status;
 
825
 
 
826
        nt_status = get_object_type(c, msg, type);
 
827
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
828
 
 
829
        nt_status = get_object_id(c, msg, *type, id);
 
830
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
831
 
 
832
done:
 
833
        return nt_status;
 
834
}
 
835
 
 
836
/********************************************************************
 
837
 Pull an attribute string value
 
838
 *******************************************************************/
 
839
 
 
840
static NTSTATUS get_object_string(struct likewise_cell *c,
 
841
                                  LDAPMessage *msg,
 
842
                                  TALLOC_CTX *ctx,
 
843
                                  const char *attrib,
 
844
                                  char **string)
 
845
{
 
846
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
847
        char **keywords = NULL;
 
848
        size_t list_size = 0;
 
849
        TALLOC_CTX *frame = talloc_stackframe();
 
850
        ADS_STRUCT *ads = NULL;
 
851
 
 
852
        *string = NULL;
 
853
 
 
854
        ads = cell_connection(c);
 
855
 
 
856
        /* Deal with RFC2307 schema */
 
857
 
 
858
        if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
 
859
                *string = ads_pull_string(ads, ctx, msg, attrib);
 
860
        } else {
 
861
                /* Non-schema mode */
 
862
 
 
863
                char *s = NULL;
 
864
 
 
865
                keywords = ads_pull_strings(ads, frame, msg,
 
866
                                            "keywords", &list_size);
 
867
                if (!keywords) {
 
868
                        nt_status = NT_STATUS_NO_MEMORY;
 
869
                        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
870
                }
 
871
                s = find_attr_string(keywords, list_size, attrib);
 
872
                if (s) {
 
873
                        *string = talloc_strdup(ctx, s);
 
874
                }
 
875
        }
 
876
 
 
877
        if (!*string) {
 
878
                nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
879
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
880
        }
 
881
 
 
882
        nt_status = NT_STATUS_OK;
 
883
 
 
884
done:
 
885
        talloc_destroy(frame);
 
886
 
 
887
        return nt_status;
 
888
}
 
889
 
 
890
/********************************************************************
 
891
 Pull the struct passwd fields for a user
 
892
 *******************************************************************/
 
893
 
 
894
static NTSTATUS pull_nss_info(struct likewise_cell *c,
 
895
                              LDAPMessage *msg,
 
896
                              TALLOC_CTX *ctx,
 
897
                              char **homedir,
 
898
                              char **shell,
 
899
                              char **gecos,
 
900
                              gid_t *p_gid)
 
901
{
 
902
        NTSTATUS nt_status;
 
903
 
 
904
        nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, homedir);
 
905
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
906
 
 
907
        nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, shell);
 
908
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
909
 
 
910
        nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, gecos);
 
911
        /* Gecos is often not set so ignore failures */
 
912
 
 
913
        nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid);
 
914
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
915
 
 
916
done:
 
917
        return nt_status;
 
918
}
 
919
 
 
920
/********************************************************************
 
921
 Pull the struct passwd fields for a user
 
922
 *******************************************************************/
 
923
 
 
924
static NTSTATUS pull_alias(struct likewise_cell *c,
 
925
                           LDAPMessage *msg,
 
926
                           TALLOC_CTX *ctx,
 
927
                           char **alias)
 
928
{
 
929
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
930
        enum id_type type;
 
931
        const char *attr = NULL;
 
932
 
 
933
        /* Figure out if this is a user or a group */
 
934
 
 
935
        nt_status = get_object_type(c, msg, &type);
 
936
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
937
 
 
938
        switch (type) {
 
939
        case ID_TYPE_UID:
 
940
                attr = ADEX_ATTR_UID;
 
941
                break;
 
942
        case ID_TYPE_GID:
 
943
                /* What is the group attr for RFC2307 Forests? */
 
944
                attr = ADEX_ATTR_DISPLAYNAME;
 
945
                break;
 
946
        default:
 
947
                nt_status = NT_STATUS_INVALID_PARAMETER;
 
948
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
949
                break;
 
950
        }
 
951
 
 
952
        nt_status = get_object_string(c, msg, ctx, attr, alias);
 
953
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
954
 
 
955
done:
 
956
        return nt_status;
 
957
}
 
958
 
 
959
/********************************************************************
 
960
 *******************************************************************/
 
961
 
 
962
static NTSTATUS _ccp_get_sid_from_id(DOM_SID * sid,
 
963
                                     uint32_t id, enum id_type type)
 
964
{
 
965
        struct likewise_cell *cell = NULL;
 
966
        LDAPMessage *msg = NULL;
 
967
        NTSTATUS nt_status;
 
968
        struct lwcell_filter filter;
 
969
 
 
970
        filter.ftype = IdFilter;
 
971
        filter.filter.id.id = id;
 
972
        filter.filter.id.type = type;
 
973
 
 
974
        nt_status = search_cell_list(&cell, &msg, &filter);
 
975
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
976
 
 
977
        nt_status = pull_sid(cell, msg, sid);
 
978
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
979
 
 
980
done:
 
981
        ads_msgfree(cell->conn, msg);
 
982
 
 
983
        return nt_status;
 
984
}
 
985
 
 
986
/********************************************************************
 
987
 *******************************************************************/
 
988
 
 
989
static NTSTATUS _ccp_get_id_from_sid(uint32_t * id,
 
990
                                     enum id_type *type,
 
991
                                     const DOM_SID * sid)
 
992
{
 
993
        struct likewise_cell *cell = NULL;
 
994
        LDAPMessage *msg = NULL;
 
995
        NTSTATUS nt_status;
 
996
        struct lwcell_filter filter;
 
997
 
 
998
        filter.ftype = SidFilter;
 
999
        sid_copy(&filter.filter.sid, sid);
 
1000
 
 
1001
        nt_status = search_cell_list(&cell, &msg, &filter);
 
1002
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1003
 
 
1004
        nt_status = pull_id(cell, msg, id, type);
 
1005
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1006
 
 
1007
        if (*id < min_id_value()) {
 
1008
                nt_status = NT_STATUS_INVALID_PARAMETER;
 
1009
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1010
        }
 
1011
 
 
1012
done:
 
1013
        ads_msgfree(cell->conn, msg);
 
1014
 
 
1015
        return nt_status;
 
1016
}
 
1017
 
 
1018
/********************************************************************
 
1019
 *******************************************************************/
 
1020
 
 
1021
static NTSTATUS _ccp_nss_get_info(const DOM_SID * sid,
 
1022
                                  TALLOC_CTX * ctx,
 
1023
                                  char **homedir,
 
1024
                                  char **shell,
 
1025
                                  char **gecos, gid_t * p_gid)
 
1026
{
 
1027
        struct likewise_cell *cell = NULL;
 
1028
        LDAPMessage *msg = NULL;
 
1029
        NTSTATUS nt_status;
 
1030
        struct lwcell_filter filter;
 
1031
        enum id_type type;
 
1032
 
 
1033
        filter.ftype = SidFilter;
 
1034
        sid_copy(&filter.filter.sid, sid);
 
1035
 
 
1036
        nt_status = search_cell_list(&cell, &msg, &filter);
 
1037
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1038
 
 
1039
        nt_status = get_object_type(cell, msg, &type);
 
1040
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1041
 
 
1042
        if (type != ID_TYPE_UID) {
 
1043
                nt_status = NT_STATUS_NO_SUCH_USER;
 
1044
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1045
        }
 
1046
 
 
1047
        nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos,
 
1048
                                  (uint32_t*) p_gid);
 
1049
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1050
 
 
1051
done:
 
1052
        ads_msgfree(cell->conn, msg);
 
1053
 
 
1054
        return nt_status;
 
1055
}
 
1056
 
 
1057
/**********************************************************************
 
1058
 *********************************************************************/
 
1059
 
 
1060
static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx,
 
1061
                                  const char *domain,
 
1062
                                  const char *name, char **alias)
 
1063
{
 
1064
        TALLOC_CTX *frame = talloc_stackframe();
 
1065
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
1066
        DOM_SID sid;
 
1067
        struct likewise_cell *cell = NULL;
 
1068
        LDAPMessage *msg = NULL;
 
1069
        struct lwcell_filter filter;
 
1070
        enum lsa_SidType sid_type;
 
1071
 
 
1072
        /* Convert the name to a SID */
 
1073
 
 
1074
        nt_status = gc_name_to_sid(domain, name, &sid, &sid_type);
 
1075
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1076
 
 
1077
        /* Find the user/group */
 
1078
 
 
1079
        filter.ftype = SidFilter;
 
1080
        sid_copy(&filter.filter.sid, &sid);
 
1081
 
 
1082
        nt_status = search_cell_list(&cell, &msg, &filter);
 
1083
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1084
 
 
1085
        /* Pull the alias and return */
 
1086
 
 
1087
        nt_status = pull_alias(cell, msg, ctx, alias);
 
1088
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1089
 
 
1090
done:
 
1091
        PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3);
 
1092
 
 
1093
        talloc_destroy(frame);
 
1094
        ads_msgfree(cell_connection(cell), msg);
 
1095
 
 
1096
        return nt_status;
 
1097
}
 
1098
 
 
1099
/**********************************************************************
 
1100
 Map from an alias name to the canonical, qualified name.
 
1101
 Ensure that the alias is only pull from the closest in which
 
1102
 the user or gorup is enabled in
 
1103
 *********************************************************************/
 
1104
 
 
1105
static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx,
 
1106
                                    const char *domain,
 
1107
                                    const char *alias, char **name)
 
1108
{
 
1109
        TALLOC_CTX *frame = talloc_stackframe();
 
1110
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
1111
        DOM_SID sid;
 
1112
        struct likewise_cell *cell_alias = NULL;
 
1113
        LDAPMessage *msg_alias = NULL;
 
1114
        struct likewise_cell *cell_sid = NULL;
 
1115
        LDAPMessage *msg_sid = NULL;
 
1116
        struct lwcell_filter filter;
 
1117
        char *canonical_name = NULL;
 
1118
        enum lsa_SidType type;
 
1119
 
 
1120
        /* Find the user/group */
 
1121
 
 
1122
        filter.ftype = AliasFilter;
 
1123
        fstrcpy(filter.filter.alias, alias);
 
1124
 
 
1125
        nt_status = search_cell_list(&cell_alias, &msg_alias, &filter);
 
1126
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1127
 
 
1128
        nt_status = pull_sid(cell_alias, msg_alias, &sid);
 
1129
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1130
 
 
1131
        /* Now search again for the SID according to the cell list.
 
1132
           Verify that the cell of both search results is the same
 
1133
           so that we only match an alias from the closest cell
 
1134
           in which a user/group has been instantied. */
 
1135
 
 
1136
        filter.ftype = SidFilter;
 
1137
        sid_copy(&filter.filter.sid, &sid);
 
1138
 
 
1139
        nt_status = search_cell_list(&cell_sid, &msg_sid, &filter);
 
1140
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1141
 
 
1142
        if (cell_alias != cell_sid) {
 
1143
                nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
 
1144
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1145
        }
 
1146
 
 
1147
        /* Finally do the GC sid/name conversion */
 
1148
 
 
1149
        nt_status = gc_sid_to_name(&sid, &canonical_name, &type);
 
1150
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
1151
 
 
1152
        *name = talloc_strdup(mem_ctx, canonical_name);
 
1153
        BAIL_ON_PTR_ERROR((*name), nt_status);
 
1154
 
 
1155
        nt_status = NT_STATUS_OK;
 
1156
 
 
1157
done:
 
1158
        PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3);
 
1159
 
 
1160
        ads_msgfree(cell_connection(cell_alias), msg_alias);
 
1161
        ads_msgfree(cell_connection(cell_sid), msg_sid);
 
1162
 
 
1163
        SAFE_FREE(canonical_name);
 
1164
 
 
1165
        talloc_destroy(frame);
 
1166
 
 
1167
        return nt_status;
 
1168
}
 
1169
 
 
1170
/********************************************************************
 
1171
 *******************************************************************/
 
1172
 
 
1173
struct cell_provider_api ccp_unified = {
 
1174
        .get_sid_from_id = _ccp_get_sid_from_id,
 
1175
        .get_id_from_sid = _ccp_get_id_from_sid,
 
1176
        .get_nss_info    = _ccp_nss_get_info,
 
1177
        .map_to_alias    = _ccp_map_to_alias,
 
1178
        .map_from_alias  = _ccp_map_from_alias
 
1179
};