From d471e52d23bf89e472c34c58dd9f113e669323a4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 13 Dec 2006 11:19:51 +0000 Subject: r20149: Remove the smb.conf distinction between PDC and BDC. Now the correct way to setup a Samba4 DC is to set 'server role = domain controller'. We use the fSMORoleOwner attribute in the base DN to determine the PDC. This patch is quite large, as I have corrected a number of places that assumed taht we are always the PDC, or that used the smb.conf lp_server_role() to determine that. Also included is a warning fix in the SAMR code, where the IDL has seperated a couple of types for group display enumeration. We also now use the ldb database to determine if we should run the global catalog service. In the near future, I will complete the DRSUAPI DsGetDomainControllerInfo server-side on the same basis. Andrew Bartlett (This used to be commit 67d8365e831adf3eaecd8b34dcc481fc82565893) --- source4/auth/auth_sam.c | 6 +- source4/dsdb/samdb/samdb.c | 157 +++++++++++++++++++++++++++----- source4/include/core.h | 12 +++ source4/ldap_server/ldap_server.c | 45 ++++++++- source4/librpc/idl/samr.idl | 8 +- source4/nbt_server/nbt_server.c | 10 ++ source4/nbt_server/nbt_server.h | 2 + source4/nbt_server/register.c | 18 ++-- source4/param/loadparm.c | 113 +---------------------- source4/rpc_server/common/server_info.c | 75 ++++++++++++++- source4/rpc_server/lsa/dcesrv_lsa.c | 19 ++-- source4/rpc_server/samr/dcesrv_samr.c | 105 +++++++++++++++++---- source4/script/tests/mktestsetup.sh | 2 +- source4/torture/rpc/samr.c | 17 ++++ 14 files changed, 406 insertions(+), 183 deletions(-) diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index 6b290360ec..56187a6d54 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -382,8 +382,7 @@ static NTSTATUS authsam_want_check(struct auth_method_context *ctx, } return NT_STATUS_OK; - case ROLE_DOMAIN_PDC: - case ROLE_DOMAIN_BDC: + case ROLE_DOMAIN_CONTROLLER: if (!is_local_name && !is_my_domain) { DEBUG(6,("authsam_check_password: %s is not one of my local names or domain name (DC)\n", user_info->mapped.domain_name)); @@ -413,8 +412,7 @@ static NTSTATUS authsam_check_password(struct auth_method_context *ctx, domain = lp_netbios_name(); break; - case ROLE_DOMAIN_PDC: - case ROLE_DOMAIN_BDC: + case ROLE_DOMAIN_CONTROLLER: domain = lp_workgroup(); break; diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c index da04be1dbb..9296352b0b 100644 --- a/source4/dsdb/samdb/samdb.c +++ b/source4/dsdb/samdb/samdb.c @@ -1047,18 +1047,25 @@ struct ldb_dn *samdb_partitions_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ return new_dn; } +struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx) +{ + struct ldb_dn *new_dn; + + new_dn = ldb_dn_copy(mem_ctx, samdb_base_dn(sam_ctx)); + if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Sites,CN=Configuration")) { + talloc_free(new_dn); + return NULL; + } + return new_dn; +} + /* work out the domain sid for the current open ldb */ const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb) { - const char *attrs[] = { "rootDomainNamingContext", NULL }; - int ret; - struct ldb_result *res = NULL; TALLOC_CTX *tmp_ctx; struct dom_sid *domain_sid; - const char *basedn_s; - struct ldb_dn *basedn; /* see if we have a cached copy */ domain_sid = ldb_get_opaque(ldb, "cache.domain_sid"); @@ -1071,51 +1078,153 @@ const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb) goto failed; } - basedn = ldb_dn_new(tmp_ctx, ldb, NULL); - if (basedn == NULL) { + /* find the domain_sid */ + domain_sid = samdb_search_dom_sid(ldb, tmp_ctx, ldb_get_default_basedn(ldb), + "objectSid", "objectClass=domainDNS"); + if (domain_sid == NULL) { goto failed; } - - /* find the basedn of the domain from the rootdse */ - ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, NULL, attrs, &res); - talloc_steal(tmp_ctx, res); - if (ret != LDB_SUCCESS || res->count != 1) { + + /* cache the domain_sid in the ldb */ + if (ldb_set_opaque(ldb, "cache.domain_sid", domain_sid) != LDB_SUCCESS) { goto failed; } - basedn_s = ldb_msg_find_attr_as_string(res->msgs[0], "rootDomainNamingContext", NULL); - if (basedn_s == NULL) { + talloc_steal(ldb, domain_sid); + talloc_free(tmp_ctx); + + return domain_sid; + +failed: + DEBUG(1,("Failed to find domain_sid for open ldb\n")); + talloc_free(tmp_ctx); + return NULL; +} + +/* Obtain the short name of the flexible single master operator + * (FSMO), such as the PDC Emulator */ +const char *samdb_result_fsmo_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg, + const char *attr) +{ + /* Format is cn=NTDS Settings,cn=,.... */ + struct ldb_dn *fsmo_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr); + const struct ldb_val *val = ldb_dn_get_component_val(fsmo_dn, 1); + const char *name = ldb_dn_get_component_name(fsmo_dn, 1); + + if (!name || (ldb_attr_cmp(name, "cn") != 0)) { + /* Ensure this matches the format. This gives us a + * bit more confidence that a 'cn' value will be a + * ascii string */ + return NULL; + } + if (val) { + return (char *)val->data; + } + return NULL; +} + +/* + work out the ntds settings dn for the current open ldb +*/ +const struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb) +{ + TALLOC_CTX *tmp_ctx; + const char *root_attrs[] = { "dsServiceName", NULL }; + int ret; + struct ldb_result *root_res; + struct ldb_dn *settings_dn; + + /* see if we have a cached copy */ + settings_dn = ldb_get_opaque(ldb, "cache.settings_dn"); + if (settings_dn) { + return settings_dn; + } + + tmp_ctx = talloc_new(ldb); + if (tmp_ctx == NULL) { goto failed; } + - basedn = ldb_dn_new(tmp_ctx, ldb, basedn_s); - if ( ! ldb_dn_validate(basedn)) { + ret = ldb_search(ldb, ldb_dn_new(tmp_ctx, ldb, ""), LDB_SCOPE_BASE, NULL, root_attrs, &root_res); + if (ret) { goto failed; } - /* find the domain_sid */ - domain_sid = samdb_search_dom_sid(ldb, tmp_ctx, basedn, - "objectSid", "objectClass=domainDNS"); - if (domain_sid == NULL) { + if (root_res->count != 1) { goto failed; } + settings_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, root_res->msgs[0], "dsServiceName"); + /* cache the domain_sid in the ldb */ - if (ldb_set_opaque(ldb, "cache.domain_sid", domain_sid) != LDB_SUCCESS) { + if (ldb_set_opaque(ldb, "cache.settings_dn", settings_dn) != LDB_SUCCESS) { goto failed; } - talloc_steal(ldb, domain_sid); + talloc_steal(ldb, settings_dn); talloc_free(tmp_ctx); - return domain_sid; + return settings_dn; failed: - DEBUG(1,("Failed to find domain_sid for open ldb\n")); + DEBUG(1,("Failed to find our own NTDS Settings DN in the ldb!\n")); talloc_free(tmp_ctx); return NULL; } +/* + work out the server dn for the current open ldb +*/ +struct ldb_dn *samdb_server_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx) +{ + return ldb_dn_get_parent(mem_ctx, samdb_ntds_settings_dn(ldb)); +} + +/* + work out the domain sid for the current open ldb +*/ +BOOL samdb_is_pdc(struct ldb_context *ldb) +{ + const char *dom_attrs[] = { "fSMORoleOwner", NULL }; + int ret; + struct ldb_result *dom_res; + TALLOC_CTX *tmp_ctx; + BOOL is_pdc; + struct ldb_dn *pdc; + + tmp_ctx = talloc_new(ldb); + if (tmp_ctx == NULL) { + goto failed; + } + + ret = ldb_search(ldb, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res); + if (ret) { + goto failed; + } + talloc_steal(tmp_ctx, dom_res); + if (dom_res->count != 1) { + goto failed; + } + + pdc = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, dom_res->msgs[0], "fSMORoleOwner"); + + if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc) == 0) { + is_pdc = True; + } else { + is_pdc = False; + } + + talloc_free(tmp_ctx); + + return is_pdc; + +failed: + DEBUG(1,("Failed to find if we are the PDC for this ldb\n")); + talloc_free(tmp_ctx); + return False; +} + /* check that a password is sufficiently complex */ diff --git a/source4/include/core.h b/source4/include/core.h index f334c3df42..40452e6034 100644 --- a/source4/include/core.h +++ b/source4/include/core.h @@ -95,6 +95,18 @@ enum brl_type { PENDING_WRITE_LOCK }; +enum server_role { + ROLE_STANDALONE=0, + ROLE_DOMAIN_MEMBER=1, + ROLE_DOMAIN_CONTROLLER=2, +}; + +enum announce_as {/* Types of machine we can announce as. */ + ANNOUNCE_AS_NT_SERVER=1, + ANNOUNCE_AS_WIN95=2, + ANNOUNCE_AS_WFW=3, + ANNOUNCE_AS_NT_WORKSTATION=4 +}; #endif /* _SAMBA_CORE_H */ diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 82fc1d9660..c459c27961 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -40,7 +40,7 @@ #include "lib/ldb/include/ldb_errors.h" #include "system/network.h" #include "lib/socket/netif.h" - +#include "dsdb/samdb/samdb.h" /* close the socket and shutdown a server_context */ @@ -245,8 +245,13 @@ static int ldapsrv_load_limits(struct ldapsrv_connection *conn) } ret = ldb_search(conn->ldb, basedn, LDB_SCOPE_BASE, NULL, attrs, &res); + if (ret != LDB_SUCCESS) { + goto failed; + } + talloc_steal(tmp_ctx, res); - if (ret != LDB_SUCCESS || res->count != 1) { + + if (res->count != 1) { goto failed; } @@ -262,8 +267,13 @@ static int ldapsrv_load_limits(struct ldapsrv_connection *conn) } ret = ldb_search(conn->ldb, policy_dn, LDB_SCOPE_BASE, NULL, attrs2, &res); + if (ret != LDB_SUCCESS) { + goto failed; + } + talloc_steal(tmp_ctx, res); - if (ret != LDB_SUCCESS || res->count != 1) { + + if (res->count != 1) { goto failed; } @@ -431,6 +441,11 @@ static NTSTATUS add_socket(struct event_context *event_context, { uint16_t port = 389; NTSTATUS status; + const char *attrs[] = { "options", NULL }; + int ret; + struct ldb_result *res; + struct ldb_context *ldb; + int options; status = stream_setup_socket(event_context, model_ops, &ldap_stream_ops, "ipv4", address, &port, ldap_service); @@ -450,8 +465,28 @@ static NTSTATUS add_socket(struct event_context *event_context, } } - /* if we are a PDC, then also enable the global catalog server port, 3268 */ - if (lp_server_role() == ROLE_DOMAIN_PDC) { + /* Load LDAP database */ + ldb = samdb_connect(ldap_service, system_session(ldap_service)); + if (!ldb) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + /* Query cn=ntds settings,.... */ + ret = ldb_search(ldb, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, NULL, attrs, &res); + if (ret) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + if (res->count != 1) { + talloc_free(res); + return NT_STATUS_NOT_FOUND; + } + + options = ldb_msg_find_attr_as_int(res->msgs[0], "options", 0); + talloc_free(res); + talloc_free(ldb); + + /* if options attribute is 1, then enable the global catlog */ + if (options == 1) { port = 3268; status = stream_setup_socket(event_context, model_ops, &ldap_stream_ops, "ipv4", address, &port, ldap_service); diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl index 9989c821f0..5c73bfa76c 100644 --- a/source4/librpc/idl/samr.idl +++ b/source4/librpc/idl/samr.idl @@ -129,10 +129,10 @@ import "misc.idl", "lsa.idl", "security.idl"; /* Function 0x08 */ /* server roles */ typedef [v1_enum] enum { - ROLE_STANDALONE = 0, - ROLE_DOMAIN_MEMBER = 1, - ROLE_DOMAIN_BDC = 2, - ROLE_DOMAIN_PDC = 3 + SAMR_ROLE_STANDALONE = 0, + SAMR_ROLE_DOMAIN_MEMBER = 1, + SAMR_ROLE_DOMAIN_BDC = 2, + SAMR_ROLE_DOMAIN_PDC = 3 } samr_Role; /* password properties flags */ diff --git a/source4/nbt_server/nbt_server.c b/source4/nbt_server/nbt_server.c index d8f6a83e94..a2b95d76c4 100644 --- a/source4/nbt_server/nbt_server.c +++ b/source4/nbt_server/nbt_server.c @@ -27,6 +27,8 @@ #include "nbt_server/wins/winsserver.h" #include "system/network.h" #include "lib/socket/netif.h" +#include "auth/auth.h" +#include "dsdb/samdb/samdb.h" /* startup the nbtd task @@ -61,6 +63,12 @@ static void nbtd_task_init(struct task_server *task) return; } + nbtsrv->sam_ctx = samdb_connect(nbtsrv, anonymous_session(nbtsrv)); + if (nbtsrv->sam_ctx == NULL) { + task_server_terminate(task, "nbtd failed to open samdb"); + return; + } + /* start the WINS server, if appropriate */ status = nbtd_winsserver_init(nbtsrv); if (!NT_STATUS_IS_OK(status)) { @@ -74,6 +82,8 @@ static void nbtd_task_init(struct task_server *task) nbtd_register_names(nbtsrv); irpc_add_name(task->msg_ctx, "nbt_server"); + + } diff --git a/source4/nbt_server/nbt_server.h b/source4/nbt_server/nbt_server.h index ebf1edb81f..e5a33ca5f1 100644 --- a/source4/nbt_server/nbt_server.h +++ b/source4/nbt_server/nbt_server.h @@ -75,6 +75,8 @@ struct nbtd_server { struct wins_server *winssrv; struct nbtd_statistics stats; + + struct ldb_context *sam_ctx; }; diff --git a/source4/nbt_server/register.c b/source4/nbt_server/register.c index 64ceaffd9c..6e65b753b1 100644 --- a/source4/nbt_server/register.c +++ b/source4/nbt_server/register.c @@ -29,6 +29,7 @@ #include "librpc/gen_ndr/ndr_samr.h" #include "nbt_server/wins/winsserver.h" #include "librpc/gen_ndr/ndr_nbt.h" +#include "dsdb/samdb/samdb.h" static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname); @@ -271,15 +272,14 @@ void nbtd_register_names(struct nbtd_server *nbtsrv) aliases++; } - switch (lp_server_role()) { - case ROLE_DOMAIN_PDC: - nbtd_register_name(nbtsrv, lp_workgroup(), NBT_NAME_PDC, nb_flags); - nbtd_register_name(nbtsrv, lp_workgroup(), NBT_NAME_LOGON, nb_flags | NBT_NM_GROUP); - break; - case ROLE_DOMAIN_BDC: - nbtd_register_name(nbtsrv, lp_workgroup(), NBT_NAME_LOGON, nb_flags | NBT_NM_GROUP); - default: - break; + if (lp_server_role() == ROLE_DOMAIN_CONTROLLER) { + BOOL is_pdc = samdb_is_pdc(nbtsrv->sam_ctx); + if (is_pdc) { + nbtd_register_name(nbtsrv, lp_workgroup(), + NBT_NAME_PDC, nb_flags); + } + nbtd_register_name(nbtsrv, lp_workgroup(), + NBT_NAME_LOGON, nb_flags | NBT_NM_GROUP); } nb_flags |= NBT_NM_GROUP; diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index c781a00ae5..5094a7f565 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -59,8 +59,6 @@ #include "system/time.h" #include "system/locale.h" #include "system/network.h" /* needed for TCP_NODELAY */ -#include "librpc/gen_ndr/svcctl.h" -#include "librpc/gen_ndr/samr.h" #include "smb_server/smb_server.h" #include "libcli/raw/signing.h" #include "lib/util/dlinklist.h" @@ -274,7 +272,6 @@ static service **ServicePtrs = NULL; static int iNumServices = 0; static int iServiceIndex = 0; static BOOL bInGlobalSection = True; -static int default_server_announce; #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct)) @@ -282,8 +279,6 @@ static int default_server_announce; static BOOL handle_include(const char *pszParmValue, char **ptr); static BOOL handle_copy(const char *pszParmValue, char **ptr); -static void set_default_server_announce_type(void); - static const struct enum_list enum_protocol[] = { {PROTOCOL_SMB2, "SMB2"}, {PROTOCOL_NT1, "NT1"}, @@ -301,12 +296,6 @@ static const struct enum_list enum_security[] = { {-1, NULL} }; -/* Types of machine we can announce as. */ -#define ANNOUNCE_AS_NT_SERVER 1 -#define ANNOUNCE_AS_WIN95 2 -#define ANNOUNCE_AS_WFW 3 -#define ANNOUNCE_AS_NT_WORKSTATION 4 - static const struct enum_list enum_announce_as[] = { {ANNOUNCE_AS_NT_SERVER, "NT"}, {ANNOUNCE_AS_NT_SERVER, "NT Server"}, @@ -365,8 +354,7 @@ static const struct enum_list enum_smb_signing_vals[] = { static const struct enum_list enum_server_role[] = { {ROLE_STANDALONE, "standalone"}, {ROLE_DOMAIN_MEMBER, "member server"}, - {ROLE_DOMAIN_BDC, "bdc"}, - {ROLE_DOMAIN_PDC, "pdc"}, + {ROLE_DOMAIN_CONTROLLER, "domain controller"}, {-1, NULL} }; @@ -886,7 +874,7 @@ _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw) _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords) _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions) _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords) -static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer) +_PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer) _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly) _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode) _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport) @@ -912,7 +900,7 @@ _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, &Globals.cli_minprotocol) _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security) _PUBLIC_ FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods) _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security) -static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as) +_PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as) _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude) _PUBLIC_ FN_GLOBAL_STRING(lp_jsonrpc_services_dir, &Globals.jsonrpcServicesDir) _PUBLIC_ @@ -1373,8 +1361,6 @@ BOOL lp_add_printer(const char *pszPrintername, int iDefaultService) DEBUG(3, ("adding printer service %s\n", pszPrintername)); - update_server_announce_as_printserver(); - return (True); } @@ -1554,7 +1540,6 @@ static BOOL service_ok(int iService) DEBUG(0, ("WARNING: [%s] service MUST be printable!\n", ServicePtrs[iService]->szService)); ServicePtrs[iService]->bPrint_ok = True; - update_server_announce_as_printserver(); } /* [printers] service must also be non-browsable. */ if (ServicePtrs[iService]->bBrowseable) @@ -2380,15 +2365,6 @@ static void lp_add_auto_services(const char *str) return; } -/*************************************************************************** - Announce ourselves as a print server. -***************************************************************************/ - -void update_server_announce_as_printserver(void) -{ - default_server_announce |= SV_TYPE_PRINTQ_SERVER; -} - /*************************************************************************** Have we loaded a services file yet? ***************************************************************************/ @@ -2478,8 +2454,6 @@ BOOL lp_load(void) lp_add_hidden("IPC$", "IPC"); lp_add_hidden("ADMIN$", "DISK"); - set_default_server_announce_type(); - bLoaded = True; if (!Globals.szWINSservers && Globals.bWINSsupport) { @@ -2603,83 +2577,13 @@ const char *volume_label(int snum) } -/******************************************************************* - Set the server type we will announce as via nmbd. -********************************************************************/ - -static void set_default_server_announce_type(void) -{ - default_server_announce = 0; - default_server_announce |= SV_TYPE_WORKSTATION; - default_server_announce |= SV_TYPE_SERVER; - default_server_announce |= SV_TYPE_SERVER_UNIX; - - switch (lp_announce_as()) { - case ANNOUNCE_AS_NT_SERVER: - default_server_announce |= SV_TYPE_SERVER_NT; - /* fall through... */ - case ANNOUNCE_AS_NT_WORKSTATION: - default_server_announce |= SV_TYPE_NT; - break; - case ANNOUNCE_AS_WIN95: - default_server_announce |= SV_TYPE_WIN95_PLUS; - break; - case ANNOUNCE_AS_WFW: - default_server_announce |= SV_TYPE_WFW; - break; - default: - break; - } - - switch (lp_server_role()) { - case ROLE_DOMAIN_MEMBER: - default_server_announce |= SV_TYPE_DOMAIN_MEMBER; - break; - case ROLE_DOMAIN_PDC: - default_server_announce |= SV_TYPE_DOMAIN_CTRL; - break; - case ROLE_DOMAIN_BDC: - default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL; - break; - case ROLE_STANDALONE: - default: - break; - } - if (lp_time_server()) - default_server_announce |= SV_TYPE_TIME_SOURCE; - - if (lp_host_msdfs()) - default_server_announce |= SV_TYPE_DFS_SERVER; - - /* TODO: only announce us as print server when we are a print server */ - default_server_announce |= SV_TYPE_PRINTQ_SERVER; -} - -/*********************************************************** - If we are PDC then prefer us as DMB -************************************************************/ - -BOOL lp_domain_master(void) -{ - return (lp_server_role() == ROLE_DOMAIN_PDC); -} - /*********************************************************** If we are PDC then prefer us as DMB ************************************************************/ BOOL lp_domain_logons(void) { - return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC); -} - -/*********************************************************** - If we are DMB then prefer us as LMB -************************************************************/ - -BOOL lp_preferred_master(void) -{ - return (lp_local_master() && lp_domain_master()); + return (lp_server_role() == ROLE_DOMAIN_CONTROLLER); } /******************************************************************* @@ -2706,15 +2610,6 @@ void lp_copy_service(int snum, const char *new_name) } } - -/******************************************************************* - Get the default server type we will announce as via nmbd. -********************************************************************/ -int lp_default_server_announce(void) -{ - return default_server_announce; -} - const char *lp_printername(int snum) { const char *ret = _lp_printername(snum); diff --git a/source4/rpc_server/common/server_info.c b/source4/rpc_server/common/server_info.c index 12f5c90e8d..26667edc69 100644 --- a/source4/rpc_server/common/server_info.c +++ b/source4/rpc_server/common/server_info.c @@ -22,7 +22,10 @@ #include "includes.h" #include "librpc/gen_ndr/ndr_srvsvc.h" +#include "librpc/gen_ndr/svcctl.h" #include "rpc_server/dcerpc_server.h" +#include "dsdb/samdb/samdb.h" +#include "auth/auth.h" /* Here are common server info functions used by some dcerpc server interfaces @@ -81,7 +84,77 @@ _PUBLIC_ uint32_t dcesrv_common_get_version_build(TALLOC_CTX *mem_ctx, struct dc /* This hardcoded value should go into a ldb database! */ _PUBLIC_ uint32_t dcesrv_common_get_server_type(TALLOC_CTX *mem_ctx, struct dcesrv_context *dce_ctx) { - return lp_default_server_announce(); + int default_server_announce = 0; + default_server_announce |= SV_TYPE_WORKSTATION; + default_server_announce |= SV_TYPE_SERVER; + default_server_announce |= SV_TYPE_SERVER_UNIX; + + switch (lp_announce_as()) { + case ANNOUNCE_AS_NT_SERVER: + default_server_announce |= SV_TYPE_SERVER_NT; + /* fall through... */ + case ANNOUNCE_AS_NT_WORKSTATION: + default_server_announce |= SV_TYPE_NT; + break; + case ANNOUNCE_AS_WIN95: + default_server_announce |= SV_TYPE_WIN95_PLUS; + break; + case ANNOUNCE_AS_WFW: + default_server_announce |= SV_TYPE_WFW; + break; + default: + break; + } + + switch (lp_server_role()) { + case ROLE_DOMAIN_MEMBER: + default_server_announce |= SV_TYPE_DOMAIN_MEMBER; + break; + case ROLE_DOMAIN_CONTROLLER: + { + struct ldb_context *samctx; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + break; + } + /* open main ldb */ + samctx = samdb_connect(tmp_ctx, anonymous_session(tmp_ctx)); + if (samctx == NULL) { + DEBUG(2,("Unable to open samdb in determining server announce flags\n")); + } else { + /* Determine if we are the pdc */ + BOOL is_pdc = samdb_is_pdc(samctx); + if (is_pdc) { + default_server_announce |= SV_TYPE_DOMAIN_CTRL; + } else { + default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL; + } + } + /* Close it */ + talloc_free(tmp_ctx); + break; + } + case ROLE_STANDALONE: + default: + break; + } + if (lp_time_server()) + default_server_announce |= SV_TYPE_TIME_SOURCE; + + if (lp_host_msdfs()) + default_server_announce |= SV_TYPE_DFS_SERVER; + + +#if 0 + { + /* TODO: announce us as print server when we are a print server */ + BOOL is_print_server = False; + if (is_print_server) { + default_server_announce |= SV_TYPE_PRINTQ_SERVER; + } + } +#endif + return default_server_announce; } /* This hardcoded value should go into a ldb database! */ diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 0b2c5a0cfb..4a207645b4 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -277,6 +277,7 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ "objectSid", "objectGUID", "nTMixedDomain", + "fSMORoleOwner", NULL }; struct ldb_result *ref_res; @@ -317,7 +318,7 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ if (ret != LDB_SUCCESS) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } - talloc_steal(state, dom_res); + talloc_steal(mem_ctx, dom_res); if (dom_res->count != 1) { return NT_STATUS_NO_SUCH_DOMAIN; } @@ -333,7 +334,7 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ } state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0); - + talloc_free(dom_res); ret = ldb_search_exp_fmt(state->sam_ldb, state, &ref_res, @@ -431,11 +432,12 @@ static WERROR dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state case ROLE_DOMAIN_MEMBER: role = DS_ROLE_MEMBER_SERVER; break; - case ROLE_DOMAIN_BDC: - role = DS_ROLE_BACKUP_DC; - break; - case ROLE_DOMAIN_PDC: - role = DS_ROLE_PRIMARY_DC; + case ROLE_DOMAIN_CONTROLLER: + if (samdb_is_pdc(state->sam_ldb)) { + role = DS_ROLE_PRIMARY_DC; + } else { + role = DS_ROLE_BACKUP_DC; + } break; } @@ -449,8 +451,7 @@ static WERROR dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state W_ERROR_HAVE_NO_MEMORY(domain); /* TODO: what is with dns_domain and forest and guid? */ break; - case ROLE_DOMAIN_BDC: - case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_CONTROLLER: flags = DS_ROLE_PRIMARY_DS_RUNNING; if (state->mixed_domain == 1) { diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index bc85e4e665..8183c10f12 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -395,6 +395,7 @@ static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX * return NT_STATUS_INTERNAL_DB_CORRUPTION; } else if (ret == -1) { DEBUG(1, ("Failed to open domain %s: %s\n", dom_sid_string(mem_ctx, r->in.sid), ldb_errstring(c_state->sam_ctx))); + return NT_STATUS_INTERNAL_DB_CORRUPTION; } else { ret = gendb_search(c_state->sam_ctx, mem_ctx, partitions_basedn, &ref_msgs, ref_attrs, @@ -474,18 +475,39 @@ static NTSTATUS samr_info_DomInfo2(struct samr_domain_state *state, TALLOC_CTX * struct ldb_message **dom_msgs, struct samr_DomInfo2 *info) { + enum server_role role = lp_server_role(); + + /* This pulls the NetBIOS name from the + cn=NTDS Settings,cn=,.... + string */ + info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, dom_msgs[0], "fSMORoleOwner"); + info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 0x8000000000000000LL); info->comment.string = samdb_result_string(dom_msgs[0], "comment", NULL); info->domain_name.string = state->domain_name; - /* FIXME: We should find the name of the real PDC emulator */ - info->primary.string = lp_netbios_name(); info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 0); - - info->role = lp_server_role(); + switch (role) { + case ROLE_DOMAIN_CONTROLLER: + /* This pulls the NetBIOS name from the + cn=NTDS Settings,cn=,.... + string */ + if (samdb_is_pdc(state->sam_ctx)) { + info->role = SAMR_ROLE_DOMAIN_PDC; + } else { + info->role = SAMR_ROLE_DOMAIN_BDC; + } + break; + case ROLE_DOMAIN_MEMBER: + info->role = SAMR_ROLE_DOMAIN_MEMBER; + break; + case ROLE_STANDALONE: + info->role = SAMR_ROLE_STANDALONE; + break; + } /* TODO: Should these filter on SID, to avoid counting BUILTIN? */ info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn, @@ -545,12 +567,14 @@ static NTSTATUS samr_info_DomInfo5(struct samr_domain_state *state, */ static NTSTATUS samr_info_DomInfo6(struct samr_domain_state *state, TALLOC_CTX *mem_ctx, - struct ldb_message **dom_msgs, + struct ldb_message **dom_msgs, struct samr_DomInfo6 *info) { - - /* FIXME: We should find the name of the real PDC emulator */ - info->primary.string = lp_netbios_name(); + /* This pulls the NetBIOS name from the + cn=NTDS Settings,cn=,.... + string */ + info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, + dom_msgs[0], "fSMORoleOwner"); return NT_STATUS_OK; } @@ -563,7 +587,27 @@ static NTSTATUS samr_info_DomInfo7(struct samr_domain_state *state, struct ldb_message **dom_msgs, struct samr_DomInfo7 *info) { - info->role = lp_server_role(); + + enum server_role role = lp_server_role(); + + switch (role) { + case ROLE_DOMAIN_CONTROLLER: + /* This pulls the NetBIOS name from the + cn=NTDS Settings,cn=,.... + string */ + if (samdb_is_pdc(state->sam_ctx)) { + info->role = SAMR_ROLE_DOMAIN_PDC; + } else { + info->role = SAMR_ROLE_DOMAIN_BDC; + } + break; + case ROLE_DOMAIN_MEMBER: + info->role = SAMR_ROLE_DOMAIN_MEMBER; + break; + case ROLE_STANDALONE: + info->role = SAMR_ROLE_STANDALONE; + break; + } return NT_STATUS_OK; } @@ -695,6 +739,7 @@ static NTSTATUS samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_ static const char * const attrs2[] = {"forceLogoff", "comment", "modifiedCount", + "fSMORoleOwner", NULL}; attrs = attrs2; break; @@ -714,7 +759,17 @@ static NTSTATUS samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_ break; } case 5: + { + attrs = NULL; + break; + } case 6: + { + static const char * const attrs2[] = {"fSMORoleOwner", + NULL}; + attrs = attrs2; + break; + } case 7: { attrs = NULL; @@ -3517,6 +3572,7 @@ static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC const char * const attrs[4] = { "objectSid", "sAMAccountName", "description", NULL }; struct samr_DispEntryFull *entriesFull = NULL; + struct samr_DispEntryFullGroup *entriesFullGroup = NULL; struct samr_DispEntryAscii *entriesAscii = NULL; struct samr_DispEntryGeneral * entriesGeneral = NULL; const char *filter; @@ -3566,11 +3622,15 @@ static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC ldb_cnt); break; case 2: - case 3: entriesFull = talloc_array(mem_ctx, struct samr_DispEntryFull, ldb_cnt); break; + case 3: + entriesFullGroup = talloc_array(mem_ctx, + struct samr_DispEntryFullGroup, + ldb_cnt); + break; case 4: case 5: entriesAscii = talloc_array(mem_ctx, @@ -3580,7 +3640,7 @@ static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC } if ((entriesGeneral == NULL) && (entriesFull == NULL) && - (entriesAscii == NULL)) + (entriesAscii == NULL) && (entriesFullGroup == NULL)) return NT_STATUS_NO_MEMORY; count = 0; @@ -3610,23 +3670,34 @@ static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC samdb_result_string(res[i], "description", ""); break; case 2: - case 3: entriesFull[count].idx = count + 1; entriesFull[count].rid = objectsid->sub_auths[objectsid->num_auths-1]; entriesFull[count].acct_flags = samdb_result_acct_flags(res[i], "userAccountControl"); - if (r->in.level == 3) { - /* We get a "7" here for groups */ - entriesFull[count].acct_flags = 7; - } entriesFull[count].account_name.string = samdb_result_string(res[i], "sAMAccountName", ""); entriesFull[count].description.string = samdb_result_string(res[i], "description", ""); break; + case 3: + entriesFullGroup[count].idx = count + 1; + entriesFullGroup[count].rid = + objectsid->sub_auths[objectsid->num_auths-1]; + entriesFullGroup[count].acct_flags = + samdb_result_acct_flags(res[i], + "userAccountControl"); + /* We get a "7" here for groups */ + entriesFullGroup[count].acct_flags + = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; + entriesFullGroup[count].account_name.string = + samdb_result_string(res[i], "sAMAccountName", + ""); + entriesFullGroup[count].description.string = + samdb_result_string(res[i], "description", ""); + break; case 4: case 5: entriesAscii[count].idx = count + 1; @@ -3682,7 +3753,7 @@ static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC case 3: r->out.info.info3.count = r->out.returned_size; r->out.info.info3.entries = - &(entriesFull[r->in.start_idx]); + &(entriesFullGroup[r->in.start_idx]); break; case 4: r->out.info.info4.count = r->out.returned_size; diff --git a/source4/script/tests/mktestsetup.sh b/source4/script/tests/mktestsetup.sh index d6102e9d43..5264885a64 100755 --- a/source4/script/tests/mktestsetup.sh +++ b/source4/script/tests/mktestsetup.sh @@ -104,7 +104,7 @@ cat >$CONFFILE<info2.comment.string, domain_comment); ret = False; } + if (!r.out.info->info2.primary.string) { + printf("QueryDomainInfo level %u returned no PDC name\n", + levels[i]); + ret = False; + } else if (r.out.info->info2.role == SAMR_ROLE_DOMAIN_PDC) { + if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), r.out.info->info2.primary.string) != 0) { + printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n", + levels[i], r.out.info->info2.primary.string, dcerpc_server_name(p)); + } + } break; case 4: if (strcmp(r.out.info->info4.comment.string, domain_comment) != 0) { @@ -2995,6 +3005,13 @@ static BOOL test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, ret = False; } break; + case 6: + if (!r.out.info->info6.primary.string) { + printf("QueryDomainInfo level %u returned no PDC name\n", + levels[i]); + ret = False; + } + break; case 11: if (strcmp(r.out.info->info11.info2.comment.string, domain_comment) != 0) { printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n", -- cgit