X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source4%2Fcldap_server%2Fnetlogon.c;h=e9ec0745f4164b7a9f1132958f066976602bedf6;hb=f02e4ebfafa6e5911e3fe744b1780527ab12c970;hp=ec9ecc3b75fd1f7680e0bcb5f1c8227934919dbd;hpb=3f1bd92306b2f11b5c8086ef9e0a311d9e99da89;p=samba.git diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c index ec9ecc3b75f..e9ec0745f41 100644 --- a/source4/cldap_server/netlogon.c +++ b/source4/cldap_server/netlogon.c @@ -21,8 +21,8 @@ */ #include "includes.h" -#include "lib/ldb/include/ldb.h" -#include "lib/ldb/include/ldb_errors.h" +#include +#include #include "lib/events/events.h" #include "smbd/service_task.h" #include "cldap_server/cldap_server.h" @@ -36,6 +36,8 @@ #include "lib/socket/netif.h" #include "param/param.h" #include "../lib/tsocket/tsocket.h" +#include "libds/common/flag_mapping.h" +#include "lib/util/util_net.h" /* fill in the cldap netlogon union for a given version @@ -58,7 +60,8 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, const char *none_attrs[] = {NULL}; struct ldb_result *dom_res = NULL, *user_res = NULL; int ret; - const char **services = lp_server_services(lp_ctx); + const char **services = lpcfg_server_services(lp_ctx); + const char **rpc_services = lpcfg_dcerpc_endpoint_servers(lp_ctx); uint32_t server_type; const char *pdc_name; struct GUID domain_uuid; @@ -71,7 +74,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, const char *pdc_ip; struct ldb_dn *domain_dn = NULL; struct interface *ifaces; - bool user_known; + bool user_known, am_rodc; NTSTATUS status; /* the domain parameter could have an optional trailing "." */ @@ -81,10 +84,10 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, } /* Lookup using long or short domainname */ - if (domain && (strcasecmp_m(domain, lp_dnsdomain(lp_ctx)) == 0)) { + 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, lp_sam_name(lp_ctx)) == 0)) { + if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) { domain_dn = ldb_get_default_basedn(sam_ctx); } if (domain_dn) { @@ -132,22 +135,11 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, "(&(objectCategory=DomainDNS)(objectGUID=%s))", ldb_binary_encode(mem_ctx, guid_val)); } else { /* domain_sid case */ - struct dom_sid *sid; - struct ldb_val sid_val; - enum ndr_err_code ndr_err; - - /* Rather than go via the string, just push into the NDR form */ - ndr_err = ndr_push_struct_blob(&sid_val, mem_ctx, NULL, &sid, - (ndr_push_flags_fn_t)ndr_push_dom_sid); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return NT_STATUS_INVALID_PARAMETER; - } - ret = ldb_search(sam_ctx, mem_ctx, &dom_res, - NULL, LDB_SCOPE_SUBTREE, - dom_attrs, - "(&(objectCategory=DomainDNS)(objectSID=%s))", - ldb_binary_encode(mem_ctx, sid_val)); + NULL, LDB_SCOPE_SUBTREE, + dom_attrs, + "(&(objectCategory=DomainDNS)(objectSid=%s))", + dom_sid_string(mem_ctx, domain_sid)); } if (ret != LDB_SUCCESS) { @@ -180,7 +172,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, "objectClass=domain"); if (ret != LDB_SUCCESS) { DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", - lp_dnsdomain(lp_ctx), + lpcfg_dnsdomain(lp_ctx), ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; @@ -188,7 +180,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, } if (dom_res == NULL) { - DEBUG(2,(__location__ ": Unable to get domain informations with no inputs\n")); + DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n")); return NT_STATUS_NO_SUCH_DOMAIN; } @@ -233,14 +225,8 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, server_type = DS_SERVER_DS | DS_SERVER_TIMESERV | - DS_SERVER_CLOSEST | DS_SERVER_WRITABLE | DS_SERVER_GOOD_TIMESERV; -#if 0 - /* w2k8-r2 as a DC does not claim these */ - server_type |= DS_DNS_CONTROLLER | DS_DNS_DOMAIN; -#endif - if (samdb_is_pdc(sam_ctx)) { server_type |= DS_SERVER_PDC; } @@ -261,42 +247,48 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, server_type |= DS_SERVER_KDC; } -#if 0 - /* w2k8-r2 as a sole DC does not claim this */ - if (ldb_dn_compare(ldb_get_root_basedn(sam_ctx), ldb_get_default_basedn(sam_ctx)) == 0) { - server_type |= DS_DNS_FOREST_ROOT; + if (str_list_check(rpc_services, "dnsserver")) { + server_type |= DS_DNS_CONTROLLER; + } + + if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) { + server_type |= DS_SERVER_WRITABLE; } -#endif pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", - lp_netbios_name(lp_ctx)); + lpcfg_netbios_name(lp_ctx)); NT_STATUS_HAVE_NO_MEMORY(pdc_name); domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); - dns_domain = lp_dnsdomain(lp_ctx); + 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, - lp_netbios_name(lp_ctx)), + lpcfg_netbios_name(lp_ctx)), dns_domain); NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name); - flatname = lp_workgroup(lp_ctx); + 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); - load_interfaces(mem_ctx, lp_interfaces(lp_ctx), &ifaces); - /* - * TODO: the caller should pass the address which the client - * used to trigger this call, as the client is able to reach - * this ip. - */ + 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_best_ip(ifaces, src_address); + pdc_ip = iface_list_best_ip(ifaces, src_address); } else { - pdc_ip = iface_n_ip(ifaces, 0); + 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 */ @@ -312,7 +304,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, } netlogon->data.nt5_ex.pdc_name = pdc_name; netlogon->data.nt5_ex.user_name = user; - netlogon->data.nt5_ex.domain = flatname; + 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; @@ -320,7 +312,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, netlogon->data.nt5_ex.server_site = server_site; netlogon->data.nt5_ex.client_site = client_site; if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) { - /* Clearly this needs to be fixed up for IPv6 */ + /* 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; @@ -361,9 +353,9 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, } else { netlogon->data.nt4.command = LOGON_SAM_LOGON_USER_UNKNOWN; } - netlogon->data.nt4.server = pdc_name; + netlogon->data.nt4.pdc_name = pdc_name; netlogon->data.nt4.user_name = user; - netlogon->data.nt4.domain = flatname; + 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; @@ -388,7 +380,7 @@ void cldapd_netlogon_request(struct cldap_socket *cldap, const char *host = NULL; const char *user = NULL; const char *domain_guid = NULL; - const char *domain_sid = NULL; + struct dom_sid *domain_sid = NULL; int acct_control = -1; int version = -1; struct netlogon_samlogon_response netlogon; @@ -420,9 +412,19 @@ void cldapd_netlogon_request(struct cldap_socket *cldap, } } if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) { - domain_sid = talloc_strndup(tmp_ctx, - (const char *)t->u.equality.value.data, - t->u.equality.value.length); + 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, @@ -439,8 +441,8 @@ void cldapd_netlogon_request(struct cldap_socket *cldap, } } - if (domain_guid == NULL && domain == NULL) { - domain = lp_dnsdomain(cldapd->task->lp_ctx); + if ((domain == NULL) && (domain_guid == NULL) && (domain_sid == NULL)) { + domain = lpcfg_dnsdomain(cldapd->task->lp_ctx); } if (version == -1) { @@ -450,18 +452,18 @@ void cldapd_netlogon_request(struct cldap_socket *cldap, 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, NULL, 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); + version, cldapd->task->lp_ctx, + &netlogon, false); if (!NT_STATUS_IS_OK(status)) { goto failed; } - status = cldap_netlogon_reply(cldap, - lp_iconv_convenience(cldapd->task->lp_ctx), - message_id, src, version, - &netlogon); + status = cldap_netlogon_reply(cldap, message_id, src, version, &netlogon); if (!NT_STATUS_IS_OK(status)) { goto failed; }