diff options
Diffstat (limited to 'source3/winbindd/idmap_adex/cell_util.c')
-rw-r--r-- | source3/winbindd/idmap_adex/cell_util.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/source3/winbindd/idmap_adex/cell_util.c b/source3/winbindd/idmap_adex/cell_util.c new file mode 100644 index 0000000000..f5c08a0454 --- /dev/null +++ b/source3/winbindd/idmap_adex/cell_util.c @@ -0,0 +1,292 @@ +/* + * idmap_adex: Support for AD Forests + * + * Copyright (C) Gerald (Jerry) Carter 2006-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "idmap_adex.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +/********************************************************************** +**********************************************************************/ + + char *find_attr_string(char **list, size_t num_lines, const char *substr) +{ + int i; + int cmplen = strlen(substr); + + for (i = 0; i < num_lines; i++) { + /* make sure to avoid substring matches like uid + and uidNumber */ + if ((StrnCaseCmp(list[i], substr, cmplen) == 0) && + (list[i][cmplen] == '=')) { + /* Don't return an empty string */ + if (list[i][cmplen + 1] != '\0') + return &(list[i][cmplen + 1]); + + return NULL; + } + } + + return NULL; +} + +/********************************************************************** +**********************************************************************/ + + bool is_object_class(char **list, size_t num_lines, const char *substr) +{ + int i; + + for (i = 0; i < num_lines; i++) { + if (strequal(list[i], substr)) { + return true; + } + } + + return false; +} + +/********************************************************************** + Find out about the cell (e.g. use2307Attrs, etc...) +**********************************************************************/ + + NTSTATUS cell_lookup_settings(struct likewise_cell * cell) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + + /* Parameter check */ + + if (!cell) { + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Only supporting Forest-wide, schema based searches */ + + cell_set_flags(cell, LWCELL_FLAG_USE_RFC2307_ATTRS); + cell_set_flags(cell, LWCELL_FLAG_SEARCH_FOREST); + + cell->provider = &ccp_unified; + + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(1,("LWI: Failed to obtain cell settings (%s)\n", + nt_errstr(nt_status))); + } + + return nt_status; +} + + +static NTSTATUS cell_lookup_forest(struct likewise_cell *c) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct gc_info *gc = NULL; + + if (!c) { + return NT_STATUS_INVALID_PARAMETER; + } + + if ((gc = TALLOC_ZERO_P(NULL, struct gc_info)) == NULL) { + nt_status = NT_STATUS_NO_MEMORY; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Query the rootDSE for the forest root naming conect first. + Check that the a GC server for the forest has not already + been added */ + + nt_status = gc_find_forest_root(gc, cell_dns_domain(c)); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + c->forest_name = talloc_strdup(c, gc->forest_name); + BAIL_ON_PTR_ERROR(c->forest_name, nt_status); + +done: + if (gc) { + talloc_free(gc); + } + + return nt_status; +} + +/********************************************************************** +**********************************************************************/ + + NTSTATUS cell_locate_membership(ADS_STRUCT * ads) +{ + ADS_STATUS status; + char *domain_dn = ads_build_dn(lp_realm()); + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + DOM_SID sid; + struct likewise_cell *cell = NULL; + + /* In the Likewise plugin, I had to support the concept of cells + based on the machine's membership in an OU. However, now I'll + just assume our membership in the forest cell */ + + DEBUG(2, ("locate_cell_membership: Located membership " + "in cell \"%s\"\n", domain_dn)); + + if ((cell = cell_new()) == NULL) { + nt_status = NT_STATUS_NO_MEMORY; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + status = ads_domain_sid(ads, &sid); + if (!ADS_ERR_OK(status)) { + DEBUG(3,("locate_cell_membership: Failed to find " + "domain SID for %s\n", domain_dn)); + } + + /* save the SID and search base for our domain */ + + cell_set_dns_domain(cell, lp_realm()); + cell_set_connection(cell, ads); + cell_set_dn(cell, domain_dn); + cell_set_domain_sid(cell, &sid); + + /* Now save our forest root */ + + cell_lookup_forest(cell); + + /* Add the cell to the list */ + + if (!cell_list_add(cell)) { + nt_status = NT_STATUS_INSUFFICIENT_RESOURCES; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Done! */ + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0,("LWI: Failed to locate cell membership (%s)\n", + nt_errstr(nt_status))); + } + + SAFE_FREE(domain_dn); + + return nt_status; +} + +/********************************************************************* + ********************************************************************/ + + int min_id_value(void) +{ + int id_val; + + id_val = lp_parm_int(-1, "lwidentity", "min_id_value", MIN_ID_VALUE); + + /* Still don't let it go below 50 */ + + return MAX(50, id_val); +} + +/******************************************************************** + *******************************************************************/ + + char *cell_dn_to_dns(const char *dn) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + char *domain = NULL; + char *dns_name = NULL; + const char *tmp_dn; + char *buffer = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!dn || !*dn) { + goto done; + } + + tmp_dn = talloc_strdup(frame, dn); + BAIL_ON_PTR_ERROR(tmp_dn, nt_status); + + while (next_token_talloc(frame, &tmp_dn, &buffer, ",")) { + + /* skip everything up the where DC=... begins */ + if (StrnCaseCmp(buffer, "DC=", 3) != 0) + continue; + + if (!domain) { + domain = talloc_strdup(frame, &buffer[3]); + } else { + domain = talloc_asprintf_append(domain, ".%s", + &buffer[3]); + } + BAIL_ON_PTR_ERROR(domain, nt_status); + } + + dns_name = SMB_STRDUP(domain); + BAIL_ON_PTR_ERROR(dns_name, nt_status); + + nt_status = NT_STATUS_OK; + +done: + PRINT_NTSTATUS_ERROR(nt_status, "cell_dn_to_dns", 1); + + talloc_destroy(frame); + + return dns_name; +} + +/********************************************************************* + ********************************************************************/ + + NTSTATUS get_sid_type(ADS_STRUCT *ads, + LDAPMessage *msg, + enum lsa_SidType *type) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + uint32_t atype; + + if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) { + nt_status = NT_STATUS_INVALID_USER_BUFFER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + switch (atype &0xF0000000) { + case ATYPE_SECURITY_GLOBAL_GROUP: + *type = SID_NAME_DOM_GRP; + break; + case ATYPE_SECURITY_LOCAL_GROUP: + *type = SID_NAME_ALIAS; + break; + case ATYPE_NORMAL_ACCOUNT: + case ATYPE_WORKSTATION_TRUST: + case ATYPE_INTERDOMAIN_TRUST: + *type = SID_NAME_USER; + break; + default: + *type = SID_NAME_USE_NONE; + nt_status = NT_STATUS_INVALID_ACCOUNT_NAME; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + nt_status = NT_STATUS_OK; + +done: + return nt_status; +} |