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.
25 #include "idmap_adex.h"
28 #define DBGC_CLASS DBGC_IDMAP
30 /* Information needed by the LDAP search filters */
32 enum filterType { SidFilter, IdFilter, AliasFilter };
36 enum filterType ftype;
48 /********************************************************************
49 *******************************************************************/
51 static char* build_id_filter(TALLOC_CTX *mem_ctx,
54 uint32_t search_flags)
57 char *oc_filter, *attr_filter;
59 TALLOC_CTX *frame = talloc_stackframe();
60 bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
61 == LWCELL_FLAG_USE_RFC2307_ATTRS);
62 bool use_gc = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
63 == LWCELL_FLAG_SEARCH_FOREST);
66 /* Construct search filter for objectclass and attributes */
72 oc = ADEX_OC_POSIX_USER;
77 oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
78 attr_filter = talloc_asprintf(frame, "%s=%u",
79 ADEX_ATTR_UIDNUM, id);
85 oc = ADEX_OC_POSIX_GROUP;
90 oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
91 attr_filter = talloc_asprintf(frame, "%s=%u",
92 ADEX_ATTR_GIDNUM, id);
98 BAIL_ON_PTR_ERROR(oc_filter, nt_status);
99 BAIL_ON_PTR_ERROR(attr_filter, nt_status);
101 /* Use "keywords=%s" for non-schema cells */
104 filter = talloc_asprintf(mem_ctx,
109 filter = talloc_asprintf(mem_ctx,
110 "(&(keywords=%s)(keywords=%s))",
116 talloc_destroy(frame);
121 /********************************************************************
122 *******************************************************************/
124 static char* build_alias_filter(TALLOC_CTX *mem_ctx,
126 uint32_t search_flags)
129 char *user_attr_filter, *group_attr_filter;
131 TALLOC_CTX *frame = talloc_stackframe();
132 bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
133 == LWCELL_FLAG_USE_RFC2307_ATTRS);
134 bool search_forest = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
135 == LWCELL_FLAG_SEARCH_FOREST);
137 /* Construct search filter for objectclass and attributes */
139 user_attr_filter = talloc_asprintf(frame, "%s=%s",
140 ADEX_ATTR_UID, alias);
141 group_attr_filter = talloc_asprintf(frame, "%s=%s",
142 ADEX_ATTR_DISPLAYNAME, alias);
143 BAIL_ON_PTR_ERROR(user_attr_filter, nt_status);
144 BAIL_ON_PTR_ERROR(group_attr_filter, nt_status);
146 /* Use "keywords=%s" for non-schema cells */
149 filter = talloc_asprintf(mem_ctx,
150 "(|(&(%s)(objectclass=%s))(&(%s)(objectclass=%s)))",
152 search_forest ? AD_USER : ADEX_OC_POSIX_USER,
154 search_forest ? AD_GROUP : ADEX_OC_POSIX_GROUP);
156 filter = talloc_asprintf(mem_ctx,
157 "(|(keywords=%s)(keywords=%s))",
163 talloc_destroy(frame);
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(frame,
198 fdata->filter.id.type,
202 filter = build_alias_filter(frame,
207 nt_status = NT_STATUS_INVALID_PARAMETER;
210 BAIL_ON_PTR_ERROR(filter, nt_status);
212 base = cell_search_base(c);
213 BAIL_ON_PTR_ERROR(base, nt_status);
215 ads_status = cell_do_search(c, base, LDAP_SCOPE_SUBTREE,
218 nt_status = ads_ntstatus(ads_status);
219 BAIL_ON_NTSTATUS_ERROR(nt_status);
221 /* Now check that we got only one reply */
223 count = ads_count_replies(c->conn, *msg);
225 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
226 BAIL_ON_NTSTATUS_ERROR(nt_status);
230 nt_status = NT_STATUS_DUPLICATE_NAME;
231 BAIL_ON_NTSTATUS_ERROR(nt_status);
235 PRINT_NTSTATUS_ERROR(nt_status, "search_cell", 4);
237 talloc_destroy(CONST_DISCARD(char*, base));
238 talloc_destroy(frame);
243 /********************************************************************
244 *******************************************************************/
246 static NTSTATUS search_domain(struct likewise_cell **cell,
249 const struct dom_sid *sid)
251 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
252 TALLOC_CTX* frame = talloc_stackframe();
255 nt_status = dc_search_domains(cell, msg, dn, sid);
256 BAIL_ON_NTSTATUS_ERROR(nt_status);
258 /* Now check that we got only one reply */
260 count = ads_count_replies(cell_connection(*cell), *msg);
262 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
263 BAIL_ON_NTSTATUS_ERROR(nt_status);
267 nt_status = NT_STATUS_DUPLICATE_NAME;
268 BAIL_ON_NTSTATUS_ERROR(nt_status);
272 PRINT_NTSTATUS_ERROR(nt_status, "search_domain", 4);
273 talloc_destroy(frame);
279 /********************************************************************
280 Check that a DN is within the forest scope.
281 *******************************************************************/
283 static bool check_forest_scope(const char *dn)
285 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
286 TALLOC_CTX *frame = talloc_stackframe();
289 char *dns_domain = NULL;
290 struct winbindd_tdc_domain *domain;
292 /* If the DN does *not* contain "$LikewiseIdentityCell",
293 assume this is a schema mode forest and it is in the
294 forest scope by definition. */
296 if ((p = strstr_m(dn, ADEX_CELL_RDN)) == NULL) {
297 nt_status = NT_STATUS_OK;
301 /* If this is a non-schema forest, then make sure that the DN
302 is in the form "...,cn=$LikewiseIdentityCell,DC=..." */
304 if ((q = strchr_m(p, ',')) == NULL) {
305 nt_status = NT_STATUS_OBJECT_NAME_INVALID;
306 BAIL_ON_NTSTATUS_ERROR(nt_status);
310 if (StrnCaseCmp(q, "dc=", 3) != 0) {
311 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
312 BAIL_ON_NTSTATUS_ERROR(nt_status);
316 dns_domain = cell_dn_to_dns(q);
317 BAIL_ON_PTR_ERROR(dns_domain, nt_status);
319 domain = wcache_tdc_fetch_domain(frame, dns_domain);
321 nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
322 BAIL_ON_NTSTATUS_ERROR(nt_status);
325 nt_status = NT_STATUS_OK;
328 talloc_destroy(frame);
329 SAFE_FREE(dns_domain);
331 return NT_STATUS_IS_OK(nt_status);
336 /********************************************************************
337 Check that only one result was returned within the forest cell
339 *******************************************************************/
341 static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list,
342 LDAPMessage **msg_list,
345 struct dom_sid *user_sid)
347 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
349 ADS_STRUCT *ads = NULL;
350 LDAPMessage *msg = NULL;
352 char *entry_dn = NULL;
353 TALLOC_CTX *frame = talloc_stackframe();
355 if (!dn || !user_sid) {
356 nt_status = NT_STATUS_INVALID_PARAMETER;
357 BAIL_ON_NTSTATUS_ERROR(nt_status);
362 if (!ads_list || !msg_list || (num_resp == 0)) {
363 nt_status = NT_STATUS_NO_SUCH_FILE;
364 BAIL_ON_NTSTATUS_ERROR(nt_status);
367 /* Loop over all msgs */
369 for (i=0; i<num_resp; i++) {
370 LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]);
373 entry_dn = ads_get_dn(ads_list[i], talloc_tos(), e);
374 BAIL_ON_PTR_ERROR(entry_dn, nt_status);
376 if (check_forest_scope(entry_dn)) {
379 /* If we've already broken the condition, no
383 nt_status = NT_STATUS_DUPLICATE_NAME;
384 BAIL_ON_NTSTATUS_ERROR(nt_status);
389 *dn = SMB_STRDUP(entry_dn);
390 BAIL_ON_PTR_ERROR((*dn), nt_status);
393 e = ads_next_entry(ads_list[i], e);
394 TALLOC_FREE(entry_dn);
399 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
400 BAIL_ON_NTSTATUS_ERROR(nt_status);
403 /* If we made is through the loop, then grab the user_sid and
407 Try and get the SID from either objectSid or keywords.
408 We cannot use pull_sid() here since we want to try
409 both methods and not only one or the other (and we
410 have no full likewise_cell struct.
412 Fail if both are unavailable
415 if (!ads_pull_sid(ads, msg, "objectSid", user_sid)) {
418 size_t num_lines = 0;
420 keywords = ads_pull_strings(ads, frame, msg, "keywords",
422 BAIL_ON_PTR_ERROR(keywords, nt_status);
424 s = find_attr_string(keywords, num_lines, "backLink");
426 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
427 BAIL_ON_NTSTATUS_ERROR(nt_status);
430 if (!string_to_sid(user_sid, s)) {
431 nt_status = NT_STATUS_INVALID_SID;
432 BAIL_ON_NTSTATUS_ERROR(nt_status);
436 nt_status = NT_STATUS_OK;
439 if (!NT_STATUS_IS_OK(nt_status)) {
443 talloc_destroy(frame);
448 /********************************************************************
449 Search all forests. Each forest can have it's own forest-cell
450 settings so we have to generate the filter for each search.
451 We don't use gc_search_all_forests() since we may have a different
452 schema model in each forest and need to construct the search
453 filter for each GC search.
454 *******************************************************************/
456 static NTSTATUS search_forest(struct likewise_cell *forest_cell,
458 const struct lwcell_filter *fdata)
460 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
461 TALLOC_CTX *frame = talloc_stackframe();
464 struct gc_info *gc = NULL;
465 ADS_STRUCT **ads_list = NULL;
466 LDAPMessage **msg_list = NULL;
469 struct dom_sid user_sid;
470 struct likewise_cell *domain_cell = NULL;
472 if ((gc = gc_search_start()) == NULL) {
473 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
474 BAIL_ON_NTSTATUS_ERROR(nt_status);
478 char *sid_binstr = NULL;
479 uint32_t flags = LWCELL_FLAG_SEARCH_FOREST;
483 flags |= cell_flags(gc->forest_cell);
485 switch (fdata->ftype) {
487 sid_binstr = sid_binstring(frame, &fdata->filter.sid);
488 BAIL_ON_PTR_ERROR(sid_binstr, nt_status);
490 filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr);
491 TALLOC_FREE(sid_binstr);
494 filter = build_id_filter(frame,
496 fdata->filter.id.type, flags);
499 filter = build_alias_filter(frame,
505 /* First find the sparse object in GC */
506 nt_status = gc_search_forest(gc, &m, filter);
507 if (!NT_STATUS_IS_OK(nt_status)) {
512 nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
513 m, &ads_list, &msg_list,
515 BAIL_ON_NTSTATUS_ERROR(nt_status);
520 /* Uniqueness check across forests */
522 nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp,
524 BAIL_ON_NTSTATUS_ERROR(nt_status);
526 nt_status = search_domain(&domain_cell, &m, dn, &user_sid);
527 BAIL_ON_NTSTATUS_ERROR(nt_status);
529 /* Save the connection and results in the return parameters */
531 forest_cell->gc_search_cell = domain_cell;
535 PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4);
539 free_result_array(ads_list, msg_list, num_resp);
540 talloc_destroy(frame);
545 /********************************************************************
546 *******************************************************************/
548 static NTSTATUS search_cell_list(struct likewise_cell **c,
550 const struct lwcell_filter *fdata)
552 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
553 struct likewise_cell *cell = NULL;
554 LDAPMessage *msg = NULL;
555 struct likewise_cell *result_cell = NULL;
557 if ((cell = cell_list_head()) == NULL) {
558 nt_status = NT_STATUS_INVALID_SERVER_STATE;
559 BAIL_ON_NTSTATUS_ERROR(nt_status);
563 /* Clear any previous GC search results */
565 cell->gc_search_cell = NULL;
567 if (cell_search_forest(cell)) {
568 nt_status = search_forest(cell, &msg, fdata);
570 nt_status = search_cell(cell, &msg, fdata);
573 /* Always point to the search result cell.
574 In forests this might be for another domain
575 which means the schema model may be different */
577 result_cell = cell->gc_search_cell ?
578 cell->gc_search_cell : cell;
580 /* Check if we are done */
582 if (NT_STATUS_IS_OK(nt_status)) {
586 /* No luck. Free memory and hit the next cell.
587 Forest searches always set the gc_search_cell
588 so give preference to that connection if possible. */
590 ads_msgfree(cell_connection(result_cell), msg);
596 /* This might be assigning NULL but that is ok as long as we
597 give back the proper error code */
603 PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3);
608 /********************************************************************
609 Pull the SID from an object which is always stored in the keywords
610 attribute as "backLink=S-1-5-21-..."
611 *******************************************************************/
613 static NTSTATUS pull_sid(struct likewise_cell *c,
617 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
618 TALLOC_CTX *frame = talloc_stackframe();
619 ADS_STRUCT *ads = NULL;
621 ads = cell_connection(c);
624 We have two ways of getting the sid:
625 (a) from the objectSID in case of a GC search,
626 (b) from backLink in the case of a cell search.
627 Pull the keywords attributes and grab the backLink.
630 if (!ads_pull_sid(ads, msg, "objectSid", sid)) {
633 size_t num_lines = 0;
635 keywords = ads_pull_strings(ads, frame, msg,
636 "keywords", &num_lines);
637 BAIL_ON_PTR_ERROR(keywords, nt_status);
639 s = find_attr_string(keywords, num_lines, "backLink");
641 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
642 BAIL_ON_NTSTATUS_ERROR(nt_status);
645 if (!string_to_sid(sid, s)) {
646 nt_status = NT_STATUS_INVALID_SID;
647 BAIL_ON_NTSTATUS_ERROR(nt_status);
651 nt_status = NT_STATUS_OK;
654 talloc_destroy(frame);
659 /********************************************************************
660 *******************************************************************/
662 static NTSTATUS get_object_type(struct likewise_cell *c,
666 TALLOC_CTX *ctx = talloc_stackframe();
667 char **oc_list = NULL;
668 NTSTATUS nt_status = NT_STATUS_OK;
669 size_t list_size = 0;
671 ADS_STRUCT *ads = NULL;
673 ads = cell_connection(c);
675 /* Deal with RFC 2307 support first */
677 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
678 oc_list = ads_pull_strings(ads, ctx, msg,
679 "objectClass", &list_size);
681 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
685 /* Check for posix classes and AD classes */
687 if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER)
688 || is_object_class(oc_list, list_size, AD_USER)) {
690 } else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP)
691 || is_object_class(oc_list, list_size, AD_GROUP)) {
694 *type = ID_TYPE_NOT_SPECIFIED;
695 nt_status = NT_STATUS_INVALID_PARAMETER;
698 /* Default to non-schema mode */
700 oc_list = ads_pull_strings(ads, ctx, msg,
701 "keywords", &list_size);
703 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
707 s = find_attr_string(oc_list, list_size, "objectClass");
709 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
713 if (strequal(s, ADEX_OC_USER)) {
715 } else if (strequal(s, ADEX_OC_GROUP)) {
718 *type = ID_TYPE_NOT_SPECIFIED;
719 nt_status = NT_STATUS_INVALID_PARAMETER;
723 nt_status = NT_STATUS_OK;
731 /********************************************************************
732 Pull an attribute uint32_t value
733 *******************************************************************/
735 static NTSTATUS get_object_uint32(struct likewise_cell *c,
740 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
741 char **keywords = NULL;
742 size_t list_size = 0;
743 TALLOC_CTX *frame = talloc_stackframe();
744 ADS_STRUCT *ads = NULL;
746 ads = cell_connection(c);
748 /* Deal with RFC2307 schema */
750 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
751 if (!ads_pull_uint32(ads, msg, attrib, x)) {
752 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
753 BAIL_ON_NTSTATUS_ERROR(nt_status);
756 /* Non-schema mode */
760 keywords = ads_pull_strings(ads, frame, msg, "keywords",
762 BAIL_ON_PTR_ERROR(keywords, nt_status);
764 s = find_attr_string(keywords, list_size, attrib);
766 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
767 BAIL_ON_NTSTATUS_ERROR(nt_status);
770 num = strtoll(s, NULL, 10);
771 if (errno == ERANGE) {
772 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
773 BAIL_ON_NTSTATUS_ERROR(nt_status);
778 nt_status = NT_STATUS_OK;
781 talloc_destroy(frame);
786 /********************************************************************
787 *******************************************************************/
789 static NTSTATUS get_object_id(struct likewise_cell *c,
794 NTSTATUS nt_status = NT_STATUS_OK;
797 /* Figure out which attribute we need to pull */
801 id_attr = ADEX_ATTR_UIDNUM;
804 id_attr = ADEX_ATTR_GIDNUM;
807 nt_status = NT_STATUS_INVALID_PARAMETER;
808 BAIL_ON_NTSTATUS_ERROR(nt_status);
812 nt_status = get_object_uint32(c, msg, id_attr, id);
813 BAIL_ON_NTSTATUS_ERROR(nt_status);
819 /********************************************************************
820 Pull the uid/gid and type from an object. This differs depending on
822 *******************************************************************/
824 static NTSTATUS pull_id(struct likewise_cell *c,
831 nt_status = get_object_type(c, msg, type);
832 BAIL_ON_NTSTATUS_ERROR(nt_status);
834 nt_status = get_object_id(c, msg, *type, id);
835 BAIL_ON_NTSTATUS_ERROR(nt_status);
841 /********************************************************************
842 Pull an attribute string value
843 *******************************************************************/
845 static NTSTATUS get_object_string(struct likewise_cell *c,
851 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
852 char **keywords = NULL;
853 size_t list_size = 0;
854 TALLOC_CTX *frame = talloc_stackframe();
855 ADS_STRUCT *ads = NULL;
859 ads = cell_connection(c);
861 /* Deal with RFC2307 schema */
863 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
864 *string = ads_pull_string(ads, ctx, msg, attrib);
866 /* Non-schema mode */
870 keywords = ads_pull_strings(ads, frame, msg,
871 "keywords", &list_size);
873 nt_status = NT_STATUS_NO_MEMORY;
874 BAIL_ON_NTSTATUS_ERROR(nt_status);
876 s = find_attr_string(keywords, list_size, attrib);
878 *string = talloc_strdup(ctx, s);
883 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
884 BAIL_ON_NTSTATUS_ERROR(nt_status);
887 nt_status = NT_STATUS_OK;
890 talloc_destroy(frame);
895 /********************************************************************
896 Pull the struct passwd fields for a user
897 *******************************************************************/
899 static NTSTATUS pull_nss_info(struct likewise_cell *c,
902 const char **homedir,
910 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, &tmp);
911 BAIL_ON_NTSTATUS_ERROR(nt_status);
914 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, &tmp);
915 BAIL_ON_NTSTATUS_ERROR(nt_status);
918 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, &tmp);
919 /* Gecos is often not set so ignore failures */
922 nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid);
923 BAIL_ON_NTSTATUS_ERROR(nt_status);
929 /********************************************************************
930 Pull the struct passwd fields for a user
931 *******************************************************************/
933 static NTSTATUS pull_alias(struct likewise_cell *c,
938 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
940 const char *attr = NULL;
942 /* Figure out if this is a user or a group */
944 nt_status = get_object_type(c, msg, &type);
945 BAIL_ON_NTSTATUS_ERROR(nt_status);
949 attr = ADEX_ATTR_UID;
952 /* What is the group attr for RFC2307 Forests? */
953 attr = ADEX_ATTR_DISPLAYNAME;
956 nt_status = NT_STATUS_INVALID_PARAMETER;
957 BAIL_ON_NTSTATUS_ERROR(nt_status);
961 nt_status = get_object_string(c, msg, ctx, attr, alias);
962 BAIL_ON_NTSTATUS_ERROR(nt_status);
968 /********************************************************************
969 *******************************************************************/
971 static NTSTATUS _ccp_get_sid_from_id(struct dom_sid * sid,
972 uint32_t id, enum id_type type)
974 struct likewise_cell *cell = NULL;
975 LDAPMessage *msg = NULL;
977 struct lwcell_filter filter;
979 filter.ftype = IdFilter;
980 filter.filter.id.id = id;
981 filter.filter.id.type = type;
983 nt_status = search_cell_list(&cell, &msg, &filter);
984 BAIL_ON_NTSTATUS_ERROR(nt_status);
986 nt_status = pull_sid(cell, msg, sid);
987 BAIL_ON_NTSTATUS_ERROR(nt_status);
990 ads_msgfree(cell->conn, msg);
995 /********************************************************************
996 *******************************************************************/
998 static NTSTATUS _ccp_get_id_from_sid(uint32_t * id,
1000 const struct dom_sid * sid)
1002 struct likewise_cell *cell = NULL;
1003 LDAPMessage *msg = NULL;
1005 struct lwcell_filter filter;
1007 filter.ftype = SidFilter;
1008 sid_copy(&filter.filter.sid, sid);
1010 nt_status = search_cell_list(&cell, &msg, &filter);
1011 BAIL_ON_NTSTATUS_ERROR(nt_status);
1013 nt_status = pull_id(cell, msg, id, type);
1014 BAIL_ON_NTSTATUS_ERROR(nt_status);
1016 if (*id < min_id_value()) {
1017 nt_status = NT_STATUS_INVALID_PARAMETER;
1018 BAIL_ON_NTSTATUS_ERROR(nt_status);
1022 ads_msgfree(cell->conn, msg);
1027 /********************************************************************
1028 *******************************************************************/
1030 static NTSTATUS _ccp_nss_get_info(const struct dom_sid * sid,
1032 const char **homedir,
1034 const char **gecos, gid_t * p_gid)
1036 struct likewise_cell *cell = NULL;
1037 LDAPMessage *msg = NULL;
1039 struct lwcell_filter filter;
1042 filter.ftype = SidFilter;
1043 sid_copy(&filter.filter.sid, sid);
1045 nt_status = search_cell_list(&cell, &msg, &filter);
1046 BAIL_ON_NTSTATUS_ERROR(nt_status);
1048 nt_status = get_object_type(cell, msg, &type);
1049 BAIL_ON_NTSTATUS_ERROR(nt_status);
1051 if (type != ID_TYPE_UID) {
1052 nt_status = NT_STATUS_NO_SUCH_USER;
1053 BAIL_ON_NTSTATUS_ERROR(nt_status);
1056 nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos,
1058 BAIL_ON_NTSTATUS_ERROR(nt_status);
1061 ads_msgfree(cell->conn, msg);
1066 /**********************************************************************
1067 *********************************************************************/
1069 static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx,
1071 const char *name, char **alias)
1073 TALLOC_CTX *frame = talloc_stackframe();
1074 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1076 struct likewise_cell *cell = NULL;
1077 LDAPMessage *msg = NULL;
1078 struct lwcell_filter filter;
1079 enum lsa_SidType sid_type;
1081 /* Convert the name to a SID */
1083 nt_status = gc_name_to_sid(domain, name, &sid, &sid_type);
1084 BAIL_ON_NTSTATUS_ERROR(nt_status);
1086 /* Find the user/group */
1088 filter.ftype = SidFilter;
1089 sid_copy(&filter.filter.sid, &sid);
1091 nt_status = search_cell_list(&cell, &msg, &filter);
1092 BAIL_ON_NTSTATUS_ERROR(nt_status);
1094 /* Pull the alias and return */
1096 nt_status = pull_alias(cell, msg, ctx, alias);
1097 BAIL_ON_NTSTATUS_ERROR(nt_status);
1100 PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3);
1102 talloc_destroy(frame);
1103 ads_msgfree(cell_connection(cell), msg);
1108 /**********************************************************************
1109 Map from an alias name to the canonical, qualified name.
1110 Ensure that the alias is only pull from the closest in which
1111 the user or gorup is enabled in
1112 *********************************************************************/
1114 static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx,
1116 const char *alias, char **name)
1118 TALLOC_CTX *frame = talloc_stackframe();
1119 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1121 struct likewise_cell *cell_alias = NULL;
1122 LDAPMessage *msg_alias = NULL;
1123 struct likewise_cell *cell_sid = NULL;
1124 LDAPMessage *msg_sid = NULL;
1125 struct lwcell_filter filter;
1126 char *canonical_name = NULL;
1127 enum lsa_SidType type;
1129 /* Find the user/group */
1131 filter.ftype = AliasFilter;
1132 fstrcpy(filter.filter.alias, alias);
1134 nt_status = search_cell_list(&cell_alias, &msg_alias, &filter);
1135 BAIL_ON_NTSTATUS_ERROR(nt_status);
1137 nt_status = pull_sid(cell_alias, msg_alias, &sid);
1138 BAIL_ON_NTSTATUS_ERROR(nt_status);
1140 /* Now search again for the SID according to the cell list.
1141 Verify that the cell of both search results is the same
1142 so that we only match an alias from the closest cell
1143 in which a user/group has been instantied. */
1145 filter.ftype = SidFilter;
1146 sid_copy(&filter.filter.sid, &sid);
1148 nt_status = search_cell_list(&cell_sid, &msg_sid, &filter);
1149 BAIL_ON_NTSTATUS_ERROR(nt_status);
1151 if (cell_alias != cell_sid) {
1152 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1153 BAIL_ON_NTSTATUS_ERROR(nt_status);
1156 /* Finally do the GC sid/name conversion */
1158 nt_status = gc_sid_to_name(&sid, &canonical_name, &type);
1159 BAIL_ON_NTSTATUS_ERROR(nt_status);
1161 *name = talloc_strdup(mem_ctx, canonical_name);
1162 BAIL_ON_PTR_ERROR((*name), nt_status);
1164 nt_status = NT_STATUS_OK;
1167 PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3);
1169 ads_msgfree(cell_connection(cell_alias), msg_alias);
1170 ads_msgfree(cell_connection(cell_sid), msg_sid);
1172 SAFE_FREE(canonical_name);
1174 talloc_destroy(frame);
1179 /********************************************************************
1180 *******************************************************************/
1182 struct cell_provider_api ccp_unified = {
1183 .get_sid_from_id = _ccp_get_sid_from_id,
1184 .get_id_from_sid = _ccp_get_id_from_sid,
1185 .get_nss_info = _ccp_nss_get_info,
1186 .map_to_alias = _ccp_map_to_alias,
1187 .map_from_alias = _ccp_map_from_alias