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], NULL, 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(&fdata->filter.sid);
487 BAIL_ON_PTR_ERROR(sid_binstr, nt_status);
489 filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr);
490 SAFE_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,
905 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, homedir);
906 BAIL_ON_NTSTATUS_ERROR(nt_status);
908 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, shell);
909 BAIL_ON_NTSTATUS_ERROR(nt_status);
911 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, gecos);
912 /* Gecos is often not set so ignore failures */
914 nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid);
915 BAIL_ON_NTSTATUS_ERROR(nt_status);
921 /********************************************************************
922 Pull the struct passwd fields for a user
923 *******************************************************************/
925 static NTSTATUS pull_alias(struct likewise_cell *c,
930 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
932 const char *attr = NULL;
934 /* Figure out if this is a user or a group */
936 nt_status = get_object_type(c, msg, &type);
937 BAIL_ON_NTSTATUS_ERROR(nt_status);
941 attr = ADEX_ATTR_UID;
944 /* What is the group attr for RFC2307 Forests? */
945 attr = ADEX_ATTR_DISPLAYNAME;
948 nt_status = NT_STATUS_INVALID_PARAMETER;
949 BAIL_ON_NTSTATUS_ERROR(nt_status);
953 nt_status = get_object_string(c, msg, ctx, attr, alias);
954 BAIL_ON_NTSTATUS_ERROR(nt_status);
960 /********************************************************************
961 *******************************************************************/
963 static NTSTATUS _ccp_get_sid_from_id(DOM_SID * sid,
964 uint32_t id, enum id_type type)
966 struct likewise_cell *cell = NULL;
967 LDAPMessage *msg = NULL;
969 struct lwcell_filter filter;
971 filter.ftype = IdFilter;
972 filter.filter.id.id = id;
973 filter.filter.id.type = type;
975 nt_status = search_cell_list(&cell, &msg, &filter);
976 BAIL_ON_NTSTATUS_ERROR(nt_status);
978 nt_status = pull_sid(cell, msg, sid);
979 BAIL_ON_NTSTATUS_ERROR(nt_status);
982 ads_msgfree(cell->conn, msg);
987 /********************************************************************
988 *******************************************************************/
990 static NTSTATUS _ccp_get_id_from_sid(uint32_t * id,
994 struct likewise_cell *cell = NULL;
995 LDAPMessage *msg = NULL;
997 struct lwcell_filter filter;
999 filter.ftype = SidFilter;
1000 sid_copy(&filter.filter.sid, sid);
1002 nt_status = search_cell_list(&cell, &msg, &filter);
1003 BAIL_ON_NTSTATUS_ERROR(nt_status);
1005 nt_status = pull_id(cell, msg, id, type);
1006 BAIL_ON_NTSTATUS_ERROR(nt_status);
1008 if (*id < min_id_value()) {
1009 nt_status = NT_STATUS_INVALID_PARAMETER;
1010 BAIL_ON_NTSTATUS_ERROR(nt_status);
1014 ads_msgfree(cell->conn, msg);
1019 /********************************************************************
1020 *******************************************************************/
1022 static NTSTATUS _ccp_nss_get_info(const DOM_SID * sid,
1026 char **gecos, gid_t * p_gid)
1028 struct likewise_cell *cell = NULL;
1029 LDAPMessage *msg = NULL;
1031 struct lwcell_filter filter;
1034 filter.ftype = SidFilter;
1035 sid_copy(&filter.filter.sid, sid);
1037 nt_status = search_cell_list(&cell, &msg, &filter);
1038 BAIL_ON_NTSTATUS_ERROR(nt_status);
1040 nt_status = get_object_type(cell, msg, &type);
1041 BAIL_ON_NTSTATUS_ERROR(nt_status);
1043 if (type != ID_TYPE_UID) {
1044 nt_status = NT_STATUS_NO_SUCH_USER;
1045 BAIL_ON_NTSTATUS_ERROR(nt_status);
1048 nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos,
1050 BAIL_ON_NTSTATUS_ERROR(nt_status);
1053 ads_msgfree(cell->conn, msg);
1058 /**********************************************************************
1059 *********************************************************************/
1061 static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx,
1063 const char *name, char **alias)
1065 TALLOC_CTX *frame = talloc_stackframe();
1066 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1068 struct likewise_cell *cell = NULL;
1069 LDAPMessage *msg = NULL;
1070 struct lwcell_filter filter;
1071 enum lsa_SidType sid_type;
1073 /* Convert the name to a SID */
1075 nt_status = gc_name_to_sid(domain, name, &sid, &sid_type);
1076 BAIL_ON_NTSTATUS_ERROR(nt_status);
1078 /* Find the user/group */
1080 filter.ftype = SidFilter;
1081 sid_copy(&filter.filter.sid, &sid);
1083 nt_status = search_cell_list(&cell, &msg, &filter);
1084 BAIL_ON_NTSTATUS_ERROR(nt_status);
1086 /* Pull the alias and return */
1088 nt_status = pull_alias(cell, msg, ctx, alias);
1089 BAIL_ON_NTSTATUS_ERROR(nt_status);
1092 PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3);
1094 talloc_destroy(frame);
1095 ads_msgfree(cell_connection(cell), msg);
1100 /**********************************************************************
1101 Map from an alias name to the canonical, qualified name.
1102 Ensure that the alias is only pull from the closest in which
1103 the user or gorup is enabled in
1104 *********************************************************************/
1106 static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx,
1108 const char *alias, char **name)
1110 TALLOC_CTX *frame = talloc_stackframe();
1111 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1113 struct likewise_cell *cell_alias = NULL;
1114 LDAPMessage *msg_alias = NULL;
1115 struct likewise_cell *cell_sid = NULL;
1116 LDAPMessage *msg_sid = NULL;
1117 struct lwcell_filter filter;
1118 char *canonical_name = NULL;
1119 enum lsa_SidType type;
1121 /* Find the user/group */
1123 filter.ftype = AliasFilter;
1124 fstrcpy(filter.filter.alias, alias);
1126 nt_status = search_cell_list(&cell_alias, &msg_alias, &filter);
1127 BAIL_ON_NTSTATUS_ERROR(nt_status);
1129 nt_status = pull_sid(cell_alias, msg_alias, &sid);
1130 BAIL_ON_NTSTATUS_ERROR(nt_status);
1132 /* Now search again for the SID according to the cell list.
1133 Verify that the cell of both search results is the same
1134 so that we only match an alias from the closest cell
1135 in which a user/group has been instantied. */
1137 filter.ftype = SidFilter;
1138 sid_copy(&filter.filter.sid, &sid);
1140 nt_status = search_cell_list(&cell_sid, &msg_sid, &filter);
1141 BAIL_ON_NTSTATUS_ERROR(nt_status);
1143 if (cell_alias != cell_sid) {
1144 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1145 BAIL_ON_NTSTATUS_ERROR(nt_status);
1148 /* Finally do the GC sid/name conversion */
1150 nt_status = gc_sid_to_name(&sid, &canonical_name, &type);
1151 BAIL_ON_NTSTATUS_ERROR(nt_status);
1153 *name = talloc_strdup(mem_ctx, canonical_name);
1154 BAIL_ON_PTR_ERROR((*name), nt_status);
1156 nt_status = NT_STATUS_OK;
1159 PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3);
1161 ads_msgfree(cell_connection(cell_alias), msg_alias);
1162 ads_msgfree(cell_connection(cell_sid), msg_sid);
1164 SAFE_FREE(canonical_name);
1166 talloc_destroy(frame);
1171 /********************************************************************
1172 *******************************************************************/
1174 struct cell_provider_api ccp_unified = {
1175 .get_sid_from_id = _ccp_get_sid_from_id,
1176 .get_id_from_sid = _ccp_get_id_from_sid,
1177 .get_nss_info = _ccp_nss_get_info,
1178 .map_to_alias = _ccp_map_to_alias,
1179 .map_from_alias = _ccp_map_from_alias