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);
442 TALLOC_FREE(entry_dn);
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;
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(fdata->filter.id.id,
494 fdata->filter.id.type, flags);
497 filter = build_alias_filter(fdata->filter.alias, flags);
501 /* First find the sparse object in GC */
502 nt_status = gc_search_forest(gc, &m, filter);
503 if (!NT_STATUS_IS_OK(nt_status)) {
508 nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
509 m, &ads_list, &msg_list,
511 BAIL_ON_NTSTATUS_ERROR(nt_status);
516 /* Uniqueness check across forests */
518 nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp,
520 BAIL_ON_NTSTATUS_ERROR(nt_status);
522 nt_status = search_domain(&domain_cell, &m, dn, &user_sid);
523 BAIL_ON_NTSTATUS_ERROR(nt_status);
525 /* Save the connection and results in the return parameters */
527 forest_cell->gc_search_cell = domain_cell;
531 PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4);
535 free_result_array(ads_list, msg_list, num_resp);
536 talloc_destroy(frame);
541 /********************************************************************
542 *******************************************************************/
544 static NTSTATUS search_cell_list(struct likewise_cell **c,
546 const struct lwcell_filter *fdata)
548 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
549 struct likewise_cell *cell = NULL;
550 LDAPMessage *msg = NULL;
551 struct likewise_cell *result_cell = NULL;
553 if ((cell = cell_list_head()) == NULL) {
554 nt_status = NT_STATUS_INVALID_SERVER_STATE;
555 BAIL_ON_NTSTATUS_ERROR(nt_status);
559 /* Clear any previous GC search results */
561 cell->gc_search_cell = NULL;
563 if (cell_search_forest(cell)) {
564 nt_status = search_forest(cell, &msg, fdata);
566 nt_status = search_cell(cell, &msg, fdata);
569 /* Always point to the search result cell.
570 In forests this might be for another domain
571 which means the schema model may be different */
573 result_cell = cell->gc_search_cell ?
574 cell->gc_search_cell : cell;
576 /* Check if we are done */
578 if (NT_STATUS_IS_OK(nt_status)) {
582 /* No luck. Free memory and hit the next cell.
583 Forest searches always set the gc_search_cell
584 so give preference to that connection if possible. */
586 ads_msgfree(cell_connection(result_cell), msg);
592 /* This might be assigning NULL but that is ok as long as we
593 give back the proper error code */
599 PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3);
604 /********************************************************************
605 Pull the SID from an object which is always stored in the keywords
606 attribute as "backLink=S-1-5-21-..."
607 *******************************************************************/
609 static NTSTATUS pull_sid(struct likewise_cell *c,
613 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
614 TALLOC_CTX *frame = talloc_stackframe();
615 ADS_STRUCT *ads = NULL;
617 ads = cell_connection(c);
620 We have two ways of getting the sid:
621 (a) from the objectSID in case of a GC search,
622 (b) from backLink in the case of a cell search.
623 Pull the keywords attributes and grab the backLink.
626 if (!ads_pull_sid(ads, msg, "objectSid", sid)) {
629 size_t num_lines = 0;
631 keywords = ads_pull_strings(ads, frame, msg,
632 "keywords", &num_lines);
633 BAIL_ON_PTR_ERROR(keywords, nt_status);
635 s = find_attr_string(keywords, num_lines, "backLink");
637 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
638 BAIL_ON_NTSTATUS_ERROR(nt_status);
641 if (!string_to_sid(sid, s)) {
642 nt_status = NT_STATUS_INVALID_SID;
643 BAIL_ON_NTSTATUS_ERROR(nt_status);
647 nt_status = NT_STATUS_OK;
650 talloc_destroy(frame);
655 /********************************************************************
656 *******************************************************************/
658 static NTSTATUS get_object_type(struct likewise_cell *c,
662 TALLOC_CTX *ctx = talloc_stackframe();
663 char **oc_list = NULL;
664 NTSTATUS nt_status = NT_STATUS_OK;
665 size_t list_size = 0;
667 ADS_STRUCT *ads = NULL;
669 ads = cell_connection(c);
671 /* Deal with RFC 2307 support first */
673 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
674 oc_list = ads_pull_strings(ads, ctx, msg,
675 "objectClass", &list_size);
677 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
681 /* Check for posix classes and AD classes */
683 if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER)
684 || is_object_class(oc_list, list_size, AD_USER)) {
686 } else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP)
687 || is_object_class(oc_list, list_size, AD_GROUP)) {
690 *type = ID_TYPE_NOT_SPECIFIED;
691 nt_status = NT_STATUS_INVALID_PARAMETER;
694 /* Default to non-schema mode */
696 oc_list = ads_pull_strings(ads, ctx, msg,
697 "keywords", &list_size);
699 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
703 s = find_attr_string(oc_list, list_size, "objectClass");
705 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
709 if (strequal(s, ADEX_OC_USER)) {
711 } else if (strequal(s, ADEX_OC_GROUP)) {
714 *type = ID_TYPE_NOT_SPECIFIED;
715 nt_status = NT_STATUS_INVALID_PARAMETER;
719 nt_status = NT_STATUS_OK;
727 /********************************************************************
728 Pull an attribute uint32_t value
729 *******************************************************************/
731 static NTSTATUS get_object_uint32(struct likewise_cell *c,
736 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
737 char **keywords = NULL;
738 size_t list_size = 0;
739 TALLOC_CTX *frame = talloc_stackframe();
740 ADS_STRUCT *ads = NULL;
742 ads = cell_connection(c);
744 /* Deal with RFC2307 schema */
746 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
747 if (!ads_pull_uint32(ads, msg, attrib, x)) {
748 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
749 BAIL_ON_NTSTATUS_ERROR(nt_status);
752 /* Non-schema mode */
756 keywords = ads_pull_strings(ads, frame, msg, "keywords",
758 BAIL_ON_PTR_ERROR(keywords, nt_status);
760 s = find_attr_string(keywords, list_size, attrib);
762 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
763 BAIL_ON_NTSTATUS_ERROR(nt_status);
766 num = strtoll(s, NULL, 10);
767 if (errno == ERANGE) {
768 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
769 BAIL_ON_NTSTATUS_ERROR(nt_status);
774 nt_status = NT_STATUS_OK;
777 talloc_destroy(frame);
782 /********************************************************************
783 *******************************************************************/
785 static NTSTATUS get_object_id(struct likewise_cell *c,
790 NTSTATUS nt_status = NT_STATUS_OK;
793 /* Figure out which attribute we need to pull */
797 id_attr = ADEX_ATTR_UIDNUM;
800 id_attr = ADEX_ATTR_GIDNUM;
803 nt_status = NT_STATUS_INVALID_PARAMETER;
804 BAIL_ON_NTSTATUS_ERROR(nt_status);
808 nt_status = get_object_uint32(c, msg, id_attr, id);
809 BAIL_ON_NTSTATUS_ERROR(nt_status);
815 /********************************************************************
816 Pull the uid/gid and type from an object. This differs depending on
818 *******************************************************************/
820 static NTSTATUS pull_id(struct likewise_cell *c,
827 nt_status = get_object_type(c, msg, type);
828 BAIL_ON_NTSTATUS_ERROR(nt_status);
830 nt_status = get_object_id(c, msg, *type, id);
831 BAIL_ON_NTSTATUS_ERROR(nt_status);
837 /********************************************************************
838 Pull an attribute string value
839 *******************************************************************/
841 static NTSTATUS get_object_string(struct likewise_cell *c,
847 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
848 char **keywords = NULL;
849 size_t list_size = 0;
850 TALLOC_CTX *frame = talloc_stackframe();
851 ADS_STRUCT *ads = NULL;
855 ads = cell_connection(c);
857 /* Deal with RFC2307 schema */
859 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
860 *string = ads_pull_string(ads, ctx, msg, attrib);
862 /* Non-schema mode */
866 keywords = ads_pull_strings(ads, frame, msg,
867 "keywords", &list_size);
869 nt_status = NT_STATUS_NO_MEMORY;
870 BAIL_ON_NTSTATUS_ERROR(nt_status);
872 s = find_attr_string(keywords, list_size, attrib);
874 *string = talloc_strdup(ctx, s);
879 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
880 BAIL_ON_NTSTATUS_ERROR(nt_status);
883 nt_status = NT_STATUS_OK;
886 talloc_destroy(frame);
891 /********************************************************************
892 Pull the struct passwd fields for a user
893 *******************************************************************/
895 static NTSTATUS pull_nss_info(struct likewise_cell *c,
898 const char **homedir,
906 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, &tmp);
907 BAIL_ON_NTSTATUS_ERROR(nt_status);
910 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, &tmp);
911 BAIL_ON_NTSTATUS_ERROR(nt_status);
914 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, &tmp);
915 /* Gecos is often not set so ignore failures */
918 nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid);
919 BAIL_ON_NTSTATUS_ERROR(nt_status);
925 /********************************************************************
926 Pull the struct passwd fields for a user
927 *******************************************************************/
929 static NTSTATUS pull_alias(struct likewise_cell *c,
934 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
936 const char *attr = NULL;
938 /* Figure out if this is a user or a group */
940 nt_status = get_object_type(c, msg, &type);
941 BAIL_ON_NTSTATUS_ERROR(nt_status);
945 attr = ADEX_ATTR_UID;
948 /* What is the group attr for RFC2307 Forests? */
949 attr = ADEX_ATTR_DISPLAYNAME;
952 nt_status = NT_STATUS_INVALID_PARAMETER;
953 BAIL_ON_NTSTATUS_ERROR(nt_status);
957 nt_status = get_object_string(c, msg, ctx, attr, alias);
958 BAIL_ON_NTSTATUS_ERROR(nt_status);
964 /********************************************************************
965 *******************************************************************/
967 static NTSTATUS _ccp_get_sid_from_id(DOM_SID * sid,
968 uint32_t id, enum id_type type)
970 struct likewise_cell *cell = NULL;
971 LDAPMessage *msg = NULL;
973 struct lwcell_filter filter;
975 filter.ftype = IdFilter;
976 filter.filter.id.id = id;
977 filter.filter.id.type = type;
979 nt_status = search_cell_list(&cell, &msg, &filter);
980 BAIL_ON_NTSTATUS_ERROR(nt_status);
982 nt_status = pull_sid(cell, msg, sid);
983 BAIL_ON_NTSTATUS_ERROR(nt_status);
986 ads_msgfree(cell->conn, msg);
991 /********************************************************************
992 *******************************************************************/
994 static NTSTATUS _ccp_get_id_from_sid(uint32_t * id,
998 struct likewise_cell *cell = NULL;
999 LDAPMessage *msg = NULL;
1001 struct lwcell_filter filter;
1003 filter.ftype = SidFilter;
1004 sid_copy(&filter.filter.sid, sid);
1006 nt_status = search_cell_list(&cell, &msg, &filter);
1007 BAIL_ON_NTSTATUS_ERROR(nt_status);
1009 nt_status = pull_id(cell, msg, id, type);
1010 BAIL_ON_NTSTATUS_ERROR(nt_status);
1012 if (*id < min_id_value()) {
1013 nt_status = NT_STATUS_INVALID_PARAMETER;
1014 BAIL_ON_NTSTATUS_ERROR(nt_status);
1018 ads_msgfree(cell->conn, msg);
1023 /********************************************************************
1024 *******************************************************************/
1026 static NTSTATUS _ccp_nss_get_info(const DOM_SID * sid,
1028 const char **homedir,
1030 const char **gecos, gid_t * p_gid)
1032 struct likewise_cell *cell = NULL;
1033 LDAPMessage *msg = NULL;
1035 struct lwcell_filter filter;
1038 filter.ftype = SidFilter;
1039 sid_copy(&filter.filter.sid, sid);
1041 nt_status = search_cell_list(&cell, &msg, &filter);
1042 BAIL_ON_NTSTATUS_ERROR(nt_status);
1044 nt_status = get_object_type(cell, msg, &type);
1045 BAIL_ON_NTSTATUS_ERROR(nt_status);
1047 if (type != ID_TYPE_UID) {
1048 nt_status = NT_STATUS_NO_SUCH_USER;
1049 BAIL_ON_NTSTATUS_ERROR(nt_status);
1052 nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos,
1054 BAIL_ON_NTSTATUS_ERROR(nt_status);
1057 ads_msgfree(cell->conn, msg);
1062 /**********************************************************************
1063 *********************************************************************/
1065 static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx,
1067 const char *name, char **alias)
1069 TALLOC_CTX *frame = talloc_stackframe();
1070 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1072 struct likewise_cell *cell = NULL;
1073 LDAPMessage *msg = NULL;
1074 struct lwcell_filter filter;
1075 enum lsa_SidType sid_type;
1077 /* Convert the name to a SID */
1079 nt_status = gc_name_to_sid(domain, name, &sid, &sid_type);
1080 BAIL_ON_NTSTATUS_ERROR(nt_status);
1082 /* Find the user/group */
1084 filter.ftype = SidFilter;
1085 sid_copy(&filter.filter.sid, &sid);
1087 nt_status = search_cell_list(&cell, &msg, &filter);
1088 BAIL_ON_NTSTATUS_ERROR(nt_status);
1090 /* Pull the alias and return */
1092 nt_status = pull_alias(cell, msg, ctx, alias);
1093 BAIL_ON_NTSTATUS_ERROR(nt_status);
1096 PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3);
1098 talloc_destroy(frame);
1099 ads_msgfree(cell_connection(cell), msg);
1104 /**********************************************************************
1105 Map from an alias name to the canonical, qualified name.
1106 Ensure that the alias is only pull from the closest in which
1107 the user or gorup is enabled in
1108 *********************************************************************/
1110 static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx,
1112 const char *alias, char **name)
1114 TALLOC_CTX *frame = talloc_stackframe();
1115 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1117 struct likewise_cell *cell_alias = NULL;
1118 LDAPMessage *msg_alias = NULL;
1119 struct likewise_cell *cell_sid = NULL;
1120 LDAPMessage *msg_sid = NULL;
1121 struct lwcell_filter filter;
1122 char *canonical_name = NULL;
1123 enum lsa_SidType type;
1125 /* Find the user/group */
1127 filter.ftype = AliasFilter;
1128 fstrcpy(filter.filter.alias, alias);
1130 nt_status = search_cell_list(&cell_alias, &msg_alias, &filter);
1131 BAIL_ON_NTSTATUS_ERROR(nt_status);
1133 nt_status = pull_sid(cell_alias, msg_alias, &sid);
1134 BAIL_ON_NTSTATUS_ERROR(nt_status);
1136 /* Now search again for the SID according to the cell list.
1137 Verify that the cell of both search results is the same
1138 so that we only match an alias from the closest cell
1139 in which a user/group has been instantied. */
1141 filter.ftype = SidFilter;
1142 sid_copy(&filter.filter.sid, &sid);
1144 nt_status = search_cell_list(&cell_sid, &msg_sid, &filter);
1145 BAIL_ON_NTSTATUS_ERROR(nt_status);
1147 if (cell_alias != cell_sid) {
1148 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1149 BAIL_ON_NTSTATUS_ERROR(nt_status);
1152 /* Finally do the GC sid/name conversion */
1154 nt_status = gc_sid_to_name(&sid, &canonical_name, &type);
1155 BAIL_ON_NTSTATUS_ERROR(nt_status);
1157 *name = talloc_strdup(mem_ctx, canonical_name);
1158 BAIL_ON_PTR_ERROR((*name), nt_status);
1160 nt_status = NT_STATUS_OK;
1163 PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3);
1165 ads_msgfree(cell_connection(cell_alias), msg_alias);
1166 ads_msgfree(cell_connection(cell_sid), msg_sid);
1168 SAFE_FREE(canonical_name);
1170 talloc_destroy(frame);
1175 /********************************************************************
1176 *******************************************************************/
1178 struct cell_provider_api ccp_unified = {
1179 .get_sid_from_id = _ccp_get_sid_from_id,
1180 .get_id_from_sid = _ccp_get_id_from_sid,
1181 .get_nss_info = _ccp_nss_get_info,
1182 .map_to_alias = _ccp_map_to_alias,
1183 .map_from_alias = _ccp_map_from_alias