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.
26 #include "idmap_adex.h"
27 #include "../libcli/ldap/ldap_ndr.h"
28 #include "../libcli/security/dom_sid.h"
31 #define DBGC_CLASS DBGC_IDMAP
33 /* Information needed by the LDAP search filters */
35 enum filterType { SidFilter, IdFilter, AliasFilter };
39 enum filterType ftype;
51 /********************************************************************
52 *******************************************************************/
54 static char* build_id_filter(TALLOC_CTX *mem_ctx,
57 uint32_t search_flags)
60 char *oc_filter, *attr_filter;
62 TALLOC_CTX *frame = talloc_stackframe();
63 bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
64 == LWCELL_FLAG_USE_RFC2307_ATTRS);
65 bool use_gc = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
66 == LWCELL_FLAG_SEARCH_FOREST);
69 /* Construct search filter for objectclass and attributes */
75 oc = ADEX_OC_POSIX_USER;
80 oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
81 attr_filter = talloc_asprintf(frame, "%s=%u",
82 ADEX_ATTR_UIDNUM, id);
88 oc = ADEX_OC_POSIX_GROUP;
93 oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
94 attr_filter = talloc_asprintf(frame, "%s=%u",
95 ADEX_ATTR_GIDNUM, id);
101 BAIL_ON_PTR_ERROR(oc_filter, nt_status);
102 BAIL_ON_PTR_ERROR(attr_filter, nt_status);
104 /* Use "keywords=%s" for non-schema cells */
107 filter = talloc_asprintf(mem_ctx,
112 filter = talloc_asprintf(mem_ctx,
113 "(&(keywords=%s)(keywords=%s))",
119 talloc_destroy(frame);
124 /********************************************************************
125 *******************************************************************/
127 static char* build_alias_filter(TALLOC_CTX *mem_ctx,
129 uint32_t search_flags)
132 char *user_attr_filter, *group_attr_filter;
134 TALLOC_CTX *frame = talloc_stackframe();
135 bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
136 == LWCELL_FLAG_USE_RFC2307_ATTRS);
137 bool search_forest = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
138 == LWCELL_FLAG_SEARCH_FOREST);
140 /* Construct search filter for objectclass and attributes */
142 user_attr_filter = talloc_asprintf(frame, "%s=%s",
143 ADEX_ATTR_UID, alias);
144 group_attr_filter = talloc_asprintf(frame, "%s=%s",
145 ADEX_ATTR_DISPLAYNAME, alias);
146 BAIL_ON_PTR_ERROR(user_attr_filter, nt_status);
147 BAIL_ON_PTR_ERROR(group_attr_filter, nt_status);
149 /* Use "keywords=%s" for non-schema cells */
152 filter = talloc_asprintf(mem_ctx,
153 "(|(&(%s)(objectclass=%s))(&(%s)(objectclass=%s)))",
155 search_forest ? AD_USER : ADEX_OC_POSIX_USER,
157 search_forest ? AD_GROUP : ADEX_OC_POSIX_GROUP);
159 filter = talloc_asprintf(mem_ctx,
160 "(|(keywords=%s)(keywords=%s))",
166 talloc_destroy(frame);
172 /********************************************************************
173 *******************************************************************/
175 static NTSTATUS search_cell(struct likewise_cell *c,
177 const struct lwcell_filter *fdata)
179 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
180 TALLOC_CTX* frame = talloc_stackframe();
182 const char *base = NULL;
183 ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
184 const char *attrs[] = { "*", NULL };
188 /* get the filter and other search parameters */
190 switch (fdata->ftype) {
192 sid_str = sid_string_talloc(frame, &fdata->filter.sid);
193 BAIL_ON_PTR_ERROR(sid_str, nt_status);
195 filter = talloc_asprintf(frame, "(keywords=backLink=%s)",
199 filter = build_id_filter(frame,
201 fdata->filter.id.type,
205 filter = build_alias_filter(frame,
210 nt_status = NT_STATUS_INVALID_PARAMETER;
213 BAIL_ON_PTR_ERROR(filter, nt_status);
215 base = cell_search_base(c);
216 BAIL_ON_PTR_ERROR(base, nt_status);
218 ads_status = cell_do_search(c, base, LDAP_SCOPE_SUBTREE,
221 nt_status = ads_ntstatus(ads_status);
222 BAIL_ON_NTSTATUS_ERROR(nt_status);
224 /* Now check that we got only one reply */
226 count = ads_count_replies(c->conn, *msg);
228 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
229 BAIL_ON_NTSTATUS_ERROR(nt_status);
233 nt_status = NT_STATUS_DUPLICATE_NAME;
234 BAIL_ON_NTSTATUS_ERROR(nt_status);
238 PRINT_NTSTATUS_ERROR(nt_status, "search_cell", 4);
240 talloc_destroy(discard_const_p(char, base));
241 talloc_destroy(frame);
246 /********************************************************************
247 *******************************************************************/
249 static NTSTATUS search_domain(struct likewise_cell **cell,
252 const struct dom_sid *sid)
254 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
255 TALLOC_CTX* frame = talloc_stackframe();
258 nt_status = dc_search_domains(cell, msg, dn, sid);
259 BAIL_ON_NTSTATUS_ERROR(nt_status);
261 /* Now check that we got only one reply */
263 count = ads_count_replies(cell_connection(*cell), *msg);
265 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
266 BAIL_ON_NTSTATUS_ERROR(nt_status);
270 nt_status = NT_STATUS_DUPLICATE_NAME;
271 BAIL_ON_NTSTATUS_ERROR(nt_status);
275 PRINT_NTSTATUS_ERROR(nt_status, "search_domain", 4);
276 talloc_destroy(frame);
282 /********************************************************************
283 Check that a DN is within the forest scope.
284 *******************************************************************/
286 static bool check_forest_scope(const char *dn)
288 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
289 TALLOC_CTX *frame = talloc_stackframe();
292 char *dns_domain = NULL;
293 struct winbindd_tdc_domain *domain;
295 /* If the DN does *not* contain "$LikewiseIdentityCell",
296 assume this is a schema mode forest and it is in the
297 forest scope by definition. */
299 if ((p = strstr_m(dn, ADEX_CELL_RDN)) == NULL) {
300 nt_status = NT_STATUS_OK;
304 /* If this is a non-schema forest, then make sure that the DN
305 is in the form "...,cn=$LikewiseIdentityCell,DC=..." */
307 if ((q = strchr_m(p, ',')) == NULL) {
308 nt_status = NT_STATUS_OBJECT_NAME_INVALID;
309 BAIL_ON_NTSTATUS_ERROR(nt_status);
313 if (strncasecmp_m(q, "dc=", 3) != 0) {
314 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
315 BAIL_ON_NTSTATUS_ERROR(nt_status);
319 dns_domain = cell_dn_to_dns(q);
320 BAIL_ON_PTR_ERROR(dns_domain, nt_status);
322 domain = wcache_tdc_fetch_domain(frame, dns_domain);
324 nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
325 BAIL_ON_NTSTATUS_ERROR(nt_status);
328 nt_status = NT_STATUS_OK;
331 talloc_destroy(frame);
332 SAFE_FREE(dns_domain);
334 return NT_STATUS_IS_OK(nt_status);
339 /********************************************************************
340 Check that only one result was returned within the forest cell
342 *******************************************************************/
344 static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list,
345 LDAPMessage **msg_list,
348 struct dom_sid *user_sid)
350 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
352 ADS_STRUCT *ads = NULL;
353 LDAPMessage *msg = NULL;
355 char *entry_dn = NULL;
356 TALLOC_CTX *frame = talloc_stackframe();
358 if (!dn || !user_sid) {
359 nt_status = NT_STATUS_INVALID_PARAMETER;
360 BAIL_ON_NTSTATUS_ERROR(nt_status);
365 if (!ads_list || !msg_list || (num_resp == 0)) {
366 nt_status = NT_STATUS_NO_SUCH_FILE;
367 BAIL_ON_NTSTATUS_ERROR(nt_status);
370 /* Loop over all msgs */
372 for (i=0; i<num_resp; i++) {
373 LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]);
376 entry_dn = ads_get_dn(ads_list[i], talloc_tos(), e);
377 BAIL_ON_PTR_ERROR(entry_dn, nt_status);
379 if (check_forest_scope(entry_dn)) {
382 /* If we've already broken the condition, no
386 nt_status = NT_STATUS_DUPLICATE_NAME;
387 BAIL_ON_NTSTATUS_ERROR(nt_status);
392 *dn = SMB_STRDUP(entry_dn);
393 BAIL_ON_PTR_ERROR((*dn), nt_status);
396 e = ads_next_entry(ads_list[i], e);
397 TALLOC_FREE(entry_dn);
402 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
403 BAIL_ON_NTSTATUS_ERROR(nt_status);
406 /* If we made is through the loop, then grab the user_sid and
410 Try and get the SID from either objectSid or keywords.
411 We cannot use pull_sid() here since we want to try
412 both methods and not only one or the other (and we
413 have no full likewise_cell struct.
415 Fail if both are unavailable
418 if (!ads_pull_sid(ads, msg, "objectSid", user_sid)) {
421 size_t num_lines = 0;
423 keywords = ads_pull_strings(ads, frame, msg, "keywords",
425 BAIL_ON_PTR_ERROR(keywords, nt_status);
427 s = find_attr_string(keywords, num_lines, "backLink");
429 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
430 BAIL_ON_NTSTATUS_ERROR(nt_status);
433 if (!string_to_sid(user_sid, s)) {
434 nt_status = NT_STATUS_INVALID_SID;
435 BAIL_ON_NTSTATUS_ERROR(nt_status);
439 nt_status = NT_STATUS_OK;
442 if (!NT_STATUS_IS_OK(nt_status)) {
446 talloc_destroy(frame);
451 /********************************************************************
452 Search all forests. Each forest can have it's own forest-cell
453 settings so we have to generate the filter for each search.
454 We don't use gc_search_all_forests() since we may have a different
455 schema model in each forest and need to construct the search
456 filter for each GC search.
457 *******************************************************************/
459 static NTSTATUS search_forest(struct likewise_cell *forest_cell,
461 const struct lwcell_filter *fdata)
463 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
464 TALLOC_CTX *frame = talloc_stackframe();
467 struct gc_info *gc = NULL;
468 ADS_STRUCT **ads_list = NULL;
469 LDAPMessage **msg_list = NULL;
472 struct dom_sid user_sid;
473 struct likewise_cell *domain_cell = NULL;
475 if ((gc = gc_search_start()) == NULL) {
476 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
477 BAIL_ON_NTSTATUS_ERROR(nt_status);
481 char *sid_binstr = NULL;
482 uint32_t flags = LWCELL_FLAG_SEARCH_FOREST;
486 flags |= cell_flags(gc->forest_cell);
488 switch (fdata->ftype) {
490 sid_binstr = ldap_encode_ndr_dom_sid(frame, &fdata->filter.sid);
491 BAIL_ON_PTR_ERROR(sid_binstr, nt_status);
493 filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr);
494 TALLOC_FREE(sid_binstr);
497 filter = build_id_filter(frame,
499 fdata->filter.id.type, flags);
502 filter = build_alias_filter(frame,
508 /* First find the sparse object in GC */
509 nt_status = gc_search_forest(gc, &m, filter);
510 if (!NT_STATUS_IS_OK(nt_status)) {
515 nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
516 m, &ads_list, &msg_list,
518 BAIL_ON_NTSTATUS_ERROR(nt_status);
523 /* Uniqueness check across forests */
525 nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp,
527 BAIL_ON_NTSTATUS_ERROR(nt_status);
529 nt_status = search_domain(&domain_cell, &m, dn, &user_sid);
530 BAIL_ON_NTSTATUS_ERROR(nt_status);
532 /* Save the connection and results in the return parameters */
534 forest_cell->gc_search_cell = domain_cell;
538 PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4);
542 free_result_array(ads_list, msg_list, num_resp);
543 talloc_destroy(frame);
548 /********************************************************************
549 *******************************************************************/
551 static NTSTATUS search_cell_list(struct likewise_cell **c,
553 const struct lwcell_filter *fdata)
555 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
556 struct likewise_cell *cell = NULL;
557 LDAPMessage *msg = NULL;
558 struct likewise_cell *result_cell = NULL;
560 if ((cell = cell_list_head()) == NULL) {
561 nt_status = NT_STATUS_INVALID_SERVER_STATE;
562 BAIL_ON_NTSTATUS_ERROR(nt_status);
566 /* Clear any previous GC search results */
568 cell->gc_search_cell = NULL;
570 if (cell_search_forest(cell)) {
571 nt_status = search_forest(cell, &msg, fdata);
573 nt_status = search_cell(cell, &msg, fdata);
576 /* Always point to the search result cell.
577 In forests this might be for another domain
578 which means the schema model may be different */
580 result_cell = cell->gc_search_cell ?
581 cell->gc_search_cell : cell;
583 /* Check if we are done */
585 if (NT_STATUS_IS_OK(nt_status)) {
589 /* No luck. Free memory and hit the next cell.
590 Forest searches always set the gc_search_cell
591 so give preference to that connection if possible. */
593 ads_msgfree(cell_connection(result_cell), msg);
599 /* This might be assigning NULL but that is ok as long as we
600 give back the proper error code */
606 PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3);
611 /********************************************************************
612 Pull the SID from an object which is always stored in the keywords
613 attribute as "backLink=S-1-5-21-..."
614 *******************************************************************/
616 static NTSTATUS pull_sid(struct likewise_cell *c,
620 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
621 TALLOC_CTX *frame = talloc_stackframe();
622 ADS_STRUCT *ads = NULL;
624 ads = cell_connection(c);
627 We have two ways of getting the sid:
628 (a) from the objectSID in case of a GC search,
629 (b) from backLink in the case of a cell search.
630 Pull the keywords attributes and grab the backLink.
633 if (!ads_pull_sid(ads, msg, "objectSid", sid)) {
636 size_t num_lines = 0;
638 keywords = ads_pull_strings(ads, frame, msg,
639 "keywords", &num_lines);
640 BAIL_ON_PTR_ERROR(keywords, nt_status);
642 s = find_attr_string(keywords, num_lines, "backLink");
644 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
645 BAIL_ON_NTSTATUS_ERROR(nt_status);
648 if (!string_to_sid(sid, s)) {
649 nt_status = NT_STATUS_INVALID_SID;
650 BAIL_ON_NTSTATUS_ERROR(nt_status);
654 nt_status = NT_STATUS_OK;
657 talloc_destroy(frame);
662 /********************************************************************
663 *******************************************************************/
665 static NTSTATUS get_object_type(struct likewise_cell *c,
669 TALLOC_CTX *ctx = talloc_stackframe();
670 char **oc_list = NULL;
671 NTSTATUS nt_status = NT_STATUS_OK;
672 size_t list_size = 0;
674 ADS_STRUCT *ads = NULL;
676 ads = cell_connection(c);
678 /* Deal with RFC 2307 support first */
680 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
681 oc_list = ads_pull_strings(ads, ctx, msg,
682 "objectClass", &list_size);
684 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
688 /* Check for posix classes and AD classes */
690 if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER)
691 || is_object_class(oc_list, list_size, AD_USER)) {
693 } else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP)
694 || is_object_class(oc_list, list_size, AD_GROUP)) {
697 *type = ID_TYPE_NOT_SPECIFIED;
698 nt_status = NT_STATUS_INVALID_PARAMETER;
701 /* Default to non-schema mode */
703 oc_list = ads_pull_strings(ads, ctx, msg,
704 "keywords", &list_size);
706 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
710 s = find_attr_string(oc_list, list_size, "objectClass");
712 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
716 if (strequal(s, ADEX_OC_USER)) {
718 } else if (strequal(s, ADEX_OC_GROUP)) {
721 *type = ID_TYPE_NOT_SPECIFIED;
722 nt_status = NT_STATUS_INVALID_PARAMETER;
726 nt_status = NT_STATUS_OK;
734 /********************************************************************
735 Pull an attribute uint32_t value
736 *******************************************************************/
738 static NTSTATUS get_object_uint32(struct likewise_cell *c,
743 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
744 char **keywords = NULL;
745 size_t list_size = 0;
746 TALLOC_CTX *frame = talloc_stackframe();
747 ADS_STRUCT *ads = NULL;
749 ads = cell_connection(c);
751 /* Deal with RFC2307 schema */
753 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
754 if (!ads_pull_uint32(ads, msg, attrib, x)) {
755 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
756 BAIL_ON_NTSTATUS_ERROR(nt_status);
759 /* Non-schema mode */
763 keywords = ads_pull_strings(ads, frame, msg, "keywords",
765 BAIL_ON_PTR_ERROR(keywords, nt_status);
767 s = find_attr_string(keywords, list_size, attrib);
769 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
770 BAIL_ON_NTSTATUS_ERROR(nt_status);
773 num = strtoll(s, NULL, 10);
774 if (errno == ERANGE) {
775 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
776 BAIL_ON_NTSTATUS_ERROR(nt_status);
781 nt_status = NT_STATUS_OK;
784 talloc_destroy(frame);
789 /********************************************************************
790 *******************************************************************/
792 static NTSTATUS get_object_id(struct likewise_cell *c,
797 NTSTATUS nt_status = NT_STATUS_OK;
800 /* Figure out which attribute we need to pull */
804 id_attr = ADEX_ATTR_UIDNUM;
807 id_attr = ADEX_ATTR_GIDNUM;
810 nt_status = NT_STATUS_INVALID_PARAMETER;
811 BAIL_ON_NTSTATUS_ERROR(nt_status);
815 nt_status = get_object_uint32(c, msg, id_attr, id);
816 BAIL_ON_NTSTATUS_ERROR(nt_status);
822 /********************************************************************
823 Pull the uid/gid and type from an object. This differs depending on
825 *******************************************************************/
827 static NTSTATUS pull_id(struct likewise_cell *c,
834 nt_status = get_object_type(c, msg, type);
835 BAIL_ON_NTSTATUS_ERROR(nt_status);
837 nt_status = get_object_id(c, msg, *type, id);
838 BAIL_ON_NTSTATUS_ERROR(nt_status);
844 /********************************************************************
845 Pull an attribute string value
846 *******************************************************************/
848 static NTSTATUS get_object_string(struct likewise_cell *c,
854 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
855 char **keywords = NULL;
856 size_t list_size = 0;
857 TALLOC_CTX *frame = talloc_stackframe();
858 ADS_STRUCT *ads = NULL;
862 ads = cell_connection(c);
864 /* Deal with RFC2307 schema */
866 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
867 *string = ads_pull_string(ads, ctx, msg, attrib);
869 /* Non-schema mode */
873 keywords = ads_pull_strings(ads, frame, msg,
874 "keywords", &list_size);
876 nt_status = NT_STATUS_NO_MEMORY;
877 BAIL_ON_NTSTATUS_ERROR(nt_status);
879 s = find_attr_string(keywords, list_size, attrib);
881 *string = talloc_strdup(ctx, s);
886 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
887 BAIL_ON_NTSTATUS_ERROR(nt_status);
890 nt_status = NT_STATUS_OK;
893 talloc_destroy(frame);
898 /********************************************************************
899 Pull the struct passwd fields for a user
900 *******************************************************************/
902 static NTSTATUS pull_nss_info(struct likewise_cell *c,
905 const char **homedir,
913 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, &tmp);
914 BAIL_ON_NTSTATUS_ERROR(nt_status);
917 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, &tmp);
918 BAIL_ON_NTSTATUS_ERROR(nt_status);
921 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, &tmp);
922 /* Gecos is often not set so ignore failures */
925 nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid);
926 BAIL_ON_NTSTATUS_ERROR(nt_status);
932 /********************************************************************
933 Pull the struct passwd fields for a user
934 *******************************************************************/
936 static NTSTATUS pull_alias(struct likewise_cell *c,
941 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
943 const char *attr = NULL;
945 /* Figure out if this is a user or a group */
947 nt_status = get_object_type(c, msg, &type);
948 BAIL_ON_NTSTATUS_ERROR(nt_status);
952 attr = ADEX_ATTR_UID;
955 /* What is the group attr for RFC2307 Forests? */
956 attr = ADEX_ATTR_DISPLAYNAME;
959 nt_status = NT_STATUS_INVALID_PARAMETER;
960 BAIL_ON_NTSTATUS_ERROR(nt_status);
964 nt_status = get_object_string(c, msg, ctx, attr, alias);
965 BAIL_ON_NTSTATUS_ERROR(nt_status);
971 /********************************************************************
972 *******************************************************************/
974 static NTSTATUS _ccp_get_sid_from_id(struct dom_sid * sid,
975 uint32_t id, enum id_type type)
977 struct likewise_cell *cell = NULL;
978 LDAPMessage *msg = NULL;
980 struct lwcell_filter filter;
982 filter.ftype = IdFilter;
983 filter.filter.id.id = id;
984 filter.filter.id.type = type;
986 nt_status = search_cell_list(&cell, &msg, &filter);
987 BAIL_ON_NTSTATUS_ERROR(nt_status);
989 nt_status = pull_sid(cell, msg, sid);
990 BAIL_ON_NTSTATUS_ERROR(nt_status);
993 ads_msgfree(cell->conn, msg);
998 /********************************************************************
999 *******************************************************************/
1001 static NTSTATUS _ccp_get_id_from_sid(uint32_t * id,
1003 const struct dom_sid * sid)
1005 struct likewise_cell *cell = NULL;
1006 LDAPMessage *msg = NULL;
1008 struct lwcell_filter filter;
1010 filter.ftype = SidFilter;
1011 sid_copy(&filter.filter.sid, sid);
1013 nt_status = search_cell_list(&cell, &msg, &filter);
1014 BAIL_ON_NTSTATUS_ERROR(nt_status);
1016 nt_status = pull_id(cell, msg, id, type);
1017 BAIL_ON_NTSTATUS_ERROR(nt_status);
1019 if (*id < min_id_value()) {
1020 nt_status = NT_STATUS_INVALID_PARAMETER;
1021 BAIL_ON_NTSTATUS_ERROR(nt_status);
1025 ads_msgfree(cell->conn, msg);
1030 /********************************************************************
1031 *******************************************************************/
1033 static NTSTATUS _ccp_nss_get_info(const struct dom_sid * sid,
1035 const char **homedir,
1037 const char **gecos, gid_t * p_gid)
1039 struct likewise_cell *cell = NULL;
1040 LDAPMessage *msg = NULL;
1042 struct lwcell_filter filter;
1045 filter.ftype = SidFilter;
1046 sid_copy(&filter.filter.sid, sid);
1048 nt_status = search_cell_list(&cell, &msg, &filter);
1049 BAIL_ON_NTSTATUS_ERROR(nt_status);
1051 nt_status = get_object_type(cell, msg, &type);
1052 BAIL_ON_NTSTATUS_ERROR(nt_status);
1054 if (type != ID_TYPE_UID) {
1055 nt_status = NT_STATUS_NO_SUCH_USER;
1056 BAIL_ON_NTSTATUS_ERROR(nt_status);
1059 nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos,
1061 BAIL_ON_NTSTATUS_ERROR(nt_status);
1064 ads_msgfree(cell->conn, msg);
1069 /**********************************************************************
1070 *********************************************************************/
1072 static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx,
1074 const char *name, char **alias)
1076 TALLOC_CTX *frame = talloc_stackframe();
1077 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1079 struct likewise_cell *cell = NULL;
1080 LDAPMessage *msg = NULL;
1081 struct lwcell_filter filter;
1082 enum lsa_SidType sid_type;
1084 /* Convert the name to a SID */
1086 nt_status = gc_name_to_sid(domain, name, &sid, &sid_type);
1087 BAIL_ON_NTSTATUS_ERROR(nt_status);
1089 /* Find the user/group */
1091 filter.ftype = SidFilter;
1092 sid_copy(&filter.filter.sid, &sid);
1094 nt_status = search_cell_list(&cell, &msg, &filter);
1095 BAIL_ON_NTSTATUS_ERROR(nt_status);
1097 /* Pull the alias and return */
1099 nt_status = pull_alias(cell, msg, ctx, alias);
1100 BAIL_ON_NTSTATUS_ERROR(nt_status);
1103 PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3);
1105 talloc_destroy(frame);
1106 ads_msgfree(cell_connection(cell), msg);
1111 /**********************************************************************
1112 Map from an alias name to the canonical, qualified name.
1113 Ensure that the alias is only pull from the closest in which
1114 the user or gorup is enabled in
1115 *********************************************************************/
1117 static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx,
1119 const char *alias, char **name)
1121 TALLOC_CTX *frame = talloc_stackframe();
1122 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1124 struct likewise_cell *cell_alias = NULL;
1125 LDAPMessage *msg_alias = NULL;
1126 struct likewise_cell *cell_sid = NULL;
1127 LDAPMessage *msg_sid = NULL;
1128 struct lwcell_filter filter;
1129 char *canonical_name = NULL;
1130 enum lsa_SidType type;
1132 /* Find the user/group */
1134 filter.ftype = AliasFilter;
1135 fstrcpy(filter.filter.alias, alias);
1137 nt_status = search_cell_list(&cell_alias, &msg_alias, &filter);
1138 BAIL_ON_NTSTATUS_ERROR(nt_status);
1140 nt_status = pull_sid(cell_alias, msg_alias, &sid);
1141 BAIL_ON_NTSTATUS_ERROR(nt_status);
1143 /* Now search again for the SID according to the cell list.
1144 Verify that the cell of both search results is the same
1145 so that we only match an alias from the closest cell
1146 in which a user/group has been instantied. */
1148 filter.ftype = SidFilter;
1149 sid_copy(&filter.filter.sid, &sid);
1151 nt_status = search_cell_list(&cell_sid, &msg_sid, &filter);
1152 BAIL_ON_NTSTATUS_ERROR(nt_status);
1154 if (cell_alias != cell_sid) {
1155 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1156 BAIL_ON_NTSTATUS_ERROR(nt_status);
1159 /* Finally do the GC sid/name conversion */
1161 nt_status = gc_sid_to_name(&sid, &canonical_name, &type);
1162 BAIL_ON_NTSTATUS_ERROR(nt_status);
1164 *name = talloc_strdup(mem_ctx, canonical_name);
1165 BAIL_ON_PTR_ERROR((*name), nt_status);
1167 nt_status = NT_STATUS_OK;
1170 PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3);
1172 ads_msgfree(cell_connection(cell_alias), msg_alias);
1173 ads_msgfree(cell_connection(cell_sid), msg_sid);
1175 SAFE_FREE(canonical_name);
1177 talloc_destroy(frame);
1182 /********************************************************************
1183 *******************************************************************/
1185 struct cell_provider_api ccp_unified = {
1186 .get_sid_from_id = _ccp_get_sid_from_id,
1187 .get_id_from_sid = _ccp_get_id_from_sid,
1188 .get_nss_info = _ccp_nss_get_info,
1189 .map_to_alias = _ccp_map_to_alias,
1190 .map_from_alias = _ccp_map_from_alias