mirror of
				https://github.com/samba-team/samba.git
				synced 2025-11-04 00:23:49 +03:00 
			
		
		
		
	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 commit is contained in:
		
				
					committed by
					
						
						Gerald (Jerry) Carter
					
				
			
			
				
	
			
			
			
						parent
						
							d2d9842914
						
					
				
				
					commit
					67d8365e83
				
			@@ -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! */
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user