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(TALLOC_CTX *mem_ctx,
53 uint32_t search_flags)
56 char *oc_filter, *attr_filter;
58 TALLOC_CTX *frame = talloc_stackframe();
59 bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
60 == LWCELL_FLAG_USE_RFC2307_ATTRS);
61 bool use_gc = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
62 == LWCELL_FLAG_SEARCH_FOREST);
65 /* Construct search filter for objectclass and attributes */
71 oc = ADEX_OC_POSIX_USER;
76 oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
77 attr_filter = talloc_asprintf(frame, "%s=%u",
78 ADEX_ATTR_UIDNUM, id);
84 oc = ADEX_OC_POSIX_GROUP;
89 oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
90 attr_filter = talloc_asprintf(frame, "%s=%u",
91 ADEX_ATTR_GIDNUM, id);
97 BAIL_ON_PTR_ERROR(oc_filter, nt_status);
98 BAIL_ON_PTR_ERROR(attr_filter, nt_status);
100 /* Use "keywords=%s" for non-schema cells */
103 filter = talloc_asprintf(mem_ctx,
108 filter = talloc_asprintf(mem_ctx,
109 "(&(keywords=%s)(keywords=%s))",
115 talloc_destroy(frame);
120 /********************************************************************
121 *******************************************************************/
123 static char* build_alias_filter(TALLOC_CTX *mem_ctx,
125 uint32_t search_flags)
128 char *user_attr_filter, *group_attr_filter;
130 TALLOC_CTX *frame = talloc_stackframe();
131 bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
132 == LWCELL_FLAG_USE_RFC2307_ATTRS);
133 bool search_forest = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
134 == LWCELL_FLAG_SEARCH_FOREST);
136 /* Construct search filter for objectclass and attributes */
138 user_attr_filter = talloc_asprintf(frame, "%s=%s",
139 ADEX_ATTR_UID, alias);
140 group_attr_filter = talloc_asprintf(frame, "%s=%s",
141 ADEX_ATTR_DISPLAYNAME, alias);
142 BAIL_ON_PTR_ERROR(user_attr_filter, nt_status);
143 BAIL_ON_PTR_ERROR(group_attr_filter, nt_status);
145 /* Use "keywords=%s" for non-schema cells */
148 filter = talloc_asprintf(mem_ctx,
149 "(|(&(%s)(objectclass=%s))(&(%s)(objectclass=%s)))",
151 search_forest ? AD_USER : ADEX_OC_POSIX_USER,
153 search_forest ? AD_GROUP : ADEX_OC_POSIX_GROUP);
155 filter = talloc_asprintf(mem_ctx,
156 "(|(keywords=%s)(keywords=%s))",
162 talloc_destroy(frame);
168 /********************************************************************
169 *******************************************************************/
171 static NTSTATUS search_cell(struct likewise_cell *c,
173 const struct lwcell_filter *fdata)
175 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
176 TALLOC_CTX* frame = talloc_stackframe();
178 const char *base = NULL;
179 ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
180 const char *attrs[] = { "*", NULL };
184 /* get the filter and other search parameters */
186 switch (fdata->ftype) {
188 sid_str = sid_string_talloc(frame, &fdata->filter.sid);
189 BAIL_ON_PTR_ERROR(sid_str, nt_status);
191 filter = talloc_asprintf(frame, "(keywords=backLink=%s)",
195 filter = build_id_filter(frame,
197 fdata->filter.id.type,
201 filter = build_alias_filter(frame,
206 nt_status = NT_STATUS_INVALID_PARAMETER;
209 BAIL_ON_PTR_ERROR(filter, nt_status);
211 base = cell_search_base(c);
212 BAIL_ON_PTR_ERROR(base, nt_status);
214 ads_status = cell_do_search(c, base, LDAP_SCOPE_SUBTREE,
217 nt_status = ads_ntstatus(ads_status);
218 BAIL_ON_NTSTATUS_ERROR(nt_status);
220 /* Now check that we got only one reply */
222 count = ads_count_replies(c->conn, *msg);
224 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
225 BAIL_ON_NTSTATUS_ERROR(nt_status);
229 nt_status = NT_STATUS_DUPLICATE_NAME;
230 BAIL_ON_NTSTATUS_ERROR(nt_status);
234 PRINT_NTSTATUS_ERROR(nt_status, "search_cell", 4);
236 talloc_destroy(CONST_DISCARD(char*, base));
237 talloc_destroy(frame);
242 /********************************************************************
243 *******************************************************************/
245 static NTSTATUS search_domain(struct likewise_cell **cell,
248 const struct dom_sid *sid)
250 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
251 TALLOC_CTX* frame = talloc_stackframe();
254 nt_status = dc_search_domains(cell, msg, dn, sid);
255 BAIL_ON_NTSTATUS_ERROR(nt_status);
257 /* Now check that we got only one reply */
259 count = ads_count_replies(cell_connection(*cell), *msg);
261 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
262 BAIL_ON_NTSTATUS_ERROR(nt_status);
266 nt_status = NT_STATUS_DUPLICATE_NAME;
267 BAIL_ON_NTSTATUS_ERROR(nt_status);
271 PRINT_NTSTATUS_ERROR(nt_status, "search_domain", 4);
272 talloc_destroy(frame);
278 /********************************************************************
279 Check that a DN is within the forest scope.
280 *******************************************************************/
282 static bool check_forest_scope(const char *dn)
284 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
285 TALLOC_CTX *frame = talloc_stackframe();
288 char *dns_domain = NULL;
289 struct winbindd_tdc_domain *domain;
291 /* If the DN does *not* contain "$LikewiseIdentityCell",
292 assume this is a schema mode forest and it is in the
293 forest scope by definition. */
295 if ((p = strstr_m(dn, ADEX_CELL_RDN)) == NULL) {
296 nt_status = NT_STATUS_OK;
300 /* If this is a non-schema forest, then make sure that the DN
301 is in the form "...,cn=$LikewiseIdentityCell,DC=..." */
303 if ((q = strchr_m(p, ',')) == NULL) {
304 nt_status = NT_STATUS_OBJECT_NAME_INVALID;
305 BAIL_ON_NTSTATUS_ERROR(nt_status);
309 if (StrnCaseCmp(q, "dc=", 3) != 0) {
310 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
311 BAIL_ON_NTSTATUS_ERROR(nt_status);
315 dns_domain = cell_dn_to_dns(q);
316 BAIL_ON_PTR_ERROR(dns_domain, nt_status);
318 domain = wcache_tdc_fetch_domain(frame, dns_domain);
320 nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
321 BAIL_ON_NTSTATUS_ERROR(nt_status);
324 nt_status = NT_STATUS_OK;
327 talloc_destroy(frame);
328 SAFE_FREE(dns_domain);
330 return NT_STATUS_IS_OK(nt_status);
335 /********************************************************************
336 Check that only one result was returned within the forest cell
338 *******************************************************************/
340 static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list,
341 LDAPMessage **msg_list,
344 struct dom_sid *user_sid)
346 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
348 ADS_STRUCT *ads = NULL;
349 LDAPMessage *msg = NULL;
351 char *entry_dn = NULL;
352 TALLOC_CTX *frame = talloc_stackframe();
354 if (!dn || !user_sid) {
355 nt_status = NT_STATUS_INVALID_PARAMETER;
356 BAIL_ON_NTSTATUS_ERROR(nt_status);
361 if (!ads_list || !msg_list || (num_resp == 0)) {
362 nt_status = NT_STATUS_NO_SUCH_FILE;
363 BAIL_ON_NTSTATUS_ERROR(nt_status);
366 /* Loop over all msgs */
368 for (i=0; i<num_resp; i++) {
369 LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]);
372 entry_dn = ads_get_dn(ads_list[i], talloc_tos(), e);
373 BAIL_ON_PTR_ERROR(entry_dn, nt_status);
375 if (check_forest_scope(entry_dn)) {
378 /* If we've already broken the condition, no
382 nt_status = NT_STATUS_DUPLICATE_NAME;
383 BAIL_ON_NTSTATUS_ERROR(nt_status);
388 *dn = SMB_STRDUP(entry_dn);
389 BAIL_ON_PTR_ERROR((*dn), nt_status);
392 e = ads_next_entry(ads_list[i], e);
393 TALLOC_FREE(entry_dn);
398 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
399 BAIL_ON_NTSTATUS_ERROR(nt_status);
402 /* If we made is through the loop, then grab the user_sid and
406 Try and get the SID from either objectSid or keywords.
407 We cannot use pull_sid() here since we want to try
408 both methods and not only one or the other (and we
409 have no full likewise_cell struct.
411 Fail if both are unavailable
414 if (!ads_pull_sid(ads, msg, "objectSid", user_sid)) {
417 size_t num_lines = 0;
419 keywords = ads_pull_strings(ads, frame, msg, "keywords",
421 BAIL_ON_PTR_ERROR(keywords, nt_status);
423 s = find_attr_string(keywords, num_lines, "backLink");
425 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
426 BAIL_ON_NTSTATUS_ERROR(nt_status);
429 if (!string_to_sid(user_sid, s)) {
430 nt_status = NT_STATUS_INVALID_SID;
431 BAIL_ON_NTSTATUS_ERROR(nt_status);
435 nt_status = NT_STATUS_OK;
438 if (!NT_STATUS_IS_OK(nt_status)) {
442 talloc_destroy(frame);
447 /********************************************************************
448 Search all forests. Each forest can have it's own forest-cell
449 settings so we have to generate the filter for each search.
450 We don't use gc_search_all_forests() since we may have a different
451 schema model in each forest and need to construct the search
452 filter for each GC search.
453 *******************************************************************/
455 static NTSTATUS search_forest(struct likewise_cell *forest_cell,
457 const struct lwcell_filter *fdata)
459 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
460 TALLOC_CTX *frame = talloc_stackframe();
463 struct gc_info *gc = NULL;
464 ADS_STRUCT **ads_list = NULL;
465 LDAPMessage **msg_list = NULL;
468 struct dom_sid user_sid;
469 struct likewise_cell *domain_cell = NULL;
471 if ((gc = gc_search_start()) == NULL) {
472 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
473 BAIL_ON_NTSTATUS_ERROR(nt_status);
477 char *sid_binstr = NULL;
478 uint32_t flags = LWCELL_FLAG_SEARCH_FOREST;
482 flags |= cell_flags(gc->forest_cell);
484 switch (fdata->ftype) {
486 sid_binstr = sid_binstring(frame, &fdata->filter.sid);
487 BAIL_ON_PTR_ERROR(sid_binstr, nt_status);
489 filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr);
490 TALLOC_FREE(sid_binstr);
493 filter = build_id_filter(frame,
495 fdata->filter.id.type, flags);
498 filter = build_alias_filter(frame,
504 /* First find the sparse object in GC */
505 nt_status = gc_search_forest(gc, &m, filter);
506 if (!NT_STATUS_IS_OK(nt_status)) {
511 nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
512 m, &ads_list, &msg_list,
514 BAIL_ON_NTSTATUS_ERROR(nt_status);
519 /* Uniqueness check across forests */
521 nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp,
523 BAIL_ON_NTSTATUS_ERROR(nt_status);
525 nt_status = search_domain(&domain_cell, &m, dn, &user_sid);
526 BAIL_ON_NTSTATUS_ERROR(nt_status);
528 /* Save the connection and results in the return parameters */
530 forest_cell->gc_search_cell = domain_cell;
534 PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4);
538 free_result_array(ads_list, msg_list, num_resp);
539 talloc_destroy(frame);
544 /********************************************************************
545 *******************************************************************/
547 static NTSTATUS search_cell_list(struct likewise_cell **c,
549 const struct lwcell_filter *fdata)
551 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
552 struct likewise_cell *cell = NULL;
553 LDAPMessage *msg = NULL;
554 struct likewise_cell *result_cell = NULL;
556 if ((cell = cell_list_head()) == NULL) {
557 nt_status = NT_STATUS_INVALID_SERVER_STATE;
558 BAIL_ON_NTSTATUS_ERROR(nt_status);
562 /* Clear any previous GC search results */
564 cell->gc_search_cell = NULL;
566 if (cell_search_forest(cell)) {
567 nt_status = search_forest(cell, &msg, fdata);
569 nt_status = search_cell(cell, &msg, fdata);
572 /* Always point to the search result cell.
573 In forests this might be for another domain
574 which means the schema model may be different */
576 result_cell = cell->gc_search_cell ?
577 cell->gc_search_cell : cell;
579 /* Check if we are done */
581 if (NT_STATUS_IS_OK(nt_status)) {
585 /* No luck. Free memory and hit the next cell.
586 Forest searches always set the gc_search_cell
587 so give preference to that connection if possible. */
589 ads_msgfree(cell_connection(result_cell), msg);
595 /* This might be assigning NULL but that is ok as long as we
596 give back the proper error code */
602 PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3);
607 /********************************************************************
608 Pull the SID from an object which is always stored in the keywords
609 attribute as "backLink=S-1-5-21-..."
610 *******************************************************************/
612 static NTSTATUS pull_sid(struct likewise_cell *c,
616 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
617 TALLOC_CTX *frame = talloc_stackframe();
618 ADS_STRUCT *ads = NULL;
620 ads = cell_connection(c);
623 We have two ways of getting the sid:
624 (a) from the objectSID in case of a GC search,
625 (b) from backLink in the case of a cell search.
626 Pull the keywords attributes and grab the backLink.
629 if (!ads_pull_sid(ads, msg, "objectSid", sid)) {
632 size_t num_lines = 0;
634 keywords = ads_pull_strings(ads, frame, msg,
635 "keywords", &num_lines);
636 BAIL_ON_PTR_ERROR(keywords, nt_status);
638 s = find_attr_string(keywords, num_lines, "backLink");
640 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
641 BAIL_ON_NTSTATUS_ERROR(nt_status);
644 if (!string_to_sid(sid, s)) {
645 nt_status = NT_STATUS_INVALID_SID;
646 BAIL_ON_NTSTATUS_ERROR(nt_status);
650 nt_status = NT_STATUS_OK;
653 talloc_destroy(frame);
658 /********************************************************************
659 *******************************************************************/
661 static NTSTATUS get_object_type(struct likewise_cell *c,
665 TALLOC_CTX *ctx = talloc_stackframe();
666 char **oc_list = NULL;
667 NTSTATUS nt_status = NT_STATUS_OK;
668 size_t list_size = 0;
670 ADS_STRUCT *ads = NULL;
672 ads = cell_connection(c);
674 /* Deal with RFC 2307 support first */
676 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
677 oc_list = ads_pull_strings(ads, ctx, msg,
678 "objectClass", &list_size);
680 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
684 /* Check for posix classes and AD classes */
686 if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER)
687 || is_object_class(oc_list, list_size, AD_USER)) {
689 } else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP)
690 || is_object_class(oc_list, list_size, AD_GROUP)) {
693 *type = ID_TYPE_NOT_SPECIFIED;
694 nt_status = NT_STATUS_INVALID_PARAMETER;
697 /* Default to non-schema mode */
699 oc_list = ads_pull_strings(ads, ctx, msg,
700 "keywords", &list_size);
702 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
706 s = find_attr_string(oc_list, list_size, "objectClass");
708 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
712 if (strequal(s, ADEX_OC_USER)) {
714 } else if (strequal(s, ADEX_OC_GROUP)) {
717 *type = ID_TYPE_NOT_SPECIFIED;
718 nt_status = NT_STATUS_INVALID_PARAMETER;
722 nt_status = NT_STATUS_OK;
730 /********************************************************************
731 Pull an attribute uint32_t value
732 *******************************************************************/
734 static NTSTATUS get_object_uint32(struct likewise_cell *c,
739 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
740 char **keywords = NULL;
741 size_t list_size = 0;
742 TALLOC_CTX *frame = talloc_stackframe();
743 ADS_STRUCT *ads = NULL;
745 ads = cell_connection(c);
747 /* Deal with RFC2307 schema */
749 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
750 if (!ads_pull_uint32(ads, msg, attrib, x)) {
751 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
752 BAIL_ON_NTSTATUS_ERROR(nt_status);
755 /* Non-schema mode */
759 keywords = ads_pull_strings(ads, frame, msg, "keywords",
761 BAIL_ON_PTR_ERROR(keywords, nt_status);
763 s = find_attr_string(keywords, list_size, attrib);
765 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
766 BAIL_ON_NTSTATUS_ERROR(nt_status);
769 num = strtoll(s, NULL, 10);
770 if (errno == ERANGE) {
771 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
772 BAIL_ON_NTSTATUS_ERROR(nt_status);
777 nt_status = NT_STATUS_OK;
780 talloc_destroy(frame);
785 /********************************************************************
786 *******************************************************************/
788 static NTSTATUS get_object_id(struct likewise_cell *c,
793 NTSTATUS nt_status = NT_STATUS_OK;
796 /* Figure out which attribute we need to pull */
800 id_attr = ADEX_ATTR_UIDNUM;
803 id_attr = ADEX_ATTR_GIDNUM;
806 nt_status = NT_STATUS_INVALID_PARAMETER;
807 BAIL_ON_NTSTATUS_ERROR(nt_status);
811 nt_status = get_object_uint32(c, msg, id_attr, id);
812 BAIL_ON_NTSTATUS_ERROR(nt_status);
818 /********************************************************************
819 Pull the uid/gid and type from an object. This differs depending on
821 *******************************************************************/
823 static NTSTATUS pull_id(struct likewise_cell *c,
830 nt_status = get_object_type(c, msg, type);
831 BAIL_ON_NTSTATUS_ERROR(nt_status);
833 nt_status = get_object_id(c, msg, *type, id);
834 BAIL_ON_NTSTATUS_ERROR(nt_status);
840 /********************************************************************
841 Pull an attribute string value
842 *******************************************************************/
844 static NTSTATUS get_object_string(struct likewise_cell *c,
850 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
851 char **keywords = NULL;
852 size_t list_size = 0;
853 TALLOC_CTX *frame = talloc_stackframe();
854 ADS_STRUCT *ads = NULL;
858 ads = cell_connection(c);
860 /* Deal with RFC2307 schema */
862 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
863 *string = ads_pull_string(ads, ctx, msg, attrib);
865 /* Non-schema mode */
869 keywords = ads_pull_strings(ads, frame, msg,
870 "keywords", &list_size);
872 nt_status = NT_STATUS_NO_MEMORY;
873 BAIL_ON_NTSTATUS_ERROR(nt_status);
875 s = find_attr_string(keywords, list_size, attrib);
877 *string = talloc_strdup(ctx, s);
882 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
883 BAIL_ON_NTSTATUS_ERROR(nt_status);
886 nt_status = NT_STATUS_OK;
889 talloc_destroy(frame);
894 /********************************************************************
895 Pull the struct passwd fields for a user
896 *******************************************************************/
898 static NTSTATUS pull_nss_info(struct likewise_cell *c,
901 const char **homedir,
909 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, &tmp);
910 BAIL_ON_NTSTATUS_ERROR(nt_status);
913 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, &tmp);
914 BAIL_ON_NTSTATUS_ERROR(nt_status);
917 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, &tmp);
918 /* Gecos is often not set so ignore failures */
921 nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid);
922 BAIL_ON_NTSTATUS_ERROR(nt_status);
928 /********************************************************************
929 Pull the struct passwd fields for a user
930 *******************************************************************/
932 static NTSTATUS pull_alias(struct likewise_cell *c,
937 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
939 const char *attr = NULL;
941 /* Figure out if this is a user or a group */
943 nt_status = get_object_type(c, msg, &type);
944 BAIL_ON_NTSTATUS_ERROR(nt_status);
948 attr = ADEX_ATTR_UID;
951 /* What is the group attr for RFC2307 Forests? */
952 attr = ADEX_ATTR_DISPLAYNAME;
955 nt_status = NT_STATUS_INVALID_PARAMETER;
956 BAIL_ON_NTSTATUS_ERROR(nt_status);
960 nt_status = get_object_string(c, msg, ctx, attr, alias);
961 BAIL_ON_NTSTATUS_ERROR(nt_status);
967 /********************************************************************
968 *******************************************************************/
970 static NTSTATUS _ccp_get_sid_from_id(struct dom_sid * sid,
971 uint32_t id, enum id_type type)
973 struct likewise_cell *cell = NULL;
974 LDAPMessage *msg = NULL;
976 struct lwcell_filter filter;
978 filter.ftype = IdFilter;
979 filter.filter.id.id = id;
980 filter.filter.id.type = type;
982 nt_status = search_cell_list(&cell, &msg, &filter);
983 BAIL_ON_NTSTATUS_ERROR(nt_status);
985 nt_status = pull_sid(cell, msg, sid);
986 BAIL_ON_NTSTATUS_ERROR(nt_status);
989 ads_msgfree(cell->conn, msg);
994 /********************************************************************
995 *******************************************************************/
997 static NTSTATUS _ccp_get_id_from_sid(uint32_t * id,
999 const struct dom_sid * sid)
1001 struct likewise_cell *cell = NULL;
1002 LDAPMessage *msg = NULL;
1004 struct lwcell_filter filter;
1006 filter.ftype = SidFilter;
1007 sid_copy(&filter.filter.sid, sid);
1009 nt_status = search_cell_list(&cell, &msg, &filter);
1010 BAIL_ON_NTSTATUS_ERROR(nt_status);
1012 nt_status = pull_id(cell, msg, id, type);
1013 BAIL_ON_NTSTATUS_ERROR(nt_status);
1015 if (*id < min_id_value()) {
1016 nt_status = NT_STATUS_INVALID_PARAMETER;
1017 BAIL_ON_NTSTATUS_ERROR(nt_status);
1021 ads_msgfree(cell->conn, msg);
1026 /********************************************************************
1027 *******************************************************************/
1029 static NTSTATUS _ccp_nss_get_info(const struct dom_sid * sid,
1031 const char **homedir,
1033 const char **gecos, gid_t * p_gid)
1035 struct likewise_cell *cell = NULL;
1036 LDAPMessage *msg = NULL;
1038 struct lwcell_filter filter;
1041 filter.ftype = SidFilter;
1042 sid_copy(&filter.filter.sid, sid);
1044 nt_status = search_cell_list(&cell, &msg, &filter);
1045 BAIL_ON_NTSTATUS_ERROR(nt_status);
1047 nt_status = get_object_type(cell, msg, &type);
1048 BAIL_ON_NTSTATUS_ERROR(nt_status);
1050 if (type != ID_TYPE_UID) {
1051 nt_status = NT_STATUS_NO_SUCH_USER;
1052 BAIL_ON_NTSTATUS_ERROR(nt_status);
1055 nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos,
1057 BAIL_ON_NTSTATUS_ERROR(nt_status);
1060 ads_msgfree(cell->conn, msg);
1065 /**********************************************************************
1066 *********************************************************************/
1068 static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx,
1070 const char *name, char **alias)
1072 TALLOC_CTX *frame = talloc_stackframe();
1073 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1075 struct likewise_cell *cell = NULL;
1076 LDAPMessage *msg = NULL;
1077 struct lwcell_filter filter;
1078 enum lsa_SidType sid_type;
1080 /* Convert the name to a SID */
1082 nt_status = gc_name_to_sid(domain, name, &sid, &sid_type);
1083 BAIL_ON_NTSTATUS_ERROR(nt_status);
1085 /* Find the user/group */
1087 filter.ftype = SidFilter;
1088 sid_copy(&filter.filter.sid, &sid);
1090 nt_status = search_cell_list(&cell, &msg, &filter);
1091 BAIL_ON_NTSTATUS_ERROR(nt_status);
1093 /* Pull the alias and return */
1095 nt_status = pull_alias(cell, msg, ctx, alias);
1096 BAIL_ON_NTSTATUS_ERROR(nt_status);
1099 PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3);
1101 talloc_destroy(frame);
1102 ads_msgfree(cell_connection(cell), msg);
1107 /**********************************************************************
1108 Map from an alias name to the canonical, qualified name.
1109 Ensure that the alias is only pull from the closest in which
1110 the user or gorup is enabled in
1111 *********************************************************************/
1113 static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx,
1115 const char *alias, char **name)
1117 TALLOC_CTX *frame = talloc_stackframe();
1118 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1120 struct likewise_cell *cell_alias = NULL;
1121 LDAPMessage *msg_alias = NULL;
1122 struct likewise_cell *cell_sid = NULL;
1123 LDAPMessage *msg_sid = NULL;
1124 struct lwcell_filter filter;
1125 char *canonical_name = NULL;
1126 enum lsa_SidType type;
1128 /* Find the user/group */
1130 filter.ftype = AliasFilter;
1131 fstrcpy(filter.filter.alias, alias);
1133 nt_status = search_cell_list(&cell_alias, &msg_alias, &filter);
1134 BAIL_ON_NTSTATUS_ERROR(nt_status);
1136 nt_status = pull_sid(cell_alias, msg_alias, &sid);
1137 BAIL_ON_NTSTATUS_ERROR(nt_status);
1139 /* Now search again for the SID according to the cell list.
1140 Verify that the cell of both search results is the same
1141 so that we only match an alias from the closest cell
1142 in which a user/group has been instantied. */
1144 filter.ftype = SidFilter;
1145 sid_copy(&filter.filter.sid, &sid);
1147 nt_status = search_cell_list(&cell_sid, &msg_sid, &filter);
1148 BAIL_ON_NTSTATUS_ERROR(nt_status);
1150 if (cell_alias != cell_sid) {
1151 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1152 BAIL_ON_NTSTATUS_ERROR(nt_status);
1155 /* Finally do the GC sid/name conversion */
1157 nt_status = gc_sid_to_name(&sid, &canonical_name, &type);
1158 BAIL_ON_NTSTATUS_ERROR(nt_status);
1160 *name = talloc_strdup(mem_ctx, canonical_name);
1161 BAIL_ON_PTR_ERROR((*name), nt_status);
1163 nt_status = NT_STATUS_OK;
1166 PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3);
1168 ads_msgfree(cell_connection(cell_alias), msg_alias);
1169 ads_msgfree(cell_connection(cell_sid), msg_sid);
1171 SAFE_FREE(canonical_name);
1173 talloc_destroy(frame);
1178 /********************************************************************
1179 *******************************************************************/
1181 struct cell_provider_api ccp_unified = {
1182 .get_sid_from_id = _ccp_get_sid_from_id,
1183 .get_id_from_sid = _ccp_get_id_from_sid,
1184 .get_nss_info = _ccp_nss_get_info,
1185 .map_to_alias = _ccp_map_to_alias,
1186 .map_from_alias = _ccp_map_from_alias