summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2006-12-13 11:19:51 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:29:15 -0500
commitd471e52d23bf89e472c34c58dd9f113e669323a4 (patch)
tree45368b84653c14680c856cf54469e7e99ebb1720 /source4
parent5cc44027dc34812153831bd559e8fb7205d09328 (diff)
downloadsamba-d471e52d23bf89e472c34c58dd9f113e669323a4.tar.gz
samba-d471e52d23bf89e472c34c58dd9f113e669323a4.tar.bz2
samba-d471e52d23bf89e472c34c58dd9f113e669323a4.zip
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)
Diffstat (limited to 'source4')
-rw-r--r--source4/auth/auth_sam.c6
-rw-r--r--source4/dsdb/samdb/samdb.c157
-rw-r--r--source4/include/core.h12
-rw-r--r--source4/ldap_server/ldap_server.c45
-rw-r--r--source4/librpc/idl/samr.idl8
-rw-r--r--source4/nbt_server/nbt_server.c10
-rw-r--r--source4/nbt_server/nbt_server.h2
-rw-r--r--source4/nbt_server/register.c18
-rw-r--r--source4/param/loadparm.c113
-rw-r--r--source4/rpc_server/common/server_info.c75
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c19
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c105
-rwxr-xr-xsource4/script/tests/mktestsetup.sh2
-rw-r--r--source4/torture/rpc/samr.c17
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,52 +1078,154 @@ 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=<NETBIOS name of FSMO>,.... */
+ 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
*/
static BOOL samdb_password_complexity_ok(const char *pass)
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)
@@ -2381,15 +2366,6 @@ static void lp_add_auto_services(const char *str)
}
/***************************************************************************
- 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=<NETBIOS name of PDC>,....
+ 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=<NETBIOS name of PDC>,....
+ 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=<NETBIOS name of PDC>,....
+ 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=<NETBIOS name of PDC>,....
+ 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<<EOF
tls dh params file = $DHFILE
panic action = $SRCDIR/script/gdb_backtrace %PID% %PROG%
wins support = yes
- server role = pdc
+ server role = domain controller
max xmit = 32K
server max protocol = SMB2
notify:inotify = false
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c
index 25db0228c5..28dd03e803 100644
--- a/source4/torture/rpc/samr.c
+++ b/source4/torture/rpc/samr.c
@@ -2987,6 +2987,16 @@ static BOOL test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
levels[i], r.out.info->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",