4
* Provider for RFC2307 and SFU AD Forests
6
* Copyright (C) Gerald (Jerry) Carter 2006-2008
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.
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.
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.
24
#include "idmap_adex.h"
27
#define DBGC_CLASS DBGC_IDMAP
29
/* Information needed by the LDAP search filters */
31
enum filterType { SidFilter, IdFilter, AliasFilter };
35
enum filterType ftype;
47
/********************************************************************
48
*******************************************************************/
50
static char* build_id_filter(uint32_t id,
52
uint32_t search_flags)
55
char *oc_filter, *attr_filter;
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);
64
/* Construct search filter for objectclass and attributes */
70
oc = ADEX_OC_POSIX_USER;
75
oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
76
attr_filter = talloc_asprintf(frame, "%s=%u",
77
ADEX_ATTR_UIDNUM, id);
83
oc = ADEX_OC_POSIX_GROUP;
88
oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
89
attr_filter = talloc_asprintf(frame, "%s=%u",
90
ADEX_ATTR_GIDNUM, id);
96
BAIL_ON_PTR_ERROR(oc_filter, nt_status);
97
BAIL_ON_PTR_ERROR(attr_filter, nt_status);
99
/* Use "keywords=%s" for non-schema cells */
102
filter = talloc_asprintf(frame, "(&(%s)(%s))",
103
oc_filter, attr_filter);
105
filter = talloc_asprintf(frame, "(&(keywords=%s)(keywords=%s))",
106
oc_filter, attr_filter);
109
talloc_destroy(oc_filter);
110
talloc_destroy(attr_filter);
113
/* Don't destroy the stackframe CTX since we are returning
119
/********************************************************************
120
*******************************************************************/
122
static char* build_alias_filter(const char *alias, uint32_t search_flags)
125
char *user_attr_filter, *group_attr_filter;
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);
133
/* Construct search filter for objectclass and attributes */
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);
142
/* Use "keywords=%s" for non-schema cells */
145
filter = talloc_asprintf(frame,
146
"(|(&(%s)(objectclass=%s))(&(%s)(objectclass=%s)))",
148
search_forest ? AD_USER : ADEX_OC_POSIX_USER,
150
search_forest ? AD_GROUP : ADEX_OC_POSIX_GROUP);
152
filter = talloc_asprintf(frame,
153
"(|(keywords=%s)(keywords=%s))",
158
talloc_destroy(user_attr_filter);
159
talloc_destroy(group_attr_filter);
162
/* Don't destroy the stackframe CTX since we are returning
169
/********************************************************************
170
*******************************************************************/
172
static NTSTATUS search_cell(struct likewise_cell *c,
174
const struct lwcell_filter *fdata)
176
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
177
TALLOC_CTX* frame = talloc_stackframe();
179
const char *base = NULL;
180
ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
181
const char *attrs[] = { "*", NULL };
185
/* get the filter and other search parameters */
187
switch (fdata->ftype) {
189
sid_str = sid_string_talloc(frame, &fdata->filter.sid);
190
BAIL_ON_PTR_ERROR(sid_str, nt_status);
192
filter = talloc_asprintf(frame, "(keywords=backLink=%s)",
196
filter = build_id_filter(fdata->filter.id.id,
197
fdata->filter.id.type,
201
filter = build_alias_filter(fdata->filter.alias,
205
nt_status = NT_STATUS_INVALID_PARAMETER;
208
BAIL_ON_PTR_ERROR(filter, nt_status);
210
base = cell_search_base(c);
211
BAIL_ON_PTR_ERROR(base, nt_status);
213
ads_status = cell_do_search(c, base, LDAP_SCOPE_SUBTREE,
216
nt_status = ads_ntstatus(ads_status);
217
BAIL_ON_NTSTATUS_ERROR(nt_status);
219
/* Now check that we got only one reply */
221
count = ads_count_replies(c->conn, *msg);
223
nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
224
BAIL_ON_NTSTATUS_ERROR(nt_status);
228
nt_status = NT_STATUS_DUPLICATE_NAME;
229
BAIL_ON_NTSTATUS_ERROR(nt_status);
233
PRINT_NTSTATUS_ERROR(nt_status, "search_cell", 4);
235
talloc_destroy(CONST_DISCARD(char*, base));
236
talloc_destroy(frame);
241
/********************************************************************
242
*******************************************************************/
244
static NTSTATUS search_domain(struct likewise_cell **cell,
249
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
250
TALLOC_CTX* frame = talloc_stackframe();
253
nt_status = dc_search_domains(cell, msg, dn, sid);
254
BAIL_ON_NTSTATUS_ERROR(nt_status);
256
/* Now check that we got only one reply */
258
count = ads_count_replies(cell_connection(*cell), *msg);
260
nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
261
BAIL_ON_NTSTATUS_ERROR(nt_status);
265
nt_status = NT_STATUS_DUPLICATE_NAME;
266
BAIL_ON_NTSTATUS_ERROR(nt_status);
270
PRINT_NTSTATUS_ERROR(nt_status, "search_domain", 4);
271
talloc_destroy(frame);
277
/********************************************************************
278
Check that a DN is within the forest scope.
279
*******************************************************************/
281
static bool check_forest_scope(const char *dn)
283
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
284
TALLOC_CTX *frame = talloc_stackframe();
287
char *dns_domain = NULL;
288
struct winbindd_tdc_domain *domain;
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. */
294
if ((p = strstr_m(dn, ADEX_CELL_RDN)) == NULL) {
295
nt_status = NT_STATUS_OK;
299
/* If this is a non-schema forest, then make sure that the DN
300
is in the form "...,cn=$LikewiseIdentityCell,DC=..." */
302
if ((q = strchr_m(p, ',')) == NULL) {
303
nt_status = NT_STATUS_OBJECT_NAME_INVALID;
304
BAIL_ON_NTSTATUS_ERROR(nt_status);
308
if (StrnCaseCmp(q, "dc=", 3) != 0) {
309
nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
310
BAIL_ON_NTSTATUS_ERROR(nt_status);
314
dns_domain = cell_dn_to_dns(q);
315
BAIL_ON_PTR_ERROR(dns_domain, nt_status);
317
domain = wcache_tdc_fetch_domain(frame, dns_domain);
319
nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
320
BAIL_ON_NTSTATUS_ERROR(nt_status);
323
nt_status = NT_STATUS_OK;
326
talloc_destroy(frame);
327
SAFE_FREE(dns_domain);
329
return NT_STATUS_IS_OK(nt_status);
334
/********************************************************************
335
Check that only one result was returned within the forest cell
337
*******************************************************************/
339
static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list,
340
LDAPMessage **msg_list,
345
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
347
ADS_STRUCT *ads = NULL;
348
LDAPMessage *msg = NULL;
350
char *entry_dn = NULL;
351
TALLOC_CTX *frame = talloc_stackframe();
353
if (!dn || !user_sid) {
354
nt_status = NT_STATUS_INVALID_PARAMETER;
355
BAIL_ON_NTSTATUS_ERROR(nt_status);
360
if (!ads_list || !msg_list || (num_resp == 0)) {
361
nt_status = NT_STATUS_NO_SUCH_FILE;
362
BAIL_ON_NTSTATUS_ERROR(nt_status);
365
/* Loop over all msgs */
367
for (i=0; i<num_resp; i++) {
368
LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]);
371
entry_dn = ads_get_dn(ads_list[i], talloc_tos(), e);
372
BAIL_ON_PTR_ERROR(entry_dn, nt_status);
374
if (check_forest_scope(entry_dn)) {
377
/* If we've already broken the condition, no
381
nt_status = NT_STATUS_DUPLICATE_NAME;
382
BAIL_ON_NTSTATUS_ERROR(nt_status);
387
*dn = SMB_STRDUP(entry_dn);
388
BAIL_ON_PTR_ERROR((*dn), nt_status);
391
e = ads_next_entry(ads_list[i], e);
392
TALLOC_FREE(entry_dn);
397
nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
398
BAIL_ON_NTSTATUS_ERROR(nt_status);
401
/* If we made is through the loop, then grab the user_sid and
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.
410
Fail if both are unavailable
413
if (!ads_pull_sid(ads, msg, "objectSid", user_sid)) {
416
size_t num_lines = 0;
418
keywords = ads_pull_strings(ads, frame, msg, "keywords",
420
BAIL_ON_PTR_ERROR(keywords, nt_status);
422
s = find_attr_string(keywords, num_lines, "backLink");
424
nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
425
BAIL_ON_NTSTATUS_ERROR(nt_status);
428
if (!string_to_sid(user_sid, s)) {
429
nt_status = NT_STATUS_INVALID_SID;
430
BAIL_ON_NTSTATUS_ERROR(nt_status);
434
nt_status = NT_STATUS_OK;
437
if (!NT_STATUS_IS_OK(nt_status)) {
441
talloc_destroy(frame);
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
*******************************************************************/
454
static NTSTATUS search_forest(struct likewise_cell *forest_cell,
456
const struct lwcell_filter *fdata)
458
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
459
TALLOC_CTX *frame = talloc_stackframe();
462
struct gc_info *gc = NULL;
463
ADS_STRUCT **ads_list = NULL;
464
LDAPMessage **msg_list = NULL;
468
struct likewise_cell *domain_cell = NULL;
470
if ((gc = gc_search_start()) == NULL) {
471
nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
472
BAIL_ON_NTSTATUS_ERROR(nt_status);
476
char *sid_binstr = NULL;
477
uint32_t flags = LWCELL_FLAG_SEARCH_FOREST;
481
flags |= cell_flags(gc->forest_cell);
483
switch (fdata->ftype) {
485
sid_binstr = sid_binstring(&fdata->filter.sid);
486
BAIL_ON_PTR_ERROR(sid_binstr, nt_status);
488
filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr);
489
SAFE_FREE(sid_binstr);
492
filter = build_id_filter(fdata->filter.id.id,
493
fdata->filter.id.type, flags);
496
filter = build_alias_filter(fdata->filter.alias, flags);
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)) {
507
nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
508
m, &ads_list, &msg_list,
510
BAIL_ON_NTSTATUS_ERROR(nt_status);
515
/* Uniqueness check across forests */
517
nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp,
519
BAIL_ON_NTSTATUS_ERROR(nt_status);
521
nt_status = search_domain(&domain_cell, &m, dn, &user_sid);
522
BAIL_ON_NTSTATUS_ERROR(nt_status);
524
/* Save the connection and results in the return parameters */
526
forest_cell->gc_search_cell = domain_cell;
530
PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4);
534
free_result_array(ads_list, msg_list, num_resp);
535
talloc_destroy(frame);
540
/********************************************************************
541
*******************************************************************/
543
static NTSTATUS search_cell_list(struct likewise_cell **c,
545
const struct lwcell_filter *fdata)
547
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
548
struct likewise_cell *cell = NULL;
549
LDAPMessage *msg = NULL;
550
struct likewise_cell *result_cell = NULL;
552
if ((cell = cell_list_head()) == NULL) {
553
nt_status = NT_STATUS_INVALID_SERVER_STATE;
554
BAIL_ON_NTSTATUS_ERROR(nt_status);
558
/* Clear any previous GC search results */
560
cell->gc_search_cell = NULL;
562
if (cell_search_forest(cell)) {
563
nt_status = search_forest(cell, &msg, fdata);
565
nt_status = search_cell(cell, &msg, fdata);
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 */
572
result_cell = cell->gc_search_cell ?
573
cell->gc_search_cell : cell;
575
/* Check if we are done */
577
if (NT_STATUS_IS_OK(nt_status)) {
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. */
585
ads_msgfree(cell_connection(result_cell), msg);
591
/* This might be assigning NULL but that is ok as long as we
592
give back the proper error code */
598
PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3);
603
/********************************************************************
604
Pull the SID from an object which is always stored in the keywords
605
attribute as "backLink=S-1-5-21-..."
606
*******************************************************************/
608
static NTSTATUS pull_sid(struct likewise_cell *c,
612
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
613
TALLOC_CTX *frame = talloc_stackframe();
614
ADS_STRUCT *ads = NULL;
616
ads = cell_connection(c);
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.
625
if (!ads_pull_sid(ads, msg, "objectSid", sid)) {
628
size_t num_lines = 0;
630
keywords = ads_pull_strings(ads, frame, msg,
631
"keywords", &num_lines);
632
BAIL_ON_PTR_ERROR(keywords, nt_status);
634
s = find_attr_string(keywords, num_lines, "backLink");
636
nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
637
BAIL_ON_NTSTATUS_ERROR(nt_status);
640
if (!string_to_sid(sid, s)) {
641
nt_status = NT_STATUS_INVALID_SID;
642
BAIL_ON_NTSTATUS_ERROR(nt_status);
646
nt_status = NT_STATUS_OK;
649
talloc_destroy(frame);
654
/********************************************************************
655
*******************************************************************/
657
static NTSTATUS get_object_type(struct likewise_cell *c,
661
TALLOC_CTX *ctx = talloc_stackframe();
662
char **oc_list = NULL;
663
NTSTATUS nt_status = NT_STATUS_OK;
664
size_t list_size = 0;
666
ADS_STRUCT *ads = NULL;
668
ads = cell_connection(c);
670
/* Deal with RFC 2307 support first */
672
if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
673
oc_list = ads_pull_strings(ads, ctx, msg,
674
"objectClass", &list_size);
676
nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
680
/* Check for posix classes and AD classes */
682
if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER)
683
|| is_object_class(oc_list, list_size, AD_USER)) {
685
} else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP)
686
|| is_object_class(oc_list, list_size, AD_GROUP)) {
689
*type = ID_TYPE_NOT_SPECIFIED;
690
nt_status = NT_STATUS_INVALID_PARAMETER;
693
/* Default to non-schema mode */
695
oc_list = ads_pull_strings(ads, ctx, msg,
696
"keywords", &list_size);
698
nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
702
s = find_attr_string(oc_list, list_size, "objectClass");
704
nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
708
if (strequal(s, ADEX_OC_USER)) {
710
} else if (strequal(s, ADEX_OC_GROUP)) {
713
*type = ID_TYPE_NOT_SPECIFIED;
714
nt_status = NT_STATUS_INVALID_PARAMETER;
718
nt_status = NT_STATUS_OK;
726
/********************************************************************
727
Pull an attribute uint32_t value
728
*******************************************************************/
730
static NTSTATUS get_object_uint32(struct likewise_cell *c,
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;
741
ads = cell_connection(c);
743
/* Deal with RFC2307 schema */
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);
751
/* Non-schema mode */
755
keywords = ads_pull_strings(ads, frame, msg, "keywords",
757
BAIL_ON_PTR_ERROR(keywords, nt_status);
759
s = find_attr_string(keywords, list_size, attrib);
761
nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
762
BAIL_ON_NTSTATUS_ERROR(nt_status);
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);
773
nt_status = NT_STATUS_OK;
776
talloc_destroy(frame);
781
/********************************************************************
782
*******************************************************************/
784
static NTSTATUS get_object_id(struct likewise_cell *c,
789
NTSTATUS nt_status = NT_STATUS_OK;
792
/* Figure out which attribute we need to pull */
796
id_attr = ADEX_ATTR_UIDNUM;
799
id_attr = ADEX_ATTR_GIDNUM;
802
nt_status = NT_STATUS_INVALID_PARAMETER;
803
BAIL_ON_NTSTATUS_ERROR(nt_status);
807
nt_status = get_object_uint32(c, msg, id_attr, id);
808
BAIL_ON_NTSTATUS_ERROR(nt_status);
814
/********************************************************************
815
Pull the uid/gid and type from an object. This differs depending on
817
*******************************************************************/
819
static NTSTATUS pull_id(struct likewise_cell *c,
826
nt_status = get_object_type(c, msg, type);
827
BAIL_ON_NTSTATUS_ERROR(nt_status);
829
nt_status = get_object_id(c, msg, *type, id);
830
BAIL_ON_NTSTATUS_ERROR(nt_status);
836
/********************************************************************
837
Pull an attribute string value
838
*******************************************************************/
840
static NTSTATUS get_object_string(struct likewise_cell *c,
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;
854
ads = cell_connection(c);
856
/* Deal with RFC2307 schema */
858
if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
859
*string = ads_pull_string(ads, ctx, msg, attrib);
861
/* Non-schema mode */
865
keywords = ads_pull_strings(ads, frame, msg,
866
"keywords", &list_size);
868
nt_status = NT_STATUS_NO_MEMORY;
869
BAIL_ON_NTSTATUS_ERROR(nt_status);
871
s = find_attr_string(keywords, list_size, attrib);
873
*string = talloc_strdup(ctx, s);
878
nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
879
BAIL_ON_NTSTATUS_ERROR(nt_status);
882
nt_status = NT_STATUS_OK;
885
talloc_destroy(frame);
890
/********************************************************************
891
Pull the struct passwd fields for a user
892
*******************************************************************/
894
static NTSTATUS pull_nss_info(struct likewise_cell *c,
904
nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, homedir);
905
BAIL_ON_NTSTATUS_ERROR(nt_status);
907
nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, shell);
908
BAIL_ON_NTSTATUS_ERROR(nt_status);
910
nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, gecos);
911
/* Gecos is often not set so ignore failures */
913
nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid);
914
BAIL_ON_NTSTATUS_ERROR(nt_status);
920
/********************************************************************
921
Pull the struct passwd fields for a user
922
*******************************************************************/
924
static NTSTATUS pull_alias(struct likewise_cell *c,
929
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
931
const char *attr = NULL;
933
/* Figure out if this is a user or a group */
935
nt_status = get_object_type(c, msg, &type);
936
BAIL_ON_NTSTATUS_ERROR(nt_status);
940
attr = ADEX_ATTR_UID;
943
/* What is the group attr for RFC2307 Forests? */
944
attr = ADEX_ATTR_DISPLAYNAME;
947
nt_status = NT_STATUS_INVALID_PARAMETER;
948
BAIL_ON_NTSTATUS_ERROR(nt_status);
952
nt_status = get_object_string(c, msg, ctx, attr, alias);
953
BAIL_ON_NTSTATUS_ERROR(nt_status);
959
/********************************************************************
960
*******************************************************************/
962
static NTSTATUS _ccp_get_sid_from_id(DOM_SID * sid,
963
uint32_t id, enum id_type type)
965
struct likewise_cell *cell = NULL;
966
LDAPMessage *msg = NULL;
968
struct lwcell_filter filter;
970
filter.ftype = IdFilter;
971
filter.filter.id.id = id;
972
filter.filter.id.type = type;
974
nt_status = search_cell_list(&cell, &msg, &filter);
975
BAIL_ON_NTSTATUS_ERROR(nt_status);
977
nt_status = pull_sid(cell, msg, sid);
978
BAIL_ON_NTSTATUS_ERROR(nt_status);
981
ads_msgfree(cell->conn, msg);
986
/********************************************************************
987
*******************************************************************/
989
static NTSTATUS _ccp_get_id_from_sid(uint32_t * id,
993
struct likewise_cell *cell = NULL;
994
LDAPMessage *msg = NULL;
996
struct lwcell_filter filter;
998
filter.ftype = SidFilter;
999
sid_copy(&filter.filter.sid, sid);
1001
nt_status = search_cell_list(&cell, &msg, &filter);
1002
BAIL_ON_NTSTATUS_ERROR(nt_status);
1004
nt_status = pull_id(cell, msg, id, type);
1005
BAIL_ON_NTSTATUS_ERROR(nt_status);
1007
if (*id < min_id_value()) {
1008
nt_status = NT_STATUS_INVALID_PARAMETER;
1009
BAIL_ON_NTSTATUS_ERROR(nt_status);
1013
ads_msgfree(cell->conn, msg);
1018
/********************************************************************
1019
*******************************************************************/
1021
static NTSTATUS _ccp_nss_get_info(const DOM_SID * sid,
1025
char **gecos, gid_t * p_gid)
1027
struct likewise_cell *cell = NULL;
1028
LDAPMessage *msg = NULL;
1030
struct lwcell_filter filter;
1033
filter.ftype = SidFilter;
1034
sid_copy(&filter.filter.sid, sid);
1036
nt_status = search_cell_list(&cell, &msg, &filter);
1037
BAIL_ON_NTSTATUS_ERROR(nt_status);
1039
nt_status = get_object_type(cell, msg, &type);
1040
BAIL_ON_NTSTATUS_ERROR(nt_status);
1042
if (type != ID_TYPE_UID) {
1043
nt_status = NT_STATUS_NO_SUCH_USER;
1044
BAIL_ON_NTSTATUS_ERROR(nt_status);
1047
nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos,
1049
BAIL_ON_NTSTATUS_ERROR(nt_status);
1052
ads_msgfree(cell->conn, msg);
1057
/**********************************************************************
1058
*********************************************************************/
1060
static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx,
1062
const char *name, char **alias)
1064
TALLOC_CTX *frame = talloc_stackframe();
1065
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1067
struct likewise_cell *cell = NULL;
1068
LDAPMessage *msg = NULL;
1069
struct lwcell_filter filter;
1070
enum lsa_SidType sid_type;
1072
/* Convert the name to a SID */
1074
nt_status = gc_name_to_sid(domain, name, &sid, &sid_type);
1075
BAIL_ON_NTSTATUS_ERROR(nt_status);
1077
/* Find the user/group */
1079
filter.ftype = SidFilter;
1080
sid_copy(&filter.filter.sid, &sid);
1082
nt_status = search_cell_list(&cell, &msg, &filter);
1083
BAIL_ON_NTSTATUS_ERROR(nt_status);
1085
/* Pull the alias and return */
1087
nt_status = pull_alias(cell, msg, ctx, alias);
1088
BAIL_ON_NTSTATUS_ERROR(nt_status);
1091
PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3);
1093
talloc_destroy(frame);
1094
ads_msgfree(cell_connection(cell), msg);
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
*********************************************************************/
1105
static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx,
1107
const char *alias, char **name)
1109
TALLOC_CTX *frame = talloc_stackframe();
1110
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
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;
1120
/* Find the user/group */
1122
filter.ftype = AliasFilter;
1123
fstrcpy(filter.filter.alias, alias);
1125
nt_status = search_cell_list(&cell_alias, &msg_alias, &filter);
1126
BAIL_ON_NTSTATUS_ERROR(nt_status);
1128
nt_status = pull_sid(cell_alias, msg_alias, &sid);
1129
BAIL_ON_NTSTATUS_ERROR(nt_status);
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. */
1136
filter.ftype = SidFilter;
1137
sid_copy(&filter.filter.sid, &sid);
1139
nt_status = search_cell_list(&cell_sid, &msg_sid, &filter);
1140
BAIL_ON_NTSTATUS_ERROR(nt_status);
1142
if (cell_alias != cell_sid) {
1143
nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1144
BAIL_ON_NTSTATUS_ERROR(nt_status);
1147
/* Finally do the GC sid/name conversion */
1149
nt_status = gc_sid_to_name(&sid, &canonical_name, &type);
1150
BAIL_ON_NTSTATUS_ERROR(nt_status);
1152
*name = talloc_strdup(mem_ctx, canonical_name);
1153
BAIL_ON_PTR_ERROR((*name), nt_status);
1155
nt_status = NT_STATUS_OK;
1158
PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3);
1160
ads_msgfree(cell_connection(cell_alias), msg_alias);
1161
ads_msgfree(cell_connection(cell_sid), msg_sid);
1163
SAFE_FREE(canonical_name);
1165
talloc_destroy(frame);
1170
/********************************************************************
1171
*******************************************************************/
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