static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx, struct netr_SamInfo3 *info3) { const char *guest_account = lp_guestaccount(); struct dom_sid domain_sid; struct passwd *pwd; const char *tmp; pwd = Get_Pwnam_alloc(mem_ctx, guest_account); if (pwd == NULL) { DEBUG(0,("SamInfo3_for_guest: Unable to locate guest " "account [%s]!\n", guest_account)); return NT_STATUS_NO_SUCH_USER; } /* Set acount name */ tmp = talloc_strdup(mem_ctx, pwd->pw_name); if (tmp == NULL) { return NT_STATUS_NO_MEMORY; } init_lsa_String(&info3->base.account_name, tmp); /* Set domain name */ tmp = talloc_strdup(mem_ctx, get_global_sam_name()); if (tmp == NULL) { return NT_STATUS_NO_MEMORY; } init_lsa_StringLarge(&info3->base.domain, tmp); /* Domain sid */ sid_copy(&domain_sid, get_global_sam_sid()); info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid); if (info3->base.domain_sid == NULL) { return NT_STATUS_NO_MEMORY; } /* Guest rid */ info3->base.rid = DOMAIN_RID_GUEST; /* Primary gid */ info3->base.primary_gid = DOMAIN_RID_GUESTS; TALLOC_FREE(pwd); return NT_STATUS_OK; }
bool secrets_store_domain_guid(const char *domain, struct GUID *guid) { fstring key; #if _SAMBA_BUILD_ == 4 if (strequal(domain, get_global_sam_name()) && (pdb_capabilities() & PDB_CAP_ADS)) { /* If we have a ADS-capable passdb backend, we * must never make up our own GUID, it will * already be in the directory */ DEBUG(0, ("Refusing to store a Domain GUID, this should be read from the directory not stored here\n")); return false; } #endif slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper_m(key); return secrets_store(key, guid, sizeof(struct GUID)); }
NTSTATUS create_builtin_administrators(const struct dom_sid *dom_sid) { NTSTATUS status; struct dom_sid dom_admins, root_sid; fstring root_name; enum lsa_SidType type; TALLOC_CTX *ctx; bool ret; status = create_builtin(BUILTIN_RID_ADMINISTRATORS); if ( !NT_STATUS_IS_OK(status) ) { DEBUG(5,("create_builtin_administrators: Failed to create Administrators\n")); return status; } /* add domain admins */ if ((IS_DC || (lp_server_role() == ROLE_DOMAIN_MEMBER)) && sid_compose(&dom_admins, dom_sid, DOMAIN_RID_ADMINS)) { status = add_sid_to_builtin(&global_sid_Builtin_Administrators, &dom_admins); if (!NT_STATUS_IS_OK(status)) { return status; } } /* add root */ if ( (ctx = talloc_init("create_builtin_administrators")) == NULL ) { return NT_STATUS_NO_MEMORY; } fstr_sprintf( root_name, "%s\\root", get_global_sam_name() ); ret = lookup_name(ctx, root_name, LOOKUP_NAME_DOMAIN, NULL, NULL, &root_sid, &type); TALLOC_FREE( ctx ); if ( ret ) { status = add_sid_to_builtin(&global_sid_Builtin_Administrators, &root_sid); } return status; }
static int net_getdomainsid(int argc, const char **argv) { DOM_SID domain_sid; fstring sid_str; if(!initialize_password_db(False)) { DEBUG(1, ("WARNING: Could not open passdb - domain sid may not reflect passdb\n" "backend knowlege (such as the sid stored in LDAP)\n")); } /* first check to see if we can even access secrets, so we don't panic when we can't. */ if (!secrets_init()) { d_fprintf(stderr, "Unable to open secrets.tdb. " "Can't fetch domainSID for name: %s\n", get_global_sam_name()); return 1; } /* Generate one, if it doesn't exist */ get_global_sam_sid(); if (!secrets_fetch_domain_sid(global_myname(), &domain_sid)) { d_fprintf(stderr, "Could not fetch local SID\n"); return 1; } sid_to_string(sid_str, &domain_sid); d_printf("SID for domain %s is: %s\n", global_myname(), sid_str); if (!secrets_fetch_domain_sid(opt_workgroup, &domain_sid)) { d_fprintf(stderr, "Could not fetch domain SID\n"); return 1; } sid_to_string(sid_str, &domain_sid); d_printf("SID for domain %s is: %s\n", opt_workgroup, sid_str); return 0; }
bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid) { bool ret; #if _SAMBA_BUILD_ == 4 if (strequal(domain, get_global_sam_name()) && (pdb_capabilities() & PDB_CAP_ADS)) { /* If we have a ADS-capable passdb backend, we * must never make up our own SID, it will * already be in the directory */ DEBUG(0, ("Refusing to store a Domain SID, this should be read from the directory not stored here\n")); return false; } #endif ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid )); /* Force a re-query, in case we modified our domain */ if (ret) reset_global_sam_sid(); return ret; }
bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid) { struct dom_sid *dyn_sid; size_t size = 0; #if _SAMBA_BUILD_ == 4 if (strequal(domain, get_global_sam_name()) && (pdb_capabilities() & PDB_CAP_ADS)) { struct pdb_domain_info *domain_info; domain_info = pdb_get_domain_info(talloc_tos()); if (!domain_info) { /* If we have a ADS-capable passdb backend, we * must never make up our own SID, it will * already be in the directory */ DEBUG(0, ("Unable to fetch a Domain SID from the directory!\n")); return false; } *sid = domain_info->sid; return true; } #endif dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size); if (dyn_sid == NULL) return False; if (size != sizeof(struct dom_sid)) { SAFE_FREE(dyn_sid); return False; } *sid = *dyn_sid; SAFE_FREE(dyn_sid); return True; }
static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx, struct passwd *pwd, struct netr_SamInfo3 *info3) { struct dom_sid domain_sid; const char *tmp; /* Set account name */ tmp = talloc_strdup(mem_ctx, pwd->pw_name); if (tmp == NULL) { return NT_STATUS_NO_MEMORY; } init_lsa_String(&info3->base.account_name, tmp); /* Set domain name */ tmp = talloc_strdup(mem_ctx, get_global_sam_name()); if (tmp == NULL) { return NT_STATUS_NO_MEMORY; } init_lsa_StringLarge(&info3->base.domain, tmp); /* Domain sid */ sid_copy(&domain_sid, get_global_sam_sid()); info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid); if (info3->base.domain_sid == NULL) { return NT_STATUS_NO_MEMORY; } /* Admin rid */ info3->base.rid = DOMAIN_RID_ADMINISTRATOR; /* Primary gid */ info3->base.primary_gid = BUILTIN_RID_ADMINISTRATORS; return NT_STATUS_OK; }
bool is_trusted_domain(const char* dom_name) { struct dom_sid trustdom_sid; bool ret; /* no trusted domains for a standalone server */ if ( lp_server_role() == ROLE_STANDALONE ) return False; if (dom_name == NULL || dom_name[0] == '\0') { return false; } if (strequal(dom_name, get_global_sam_name())) { return false; } /* if we are a DC, then check for a direct trust relationships */ if ( IS_DC ) { become_root(); DEBUG (5,("is_trusted_domain: Checking for domain trust with " "[%s]\n", dom_name )); ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL); unbecome_root(); if (ret) return True; } else { wbcErr result; /* If winbind is around, ask it */ result = wb_is_trusted_domain(dom_name); if (result == WBC_ERR_SUCCESS) { return True; } if (result == WBC_ERR_DOMAIN_NOT_FOUND) { /* winbind could not find the domain */ return False; } /* The only other possible result is that winbind is not up and running. We need to update the trustdom_cache ourselves */ update_trustdom_cache(); } /* now the trustdom cache should be available a DC could still * have a transitive trust so fall back to the cache of trusted * domains (like a domain member would use */ if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) { return True; } return False; }
static NTSTATUS check_winbind_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status; wbcErr wbc_status; struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; if (!user_info) { return NT_STATUS_INVALID_PARAMETER; } if (!auth_context) { DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", user_info->internal_username)); return NT_STATUS_INVALID_PARAMETER; } if (strequal(user_info->domain, get_global_sam_name())) { DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n", user_info->domain)); return NT_STATUS_NOT_IMPLEMENTED; } /* Send off request */ params.account_name = user_info->smb_name; params.domain_name = user_info->domain; params.workstation_name = user_info->wksta_name; params.flags = 0; params.parameter_control= user_info->logon_parameters; params.level = WBC_AUTH_USER_LEVEL_RESPONSE; memcpy(params.password.response.challenge, auth_context->challenge.data, sizeof(params.password.response.challenge)); params.password.response.nt_length = user_info->nt_resp.length; params.password.response.nt_data = user_info->nt_resp.data; params.password.response.lm_length = user_info->lm_resp.length; params.password.response.lm_data = user_info->lm_resp.data; /* we are contacting the privileged pipe */ become_root(); wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); unbecome_root(); if (!WBC_ERROR_IS_OK(wbc_status)) { DEBUG(10,("check_winbind_security: wbcAuthenticateUserEx failed: %s\n", wbcErrorString(wbc_status))); } if (wbc_status == WBC_ERR_NO_MEMORY) { return NT_STATUS_NO_MEMORY; } if (wbc_status == WBC_ERR_WINBIND_NOT_AVAILABLE) { struct auth_methods *auth_method = (struct auth_methods *)my_private_data; if ( auth_method ) return auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); else /* log an error since this should not happen */ DEBUG(0,("check_winbind_security: ERROR! my_private_data == NULL!\n")); } if (wbc_status == WBC_ERR_AUTH_ERROR) { nt_status = NT_STATUS(err->nt_status); wbcFreeMemory(err); return nt_status; } if (!WBC_ERROR_IS_OK(wbc_status)) { return NT_STATUS_LOGON_FAILURE; } nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, user_info->smb_name, user_info->domain, info, server_info); wbcFreeMemory(info); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } (*server_info)->nss_token |= user_info->was_mapped; return nt_status; }
bool lookup_name_smbconf(TALLOC_CTX *mem_ctx, const char *full_name, int flags, const char **ret_domain, const char **ret_name, struct dom_sid *ret_sid, enum lsa_SidType *ret_type) { char *qualified_name; const char *p; /* NB. No winbindd_separator here as lookup_name needs \\' */ if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) { /* The name is already qualified with a domain. */ if (*lp_winbind_separator() != '\\') { char *tmp; /* lookup_name() needs '\\' as a separator */ tmp = talloc_strdup(mem_ctx, full_name); if (!tmp) { return false; } tmp[p - full_name] = '\\'; full_name = tmp; } return lookup_name(mem_ctx, full_name, flags, ret_domain, ret_name, ret_sid, ret_type); } /* Try with winbind default domain name. */ if (lp_winbind_use_default_domain()) { bool ok; qualified_name = talloc_asprintf(mem_ctx, "%s\\%s", lp_workgroup(), full_name); if (qualified_name == NULL) { return false; } ok = lookup_name(mem_ctx, qualified_name, flags, ret_domain, ret_name, ret_sid, ret_type); if (ok) { return true; } } /* Try with our own SAM name. */ qualified_name = talloc_asprintf(mem_ctx, "%s\\%s", get_global_sam_name(), full_name ); if (!qualified_name) { return false; } if (lookup_name(mem_ctx, qualified_name, flags, ret_domain, ret_name, ret_sid, ret_type)) { return true; } /* Finally try with "Unix Users" or "Unix Group" */ qualified_name = talloc_asprintf(mem_ctx, "%s\\%s", flags & LOOKUP_NAME_GROUP ? unix_groups_domain_name() : unix_users_domain_name(), full_name ); if (!qualified_name) { return false; } return lookup_name(mem_ctx, qualified_name, flags, ret_domain, ret_name, ret_sid, ret_type); }
static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name, struct winbindd_methods *methods, const struct dom_sid *sid) { struct winbindd_domain *domain; const char *alternative_name = NULL; char *idmap_config_option; const char *param; const char **ignored_domains, **dom; int role = lp_server_role(); ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL); for (dom=ignored_domains; dom && *dom; dom++) { if (gen_fnmatch(*dom, domain_name) == 0) { DEBUG(2,("Ignoring domain '%s'\n", domain_name)); return NULL; } } /* use alt_name if available to allow DNS lookups */ if (alt_name && *alt_name) { alternative_name = alt_name; } /* We can't call domain_list() as this function is called from init_domain_list() and we'll get stuck in a loop. */ for (domain = _domain_list; domain; domain = domain->next) { if (strequal(domain_name, domain->name) || strequal(domain_name, domain->alt_name)) { break; } if (alternative_name && *alternative_name) { if (strequal(alternative_name, domain->name) || strequal(alternative_name, domain->alt_name)) { break; } } if (sid) { if (is_null_sid(sid)) { continue; } if (dom_sid_equal(sid, &domain->sid)) { break; } } } if (domain != NULL) { /* * We found a match on domain->name or * domain->alt_name. Possibly update the SID * if the stored SID was the NULL SID * and return the matching entry. */ if ((sid != NULL) && dom_sid_equal(&domain->sid, &global_sid_NULL)) { sid_copy( &domain->sid, sid ); } return domain; } /* Create new domain entry */ domain = talloc_zero(NULL, struct winbindd_domain); if (domain == NULL) { return NULL; } domain->children = talloc_zero_array(domain, struct winbindd_child, lp_winbind_max_domain_connections()); if (domain->children == NULL) { TALLOC_FREE(domain); return NULL; } domain->name = talloc_strdup(domain, domain_name); if (domain->name == NULL) { TALLOC_FREE(domain); return NULL; } if (alternative_name) { domain->alt_name = talloc_strdup(domain, alternative_name); if (domain->alt_name == NULL) { TALLOC_FREE(domain); return NULL; } } domain->methods = methods; domain->backend = NULL; domain->internal = is_internal_domain(sid); domain->sequence_number = DOM_SEQUENCE_NONE; domain->last_seq_check = 0; domain->initialized = False; domain->online = is_internal_domain(sid); domain->check_online_timeout = 0; domain->dc_probe_pid = (pid_t)-1; if (sid) { sid_copy(&domain->sid, sid); } /* Is this our primary domain ? */ if (strequal(domain_name, get_global_sam_name()) && (role != ROLE_DOMAIN_MEMBER)) { domain->primary = true; } else if (strequal(domain_name, lp_workgroup()) && (role == ROLE_DOMAIN_MEMBER)) { domain->primary = true; } if (domain->primary) { if (role == ROLE_ACTIVE_DIRECTORY_DC) { domain->active_directory = true; } if (lp_security() == SEC_ADS) { domain->active_directory = true; } } /* Link to domain list */ DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *); wcache_tdc_add_domain( domain ); idmap_config_option = talloc_asprintf(talloc_tos(), "idmap config %s", domain->name); if (idmap_config_option == NULL) { DEBUG(0, ("talloc failed, not looking for idmap config\n")); goto done; } param = lp_parm_const_string(-1, idmap_config_option, "range", NULL); DEBUG(10, ("%s : range = %s\n", idmap_config_option, param ? param : "not defined")); if (param != NULL) { unsigned low_id, high_id; if (sscanf(param, "%u - %u", &low_id, &high_id) != 2) { DEBUG(1, ("invalid range syntax in %s: %s\n", idmap_config_option, param)); goto done; } if (low_id > high_id) { DEBUG(1, ("invalid range in %s: %s\n", idmap_config_option, param)); goto done; } domain->have_idmap_config = true; domain->id_range_low = low_id; domain->id_range_high = high_id; } done: setup_domain_child(domain); DEBUG(2,("Added domain %s %s %s\n", domain->name, domain->alt_name, &domain->sid?sid_string_dbg(&domain->sid):"")); return domain; }
static NTSTATUS check_winbind_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; wbcErr wbc_status; struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; ZERO_STRUCT(params); if (!user_info) { return NT_STATUS_INVALID_PARAMETER; } DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); if (!auth_context) { DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", user_info->mapped.account_name)); return NT_STATUS_INVALID_PARAMETER; } if (strequal(user_info->mapped.domain_name, get_global_sam_name())) { DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n", user_info->mapped.domain_name)); return NT_STATUS_NOT_IMPLEMENTED; } /* Send off request */ params.account_name = user_info->client.account_name; /* * We need to send the domain name from the client to the DC. With * NTLMv2 the domain name is part of the hashed second challenge, * if we change the domain name, the DC will fail to verify the * challenge cause we changed the domain name, this is like a * man in the middle attack. */ params.domain_name = user_info->client.domain_name; params.workstation_name = user_info->workstation_name; params.flags = 0; params.parameter_control= user_info->logon_parameters; params.level = WBC_AUTH_USER_LEVEL_RESPONSE; memcpy(params.password.response.challenge, auth_context->challenge.data, sizeof(params.password.response.challenge)); if (user_info->password.response.nt.length != 0) { params.password.response.nt_length = user_info->password.response.nt.length; params.password.response.nt_data = user_info->password.response.nt.data; } if (user_info->password.response.lanman.length != 0) { params.password.response.lm_length = user_info->password.response.lanman.length; params.password.response.lm_data = user_info->password.response.lanman.data; } /* we are contacting the privileged pipe */ become_root(); wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); unbecome_root(); if (!WBC_ERROR_IS_OK(wbc_status)) { DEBUG(10,("check_winbind_security: wbcAuthenticateUserEx failed: %s\n", wbcErrorString(wbc_status))); } if (wbc_status == WBC_ERR_NO_MEMORY) { return NT_STATUS_NO_MEMORY; } if (wbc_status == WBC_ERR_WINBIND_NOT_AVAILABLE) { struct auth_methods *auth_method = (struct auth_methods *)my_private_data; if ( auth_method ) return auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); return NT_STATUS_LOGON_FAILURE; } if (wbc_status == WBC_ERR_AUTH_ERROR) { nt_status = NT_STATUS(err->nt_status); wbcFreeMemory(err); return nt_status; } if (!WBC_ERROR_IS_OK(wbc_status)) { return NT_STATUS_LOGON_FAILURE; } nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, user_info->client.account_name, user_info->mapped.domain_name, info, server_info); wbcFreeMemory(info); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } (*server_info)->nss_token |= user_info->was_mapped; return nt_status; }
static NTSTATUS check_winbind_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { struct winbindd_request request; struct winbindd_response response; NSS_STATUS result; NTSTATUS nt_status; NET_USER_INFO_3 info3; if (!user_info) { return NT_STATUS_INVALID_PARAMETER; } if (!auth_context) { DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", user_info->internal_username.str)); return NT_STATUS_INVALID_PARAMETER; } if (strequal(user_info->domain.str, get_global_sam_name())) { DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n", user_info->domain.str)); return NT_STATUS_NOT_IMPLEMENTED; } /* Send off request */ ZERO_STRUCT(request); ZERO_STRUCT(response); request.flags = WBFLAG_PAM_INFO3_NDR; fstrcpy(request.data.auth_crap.user, user_info->smb_name.str); fstrcpy(request.data.auth_crap.domain, user_info->domain.str); fstrcpy(request.data.auth_crap.workstation, user_info->wksta_name.str); memcpy(request.data.auth_crap.chal, auth_context->challenge.data, sizeof(request.data.auth_crap.chal)); request.data.auth_crap.lm_resp_len = MIN(user_info->lm_resp.length, sizeof(request.data.auth_crap.lm_resp)); request.data.auth_crap.nt_resp_len = MIN(user_info->nt_resp.length, sizeof(request.data.auth_crap.nt_resp)); memcpy(request.data.auth_crap.lm_resp, user_info->lm_resp.data, request.data.auth_crap.lm_resp_len); memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data, request.data.auth_crap.nt_resp_len); /* we are contacting the privileged pipe */ become_root(); result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); unbecome_root(); if ( result == NSS_STATUS_UNAVAIL ) { struct auth_methods *auth_method = my_private_data; if ( auth_method ) return auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); else /* log an error since this should not happen */ DEBUG(0,("check_winbind_security: ERROR! my_private_data == NULL!\n")); } nt_status = NT_STATUS(response.data.auth.nt_status); if (result == NSS_STATUS_SUCCESS && response.extra_data) { if (NT_STATUS_IS_OK(nt_status)) { if (NT_STATUS_IS_OK(nt_status = get_info3_from_ndr(mem_ctx, &response, &info3))) { nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str, user_info->smb_name.str, user_info->domain.str, server_info, &info3); } } } else if (NT_STATUS_IS_OK(nt_status)) { nt_status = NT_STATUS_NO_LOGON_SERVERS; } SAFE_FREE(response.extra_data); return nt_status; }
static NTSTATUS fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, DSROLE_PRIMARY_DOMAIN_INFO_BASIC **info) { DSROLE_PRIMARY_DOMAIN_INFO_BASIC *basic; const char *netbios_domain; fstring dnsdomain; DEBUG(10,("fill_dsrole_dominfo_basic: enter\n")); if ( !(basic = talloc_zero(ctx, sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC))) ) { DEBUG(0,("fill_dsrole_dominfo_basic: FATAL error! talloc_xero() failed\n")); return NT_STATUS_NO_MEMORY; } switch ( lp_server_role() ) { case ROLE_STANDALONE: basic->machine_role = DSROLE_STANDALONE_SRV; break; case ROLE_DOMAIN_MEMBER: basic->machine_role = DSROLE_DOMAIN_MEMBER_SRV; break; case ROLE_DOMAIN_BDC: basic->machine_role = DSROLE_BDC; basic->flags = DSROLE_PRIMARY_DS_RUNNING|DSROLE_PRIMARY_DS_MIXED_MODE; if ( secrets_fetch_domain_guid( lp_workgroup(), &basic->domain_guid ) ) basic->flags |= DSROLE_PRIMARY_DOMAIN_GUID_PRESENT; get_mydnsdomname(dnsdomain); strlower_m(dnsdomain); break; case ROLE_DOMAIN_PDC: basic->machine_role = DSROLE_PDC; basic->flags = DSROLE_PRIMARY_DS_RUNNING|DSROLE_PRIMARY_DS_MIXED_MODE; if ( secrets_fetch_domain_guid( lp_workgroup(), &basic->domain_guid ) ) basic->flags |= DSROLE_PRIMARY_DOMAIN_GUID_PRESENT; get_mydnsdomname(dnsdomain); strlower_m(dnsdomain); break; } basic->unknown = 0x6173; /* seen on the wire; maybe padding */ /* always set netbios name */ basic->netbios_ptr = 1; netbios_domain = get_global_sam_name(); init_unistr2( &basic->netbios_domain, netbios_domain, UNI_FLAGS_NONE); basic->dnsname_ptr = 1; init_unistr2( &basic->dns_domain, dnsdomain, UNI_FLAGS_NONE); basic->forestname_ptr = 1; init_unistr2( &basic->forest_domain, dnsdomain, UNI_FLAGS_NONE); /* fill in some additional fields if we are a member of an AD domain */ if ( lp_security() == SEC_ADS ) { /* TODO */ ;; } *info = basic; return NT_STATUS_OK; }
/* dump sam database via samsync rpc calls */ NTSTATUS rpc_vampire_internals(struct net_context *c, const DOM_SID *domain_sid, const char *domain_name, struct cli_state *cli, struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS result; struct samsync_context *ctx = NULL; if (!sid_equal(domain_sid, get_global_sam_sid())) { d_printf("Cannot import users from %s at this time, " "as the current domain:\n\t%s: %s\nconflicts " "with the remote domain\n\t%s: %s\n" "Perhaps you need to set: \n\n\tsecurity=user\n\t" "workgroup=%s\n\n in your smb.conf?\n", domain_name, get_global_sam_name(), sid_string_dbg(get_global_sam_sid()), domain_name, sid_string_dbg(domain_sid), domain_name); return NT_STATUS_UNSUCCESSFUL; } result = libnet_samsync_init_context(mem_ctx, domain_sid, &ctx); if (!NT_STATUS_IS_OK(result)) { return result; } ctx->mode = NET_SAMSYNC_MODE_FETCH_PASSDB; ctx->cli = pipe_hnd; ctx->ops = &libnet_samsync_passdb_ops; ctx->domain_name = domain_name; ctx->force_full_replication = c->opt_force_full_repl ? true : false; ctx->clean_old_entries = c->opt_clean_old_entries ? true : false; parse_samsync_partial_replication_objects(ctx, argc, argv, &ctx->single_object_replication, &ctx->objects, &ctx->num_objects); /* fetch domain */ result = libnet_samsync(SAM_DATABASE_DOMAIN, ctx); if (!NT_STATUS_IS_OK(result) && ctx->error_message) { d_fprintf(stderr, "%s\n", ctx->error_message); goto fail; } if (ctx->result_message) { d_fprintf(stdout, "%s\n", ctx->result_message); } /* fetch builtin */ ctx->domain_sid = sid_dup_talloc(mem_ctx, &global_sid_Builtin); ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid); result = libnet_samsync(SAM_DATABASE_BUILTIN, ctx); if (!NT_STATUS_IS_OK(result) && ctx->error_message) { d_fprintf(stderr, "%s\n", ctx->error_message); goto fail; } if (ctx->result_message) { d_fprintf(stdout, "%s\n", ctx->result_message); } fail: TALLOC_FREE(ctx); return result; }
NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *workstation_name, DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd, const struct samr_Password *lm_interactive_pwd, const struct samr_Password *nt_interactive_pwd, const char *plaintext, enum auth_password_state password_state) { const char *domain; NTSTATUS result; bool was_mapped; char *internal_username = NULL; was_mapped = map_username(talloc_tos(), smb_name, &internal_username); if (!internal_username) { return NT_STATUS_NO_MEMORY; } DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n", client_domain, smb_name, workstation_name)); domain = client_domain; /* If you connect to a Windows domain member using a bogus domain name, * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if * the Windows box is a DC the name will become DOMAIN\user and be * authenticated against AD, if the Windows box is a member server but * not a DC the name will become WORKSTATION\user. A standalone * non-domain member box will also map to WORKSTATION\user. * This also deals with the client passing in a "" domain */ if (!is_trusted_domain(domain) && !strequal(domain, my_sam_name()) && !strequal(domain, get_global_sam_name())) { if (lp_map_untrusted_to_domain()) domain = my_sam_name(); else domain = get_global_sam_name(); DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from " "workstation [%s]\n", client_domain, domain, smb_name, workstation_name)); } /* We know that the given domain is trusted (and we are allowing them), * it is our global SAM name, or for legacy behavior it is our * primary domain name */ result = make_user_info(user_info, smb_name, internal_username, client_domain, domain, workstation_name, lm_pwd, nt_pwd, lm_interactive_pwd, nt_interactive_pwd, plaintext, password_state); if (NT_STATUS_IS_OK(result)) { /* We have tried mapping */ (*user_info)->mapped_state = True; /* did we actually map the user to a different name? */ (*user_info)->was_mapped = was_mapped; } return result; }
/* Add a trusted domain out of a trusted domain cache entry */ static struct winbindd_domain * add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc) { struct winbindd_domain *domain; const char *alternative_name = NULL; const char **ignored_domains, **dom; int role = lp_server_role(); const char *domain_name = tdc->domain_name; const struct dom_sid *sid = &tdc->sid; if (is_null_sid(sid)) { sid = NULL; } ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL); for (dom=ignored_domains; dom && *dom; dom++) { if (gen_fnmatch(*dom, domain_name) == 0) { DEBUG(2,("Ignoring domain '%s'\n", domain_name)); return NULL; } } /* use alt_name if available to allow DNS lookups */ if (tdc->dns_name && *tdc->dns_name) { alternative_name = tdc->dns_name; } /* We can't call domain_list() as this function is called from init_domain_list() and we'll get stuck in a loop. */ for (domain = _domain_list; domain; domain = domain->next) { if (strequal(domain_name, domain->name) || strequal(domain_name, domain->alt_name)) { break; } if (alternative_name) { if (strequal(alternative_name, domain->name) || strequal(alternative_name, domain->alt_name)) { break; } } if (sid != NULL) { if (dom_sid_equal(sid, &domain->sid)) { break; } } } if (domain != NULL) { /* * We found a match on domain->name or * domain->alt_name. Possibly update the SID * if the stored SID was the NULL SID * and return the matching entry. */ if ((sid != NULL) && dom_sid_equal(&domain->sid, &global_sid_NULL)) { sid_copy( &domain->sid, sid ); } return domain; } /* Create new domain entry */ domain = talloc_zero(NULL, struct winbindd_domain); if (domain == NULL) { return NULL; } domain->children = talloc_zero_array(domain, struct winbindd_child, lp_winbind_max_domain_connections()); if (domain->children == NULL) { TALLOC_FREE(domain); return NULL; } domain->name = talloc_strdup(domain, domain_name); if (domain->name == NULL) { TALLOC_FREE(domain); return NULL; } if (alternative_name) { domain->alt_name = talloc_strdup(domain, alternative_name); if (domain->alt_name == NULL) { TALLOC_FREE(domain); return NULL; } } domain->backend = NULL; domain->internal = is_internal_domain(sid); domain->sequence_number = DOM_SEQUENCE_NONE; domain->last_seq_check = 0; domain->initialized = false; domain->online = is_internal_domain(sid); domain->check_online_timeout = 0; domain->dc_probe_pid = (pid_t)-1; if (sid != NULL) { sid_copy(&domain->sid, sid); } domain->domain_flags = tdc->trust_flags; domain->domain_type = tdc->trust_type; domain->domain_trust_attribs = tdc->trust_attribs; /* Is this our primary domain ? */ if (strequal(domain_name, get_global_sam_name()) && (role != ROLE_DOMAIN_MEMBER)) { domain->primary = true; } else if (strequal(domain_name, lp_workgroup()) && (role == ROLE_DOMAIN_MEMBER)) { domain->primary = true; } if (domain->primary) { if (role == ROLE_ACTIVE_DIRECTORY_DC) { domain->active_directory = true; } if (lp_security() == SEC_ADS) { domain->active_directory = true; } } else if (!domain->internal) { if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) { domain->active_directory = true; } } /* Link to domain list */ DLIST_ADD_END(_domain_list, domain); wcache_tdc_add_domain( domain ); setup_domain_child(domain); DEBUG(2, ("Added domain %s %s %s\n", domain->name, domain->alt_name, !is_null_sid(&domain->sid) ? sid_string_dbg(&domain->sid) : "")); return domain; }
bool lookup_name(TALLOC_CTX *mem_ctx, const char *full_name, int flags, const char **ret_domain, const char **ret_name, DOM_SID *ret_sid, enum lsa_SidType *ret_type) { char *p; const char *tmp; const char *domain = NULL; const char *name = NULL; uint32 rid; DOM_SID sid; enum lsa_SidType type; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); if (tmp_ctx == NULL) { DEBUG(0, ("talloc_new failed\n")); return false; } p = strchr_m(full_name, '\\'); if (p != NULL) { domain = talloc_strndup(tmp_ctx, full_name, PTR_DIFF(p, full_name)); name = talloc_strdup(tmp_ctx, p+1); } else { domain = talloc_strdup(tmp_ctx, ""); name = talloc_strdup(tmp_ctx, full_name); } if ((domain == NULL) || (name == NULL)) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return false; } DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n", full_name, domain, name)); DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags)); if ((flags & LOOKUP_NAME_DOMAIN) && strequal(domain, get_global_sam_name())) { /* It's our own domain, lookup the name in passdb */ if (lookup_global_sam_name(name, flags, &rid, &type)) { sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, rid); goto ok; } TALLOC_FREE(tmp_ctx); return false; } if ((flags & LOOKUP_NAME_BUILTIN) && strequal(domain, builtin_domain_name())) { /* Explicit request for a name in BUILTIN */ if (lookup_builtin_name(name, &rid)) { sid_copy(&sid, &global_sid_Builtin); sid_append_rid(&sid, rid); type = SID_NAME_ALIAS; goto ok; } TALLOC_FREE(tmp_ctx); return false; } /* Try the explicit winbind lookup first, don't let it guess the * domain yet at this point yet. This comes later. */ if ((domain[0] != '\0') && (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) && (winbind_lookup_name(domain, name, &sid, &type))) { goto ok; } if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_users_domain_name())) { if (lookup_unix_user_name(name, &sid)) { type = SID_NAME_USER; goto ok; } TALLOC_FREE(tmp_ctx); return false; } if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_groups_domain_name())) { if (lookup_unix_group_name(name, &sid)) { type = SID_NAME_DOM_GRP; goto ok; } TALLOC_FREE(tmp_ctx); return false; } if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) { TALLOC_FREE(tmp_ctx); return false; } /* Now the guesswork begins, we haven't been given an explicit * domain. Try the sequence as documented on * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp * November 27, 2005 */ /* 1. well-known names */ if ((flags & LOOKUP_NAME_WKN) && lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) { type = SID_NAME_WKN_GRP; goto ok; } /* 2. Builtin domain as such */ if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) && strequal(name, builtin_domain_name())) { /* Swap domain and name */ tmp = name; name = domain; domain = tmp; sid_copy(&sid, &global_sid_Builtin); type = SID_NAME_DOMAIN; goto ok; } /* 3. Account domain */ if ((flags & LOOKUP_NAME_DOMAIN) && strequal(name, get_global_sam_name())) { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch my SID\n")); TALLOC_FREE(tmp_ctx); return false; } /* Swap domain and name */ tmp = name; name = domain; domain = tmp; type = SID_NAME_DOMAIN; goto ok; } /* 4. Primary domain */ if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC && strequal(name, lp_workgroup())) { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch the domain SID\n")); TALLOC_FREE(tmp_ctx); return false; } /* Swap domain and name */ tmp = name; name = domain; domain = tmp; type = SID_NAME_DOMAIN; goto ok; } /* 5. Trusted domains as such, to me it looks as if members don't do this, tested an XP workstation in a NT domain -- vl */ if ((flags & LOOKUP_NAME_REMOTE) && IS_DC && (pdb_get_trusteddom_pw(name, NULL, &sid, NULL))) { /* Swap domain and name */ tmp = name; name = domain; domain = tmp; type = SID_NAME_DOMAIN; goto ok; } /* 6. Builtin aliases */ if ((flags & LOOKUP_NAME_BUILTIN) && lookup_builtin_name(name, &rid)) { domain = talloc_strdup(tmp_ctx, builtin_domain_name()); sid_copy(&sid, &global_sid_Builtin); sid_append_rid(&sid, rid); type = SID_NAME_ALIAS; goto ok; } /* 7. Local systems' SAM (DCs don't have a local SAM) */ /* 8. Primary SAM (On members, this is the domain) */ /* Both cases are done by looking at our passdb */ if ((flags & LOOKUP_NAME_DOMAIN) && lookup_global_sam_name(name, flags, &rid, &type)) { domain = talloc_strdup(tmp_ctx, get_global_sam_name()); sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, rid); goto ok; } /* Now our local possibilities are exhausted. */ if (!(flags & LOOKUP_NAME_REMOTE)) { TALLOC_FREE(tmp_ctx); return false; } /* If we are not a DC, we have to ask in our primary domain. Let * winbind do that. */ if (!IS_DC && (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) { domain = talloc_strdup(tmp_ctx, lp_workgroup()); goto ok; } /* 9. Trusted domains */ /* If we're a DC we have to ask all trusted DC's. Winbind does not do * that (yet), but give it a chance. */ if (IS_DC && winbind_lookup_name("", name, &sid, &type)) { DOM_SID dom_sid; uint32 tmp_rid; enum lsa_SidType domain_type; if (type == SID_NAME_DOMAIN) { /* Swap name and type */ tmp = name; name = domain; domain = tmp; goto ok; } /* Here we have to cope with a little deficiency in the * winbind API: We have to ask it again for the name of the * domain it figured out itself. Maybe fix that later... */ sid_copy(&dom_sid, &sid); sid_split_rid(&dom_sid, &tmp_rid); if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL, &domain_type) || (domain_type != SID_NAME_DOMAIN)) { DEBUG(2, ("winbind could not find the domain's name " "it just looked up for us\n")); TALLOC_FREE(tmp_ctx); return false; } goto ok; } /* 10. Don't translate */ /* 11. Ok, windows would end here. Samba has two more options: Unmapped users and unmapped groups */ if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) { domain = talloc_strdup(tmp_ctx, unix_users_domain_name()); type = SID_NAME_USER; goto ok; } if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) { domain = talloc_strdup(tmp_ctx, unix_groups_domain_name()); type = SID_NAME_DOM_GRP; goto ok; } /* * Ok, all possibilities tried. Fail. */ TALLOC_FREE(tmp_ctx); return false; ok: if ((domain == NULL) || (name == NULL)) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return false; } /* * Hand over the results to the talloc context we've been given. */ if ((ret_name != NULL) && !(*ret_name = talloc_strdup(mem_ctx, name))) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return false; } if (ret_domain != NULL) { char *tmp_dom; if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return false; } strupper_m(tmp_dom); *ret_domain = tmp_dom; } if (ret_sid != NULL) { sid_copy(ret_sid, &sid); } if (ret_type != NULL) { *ret_type = type; } TALLOC_FREE(tmp_ctx); return true; }
static NTSTATUS fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, DSROLE_PRIMARY_DOMAIN_INFO_BASIC **info) { DSROLE_PRIMARY_DOMAIN_INFO_BASIC *basic; const char *netbios_domain = ""; fstring dnsdomain; DEBUG(10,("fill_dsrole_dominfo_basic: enter\n")); if ( !(basic = TALLOC_ZERO_P(ctx, DSROLE_PRIMARY_DOMAIN_INFO_BASIC)) ) { DEBUG(0,("fill_dsrole_dominfo_basic: FATAL error! talloc_xero() failed\n")); return NT_STATUS_NO_MEMORY; } switch ( lp_server_role() ) { case ROLE_STANDALONE: basic->machine_role = DSROLE_STANDALONE_SRV; basic->netbios_ptr = 1; netbios_domain = get_global_sam_name(); break; case ROLE_DOMAIN_MEMBER: basic->netbios_ptr = 1; netbios_domain = lp_workgroup(); basic->machine_role = DSROLE_DOMAIN_MEMBER_SRV; break; case ROLE_DOMAIN_BDC: basic->netbios_ptr = 1; netbios_domain = get_global_sam_name(); basic->machine_role = DSROLE_BDC; break; case ROLE_DOMAIN_PDC: basic->netbios_ptr = 1; netbios_domain = get_global_sam_name(); basic->machine_role = DSROLE_PDC; break; } /* always set netbios name */ init_unistr2( &basic->netbios_domain, netbios_domain, UNI_STR_TERMINATE); if ( secrets_fetch_domain_guid( lp_workgroup(), &basic->domain_guid ) ) basic->flags |= DSROLE_PRIMARY_DOMAIN_GUID_PRESENT; /* fill in some additional fields if we are a member of an AD domain */ if ( lp_security() == SEC_ADS ) { fstrcpy( dnsdomain, lp_realm() ); strlower_m( dnsdomain ); basic->dnsname_ptr = 1; init_unistr2( &basic->dns_domain, dnsdomain, UNI_STR_TERMINATE); /* FIXME!! We really should fill in the correct forest name. Should get this information from winbindd. */ basic->forestname_ptr = 1; init_unistr2( &basic->forest_domain, dnsdomain, UNI_STR_TERMINATE); } else { /* security = domain should not fill in the dns or forest name */ basic->dnsname_ptr = 0; basic->forestname_ptr = 0; } *info = basic; return NT_STATUS_OK; }