summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c178
1 files changed, 172 insertions, 6 deletions
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 417035e8a2..a5308bb84e 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -1816,23 +1816,189 @@ static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dc
}
+static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
+ struct ldb_context *sam_ctx,
+ struct loadparm_context *lp_ctx,
+ struct lsa_ForestTrustInformation *info)
+{
+ struct lsa_ForestTrustDomainInfo *domain_info;
+ struct lsa_ForestTrustRecord *e;
+ struct ldb_message **dom_res;
+ const char * const dom_attrs[] = { "objectSid", NULL };
+ int ret;
+
+ /* we need to provide 2 entries:
+ * 1. the Root Forest name
+ * 2. the Domain Information
+ */
+
+ info->count = 2;
+ info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
+ W_ERROR_HAVE_NO_MEMORY(info->entries);
+
+ /* Forest root info */
+ e = talloc(info, struct lsa_ForestTrustRecord);
+ W_ERROR_HAVE_NO_MEMORY(e);
+
+ e->flags = 0;
+ e->level = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
+ e->time = 0; /* so far always 0 in trces. */
+ e->forest_trust_data.top_level_name.string = lp_dnsdomain(lp_ctx);
+
+ info->entries[0] = e;
+
+ /* Domain info */
+ e = talloc(info, struct lsa_ForestTrustRecord);
+ W_ERROR_HAVE_NO_MEMORY(e);
+
+ /* get our own domain info */
+ ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
+ if (ret != 1) {
+ return WERR_GENERAL_FAILURE;
+ }
+
+ /* TODO: check if disabled and set flags accordingly */
+ e->flags = 0;
+ e->level = LSA_FOREST_TRUST_DOMAIN_INFO;
+ e->time = 0; /* so far always 0 in traces. */
+
+ domain_info = &e->forest_trust_data.domain_info;
+ domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
+ "objectSid");
+ domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
+ domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
+
+ info->entries[1] = e;
+
+ talloc_free(dom_res);
+
+ return WERR_OK;
+}
+
/*
netr_DsRGetForestTrustInformation
*/
-static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct netr_DsRGetForestTrustInformation *r)
+static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct netr_DsRGetForestTrustInformation *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+ struct lsa_ForestTrustInformation *info, **info_ptr;
+ struct ldb_context *sam_ctx;
+ WERROR werr;
+
+ ZERO_STRUCT(r->out);
+
+ if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
+ return WERR_CALL_NOT_IMPLEMENTED;
+ }
+
+ if (r->in.flags & 0xFFFFFFFE) {
+ return WERR_INVALID_FLAGS;
+ }
+
+ sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
+ dce_call->conn->auth_state.session_info);
+ if (sam_ctx == NULL) {
+ return WERR_GENERAL_FAILURE;
+ }
+
+ if (r->in.flags & DS_GFTI_UPDATE_TDO) {
+ if (!samdb_is_pdc(sam_ctx)) {
+ return WERR_NERR_NOTPRIMARY;
+ }
+
+ if (r->in.trusted_domain_name == NULL) {
+ return WERR_INVALID_FLAGS;
+ }
+
+ /* TODO: establish an schannel connection with
+ * r->in.trusted_domain_name and perform a
+ * netr_GetForestTrustInformation call against it */
+
+ /* for now return not implementd */
+ return WERR_CALL_NOT_IMPLEMENTED;
+ }
+
+ /* TODO: check r->in.server_name is our name */
+
+ info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
+ W_ERROR_HAVE_NO_MEMORY(info_ptr);
+
+ info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
+ W_ERROR_HAVE_NO_MEMORY(info);
+
+ werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
+ W_ERROR_NOT_OK_RETURN(werr);
+
+ *info_ptr = info;
+ r->out.forest_trust_info = info_ptr;
+
+ return WERR_OK;
}
/*
netr_GetForestTrustInformation
*/
-static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct netr_GetForestTrustInformation *r)
+static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct netr_GetForestTrustInformation *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+ struct netlogon_creds_CredentialState *creds;
+ struct lsa_ForestTrustInformation *info, **info_ptr;
+ struct ldb_context *sam_ctx;
+ NTSTATUS status;
+ WERROR werr;
+
+ if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ ZERO_STRUCT(r->out);
+
+ status = dcesrv_netr_creds_server_step_check(dce_call,
+ mem_ctx,
+ r->in.computer_name,
+ r->in.credential,
+ r->out.return_authenticator,
+ &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
+ (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
+ dce_call->conn->auth_state.session_info);
+ if (sam_ctx == NULL) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* TODO: check r->in.server_name is our name */
+
+ info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
+ if (!info_ptr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
+ if (!info) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werror_to_ntstatus(werr);
+ }
+
+ *info_ptr = info;
+ r->out.forest_trust_info = info_ptr;
+
+ return NT_STATUS_OK;
}