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/rpc_server/common/server_info.c | 75 ++++++++++++++++++++++- source4/rpc_server/lsa/dcesrv_lsa.c | 19 +++--- source4/rpc_server/samr/dcesrv_samr.c | 105 ++++++++++++++++++++++++++------ 3 files changed, 172 insertions(+), 27 deletions(-) (limited to 'source4/rpc_server') 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; -- cgit