/* * Test that a ticket obtained for the DNS service will be accepted on the Samba DLZ side * */ static bool test_dlz_bind9_gensec(struct torture_context *tctx, const char *mech) { NTSTATUS status; struct gensec_security *gensec_client_context; DATA_BLOB client_to_server, server_to_client; void *dbdata; const char *argv[] = { "samba_dlz", "-H", lpcfg_private_path(tctx, tctx->lp_ctx, "dns/sam.ldb"), NULL }; tctx_static = tctx; torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, discard_const_p(char *, argv), &dbdata, "log", dlz_bind9_log_wrapper, "writeable_zone", dlz_bind9_writeable_zone_hook, NULL), ISC_R_SUCCESS, "Failed to create samba_dlz"); torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata), ISC_R_SUCCESS, "Failed to configure samba_dlz"); status = gensec_client_start(tctx, &gensec_client_context, lpcfg_gensec_settings(tctx, tctx->lp_ctx)); torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed"); status = gensec_set_target_hostname(gensec_client_context, torture_setting_string(tctx, "host", NULL)); torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed"); status = gensec_set_credentials(gensec_client_context, cmdline_credentials); torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed"); status = gensec_start_mech_by_sasl_name(gensec_client_context, mech); torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed"); server_to_client = data_blob(NULL, 0); /* Do one step of the client-server update dance */ status = gensec_update(gensec_client_context, tctx, tctx->ev, server_to_client, &client_to_server); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {; torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed"); } torture_assert_int_equal(tctx, dlz_ssumatch(cli_credentials_get_username(cmdline_credentials), lpcfg_dnsdomain(tctx->lp_ctx), "127.0.0.1", "type", "key", client_to_server.length, client_to_server.data, dbdata), ISC_R_SUCCESS, "Failed to check key for update rights samba_dlz"); dlz_destroy(dbdata); return true; }
static bool test_NetrJoinDomain(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct wkssvc_NetrJoinDomain r; struct cli_credentials *creds = cmdline_credentials; const char *user = cli_credentials_get_username(creds); const char *admin_account = NULL; struct dcerpc_binding_handle *b = p->binding_handle; admin_account = talloc_asprintf(tctx, "%s\\%s", lpcfg_workgroup(tctx->lp_ctx), user); r.in.server_name = dcerpc_server_name(p); r.in.domain_name = lpcfg_dnsdomain(tctx->lp_ctx); r.in.account_ou = NULL; r.in.Account = admin_account; r.in.password = NULL; r.in.join_flags = 0; torture_comment(tctx, "Testing NetrJoinDomain\n"); status = dcerpc_wkssvc_NetrJoinDomain_r(b, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "NetrJoinDomain failed"); torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED, "NetrJoinDomain failed"); return true; }
/* work out the principal to use for DRS replication connections */ NTSTATUS dreplsrv_get_target_principal(struct dreplsrv_service *s, TALLOC_CTX *mem_ctx, const struct repsFromTo1 *rft, const char **target_principal) { TALLOC_CTX *tmp_ctx; struct ldb_result *res; const char *attrs[] = { "dNSHostName", NULL }; int ret; const char *hostname; struct ldb_dn *dn; *target_principal = NULL; tmp_ctx = talloc_new(mem_ctx); /* we need to find their hostname */ ret = dsdb_find_dn_by_guid(s->samdb, tmp_ctx, &rft->source_dsa_obj_guid, &dn); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); /* its OK for their NTDSDSA DN not to be in our database */ return NT_STATUS_OK; } /* strip off the NTDS Settings */ if (!ldb_dn_remove_child_components(dn, 1)) { talloc_free(tmp_ctx); return NT_STATUS_OK; } ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, dn, attrs, 0); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); /* its OK for their account DN not to be in our database */ return NT_STATUS_OK; } hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL); if (hostname == NULL) { talloc_free(tmp_ctx); /* its OK to not have a dnshostname */ return NT_STATUS_OK; } /* All DCs have the GC/hostname/realm name, but if some of the * preconditions are not satisfied, then we will fall back to * the * E3514235-4B06-11D1-AB04-00C04FC2DCD2/${NTDSGUID}/${DNSDOMAIN} * name. This means that if a AD server has a dnsHostName set * on it's record, it must also have GC/hostname/realm * servicePrincipalName */ *target_principal = talloc_asprintf(mem_ctx, "GC/%s/%s", hostname, lpcfg_dnsdomain(s->task->lp_ctx)); talloc_free(tmp_ctx); return NT_STATUS_OK; }
/* * Test some zone dumps */ static bool test_dlz_bind9_zonedump(struct torture_context *tctx) { size_t i; void *dbdata; const char *argv[] = { "samba_dlz", "-H", lpcfg_private_path(tctx, tctx->lp_ctx, "dns/sam.ldb"), NULL }; struct test_expected_rr *expected1 = NULL; tctx_static = tctx; torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, "log", dlz_bind9_log_wrapper, "writeable_zone", dlz_bind9_writeable_zone_hook, "putrr", dlz_bind9_putrr_hook, "putnamedrr", dlz_bind9_putnamedrr_hook, NULL), ISC_R_SUCCESS, "Failed to create samba_dlz"); torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata), ISC_R_SUCCESS, "Failed to configure samba_dlz"); expected1 = talloc_zero(tctx, struct test_expected_rr); torture_assert(tctx, expected1 != NULL, "talloc failed"); expected1->tctx = tctx; expected1->num_records = 7; expected1->records = talloc_zero_array(expected1, struct test_expected_record, expected1->num_records); torture_assert(tctx, expected1->records != NULL, "talloc failed"); expected1->records[0].name = talloc_asprintf(expected1->records, "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[0].type = "soa"; expected1->records[0].ttl = 3600; expected1->records[0].data = talloc_asprintf(expected1->records, "%s.%s. hostmaster.%s. 1 900 600 86400 3600", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed"); expected1->records[1].name = talloc_asprintf(expected1->records, "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[1].type = "ns"; expected1->records[1].ttl = 900; expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed"); expected1->records[2].name = talloc_asprintf(expected1->records, "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[2].type = "aaaa"; expected1->records[2].ttl = 900; expected1->records[3].name = talloc_asprintf(expected1->records, "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[3].type = "a"; expected1->records[3].ttl = 900; expected1->records[4].name = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[4].name != NULL, "unknown host"); expected1->records[4].type = "aaaa"; expected1->records[4].ttl = 900; expected1->records[5].name = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[5].name != NULL, "unknown host"); expected1->records[5].type = "a"; expected1->records[5].ttl = 900; /* * We expect multiple srv records */ expected1->records[6].name = NULL; expected1->records[6].type = "srv"; expected1->records[6].ttl = 900; torture_assert_int_equal(tctx, dlz_allnodes(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, (dns_sdlzallnodes_t *)expected1), ISC_R_SUCCESS, "Failed to configure samba_dlz"); for (i = 0; i < expected1->num_records; i++) { torture_assert(tctx, expected1->records[i].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[i].name, expected1->records[i].type)); } torture_assert_int_equal(tctx, expected1->num_rr, 24, "Got wrong record count"); dlz_destroy(dbdata); return true; }
static WERROR sptr_PrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, const char *value_name, union spoolss_PrinterData *r, enum winreg_Type *type) { struct dcerpc_server_info *server_info = lpcfg_dcerpc_server_info(mem_ctx, server->ntptr->lp_ctx); if (strcmp("W3SvcInstalled", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("BeepEnabled", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("EventLog", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("NetPopup", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("NetPopupToComputer", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("MajorVersion", value_name) == 0) { *type = REG_DWORD; r->value = 3; return WERR_OK; } else if (strcmp("MinorVersion", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("DefaultSpoolDirectory", value_name) == 0) { *type = REG_SZ; r->string = "C:\\PRINTERS"; return WERR_OK; } else if (strcmp("Architecture", value_name) == 0) { *type = REG_SZ; r->string = SPOOLSS_ARCHITECTURE_NT_X86; return WERR_OK; } else if (strcmp("DsPresent", value_name) == 0) { *type = REG_DWORD; r->value = 1; return WERR_OK; } else if (strcmp("OSVersion", value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersion os; os.major = server_info->version_major; os.minor = server_info->version_minor; os.build = server_info->version_build; os.extra_string = ""; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } *type = REG_BINARY; r->binary = blob; return WERR_OK; } else if (strcmp("OSVersionEx", value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersionEx os_ex; os_ex.major = server_info->version_major; os_ex.minor = server_info->version_minor; os_ex.build = server_info->version_build; os_ex.extra_string = ""; os_ex.service_pack_major= 0; os_ex.service_pack_minor= 0; os_ex.suite_mask = 0; os_ex.product_type = 0; os_ex.reserved = 0; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os_ex, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersionEx); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } *type = REG_BINARY; r->binary = blob; return WERR_OK; } else if (strcmp("DNSMachineName", value_name) == 0) { const char *dnsdomain = lpcfg_dnsdomain(server->ntptr->lp_ctx); if (dnsdomain == NULL) return WERR_INVALID_PARAM; *type = REG_SZ; r->string = talloc_asprintf(mem_ctx, "%s.%s", lpcfg_netbios_name(server->ntptr->lp_ctx), dnsdomain); W_ERROR_HAVE_NO_MEMORY(r->string); return WERR_OK; } return WERR_INVALID_PARAM; }
/** * Start NTLMSSP on the server side * */ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security) { NTSTATUS nt_status; struct ntlmssp_state *ntlmssp_state; struct gensec_ntlmssp_context *gensec_ntlmssp; const char *netbios_name; const char *netbios_domain; const char *dns_name; const char *dns_domain; enum server_role role; role = lpcfg_server_role(gensec_security->settings->lp_ctx); nt_status = gensec_ntlmssp_start(gensec_security); NT_STATUS_NOT_OK_RETURN(nt_status); gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data, struct gensec_ntlmssp_context); ntlmssp_state = talloc_zero(gensec_ntlmssp, struct ntlmssp_state); if (!ntlmssp_state) { return NT_STATUS_NO_MEMORY; } gensec_ntlmssp->ntlmssp_state = ntlmssp_state; ntlmssp_state->role = NTLMSSP_SERVER; ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE; ntlmssp_state->allow_lm_response = lpcfg_lanman_auth(gensec_security->settings->lp_ctx); if (ntlmssp_state->allow_lm_response && gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "allow_lm_key", false)) { ntlmssp_state->allow_lm_key = true; } ntlmssp_state->force_old_spnego = false; if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "force_old_spnego", false)) { /* * For testing Windows 2000 mode */ ntlmssp_state->force_old_spnego = true; } ntlmssp_state->neg_flags = NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_VERSION; if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "128bit", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "56bit", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "keyexchange", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "alwayssign", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "ntlm2", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; } if (ntlmssp_state->allow_lm_key) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; } /* * We always allow NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL. * * These will be removed if the client doesn't want them. */ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; } if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; if (gensec_security->want_features & GENSEC_FEATURE_LDAP_STYLE) { /* * We need to handle NTLMSSP_NEGOTIATE_SIGN as * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE * is requested. */ ntlmssp_state->force_wrap_seal = true; } } if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; } if (role == ROLE_STANDALONE) { ntlmssp_state->server.is_standalone = true; } else { ntlmssp_state->server.is_standalone = false; } if (gensec_security->settings->server_netbios_name) { netbios_name = gensec_security->settings->server_netbios_name; } else { netbios_name = lpcfg_netbios_name(gensec_security->settings->lp_ctx); } if (gensec_security->settings->server_netbios_domain) { netbios_domain = gensec_security->settings->server_netbios_domain; } else { netbios_domain = lpcfg_workgroup(gensec_security->settings->lp_ctx); } if (gensec_security->settings->server_dns_name) { dns_name = gensec_security->settings->server_dns_name; } else { const char *dnsdomain = lpcfg_dnsdomain(gensec_security->settings->lp_ctx); char *lower_netbiosname; lower_netbiosname = strlower_talloc(ntlmssp_state, netbios_name); NT_STATUS_HAVE_NO_MEMORY(lower_netbiosname); /* Find out the DNS host name */ if (dnsdomain && dnsdomain[0] != '\0') { dns_name = talloc_asprintf(ntlmssp_state, "%s.%s", lower_netbiosname, dnsdomain); talloc_free(lower_netbiosname); NT_STATUS_HAVE_NO_MEMORY(dns_name); } else { dns_name = lower_netbiosname; } } if (gensec_security->settings->server_dns_domain) { dns_domain = gensec_security->settings->server_dns_domain; } else { dns_domain = lpcfg_dnsdomain(gensec_security->settings->lp_ctx); } ntlmssp_state->server.netbios_name = talloc_strdup(ntlmssp_state, netbios_name); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.netbios_name); ntlmssp_state->server.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.netbios_domain); ntlmssp_state->server.dns_name = talloc_strdup(ntlmssp_state, dns_name); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_name); ntlmssp_state->server.dns_domain = talloc_strdup(ntlmssp_state, dns_domain); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_domain); ntlmssp_state->neg_flags |= ntlmssp_state->required_flags; ntlmssp_state->conf_flags = ntlmssp_state->neg_flags; return NT_STATUS_OK; }
/* fill in the cldap netlogon union for a given version */ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, const char *domain, const char *netbios_domain, struct dom_sid *domain_sid, const char *domain_guid, const char *user, uint32_t acct_control, const char *src_address, uint32_t version, struct loadparm_context *lp_ctx, struct netlogon_samlogon_response *netlogon, bool fill_on_blank_request) { const char *dom_attrs[] = {"objectGUID", NULL}; const char *none_attrs[] = {NULL}; struct ldb_result *dom_res = NULL, *user_res = NULL; int ret; const char **services = lpcfg_server_services(lp_ctx); uint32_t server_type; const char *pdc_name; struct GUID domain_uuid; const char *dns_domain; const char *forest_domain; const char *pdc_dns_name; const char *flatname; const char *server_site; const char *client_site; const char *pdc_ip; struct ldb_dn *domain_dn = NULL; struct interface *ifaces; bool user_known, am_rodc; NTSTATUS status; /* the domain parameter could have an optional trailing "." */ if (domain && domain[strlen(domain)-1] == '.') { domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1); NT_STATUS_HAVE_NO_MEMORY(domain); } /* Lookup using long or short domainname */ if (domain && (strcasecmp_m(domain, lpcfg_dnsdomain(lp_ctx)) == 0)) { domain_dn = ldb_get_default_basedn(sam_ctx); } if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) { domain_dn = ldb_get_default_basedn(sam_ctx); } if (domain_dn) { const char *domain_identifier = domain != NULL ? domain : netbios_domain; ret = ldb_search(sam_ctx, mem_ctx, &dom_res, domain_dn, LDB_SCOPE_BASE, dom_attrs, "objectClass=domain"); if (ret != LDB_SUCCESS) { DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain_identifier, ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } if (dom_res->count != 1) { DEBUG(2,("Error finding domain '%s'/'%s' in sam\n", domain_identifier, ldb_dn_get_linearized(domain_dn))); return NT_STATUS_NO_SUCH_DOMAIN; } } /* Lookup using GUID or SID */ if ((dom_res == NULL) && (domain_guid || domain_sid)) { if (domain_guid) { struct GUID binary_guid; struct ldb_val guid_val; /* By this means, we ensure we don't have funny stuff in the GUID */ status = GUID_from_string(domain_guid, &binary_guid); if (!NT_STATUS_IS_OK(status)) { return status; } /* And this gets the result into the binary format we want anyway */ status = GUID_to_ndr_blob(&binary_guid, mem_ctx, &guid_val); if (!NT_STATUS_IS_OK(status)) { return status; } ret = ldb_search(sam_ctx, mem_ctx, &dom_res, NULL, LDB_SCOPE_SUBTREE, dom_attrs, "(&(objectCategory=DomainDNS)(objectGUID=%s))", ldb_binary_encode(mem_ctx, guid_val)); } else { /* domain_sid case */ ret = ldb_search(sam_ctx, mem_ctx, &dom_res, NULL, LDB_SCOPE_SUBTREE, dom_attrs, "(&(objectCategory=DomainDNS)(objectSid=%s))", dom_sid_string(mem_ctx, domain_sid)); } if (ret != LDB_SUCCESS) { DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam: %s\n", domain_guid, dom_sid_string(mem_ctx, domain_sid), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } else if (dom_res->count == 1) { /* Ok, now just check it is our domain */ if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx), dom_res->msgs[0]->dn) != 0) { DEBUG(2,("The GUID '%s' or SID '%s' doesn't identify our domain\n", domain_guid, dom_sid_string(mem_ctx, domain_sid))); return NT_STATUS_NO_SUCH_DOMAIN; } } else { DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam\n", domain_guid, dom_sid_string(mem_ctx, domain_sid))); return NT_STATUS_NO_SUCH_DOMAIN; } } if (dom_res == NULL && fill_on_blank_request) { /* blank inputs gives our domain - tested against w2k8r2. Without this ADUC on Win7 won't start */ domain_dn = ldb_get_default_basedn(sam_ctx); ret = ldb_search(sam_ctx, mem_ctx, &dom_res, domain_dn, LDB_SCOPE_BASE, dom_attrs, "objectClass=domain"); if (ret != LDB_SUCCESS) { DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", lpcfg_dnsdomain(lp_ctx), ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } } if (dom_res == NULL) { DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n")); return NT_STATUS_NO_SUCH_DOMAIN; } /* work around different inputs for not-specified users */ if (!user) { user = ""; } /* Enquire about any valid username with just a CLDAP packet - * if kerberos didn't also do this, the security folks would * scream... */ if (user[0]) { \ /* Only allow some bits to be enquired: [MS-ATDS] 7.3.3.2 */ if (acct_control == (uint32_t)-1) { acct_control = 0; } acct_control = acct_control & (ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); /* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */ ret = ldb_search(sam_ctx, mem_ctx, &user_res, dom_res->msgs[0]->dn, LDB_SCOPE_SUBTREE, none_attrs, "(&(objectClass=user)(samAccountName=%s)" "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))" "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))", ldb_binary_encode_string(mem_ctx, user), UF_ACCOUNTDISABLE, ds_acb2uf(acct_control)); if (ret != LDB_SUCCESS) { DEBUG(2,("Unable to find reference to user '%s' with ACB 0x%8x under %s: %s\n", user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_USER; } else if (user_res->count == 1) { user_known = true; } else { user_known = false; } } else { user_known = true; } server_type = DS_SERVER_DS | DS_SERVER_TIMESERV | DS_SERVER_GOOD_TIMESERV; if (samdb_is_pdc(sam_ctx)) { server_type |= DS_SERVER_PDC; } if (dsdb_functional_level(sam_ctx) >= DS_DOMAIN_FUNCTION_2008) { server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6; } if (samdb_is_gc(sam_ctx)) { server_type |= DS_SERVER_GC; } if (str_list_check(services, "ldap")) { server_type |= DS_SERVER_LDAP; } if (str_list_check(services, "kdc")) { server_type |= DS_SERVER_KDC; } if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) { server_type |= DS_SERVER_WRITABLE; } pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", lpcfg_netbios_name(lp_ctx)); NT_STATUS_HAVE_NO_MEMORY(pdc_name); domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); dns_domain = lpcfg_dnsdomain(lp_ctx); forest_domain = samdb_forest_name(sam_ctx, mem_ctx); NT_STATUS_HAVE_NO_MEMORY(forest_domain); pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s", strlower_talloc(mem_ctx, lpcfg_netbios_name(lp_ctx)), dns_domain); NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name); flatname = lpcfg_workgroup(lp_ctx); server_site = samdb_server_site_name(sam_ctx, mem_ctx); NT_STATUS_HAVE_NO_MEMORY(server_site); client_site = samdb_client_site_name(sam_ctx, mem_ctx, src_address, NULL); NT_STATUS_HAVE_NO_MEMORY(client_site); if (strcasecmp(server_site, client_site) == 0) { server_type |= DS_SERVER_CLOSEST; } load_interface_list(mem_ctx, lp_ctx, &ifaces); if (src_address) { pdc_ip = iface_list_best_ip(ifaces, src_address); } else { pdc_ip = iface_list_first_v4(ifaces); } if (pdc_ip == NULL || !is_ipaddress_v4(pdc_ip)) { /* this matches windows behaviour */ pdc_ip = "127.0.0.1"; } ZERO_STRUCTP(netlogon); /* check if either of these bits is present */ if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) { uint32_t extra_flags = 0; netlogon->ntver = NETLOGON_NT_VERSION_5EX; /* could check if the user exists */ if (user_known) { netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_RESPONSE_EX; } else { netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_USER_UNKNOWN_EX; } netlogon->data.nt5_ex.pdc_name = pdc_name; netlogon->data.nt5_ex.user_name = user; netlogon->data.nt5_ex.domain_name = flatname; netlogon->data.nt5_ex.domain_uuid = domain_uuid; netlogon->data.nt5_ex.forest = forest_domain; netlogon->data.nt5_ex.dns_domain = dns_domain; netlogon->data.nt5_ex.pdc_dns_name = pdc_dns_name; netlogon->data.nt5_ex.server_site = server_site; netlogon->data.nt5_ex.client_site = client_site; if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) { /* note that this is always a IPV4 address */ extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP; netlogon->data.nt5_ex.sockaddr.sockaddr_family = 2; netlogon->data.nt5_ex.sockaddr.pdc_ip = pdc_ip; netlogon->data.nt5_ex.sockaddr.remaining = data_blob_talloc_zero(mem_ctx, 8); } netlogon->data.nt5_ex.server_type = server_type; netlogon->data.nt5_ex.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5EX|extra_flags; netlogon->data.nt5_ex.lmnt_token = 0xFFFF; netlogon->data.nt5_ex.lm20_token = 0xFFFF; } else if (version & NETLOGON_NT_VERSION_5) { netlogon->ntver = NETLOGON_NT_VERSION_5; /* could check if the user exists */ if (user_known) { netlogon->data.nt5.command = LOGON_SAM_LOGON_RESPONSE; } else { netlogon->data.nt5.command = LOGON_SAM_LOGON_USER_UNKNOWN; } netlogon->data.nt5.pdc_name = pdc_name; netlogon->data.nt5.user_name = user; netlogon->data.nt5.domain_name = flatname; netlogon->data.nt5.domain_uuid = domain_uuid; netlogon->data.nt5.forest = forest_domain; netlogon->data.nt5.dns_domain = dns_domain; netlogon->data.nt5.pdc_dns_name = pdc_dns_name; netlogon->data.nt5.pdc_ip = pdc_ip; netlogon->data.nt5.server_type = server_type; netlogon->data.nt5.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5; netlogon->data.nt5.lmnt_token = 0xFFFF; netlogon->data.nt5.lm20_token = 0xFFFF; } else /* (version & NETLOGON_NT_VERSION_1) and all other cases */ { netlogon->ntver = NETLOGON_NT_VERSION_1; /* could check if the user exists */ if (user_known) { netlogon->data.nt4.command = LOGON_SAM_LOGON_RESPONSE; } else { netlogon->data.nt4.command = LOGON_SAM_LOGON_USER_UNKNOWN; } netlogon->data.nt4.pdc_name = pdc_name; netlogon->data.nt4.user_name = user; netlogon->data.nt4.domain_name = flatname; netlogon->data.nt4.nt_version = NETLOGON_NT_VERSION_1; netlogon->data.nt4.lmnt_token = 0xFFFF; netlogon->data.nt4.lm20_token = 0xFFFF; } return NT_STATUS_OK; }
/* * Check server_name is: * - "" , functions that don't allow "", * should check that on their own, before calling this function * - our name (only netbios yet, TODO: need to test dns name!) * - our ip address of the current use socket * otherwise return WERR_INVALID_PRINTER_NAME */ static WERROR dcesrv_spoolss_check_server_name(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, const char *server_name) { bool ret; const struct tsocket_address *local_address; char *myaddr; const char **aliases; const char *dnsdomain; unsigned int i; /* NULL is ok */ if (!server_name) return WERR_OK; /* "" is ok */ ret = strequal("",server_name); if (ret) return WERR_OK; /* just "\\" is invalid */ if (strequal("\\\\", server_name)) { return WERR_INVALID_PRINTER_NAME; } /* then we need "\\" */ if (strncmp("\\\\", server_name, 2) != 0) { return WERR_INVALID_PRINTER_NAME; } server_name += 2; /* NETBIOS NAME is ok */ ret = strequal(lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx), server_name); if (ret) return WERR_OK; aliases = lpcfg_netbios_aliases(dce_call->conn->dce_ctx->lp_ctx); for (i=0; aliases && aliases[i]; i++) { if (strequal(aliases[i], server_name)) { return WERR_OK; } } /* DNS NAME is ok * TODO: we need to check if aliases are also ok */ dnsdomain = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx); if (dnsdomain != NULL) { char *str; str = talloc_asprintf(mem_ctx, "%s.%s", lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx), dnsdomain); W_ERROR_HAVE_NO_MEMORY(str); ret = strequal(str, server_name); talloc_free(str); if (ret) return WERR_OK; } local_address = dcesrv_connection_get_local_address(dce_call->conn); myaddr = tsocket_address_inet_addr_string(local_address, mem_ctx); W_ERROR_HAVE_NO_MEMORY(myaddr); ret = strequal(myaddr, server_name); talloc_free(myaddr); if (ret) return WERR_OK; return WERR_INVALID_PRINTER_NAME; }
static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, struct tevent_context *ev, const DATA_BLOB in, DATA_BLOB *out) { struct schannel_state *state = (struct schannel_state *)gensec_security->private_data; NTSTATUS status; enum ndr_err_code ndr_err; struct NL_AUTH_MESSAGE bind_schannel; struct NL_AUTH_MESSAGE bind_schannel_ack; struct netlogon_creds_CredentialState *creds; const char *workstation; const char *domain; *out = data_blob(NULL, 0); switch (gensec_security->gensec_role) { case GENSEC_CLIENT: if (state->state != SCHANNEL_STATE_START) { /* we could parse the bind ack, but we don't know what it is yet */ return NT_STATUS_OK; } state->creds = cli_credentials_get_netlogon_creds(gensec_security->credentials); if (state->creds == NULL) { return NT_STATUS_INVALID_PARAMETER_MIX; } /* * We need to create a reference here or we don't get * updates performed on the credentials if we create a * copy. */ state->creds = talloc_reference(state, state->creds); if (state->creds == NULL) { return NT_STATUS_NO_MEMORY; } bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; #if 0 /* to support this we'd need to have access to the full domain name */ /* 0x17, 23 */ bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | NL_FLAG_OEM_NETBIOS_COMPUTER_NAME | NL_FLAG_UTF8_DNS_DOMAIN_NAME | NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME; bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); bind_schannel.oem_netbios_computer.a = cli_credentials_get_workstation(gensec_security->credentials); bind_schannel.utf8_dns_domain = cli_credentials_get_realm(gensec_security->credentials); /* w2k3 refuses us if we use the full DNS workstation? why? perhaps because we don't fill in the dNSHostName attribute in the machine account? */ bind_schannel.utf8_netbios_computer = cli_credentials_get_workstation(gensec_security->credentials); #else bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); bind_schannel.oem_netbios_computer.a = cli_credentials_get_workstation(gensec_security->credentials); #endif ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel, (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(3, ("Could not create schannel bind: %s\n", nt_errstr(status))); return status; } state->state = SCHANNEL_STATE_UPDATE_1; return NT_STATUS_MORE_PROCESSING_REQUIRED; case GENSEC_SERVER: if (state->state != SCHANNEL_STATE_START) { /* no third leg on this protocol */ return NT_STATUS_INVALID_PARAMETER; } /* parse the schannel startup blob */ ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel, (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(3, ("Could not parse incoming schannel bind: %s\n", nt_errstr(status))); return status; } if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) { domain = bind_schannel.oem_netbios_domain.a; if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) { DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", domain, lpcfg_workgroup(gensec_security->settings->lp_ctx))); return NT_STATUS_LOGON_FAILURE; } } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) { domain = bind_schannel.utf8_dns_domain.u; if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) { DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx))); return NT_STATUS_LOGON_FAILURE; } } else { DEBUG(3, ("Request for schannel to without domain\n")); return NT_STATUS_LOGON_FAILURE; } if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) { workstation = bind_schannel.oem_netbios_computer.a; } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) { workstation = bind_schannel.utf8_netbios_computer.u; } else { DEBUG(3, ("Request for schannel to without netbios workstation\n")); return NT_STATUS_LOGON_FAILURE; } status = schannel_get_creds_state(out_mem_ctx, gensec_security->settings->lp_ctx, workstation, &creds); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n", workstation, nt_errstr(status))); if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { return NT_STATUS_LOGON_FAILURE; } return status; } state->creds = talloc_steal(state, creds); bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; bind_schannel_ack.Flags = 0; bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think * this does not have * any meaning here * - gd */ ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack, (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n", workstation, nt_errstr(status))); return status; } state->state = SCHANNEL_STATE_UPDATE_1; return NT_STATUS_OK; } return NT_STATUS_INVALID_PARAMETER; }
struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct ldb_context *samdb) { struct dnsserver_serverinfo *serverinfo; struct dcerpc_server_info *dinfo; struct ldb_dn *domain_dn, *forest_dn; struct interface *ifaces; int num_interfaces, i; serverinfo = talloc_zero(mem_ctx, struct dnsserver_serverinfo); if (serverinfo == NULL) { return NULL; } dinfo = lpcfg_dcerpc_server_info(mem_ctx, lp_ctx); if (dinfo) { serverinfo->dwVersion = (dinfo->version_build & 0x0000FFFF) << 16 | (dinfo->version_minor & 0x000000FF) << 8 | (dinfo->version_major & 0x000000FF); talloc_free(dinfo); } else { serverinfo->dwVersion = 0x0ECE0205; /* build, os_minor, os_major */; } serverinfo->fBootMethod = DNS_BOOT_METHOD_DIRECTORY; serverinfo->fAdminConfigured = 0; serverinfo->fAllowUpdate = 1; serverinfo->fDsAvailable = 1; serverinfo->pszServerName = talloc_asprintf(mem_ctx, "%s.%s", lpcfg_netbios_name(lp_ctx), lpcfg_dnsdomain(lp_ctx)); domain_dn = ldb_get_default_basedn(samdb); forest_dn = ldb_get_root_basedn(samdb); serverinfo->pszDsContainer = talloc_asprintf(mem_ctx, "CN=MicrosoftDNS,DC=DomainDnsZones,%s", ldb_dn_get_linearized(domain_dn)); serverinfo->dwDsForestVersion = dsdb_forest_functional_level(samdb); serverinfo->dwDsDomainVersion = dsdb_functional_level(samdb); serverinfo->dwDsDsaVersion = 4; /* need to do ldb search here */ serverinfo->pszDomainName = samdb_dn_to_dns_domain(mem_ctx, domain_dn); serverinfo->pszForestName = samdb_dn_to_dns_domain(mem_ctx, forest_dn); serverinfo->pszDomainDirectoryPartition = talloc_asprintf(mem_ctx, "DC=DomainDnsZones,%s", ldb_dn_get_linearized(domain_dn)); serverinfo->pszForestDirectoryPartition = talloc_asprintf(mem_ctx, "DC=ForestDnsZones,%s", ldb_dn_get_linearized(forest_dn)); load_interface_list(mem_ctx, lp_ctx, &ifaces); num_interfaces = iface_list_count(ifaces); serverinfo->aipServerAddrs = talloc_zero(mem_ctx, struct IP4_ARRAY); if (serverinfo->aipServerAddrs) { serverinfo->aipServerAddrs->AddrCount = num_interfaces; if (num_interfaces > 0) { serverinfo->aipServerAddrs->AddrArray = talloc_zero_array(mem_ctx, unsigned int, num_interfaces); if (serverinfo->aipServerAddrs->AddrArray) { for (i=0; i<num_interfaces; i++) { serverinfo->aipServerAddrs->AddrArray[i] = inet_addr(iface_list_n_ip(ifaces, i)); } } else { serverinfo->aipServerAddrs->AddrCount = 0; } }
NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree, struct loadparm_context *lp_ctx, TALLOC_CTX *tmp_ctx, const char **domain, const char **host, const char **user, const char **domain_guid, struct dom_sid **domain_sid, int *acct_control, int *version) { unsigned int i; *domain = NULL; *host = NULL; *user = NULL; *domain_guid = NULL; *domain_sid = NULL; *acct_control = -1; *version = -1; if (tree->operation != LDB_OP_AND) goto failed; /* extract the query elements */ for (i=0;i<tree->u.list.num_elements;i++) { struct ldb_parse_tree *t = tree->u.list.elements[i]; if (t->operation != LDB_OP_EQUALITY) goto failed; if (strcasecmp(t->u.equality.attr, "DnsDomain") == 0) { *domain = talloc_strndup(tmp_ctx, (const char *)t->u.equality.value.data, t->u.equality.value.length); } if (strcasecmp(t->u.equality.attr, "Host") == 0) { *host = talloc_strndup(tmp_ctx, (const char *)t->u.equality.value.data, t->u.equality.value.length); } if (strcasecmp(t->u.equality.attr, "DomainGuid") == 0) { NTSTATUS enc_status; struct GUID guid; enc_status = ldap_decode_ndr_GUID(tmp_ctx, t->u.equality.value, &guid); if (NT_STATUS_IS_OK(enc_status)) { *domain_guid = GUID_string(tmp_ctx, &guid); } } if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) { enum ndr_err_code ndr_err; *domain_sid = talloc(tmp_ctx, struct dom_sid); if (*domain_sid == NULL) { goto failed; } ndr_err = ndr_pull_struct_blob(&t->u.equality.value, *domain_sid, *domain_sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(*domain_sid); goto failed; } } if (strcasecmp(t->u.equality.attr, "User") == 0) { *user = talloc_strndup(tmp_ctx, (const char *)t->u.equality.value.data, t->u.equality.value.length); } if (strcasecmp(t->u.equality.attr, "NtVer") == 0 && t->u.equality.value.length == 4) { *version = IVAL(t->u.equality.value.data, 0); } if (strcasecmp(t->u.equality.attr, "AAC") == 0 && t->u.equality.value.length == 4) { *acct_control = IVAL(t->u.equality.value.data, 0); } } if ((*domain == NULL) && (*domain_guid == NULL) && (*domain_sid == NULL)) { *domain = lpcfg_dnsdomain(lp_ctx); } if (*version == -1) { goto failed; } return NT_STATUS_OK; failed: return NT_STATUS_UNSUCCESSFUL; }
/** * Start NTLMSSP on the server side * */ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security) { NTSTATUS nt_status; struct ntlmssp_state *ntlmssp_state; struct gensec_ntlmssp_context *gensec_ntlmssp; nt_status = gensec_ntlmssp_start(gensec_security); NT_STATUS_NOT_OK_RETURN(nt_status); gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data, struct gensec_ntlmssp_context); ntlmssp_state = gensec_ntlmssp->ntlmssp_state; ntlmssp_state->role = NTLMSSP_SERVER; ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE; ntlmssp_state->allow_lm_key = (lpcfg_lanman_auth(gensec_security->settings->lp_ctx) && gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "allow_lm_key", false)); ntlmssp_state->neg_flags = NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_VERSION; ntlmssp_state->lm_resp = data_blob(NULL, 0); ntlmssp_state->nt_resp = data_blob(NULL, 0); if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "128bit", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "56bit", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "keyexchange", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "alwayssign", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "ntlm2", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; } if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; } if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; } ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge; ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge; ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge; ntlmssp_state->check_password = auth_ntlmssp_check_password; if (lpcfg_server_role(gensec_security->settings->lp_ctx) == ROLE_STANDALONE) { ntlmssp_state->server.is_standalone = true; } else { ntlmssp_state->server.is_standalone = false; } ntlmssp_state->server.netbios_name = lpcfg_netbios_name(gensec_security->settings->lp_ctx); ntlmssp_state->server.netbios_domain = lpcfg_workgroup(gensec_security->settings->lp_ctx); { const char *dnsdomain = lpcfg_dnsdomain(gensec_security->settings->lp_ctx); char *dnsname, *lower_netbiosname; lower_netbiosname = strlower_talloc(ntlmssp_state, ntlmssp_state->server.netbios_name); /* Find out the DNS host name */ if (dnsdomain && dnsdomain[0] != '\0') { dnsname = talloc_asprintf(ntlmssp_state, "%s.%s", lower_netbiosname, dnsdomain); talloc_free(lower_netbiosname); ntlmssp_state->server.dns_name = dnsname; } else { ntlmssp_state->server.dns_name = lower_netbiosname; } NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_name); ntlmssp_state->server.dns_domain = talloc_strdup(ntlmssp_state, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_domain); } return NT_STATUS_OK; }
NTSTATUS gp_create_gpo (struct gp_context *gp_ctx, const char *display_name, struct gp_object **ret) { struct GUID guid_struct; char *guid_str; char *name; struct security_descriptor *sd; TALLOC_CTX *mem_ctx; struct gp_object *gpo; NTSTATUS status; /* Create a forked memory context, as a base for everything here */ mem_ctx = talloc_new(gp_ctx); NT_STATUS_HAVE_NO_MEMORY(mem_ctx); /* Create the gpo struct to return later */ gpo = talloc(gp_ctx, struct gp_object); if (gpo == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } /* Generate a GUID */ guid_struct = GUID_random(); guid_str = GUID_string2(mem_ctx, &guid_struct); if (guid_str == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } name = strupper_talloc(mem_ctx, guid_str); if (name == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } /* Prepare the GPO struct */ gpo->dn = NULL; gpo->name = name; gpo->flags = 0; gpo->version = 0; gpo->display_name = talloc_strdup(gpo, display_name); if (gpo->display_name == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } gpo->file_sys_path = talloc_asprintf(gpo, "\\\\%s\\sysvol\\%s\\Policies\\%s", lpcfg_dnsdomain(gp_ctx->lp_ctx), lpcfg_dnsdomain(gp_ctx->lp_ctx), name); if (gpo->file_sys_path == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } /* Create the GPT */ status = gp_create_gpt(gp_ctx, name, gpo->file_sys_path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to create GPT\n")); talloc_free(mem_ctx); return status; } /* Create the LDAP GPO, including CN=User and CN=Machine */ status = gp_create_ldap_gpo(gp_ctx, gpo); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to create LDAP group policy object\n")); talloc_free(mem_ctx); return status; } /* Get the new security descriptor */ status = gp_get_gpo_info(gp_ctx, gpo->dn, &gpo); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to fetch LDAP group policy object\n")); talloc_free(mem_ctx); return status; } /* Create matching file and DS security descriptors */ status = gp_create_gpt_security_descriptor(mem_ctx, gpo->security_descriptor, &sd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to convert ADS security descriptor to filesystem security descriptor\n")); talloc_free(mem_ctx); return status; } /* Set the security descriptor on the filesystem for this GPO */ status = gp_set_gpt_security_descriptor(gp_ctx, gpo, sd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to set security descriptor (ACL) on the file system\n")); talloc_free(mem_ctx); return status; } talloc_free(mem_ctx); *ret = gpo; return NT_STATUS_OK; }
/* add special SPNs needed for DRS replication to machine accounts when an AddEntry is done to create a nTDSDSA object */ static WERROR drsuapi_add_SPNs(struct drsuapi_bind_state *b_state, struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, const struct drsuapi_DsReplicaObjectListItem *first_object) { int ret; const struct drsuapi_DsReplicaObjectListItem *obj; const char *attrs[] = { "serverReference", "objectGUID", NULL }; for (obj = first_object; obj; obj=obj->next_object) { const char *dn_string = obj->object.identifier->dn; struct ldb_dn *dn = ldb_dn_new(mem_ctx, b_state->sam_ctx, dn_string); struct ldb_result *res, *res2; struct ldb_dn *ref_dn; struct GUID ntds_guid; struct ldb_message *msg; struct ldb_message_element *el; const char *ntds_guid_str; const char *dom_string; const char *attrs2[] = { "dNSHostName", "cn", NULL }; const char *dNSHostName, *cn; DEBUG(6,(__location__ ": Adding SPNs for %s\n", ldb_dn_get_linearized(dn))); ret = ldb_search(b_state->sam_ctx, mem_ctx, &res, dn, LDB_SCOPE_BASE, attrs, "(objectClass=ntDSDSA)"); if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed to find dn '%s'\n", dn_string)); return WERR_DS_DRA_INTERNAL_ERROR; } if (res->count < 1) { /* we only add SPNs for nTDSDSA objects */ continue; } ref_dn = samdb_result_dn(b_state->sam_ctx, mem_ctx, res->msgs[0], "serverReference", NULL); if (ref_dn == NULL) { /* we only add SPNs for objects with a serverReference */ continue; } DEBUG(6,(__location__ ": serverReference %s\n", ldb_dn_get_linearized(ref_dn))); ntds_guid = samdb_result_guid(res->msgs[0], "objectGUID"); ntds_guid_str = GUID_string(res, &ntds_guid); dom_string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx); /* get the dNSHostName and cn */ ret = ldb_search(b_state->sam_ctx, mem_ctx, &res2, ref_dn, LDB_SCOPE_BASE, attrs2, NULL); if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed to find ref_dn '%s'\n", ldb_dn_get_linearized(ref_dn))); return WERR_DS_DRA_INTERNAL_ERROR; } dNSHostName = ldb_msg_find_attr_as_string(res2->msgs[0], "dNSHostName", NULL); cn = ldb_msg_find_attr_as_string(res2->msgs[0], "cn", NULL); /* * construct a modify request to add the new SPNs to * the machine account */ msg = ldb_msg_new(mem_ctx); if (msg == NULL) { return WERR_NOT_ENOUGH_MEMORY; } msg->dn = ref_dn; ret = ldb_msg_add_empty(msg, "servicePrincipalName", LDB_FLAG_MOD_ADD, &el); if (ret != LDB_SUCCESS) { return WERR_NOT_ENOUGH_MEMORY; } ldb_msg_add_steal_string(msg, "servicePrincipalName", talloc_asprintf(el->values, "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s", ntds_guid_str, dom_string)); ldb_msg_add_steal_string(msg, "servicePrincipalName", talloc_asprintf(el->values, "ldap/%s._msdcs.%s", ntds_guid_str, dom_string)); if (cn) { ldb_msg_add_steal_string(msg, "servicePrincipalName", talloc_asprintf(el->values, "ldap/%s", cn)); } if (dNSHostName) { ldb_msg_add_steal_string(msg, "servicePrincipalName", talloc_asprintf(el->values, "ldap/%s", dNSHostName)); } if (el->num_values < 2) { return WERR_NOT_ENOUGH_MEMORY; } ret = dsdb_modify(b_state->sam_ctx, msg, DSDB_MODIFY_PERMISSIVE); if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed to add SPNs - %s\n", ldb_errstring(b_state->sam_ctx))); return WERR_DS_DRA_INTERNAL_ERROR; } } return WERR_OK; }
/* * Test some updates */ static bool test_dlz_bind9_update01(struct torture_context *tctx) { NTSTATUS status; struct gensec_security *gensec_client_context; DATA_BLOB client_to_server, server_to_client; void *dbdata; void *version = NULL; const char *argv[] = { "samba_dlz", "-H", lpcfg_private_path(tctx, tctx->lp_ctx, "dns/sam.ldb"), NULL }; struct test_expected_rr *expected1 = NULL; char *name = NULL; char *data0 = NULL; char *data1 = NULL; char *data2 = NULL; bool ret = false; tctx_static = tctx; torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, "log", dlz_bind9_log_wrapper, "writeable_zone", dlz_bind9_writeable_zone_hook, "putrr", dlz_bind9_putrr_hook, "putnamedrr", dlz_bind9_putnamedrr_hook, NULL), ISC_R_SUCCESS, "Failed to create samba_dlz"); torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata), ISC_R_SUCCESS, "Failed to configure samba_dlz"); expected1 = talloc_zero(tctx, struct test_expected_rr); torture_assert(tctx, expected1 != NULL, "talloc failed"); expected1->tctx = tctx; expected1->query_name = __func__; name = talloc_asprintf(expected1, "%s.%s", expected1->query_name, lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, name != NULL, "talloc failed"); expected1->num_records = 2; expected1->records = talloc_zero_array(expected1, struct test_expected_record, expected1->num_records); torture_assert(tctx, expected1->records != NULL, "talloc failed"); expected1->records[0].name = expected1->query_name; expected1->records[0].type = "a"; expected1->records[0].ttl = 3600; expected1->records[0].data = "127.1.2.3"; expected1->records[0].printed = false; data0 = talloc_asprintf(expected1, "%s.\t" "%u\t" "%s\t" "%s\t" "%s", name, (unsigned)expected1->records[0].ttl, "in", expected1->records[0].type, expected1->records[0].data); torture_assert(tctx, data0 != NULL, "talloc failed"); expected1->records[1].name = expected1->query_name; expected1->records[1].type = "a"; expected1->records[1].ttl = 3600; expected1->records[1].data = "127.3.2.1"; expected1->records[1].printed = false; data1 = talloc_asprintf(expected1, "%s.\t" "%u\t" "%s\t" "%s\t" "%s", name, (unsigned)expected1->records[1].ttl, "in", expected1->records[1].type, expected1->records[1].data); torture_assert(tctx, data1 != NULL, "talloc failed"); data2 = talloc_asprintf(expected1, "%s.\t" "0\t" "in\t" "a\t" "127.3.3.3", name); torture_assert(tctx, data2 != NULL, "talloc failed"); /* * Prepare session info */ status = gensec_client_start(tctx, &gensec_client_context, lpcfg_gensec_settings(tctx, tctx->lp_ctx)); torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed"); /* * dlz_bind9 use the special dns/host.domain account */ status = gensec_set_target_hostname(gensec_client_context, talloc_asprintf(tctx, "%s.%s", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx))); torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed"); status = gensec_set_target_service(gensec_client_context, "dns"); torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_service failed"); status = gensec_set_credentials(gensec_client_context, cmdline_credentials); torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed"); status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSS-SPNEGO"); torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed"); server_to_client = data_blob(NULL, 0); /* Do one step of the client-server update dance */ status = gensec_update(gensec_client_context, tctx, tctx->ev, server_to_client, &client_to_server); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {; torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed"); } torture_assert_int_equal(tctx, dlz_ssumatch(cli_credentials_get_username(cmdline_credentials), name, "127.0.0.1", expected1->records[0].type, "key", client_to_server.length, client_to_server.data, dbdata), ISC_TRUE, "Failed to check key for update rights samba_dlz"); /* * We test the following: * * 1. lookup the records => NOT_FOUND * 2. delete all records => NOT_FOUND * 3. delete 1st record => NOT_FOUND * 4. create 1st record => SUCCESS * 5. lookup the records => found 1st * 6. create 2nd record => SUCCESS * 7. lookup the records => found 1st and 2nd * 8. delete unknown record => NOT_FOUND * 9. lookup the records => found 1st and 2nd * 10. delete 1st record => SUCCESS * 11. lookup the records => found 2nd * 12. delete 2nd record => SUCCESS * 13. lookup the records => NOT_FOUND * 14. create 1st record => SUCCESS * 15. lookup the records => found 1st * 16. create 2nd record => SUCCESS * 17. lookup the records => found 1st and 2nd * 18. update 1st record => SUCCESS * 19. lookup the records => found 1st and 2nd * 20. delete all unknown type records => NOT_FOUND * 21. lookup the records => found 1st and 2nd * 22. delete all records => SUCCESS * 23. lookup the records => NOT_FOUND */ /* Step 1. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_NOTFOUND, "Found hostname"); torture_assert_int_equal(tctx, expected1->num_rr, 0, "Got wrong record count"); /* Step 2. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_delrdataset(name, expected1->records[0].type, dbdata, version), ISC_R_NOTFOUND, ret, cancel_version, talloc_asprintf(tctx, "Deleted name[%s] type[%s]\n", name, expected1->records[0].type)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version); /* Step 3. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_subrdataset(name, data0, dbdata, version), ISC_R_NOTFOUND, ret, cancel_version, talloc_asprintf(tctx, "Deleted name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version); /* Step 4. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data0, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 5. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert_int_equal(tctx, expected1->num_rr, 1, "Got wrong record count"); /* Step 6. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data1, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n", name, data1)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 7. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 8. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_subrdataset(name, data2, dbdata, version), ISC_R_NOTFOUND, ret, cancel_version, talloc_asprintf(tctx, "Deleted name[%s] data[%s]\n", name, data2)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 9. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 10. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_subrdataset(name, data0, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to delete name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 11. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 1, "Got wrong record count"); /* Step 12. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_subrdataset(name, data1, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to delete name[%s] data[%s]\n", name, data1)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 13. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_NOTFOUND, "Found hostname"); torture_assert_int_equal(tctx, expected1->num_rr, 0, "Got wrong record count"); /* Step 14. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data0, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 15. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert_int_equal(tctx, expected1->num_rr, 1, "Got wrong record count"); /* Step 16. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data1, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n", name, data1)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 17. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 18. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data0, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to update name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 19. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 20. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_delrdataset(name, "txt", dbdata, version), ISC_R_FAILURE, ret, cancel_version, talloc_asprintf(tctx, "Deleted name[%s] type[%s]\n", name, "txt")); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version); /* Step 21. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 22. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_delrdataset(name, expected1->records[0].type, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to delete name[%s] type[%s]\n", name, expected1->records[0].type)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 23. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_NOTFOUND, "Found hostname"); torture_assert_int_equal(tctx, expected1->num_rr, 0, "Got wrong record count"); dlz_destroy(dbdata); return true; cancel_version: dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version); return ret; }
/* format a record for bind9 */ static bool b9_format(struct dlz_bind9_data *state, TALLOC_CTX *mem_ctx, struct dnsp_DnssrvRpcRecord *rec, const char **type, const char **data) { switch (rec->wType) { case DNS_TYPE_A: *type = "a"; *data = rec->data.ipv4; break; case DNS_TYPE_AAAA: *type = "aaaa"; *data = rec->data.ipv6; break; case DNS_TYPE_CNAME: *type = "cname"; *data = rec->data.cname; break; case DNS_TYPE_TXT: *type = "txt"; *data = rec->data.txt; break; case DNS_TYPE_PTR: *type = "ptr"; *data = rec->data.ptr; break; case DNS_TYPE_SRV: *type = "srv"; *data = talloc_asprintf(mem_ctx, "%u %u %u %s", rec->data.srv.wPriority, rec->data.srv.wWeight, rec->data.srv.wPort, rec->data.srv.nameTarget); break; case DNS_TYPE_MX: *type = "mx"; *data = talloc_asprintf(mem_ctx, "%u %s", rec->data.mx.wPriority, rec->data.mx.nameTarget); break; case DNS_TYPE_HINFO: *type = "hinfo"; *data = talloc_asprintf(mem_ctx, "%s %s", rec->data.hinfo.cpu, rec->data.hinfo.os); break; case DNS_TYPE_NS: *type = "ns"; *data = rec->data.ns; break; case DNS_TYPE_SOA: { const char *mname; *type = "soa"; /* we need to fake the authoritative nameserver to * point at ourselves. This is how AD DNS servers * force clients to send updates to the right local DC */ mname = talloc_asprintf(mem_ctx, "%s.%s", lpcfg_netbios_name(state->lp), lpcfg_dnsdomain(state->lp)); if (mname == NULL) { return false; } mname = strlower_talloc(mem_ctx, mname); if (mname == NULL) { return false; } state->soa_serial = rec->data.soa.serial; *data = talloc_asprintf(mem_ctx, "%s %s %u %u %u %u %u", mname, rec->data.soa.rname, rec->data.soa.serial, rec->data.soa.refresh, rec->data.soa.retry, rec->data.soa.expire, rec->data.soa.minimum); break; } default: state->log(ISC_LOG_ERROR, "samba b9_putrr: unhandled record type %u", rec->wType); return false; } return true; }
/* handle incoming cldap requests */ void cldapd_netlogon_request(struct cldap_socket *cldap, struct cldapd_server *cldapd, TALLOC_CTX *tmp_ctx, uint32_t message_id, struct ldb_parse_tree *tree, struct tsocket_address *src) { unsigned int i; const char *domain = NULL; const char *host = NULL; const char *user = NULL; const char *domain_guid = NULL; struct dom_sid *domain_sid = NULL; int acct_control = -1; int version = -1; struct netlogon_samlogon_response netlogon; NTSTATUS status = NT_STATUS_INVALID_PARAMETER; if (tree->operation != LDB_OP_AND) goto failed; /* extract the query elements */ for (i=0;i<tree->u.list.num_elements;i++) { struct ldb_parse_tree *t = tree->u.list.elements[i]; if (t->operation != LDB_OP_EQUALITY) goto failed; if (strcasecmp(t->u.equality.attr, "DnsDomain") == 0) { domain = talloc_strndup(tmp_ctx, (const char *)t->u.equality.value.data, t->u.equality.value.length); } if (strcasecmp(t->u.equality.attr, "Host") == 0) { host = talloc_strndup(tmp_ctx, (const char *)t->u.equality.value.data, t->u.equality.value.length); } if (strcasecmp(t->u.equality.attr, "DomainGuid") == 0) { NTSTATUS enc_status; struct GUID guid; enc_status = ldap_decode_ndr_GUID(tmp_ctx, t->u.equality.value, &guid); if (NT_STATUS_IS_OK(enc_status)) { domain_guid = GUID_string(tmp_ctx, &guid); } } if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) { enum ndr_err_code ndr_err; domain_sid = talloc(tmp_ctx, struct dom_sid); if (domain_sid == NULL) { goto failed; } ndr_err = ndr_pull_struct_blob(&t->u.equality.value, domain_sid, domain_sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(domain_sid); goto failed; } } if (strcasecmp(t->u.equality.attr, "User") == 0) { user = talloc_strndup(tmp_ctx, (const char *)t->u.equality.value.data, t->u.equality.value.length); } if (strcasecmp(t->u.equality.attr, "NtVer") == 0 && t->u.equality.value.length == 4) { version = IVAL(t->u.equality.value.data, 0); } if (strcasecmp(t->u.equality.attr, "AAC") == 0 && t->u.equality.value.length == 4) { acct_control = IVAL(t->u.equality.value.data, 0); } } if ((domain == NULL) && (domain_guid == NULL) && (domain_sid == NULL)) { domain = lpcfg_dnsdomain(cldapd->task->lp_ctx); } if (version == -1) { goto failed; } DEBUG(5,("cldap netlogon query domain=%s host=%s user=%s version=%d guid=%s\n", domain, host, user, version, domain_guid)); status = fill_netlogon_samlogon_response(cldapd->samctx, tmp_ctx, domain, NULL, domain_sid, domain_guid, user, acct_control, tsocket_address_inet_addr_string(src, tmp_ctx), version, cldapd->task->lp_ctx, &netlogon, false); if (!NT_STATUS_IS_OK(status)) { goto failed; } status = cldap_netlogon_reply(cldap, message_id, src, version, &netlogon); if (!NT_STATUS_IS_OK(status)) { goto failed; } return; failed: DEBUG(2,("cldap netlogon query failed domain=%s host=%s version=%d - %s\n", domain, host, version, nt_errstr(status))); cldap_empty_reply(cldap, message_id, src); }