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"
29 #define DBGC_CLASS DBGC_IDMAP
31 /* Information needed by the LDAP search filters */
33 enum filterType { SidFilter, IdFilter, AliasFilter };
37 enum filterType ftype;
49 /********************************************************************
50 *******************************************************************/
52 static char* build_id_filter(TALLOC_CTX *mem_ctx,
55 uint32_t search_flags)
58 char *oc_filter, *attr_filter;
60 TALLOC_CTX *frame = talloc_stackframe();
61 bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
62 == LWCELL_FLAG_USE_RFC2307_ATTRS);
63 bool use_gc = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
64 == LWCELL_FLAG_SEARCH_FOREST);
67 /* Construct search filter for objectclass and attributes */
73 oc = ADEX_OC_POSIX_USER;
78 oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
79 attr_filter = talloc_asprintf(frame, "%s=%u",
80 ADEX_ATTR_UIDNUM, id);
86 oc = ADEX_OC_POSIX_GROUP;
91 oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
92 attr_filter = talloc_asprintf(frame, "%s=%u",
93 ADEX_ATTR_GIDNUM, id);
99 BAIL_ON_PTR_ERROR(oc_filter, nt_status);
100 BAIL_ON_PTR_ERROR(attr_filter, nt_status);
102 /* Use "keywords=%s" for non-schema cells */
105 filter = talloc_asprintf(mem_ctx,
110 filter = talloc_asprintf(mem_ctx,
111 "(&(keywords=%s)(keywords=%s))",
117 talloc_destroy(frame);
122 /********************************************************************
123 *******************************************************************/
125 static char* build_alias_filter(TALLOC_CTX *mem_ctx,
127 uint32_t search_flags)
130 char *user_attr_filter, *group_attr_filter;
132 TALLOC_CTX *frame = talloc_stackframe();
133 bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
134 == LWCELL_FLAG_USE_RFC2307_ATTRS);
135 bool search_forest = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
136 == LWCELL_FLAG_SEARCH_FOREST);
138 /* Construct search filter for objectclass and attributes */
140 user_attr_filter = talloc_asprintf(frame, "%s=%s",
141 ADEX_ATTR_UID, alias);
142 group_attr_filter = talloc_asprintf(frame, "%s=%s",
143 ADEX_ATTR_DISPLAYNAME, alias);
144 BAIL_ON_PTR_ERROR(user_attr_filter, nt_status);
145 BAIL_ON_PTR_ERROR(group_attr_filter, nt_status);
147 /* Use "keywords=%s" for non-schema cells */
150 filter = talloc_asprintf(mem_ctx,
151 "(|(&(%s)(objectclass=%s))(&(%s)(objectclass=%s)))",
153 search_forest ? AD_USER : ADEX_OC_POSIX_USER,
155 search_forest ? AD_GROUP : ADEX_OC_POSIX_GROUP);
157 filter = talloc_asprintf(mem_ctx,
158 "(|(keywords=%s)(keywords=%s))",
164 talloc_destroy(frame);
170 /********************************************************************
171 *******************************************************************/
173 static NTSTATUS search_cell(struct likewise_cell *c,
175 const struct lwcell_filter *fdata)
177 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
178 TALLOC_CTX* frame = talloc_stackframe();
180 const char *base = NULL;
181 ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
182 const char *attrs[] = { "*", NULL };
186 /* get the filter and other search parameters */
188 switch (fdata->ftype) {
190 sid_str = sid_string_talloc(frame, &fdata->filter.sid);
191 BAIL_ON_PTR_ERROR(sid_str, nt_status);
193 filter = talloc_asprintf(frame, "(keywords=backLink=%s)",
197 filter = build_id_filter(frame,
199 fdata->filter.id.type,
203 filter = build_alias_filter(frame,
208 nt_status = NT_STATUS_INVALID_PARAMETER;
211 BAIL_ON_PTR_ERROR(filter, nt_status);
213 base = cell_search_base(c);
214 BAIL_ON_PTR_ERROR(base, nt_status);
216 ads_status = cell_do_search(c, base, LDAP_SCOPE_SUBTREE,
219 nt_status = ads_ntstatus(ads_status);
220 BAIL_ON_NTSTATUS_ERROR(nt_status);
222 /* Now check that we got only one reply */
224 count = ads_count_replies(c->conn, *msg);
226 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
227 BAIL_ON_NTSTATUS_ERROR(nt_status);
231 nt_status = NT_STATUS_DUPLICATE_NAME;
232 BAIL_ON_NTSTATUS_ERROR(nt_status);
236 PRINT_NTSTATUS_ERROR(nt_status, "search_cell", 4);
238 talloc_destroy(CONST_DISCARD(char*, base));
239 talloc_destroy(frame);
244 /********************************************************************
245 *******************************************************************/
247 static NTSTATUS search_domain(struct likewise_cell **cell,
250 const struct dom_sid *sid)
252 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
253 TALLOC_CTX* frame = talloc_stackframe();
256 nt_status = dc_search_domains(cell, msg, dn, sid);
257 BAIL_ON_NTSTATUS_ERROR(nt_status);
259 /* Now check that we got only one reply */
261 count = ads_count_replies(cell_connection(*cell), *msg);
263 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
264 BAIL_ON_NTSTATUS_ERROR(nt_status);
268 nt_status = NT_STATUS_DUPLICATE_NAME;
269 BAIL_ON_NTSTATUS_ERROR(nt_status);
273 PRINT_NTSTATUS_ERROR(nt_status, "search_domain", 4);
274 talloc_destroy(frame);
280 /********************************************************************
281 Check that a DN is within the forest scope.
282 *******************************************************************/
284 static bool check_forest_scope(const char *dn)
286 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
287 TALLOC_CTX *frame = talloc_stackframe();
290 char *dns_domain = NULL;
291 struct winbindd_tdc_domain *domain;
293 /* If the DN does *not* contain "$LikewiseIdentityCell",
294 assume this is a schema mode forest and it is in the
295 forest scope by definition. */
297 if ((p = strstr_m(dn, ADEX_CELL_RDN)) == NULL) {
298 nt_status = NT_STATUS_OK;
302 /* If this is a non-schema forest, then make sure that the DN
303 is in the form "...,cn=$LikewiseIdentityCell,DC=..." */
305 if ((q = strchr_m(p, ',')) == NULL) {
306 nt_status = NT_STATUS_OBJECT_NAME_INVALID;
307 BAIL_ON_NTSTATUS_ERROR(nt_status);
311 if (StrnCaseCmp(q, "dc=", 3) != 0) {
312 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
313 BAIL_ON_NTSTATUS_ERROR(nt_status);
317 dns_domain = cell_dn_to_dns(q);
318 BAIL_ON_PTR_ERROR(dns_domain, nt_status);
320 domain = wcache_tdc_fetch_domain(frame, dns_domain);
322 nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
323 BAIL_ON_NTSTATUS_ERROR(nt_status);
326 nt_status = NT_STATUS_OK;
329 talloc_destroy(frame);
330 SAFE_FREE(dns_domain);
332 return NT_STATUS_IS_OK(nt_status);
337 /********************************************************************
338 Check that only one result was returned within the forest cell
340 *******************************************************************/
342 static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list,
343 LDAPMessage **msg_list,
346 struct dom_sid *user_sid)
348 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
350 ADS_STRUCT *ads = NULL;
351 LDAPMessage *msg = NULL;
353 char *entry_dn = NULL;
354 TALLOC_CTX *frame = talloc_stackframe();
356 if (!dn || !user_sid) {
357 nt_status = NT_STATUS_INVALID_PARAMETER;
358 BAIL_ON_NTSTATUS_ERROR(nt_status);
363 if (!ads_list || !msg_list || (num_resp == 0)) {
364 nt_status = NT_STATUS_NO_SUCH_FILE;
365 BAIL_ON_NTSTATUS_ERROR(nt_status);
368 /* Loop over all msgs */
370 for (i=0; i<num_resp; i++) {
371 LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]);
374 entry_dn = ads_get_dn(ads_list[i], talloc_tos(), e);
375 BAIL_ON_PTR_ERROR(entry_dn, nt_status);
377 if (check_forest_scope(entry_dn)) {
380 /* If we've already broken the condition, no
384 nt_status = NT_STATUS_DUPLICATE_NAME;
385 BAIL_ON_NTSTATUS_ERROR(nt_status);
390 *dn = SMB_STRDUP(entry_dn);
391 BAIL_ON_PTR_ERROR((*dn), nt_status);
394 e = ads_next_entry(ads_list[i], e);
395 TALLOC_FREE(entry_dn);
400 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
401 BAIL_ON_NTSTATUS_ERROR(nt_status);
404 /* If we made is through the loop, then grab the user_sid and
408 Try and get the SID from either objectSid or keywords.
409 We cannot use pull_sid() here since we want to try
410 both methods and not only one or the other (and we
411 have no full likewise_cell struct.
413 Fail if both are unavailable
416 if (!ads_pull_sid(ads, msg, "objectSid", user_sid)) {
419 size_t num_lines = 0;
421 keywords = ads_pull_strings(ads, frame, msg, "keywords",
423 BAIL_ON_PTR_ERROR(keywords, nt_status);
425 s = find_attr_string(keywords, num_lines, "backLink");
427 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
428 BAIL_ON_NTSTATUS_ERROR(nt_status);
431 if (!string_to_sid(user_sid, s)) {
432 nt_status = NT_STATUS_INVALID_SID;
433 BAIL_ON_NTSTATUS_ERROR(nt_status);
437 nt_status = NT_STATUS_OK;
440 if (!NT_STATUS_IS_OK(nt_status)) {
444 talloc_destroy(frame);
449 /********************************************************************
450 Search all forests. Each forest can have it's own forest-cell
451 settings so we have to generate the filter for each search.
452 We don't use gc_search_all_forests() since we may have a different
453 schema model in each forest and need to construct the search
454 filter for each GC search.
455 *******************************************************************/
457 static NTSTATUS search_forest(struct likewise_cell *forest_cell,
459 const struct lwcell_filter *fdata)
461 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
462 TALLOC_CTX *frame = talloc_stackframe();
465 struct gc_info *gc = NULL;
466 ADS_STRUCT **ads_list = NULL;
467 LDAPMessage **msg_list = NULL;
470 struct dom_sid user_sid;
471 struct likewise_cell *domain_cell = NULL;
473 if ((gc = gc_search_start()) == NULL) {
474 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
475 BAIL_ON_NTSTATUS_ERROR(nt_status);
479 char *sid_binstr = NULL;
480 uint32_t flags = LWCELL_FLAG_SEARCH_FOREST;
484 flags |= cell_flags(gc->forest_cell);
486 switch (fdata->ftype) {
488 sid_binstr = sid_binstring(frame, &fdata->filter.sid);
489 BAIL_ON_PTR_ERROR(sid_binstr, nt_status);
491 filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr);
492 TALLOC_FREE(sid_binstr);
495 filter = build_id_filter(frame,
497 fdata->filter.id.type, flags);
500 filter = build_alias_filter(frame,
506 /* First find the sparse object in GC */
507 nt_status = gc_search_forest(gc, &m, filter);
508 if (!NT_STATUS_IS_OK(nt_status)) {
513 nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
514 m, &ads_list, &msg_list,
516 BAIL_ON_NTSTATUS_ERROR(nt_status);
521 /* Uniqueness check across forests */
523 nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp,
525 BAIL_ON_NTSTATUS_ERROR(nt_status);
527 nt_status = search_domain(&domain_cell, &m, dn, &user_sid);
528 BAIL_ON_NTSTATUS_ERROR(nt_status);
530 /* Save the connection and results in the return parameters */
532 forest_cell->gc_search_cell = domain_cell;
536 PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4);
540 free_result_array(ads_list, msg_list, num_resp);
541 talloc_destroy(frame);
546 /********************************************************************
547 *******************************************************************/
549 static NTSTATUS search_cell_list(struct likewise_cell **c,
551 const struct lwcell_filter *fdata)
553 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
554 struct likewise_cell *cell = NULL;
555 LDAPMessage *msg = NULL;
556 struct likewise_cell *result_cell = NULL;
558 if ((cell = cell_list_head()) == NULL) {
559 nt_status = NT_STATUS_INVALID_SERVER_STATE;
560 BAIL_ON_NTSTATUS_ERROR(nt_status);
564 /* Clear any previous GC search results */
566 cell->gc_search_cell = NULL;
568 if (cell_search_forest(cell)) {
569 nt_status = search_forest(cell, &msg, fdata);
571 nt_status = search_cell(cell, &msg, fdata);
574 /* Always point to the search result cell.
575 In forests this might be for another domain
576 which means the schema model may be different */
578 result_cell = cell->gc_search_cell ?
579 cell->gc_search_cell : cell;
581 /* Check if we are done */
583 if (NT_STATUS_IS_OK(nt_status)) {
587 /* No luck. Free memory and hit the next cell.
588 Forest searches always set the gc_search_cell
589 so give preference to that connection if possible. */
591 ads_msgfree(cell_connection(result_cell), msg);
597 /* This might be assigning NULL but that is ok as long as we
598 give back the proper error code */
604 PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3);
609 /********************************************************************
610 Pull the SID from an object which is always stored in the keywords
611 attribute as "backLink=S-1-5-21-..."
612 *******************************************************************/
614 static NTSTATUS pull_sid(struct likewise_cell *c,
618 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
619 TALLOC_CTX *frame = talloc_stackframe();
620 ADS_STRUCT *ads = NULL;
622 ads = cell_connection(c);
625 We have two ways of getting the sid:
626 (a) from the objectSID in case of a GC search,
627 (b) from backLink in the case of a cell search.
628 Pull the keywords attributes and grab the backLink.
631 if (!ads_pull_sid(ads, msg, "objectSid", sid)) {
634 size_t num_lines = 0;
636 keywords = ads_pull_strings(ads, frame, msg,
637 "keywords", &num_lines);
638 BAIL_ON_PTR_ERROR(keywords, nt_status);
640 s = find_attr_string(keywords, num_lines, "backLink");
642 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
643 BAIL_ON_NTSTATUS_ERROR(nt_status);
646 if (!string_to_sid(sid, s)) {
647 nt_status = NT_STATUS_INVALID_SID;
648 BAIL_ON_NTSTATUS_ERROR(nt_status);
652 nt_status = NT_STATUS_OK;
655 talloc_destroy(frame);
660 /********************************************************************
661 *******************************************************************/
663 static NTSTATUS get_object_type(struct likewise_cell *c,
667 TALLOC_CTX *ctx = talloc_stackframe();
668 char **oc_list = NULL;
669 NTSTATUS nt_status = NT_STATUS_OK;
670 size_t list_size = 0;
672 ADS_STRUCT *ads = NULL;
674 ads = cell_connection(c);
676 /* Deal with RFC 2307 support first */
678 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
679 oc_list = ads_pull_strings(ads, ctx, msg,
680 "objectClass", &list_size);
682 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
686 /* Check for posix classes and AD classes */
688 if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER)
689 || is_object_class(oc_list, list_size, AD_USER)) {
691 } else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP)
692 || is_object_class(oc_list, list_size, AD_GROUP)) {
695 *type = ID_TYPE_NOT_SPECIFIED;
696 nt_status = NT_STATUS_INVALID_PARAMETER;
699 /* Default to non-schema mode */
701 oc_list = ads_pull_strings(ads, ctx, msg,
702 "keywords", &list_size);
704 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
708 s = find_attr_string(oc_list, list_size, "objectClass");
710 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
714 if (strequal(s, ADEX_OC_USER)) {
716 } else if (strequal(s, ADEX_OC_GROUP)) {
719 *type = ID_TYPE_NOT_SPECIFIED;
720 nt_status = NT_STATUS_INVALID_PARAMETER;
724 nt_status = NT_STATUS_OK;
732 /********************************************************************
733 Pull an attribute uint32_t value
734 *******************************************************************/
736 static NTSTATUS get_object_uint32(struct likewise_cell *c,
741 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
742 char **keywords = NULL;
743 size_t list_size = 0;
744 TALLOC_CTX *frame = talloc_stackframe();
745 ADS_STRUCT *ads = NULL;
747 ads = cell_connection(c);
749 /* Deal with RFC2307 schema */
751 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
752 if (!ads_pull_uint32(ads, msg, attrib, x)) {
753 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
754 BAIL_ON_NTSTATUS_ERROR(nt_status);
757 /* Non-schema mode */
761 keywords = ads_pull_strings(ads, frame, msg, "keywords",
763 BAIL_ON_PTR_ERROR(keywords, nt_status);
765 s = find_attr_string(keywords, list_size, attrib);
767 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
768 BAIL_ON_NTSTATUS_ERROR(nt_status);
771 num = strtoll(s, NULL, 10);
772 if (errno == ERANGE) {
773 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
774 BAIL_ON_NTSTATUS_ERROR(nt_status);
779 nt_status = NT_STATUS_OK;
782 talloc_destroy(frame);
787 /********************************************************************
788 *******************************************************************/
790 static NTSTATUS get_object_id(struct likewise_cell *c,
795 NTSTATUS nt_status = NT_STATUS_OK;
798 /* Figure out which attribute we need to pull */
802 id_attr = ADEX_ATTR_UIDNUM;
805 id_attr = ADEX_ATTR_GIDNUM;
808 nt_status = NT_STATUS_INVALID_PARAMETER;
809 BAIL_ON_NTSTATUS_ERROR(nt_status);
813 nt_status = get_object_uint32(c, msg, id_attr, id);
814 BAIL_ON_NTSTATUS_ERROR(nt_status);
820 /********************************************************************
821 Pull the uid/gid and type from an object. This differs depending on
823 *******************************************************************/
825 static NTSTATUS pull_id(struct likewise_cell *c,
832 nt_status = get_object_type(c, msg, type);
833 BAIL_ON_NTSTATUS_ERROR(nt_status);
835 nt_status = get_object_id(c, msg, *type, id);
836 BAIL_ON_NTSTATUS_ERROR(nt_status);
842 /********************************************************************
843 Pull an attribute string value
844 *******************************************************************/
846 static NTSTATUS get_object_string(struct likewise_cell *c,
852 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
853 char **keywords = NULL;
854 size_t list_size = 0;
855 TALLOC_CTX *frame = talloc_stackframe();
856 ADS_STRUCT *ads = NULL;
860 ads = cell_connection(c);
862 /* Deal with RFC2307 schema */
864 if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
865 *string = ads_pull_string(ads, ctx, msg, attrib);
867 /* Non-schema mode */
871 keywords = ads_pull_strings(ads, frame, msg,
872 "keywords", &list_size);
874 nt_status = NT_STATUS_NO_MEMORY;
875 BAIL_ON_NTSTATUS_ERROR(nt_status);
877 s = find_attr_string(keywords, list_size, attrib);
879 *string = talloc_strdup(ctx, s);
884 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
885 BAIL_ON_NTSTATUS_ERROR(nt_status);
888 nt_status = NT_STATUS_OK;
891 talloc_destroy(frame);
896 /********************************************************************
897 Pull the struct passwd fields for a user
898 *******************************************************************/
900 static NTSTATUS pull_nss_info(struct likewise_cell *c,
903 const char **homedir,
911 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, &tmp);
912 BAIL_ON_NTSTATUS_ERROR(nt_status);
915 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, &tmp);
916 BAIL_ON_NTSTATUS_ERROR(nt_status);
919 nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, &tmp);
920 /* Gecos is often not set so ignore failures */
923 nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid);
924 BAIL_ON_NTSTATUS_ERROR(nt_status);
930 /********************************************************************
931 Pull the struct passwd fields for a user
932 *******************************************************************/
934 static NTSTATUS pull_alias(struct likewise_cell *c,
939 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
941 const char *attr = NULL;
943 /* Figure out if this is a user or a group */
945 nt_status = get_object_type(c, msg, &type);
946 BAIL_ON_NTSTATUS_ERROR(nt_status);
950 attr = ADEX_ATTR_UID;
953 /* What is the group attr for RFC2307 Forests? */
954 attr = ADEX_ATTR_DISPLAYNAME;
957 nt_status = NT_STATUS_INVALID_PARAMETER;
958 BAIL_ON_NTSTATUS_ERROR(nt_status);
962 nt_status = get_object_string(c, msg, ctx, attr, alias);
963 BAIL_ON_NTSTATUS_ERROR(nt_status);
969 /********************************************************************
970 *******************************************************************/
972 static NTSTATUS _ccp_get_sid_from_id(struct dom_sid * sid,
973 uint32_t id, enum id_type type)
975 struct likewise_cell *cell = NULL;
976 LDAPMessage *msg = NULL;
978 struct lwcell_filter filter;
980 filter.ftype = IdFilter;
981 filter.filter.id.id = id;
982 filter.filter.id.type = type;
984 nt_status = search_cell_list(&cell, &msg, &filter);
985 BAIL_ON_NTSTATUS_ERROR(nt_status);
987 nt_status = pull_sid(cell, msg, sid);
988 BAIL_ON_NTSTATUS_ERROR(nt_status);
991 ads_msgfree(cell->conn, msg);
996 /********************************************************************
997 *******************************************************************/
999 static NTSTATUS _ccp_get_id_from_sid(uint32_t * id,
1001 const struct dom_sid * sid)
1003 struct likewise_cell *cell = NULL;
1004 LDAPMessage *msg = NULL;
1006 struct lwcell_filter filter;
1008 filter.ftype = SidFilter;
1009 sid_copy(&filter.filter.sid, sid);
1011 nt_status = search_cell_list(&cell, &msg, &filter);
1012 BAIL_ON_NTSTATUS_ERROR(nt_status);
1014 nt_status = pull_id(cell, msg, id, type);
1015 BAIL_ON_NTSTATUS_ERROR(nt_status);
1017 if (*id < min_id_value()) {
1018 nt_status = NT_STATUS_INVALID_PARAMETER;
1019 BAIL_ON_NTSTATUS_ERROR(nt_status);
1023 ads_msgfree(cell->conn, msg);
1028 /********************************************************************
1029 *******************************************************************/
1031 static NTSTATUS _ccp_nss_get_info(const struct dom_sid * sid,
1033 const char **homedir,
1035 const char **gecos, gid_t * p_gid)
1037 struct likewise_cell *cell = NULL;
1038 LDAPMessage *msg = NULL;
1040 struct lwcell_filter filter;
1043 filter.ftype = SidFilter;
1044 sid_copy(&filter.filter.sid, sid);
1046 nt_status = search_cell_list(&cell, &msg, &filter);
1047 BAIL_ON_NTSTATUS_ERROR(nt_status);
1049 nt_status = get_object_type(cell, msg, &type);
1050 BAIL_ON_NTSTATUS_ERROR(nt_status);
1052 if (type != ID_TYPE_UID) {
1053 nt_status = NT_STATUS_NO_SUCH_USER;
1054 BAIL_ON_NTSTATUS_ERROR(nt_status);
1057 nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos,
1059 BAIL_ON_NTSTATUS_ERROR(nt_status);
1062 ads_msgfree(cell->conn, msg);
1067 /**********************************************************************
1068 *********************************************************************/
1070 static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx,
1072 const char *name, char **alias)
1074 TALLOC_CTX *frame = talloc_stackframe();
1075 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1077 struct likewise_cell *cell = NULL;
1078 LDAPMessage *msg = NULL;
1079 struct lwcell_filter filter;
1080 enum lsa_SidType sid_type;
1082 /* Convert the name to a SID */
1084 nt_status = gc_name_to_sid(domain, name, &sid, &sid_type);
1085 BAIL_ON_NTSTATUS_ERROR(nt_status);
1087 /* Find the user/group */
1089 filter.ftype = SidFilter;
1090 sid_copy(&filter.filter.sid, &sid);
1092 nt_status = search_cell_list(&cell, &msg, &filter);
1093 BAIL_ON_NTSTATUS_ERROR(nt_status);
1095 /* Pull the alias and return */
1097 nt_status = pull_alias(cell, msg, ctx, alias);
1098 BAIL_ON_NTSTATUS_ERROR(nt_status);
1101 PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3);
1103 talloc_destroy(frame);
1104 ads_msgfree(cell_connection(cell), msg);
1109 /**********************************************************************
1110 Map from an alias name to the canonical, qualified name.
1111 Ensure that the alias is only pull from the closest in which
1112 the user or gorup is enabled in
1113 *********************************************************************/
1115 static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx,
1117 const char *alias, char **name)
1119 TALLOC_CTX *frame = talloc_stackframe();
1120 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1122 struct likewise_cell *cell_alias = NULL;
1123 LDAPMessage *msg_alias = NULL;
1124 struct likewise_cell *cell_sid = NULL;
1125 LDAPMessage *msg_sid = NULL;
1126 struct lwcell_filter filter;
1127 char *canonical_name = NULL;
1128 enum lsa_SidType type;
1130 /* Find the user/group */
1132 filter.ftype = AliasFilter;
1133 fstrcpy(filter.filter.alias, alias);
1135 nt_status = search_cell_list(&cell_alias, &msg_alias, &filter);
1136 BAIL_ON_NTSTATUS_ERROR(nt_status);
1138 nt_status = pull_sid(cell_alias, msg_alias, &sid);
1139 BAIL_ON_NTSTATUS_ERROR(nt_status);
1141 /* Now search again for the SID according to the cell list.
1142 Verify that the cell of both search results is the same
1143 so that we only match an alias from the closest cell
1144 in which a user/group has been instantied. */
1146 filter.ftype = SidFilter;
1147 sid_copy(&filter.filter.sid, &sid);
1149 nt_status = search_cell_list(&cell_sid, &msg_sid, &filter);
1150 BAIL_ON_NTSTATUS_ERROR(nt_status);
1152 if (cell_alias != cell_sid) {
1153 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1154 BAIL_ON_NTSTATUS_ERROR(nt_status);
1157 /* Finally do the GC sid/name conversion */
1159 nt_status = gc_sid_to_name(&sid, &canonical_name, &type);
1160 BAIL_ON_NTSTATUS_ERROR(nt_status);
1162 *name = talloc_strdup(mem_ctx, canonical_name);
1163 BAIL_ON_PTR_ERROR((*name), nt_status);
1165 nt_status = NT_STATUS_OK;
1168 PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3);
1170 ads_msgfree(cell_connection(cell_alias), msg_alias);
1171 ads_msgfree(cell_connection(cell_sid), msg_sid);
1173 SAFE_FREE(canonical_name);
1175 talloc_destroy(frame);
1180 /********************************************************************
1181 *******************************************************************/
1183 struct cell_provider_api ccp_unified = {
1184 .get_sid_from_id = _ccp_get_sid_from_id,
1185 .get_id_from_sid = _ccp_get_id_from_sid,
1186 .get_nss_info = _ccp_nss_get_info,
1187 .map_to_alias = _ccp_map_to_alias,
1188 .map_from_alias = _ccp_map_from_alias