s4:rpc_server: only use context within op_bind() hooks and dcesrv_interface_bind_...
[samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
index c55f679bfd9deb861fbf0ba895b72f1d60216122..4a1bf60ac64e60fa20b91bb6dc669d022ef1948f 100644 (file)
 #include "lib/messaging/irpc.h"
 #include "libds/common/roles.h"
 
+#define DCESRV_INTERFACE_LSARPC_BIND(call, iface) \
+       dcesrv_interface_lsarpc_bind(call, iface)
+static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_call_state *dce_call,
+                                            const struct dcesrv_interface *iface)
+{
+       struct dcesrv_connection_context *context = dce_call->context;
+       return dcesrv_interface_bind_reject_connect(context, iface);
+}
+
+static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
+                                      const struct dcesrv_endpoint_server *ep_server);
+static const struct dcesrv_interface dcesrv_lsarpc_interface;
+
+#define DCESRV_INTERFACE_LSARPC_INIT_SERVER    \
+       dcesrv_interface_lsarpc_init_server
+static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
+                                                   const struct dcesrv_endpoint_server *ep_server)
+{
+       if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
+               NTSTATUS ret = dcesrv_interface_register(dce_ctx,
+                                               "ncacn_np:[\\pipe\\netlogon]",
+                                               &dcesrv_lsarpc_interface, NULL);
+               if (!NT_STATUS_IS_OK(ret)) {
+                       DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
+                       return ret;
+               }
+       }
+       return lsarpc__op_init_server(dce_ctx, ep_server);
+}
+
 /*
   this type allows us to distinguish handle types
 */
@@ -70,6 +100,24 @@ struct lsa_trusted_domain_state {
        struct ldb_dn *trusted_domain_user_dn;
 };
 
+static bool dcesrc_lsa_valid_AccountRight(const char *right)
+{
+       enum sec_privilege priv_id;
+       uint32_t right_bit;
+
+       priv_id = sec_privilege_id(right);
+       if (priv_id != SEC_PRIV_INVALID) {
+               return true;
+       }
+
+       right_bit = sec_right_bit(right);
+       if (right_bit != 0) {
+               return true;
+       }
+
+       return false;
+}
+
 /*
   this is based on the samba3 function make_lsa_object_sd()
   It uses the same logic, but with samba4 helper functions
@@ -194,6 +242,8 @@ static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX
 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_DeleteObject *r)
 {
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(dce_call);
        struct dcesrv_handle *h;
        int ret;
 
@@ -203,7 +253,7 @@ static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALL
                struct lsa_secret_state *secret_state = h->data;
 
                /* Ensure user is permitted to delete this... */
-               switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
+               switch (security_session_user_level(session_info, NULL))
                {
                case SECURITY_SYSTEM:
                case SECURITY_ADMINISTRATOR:
@@ -350,6 +400,8 @@ static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_
 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                         struct lsa_QuerySecurity *r)
 {
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(dce_call);
        struct dcesrv_handle *h;
        const struct security_descriptor *sd = NULL;
        uint32_t access_granted = 0;
@@ -359,7 +411,7 @@ static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TAL
 
        DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
 
-       sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
+       sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
 
        if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
                struct lsa_policy_state *pstate = h->data;
@@ -521,7 +573,7 @@ static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_cal
                return WERR_OK;
        }
        default:
-               return WERR_INVALID_PARAM;
+               return WERR_INVALID_PARAMETER;
        }
 }
 
@@ -727,7 +779,7 @@ static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TAL
                 (unsigned)r->in.access_mask,
                 (unsigned)astate->access_mask));
 
-       ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
+       ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
        if (!ah) {
                talloc_free(astate);
                return NT_STATUS_NO_MEMORY;
@@ -808,7 +860,7 @@ static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
        enum ndr_err_code ndr_err;
        NTSTATUS nt_status;
 
-       nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
+       nt_status = dcesrv_transport_session_key(dce_call, &session_key);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
@@ -1015,9 +1067,6 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
        struct server_id *server_ids = NULL;
        uint32_t num_server_ids = 0;
        NTSTATUS status;
-       struct dom_sid *tmp_sid1;
-       struct dom_sid *tmp_sid2;
-       uint32_t tmp_rid;
        bool ok;
        char *dns_encoded = NULL;
        char *netbios_encoded = NULL;
@@ -1047,35 +1096,8 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
         * We expect S-1-5-21-A-B-C, but we don't
         * allow S-1-5-21-0-0-0 as this is used
         * for claims and compound identities.
-        *
-        * So we call dom_sid_split_rid() 3 times
-        * and compare the result to S-1-5-21
         */
-       status = dom_sid_split_rid(mem_ctx, r->in.info->sid, &tmp_sid1, &tmp_rid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-       status = dom_sid_split_rid(mem_ctx, tmp_sid1, &tmp_sid2, &tmp_rid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-       status = dom_sid_split_rid(mem_ctx, tmp_sid2, &tmp_sid1, &tmp_rid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-       ok = dom_sid_parse("S-1-5-21", tmp_sid2);
-       if (!ok) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-       ok = dom_sid_equal(tmp_sid1, tmp_sid2);
-       if (!ok) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-       ok = dom_sid_parse("S-1-5-21-0-0-0", tmp_sid2);
-       if (!ok) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-       ok = !dom_sid_equal(r->in.info->sid, tmp_sid2);
+       ok = dom_sid_is_valid_account_domain(r->in.info->sid);
        if (!ok) {
                return NT_STATUS_INVALID_PARAMETER;
        }
@@ -1313,19 +1335,12 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
                                     "winbind_server",
                                     &num_server_ids, &server_ids);
        if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
-               enum ndr_err_code ndr_err;
-               DATA_BLOB b = {};
-
-               ndr_err = ndr_push_struct_blob(&b, mem_ctx, r->in.info,
-                       (ndr_push_flags_fn_t)ndr_push_lsa_TrustDomainInfoInfoEx);
-               if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-                       imessaging_send(dce_call->msg_ctx, server_ids[0],
-                               MSG_WINBIND_NEW_TRUSTED_DOMAIN, &b);
-               }
+               imessaging_send(dce_call->msg_ctx, server_ids[0],
+                               MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
        }
        TALLOC_FREE(server_ids);
 
-       handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
+       handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
        if (!handle) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1457,7 +1472,7 @@ static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
                }
        }
 
-       handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
+       handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
        if (!handle) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -2553,7 +2568,6 @@ static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALL
                                 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
 
        r->out.domains->domains = entries + *r->in.resume_handle;
-       r->out.domains->count = r->out.domains->count;
 
        if (r->out.domains->count < count - *r->in.resume_handle) {
                *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
@@ -2648,7 +2662,6 @@ static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_ca
                                 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
 
        r->out.domains->domains = entries + *r->in.resume_handle;
-       r->out.domains->count = r->out.domains->count;
 
        if (r->out.domains->count < count - *r->in.resume_handle) {
                *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
@@ -2707,7 +2720,7 @@ static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLO
                 (unsigned)r->in.access_mask,
                 (unsigned)astate->access_mask));
 
-       ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
+       ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
        if (!ah) {
                talloc_free(astate);
                return NT_STATUS_NO_MEMORY;
@@ -2863,6 +2876,8 @@ static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_
                                           struct dom_sid *sid,
                                           const struct lsa_RightSet *rights)
 {
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(dce_call);
        const char *sidstr, *sidndrstr;
        struct ldb_message *msg;
        struct ldb_message_element *el;
@@ -2871,7 +2886,7 @@ static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_
        struct lsa_EnumAccountRights r2;
        char *dnstr;
 
-       if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
+       if (security_session_user_level(session_info, NULL) <
            SECURITY_ADMINISTRATOR) {
                DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
                return NT_STATUS_ACCESS_DENIED;
@@ -2920,12 +2935,10 @@ static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_
        }
 
        for (i=0;i<rights->count;i++) {
-               if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
-                       if (sec_right_bit(rights->names[i].string) == 0) {
-                               talloc_free(msg);
-                               return NT_STATUS_NO_SUCH_PRIVILEGE;
-                       }
+               bool ok;
 
+               ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
+               if (!ok) {
                        talloc_free(msg);
                        return NT_STATUS_NO_SUCH_PRIVILEGE;
                }
@@ -3161,19 +3174,20 @@ static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
-
-
 /*
   lsa_CreateSecret
 */
 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                 struct lsa_CreateSecret *r)
 {
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(dce_call);
        struct dcesrv_handle *policy_handle;
        struct lsa_policy_state *policy_state;
        struct lsa_secret_state *secret_state;
        struct dcesrv_handle *handle;
        struct ldb_message **msgs, *msg;
+       struct ldb_context *samdb = NULL;
        const char *attrs[] = {
                NULL
        };
@@ -3185,7 +3199,7 @@ static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALL
        DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
        ZERO_STRUCTP(r->out.sec_handle);
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
+       switch (security_session_user_level(session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -3224,11 +3238,18 @@ static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALL
                                        ldb_binary_encode_string(mem_ctx, name));
                NT_STATUS_HAVE_NO_MEMORY(name2);
 
-               /* We need to connect to the database as system, as this is one
-                * of the rare RPC calls that must read the secrets (and this
-                * is denied otherwise) */
-               secret_state->sam_ldb = talloc_reference(secret_state,
-                                                        samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
+               /*
+                * We need to connect to the database as system, as this is
+                * one of the rare RPC calls that must read the secrets
+                * (and this is denied otherwise)
+                *
+                * We also save the current remote session details so they can
+                * used by the audit logging module. This allows the audit
+                * logging to report the remote users details, rather than the
+                * system users details.
+                */
+               samdb = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
+               secret_state->sam_ldb = talloc_reference(secret_state, samdb);
                NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
 
                /* search for the secret record */
@@ -3304,7 +3325,7 @@ static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALL
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
+       handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
        NT_STATUS_HAVE_NO_MEMORY(handle);
 
        handle->data = talloc_steal(handle, secret_state);
@@ -3325,18 +3346,18 @@ static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALL
 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                               struct lsa_OpenSecret *r)
 {
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(dce_call);
        struct dcesrv_handle *policy_handle;
-
        struct lsa_policy_state *policy_state;
        struct lsa_secret_state *secret_state;
        struct dcesrv_handle *handle;
        struct ldb_message **msgs;
+       struct ldb_context *samdb = NULL;
        const char *attrs[] = {
                NULL
        };
-
        const char *name;
-
        int ret;
 
        DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
@@ -3347,7 +3368,7 @@ static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
+       switch (security_session_user_level(session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -3365,9 +3386,18 @@ static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC
 
        if (strncmp("G$", r->in.name.string, 2) == 0) {
                name = &r->in.name.string[2];
-               /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
-               secret_state->sam_ldb = talloc_reference(secret_state,
-                                                        samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
+               /*
+                * We need to connect to the database as system, as this is
+                * one of the rare RPC calls that must read the secrets
+                * (and this is denied otherwise)
+                *
+                * We also save the current remote session details so they can
+                * used by the audit logging module. This allows the audit
+                * logging to report the remote users details, rather than the
+                * system users details.
+                */
+               samdb = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
+               secret_state->sam_ldb = talloc_reference(secret_state, samdb);
                secret_state->global = true;
 
                if (strlen(name) < 1) {
@@ -3417,7 +3447,7 @@ static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC
 
        secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
 
-       handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
+       handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
        if (!handle) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -3465,7 +3495,7 @@ static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_
        if (!msg->dn) {
                return NT_STATUS_NO_MEMORY;
        }
-       status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
+       status = dcesrv_transport_session_key(dce_call, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -3600,6 +3630,8 @@ static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_
 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                struct lsa_QuerySecret *r)
 {
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(dce_call);
        struct dcesrv_handle *h;
        struct lsa_secret_state *secret_state;
        struct ldb_message *msg;
@@ -3620,7 +3652,7 @@ static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLO
        DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
 
        /* Ensure user is permitted to read this... */
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
+       switch (security_session_user_level(session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -3640,7 +3672,7 @@ static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLO
        }
        msg = res[0];
 
-       nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
+       nt_status = dcesrv_transport_session_key(dce_call, &session_key);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
@@ -3827,6 +3859,7 @@ static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *d
        struct ldb_message **res;
        const char * const attrs[] = { "objectSid", NULL};
        const char *privname;
+       bool ok;
 
        DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
 
@@ -3837,7 +3870,9 @@ static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *d
        }
 
        privname = r->in.name->string;
-       if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
+
+       ok = dcesrc_lsa_valid_AccountRight(privname);
+       if (!ok) {
                return NT_STATUS_NO_SUCH_PRIVILEGE;
        }
 
@@ -3933,6 +3968,8 @@ static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLO
 {
        enum dcerpc_transport_t transport =
                dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(dce_call);
        NTSTATUS status = NT_STATUS_OK;
        const char *account_name;
        const char *authority_name;
@@ -3961,8 +3998,8 @@ static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLO
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
-       authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
+       account_name = talloc_reference(mem_ctx, session_info->info->account_name);
+       authority_name = talloc_reference(mem_ctx, session_info->info->domain_name);
 
        _account_name = talloc(mem_ctx, struct lsa_String);
        NT_STATUS_HAVE_NO_MEMORY(_account_name);
@@ -3993,7 +4030,8 @@ static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
-static void kdc_get_policy(struct loadparm_context *lp_ctx,
+static void kdc_get_policy(TALLOC_CTX *mem_ctx,
+                          struct loadparm_context *lp_ctx,
                           struct smb_krb5_context *smb_krb5_context,
                           struct lsa_DomainInfoKerberos *k)
 {
@@ -4001,12 +4039,10 @@ static void kdc_get_policy(struct loadparm_context *lp_ctx,
        time_t usr_tkt_lifetime;
        time_t renewal_lifetime;
 
-       /* These should be set and stored via Group Policy, but until then, some defaults are in order */
-
        /* Our KDC always re-validates the client */
        k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
 
-       lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
+       lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
                                 &usr_tkt_lifetime, &renewal_lifetime);
 
        unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
@@ -4055,7 +4091,7 @@ static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state
                        *r->out.info = NULL;
                        return NT_STATUS_INTERNAL_ERROR;
                }
-               kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
+               kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
                               smb_krb5_context,
                               k);
                talloc_free(smb_krb5_context);
@@ -4323,6 +4359,8 @@ static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_stat
        struct lsa_ForestTrustCollisionInfo *c_info = NULL;
        DATA_BLOB ft_blob = {};
        struct ldb_message *msg = NULL;
+       struct server_id *server_ids = NULL;
+       uint32_t num_server_ids = 0;
        NTSTATUS status;
        enum ndr_err_code ndr_err;
        int ret;
@@ -4562,6 +4600,21 @@ static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_stat
                goto done;
        }
 
+       /*
+        * Notify winbindd that we have a acquired forest trust info
+        */
+       status = irpc_servers_byname(dce_call->msg_ctx,
+                                    mem_ctx,
+                                    "winbind_server",
+                                    &num_server_ids, &server_ids);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("irpc_servers_byname failed\n");
+               goto done;
+       }
+
+       imessaging_send(dce_call->msg_ctx, server_ids[0],
+                       MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
+
        status = NT_STATUS_OK;
 
 done:
@@ -4742,15 +4795,15 @@ static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_cal
 /* include the generated boilerplate */
 #include "librpc/gen_ndr/ndr_dssetup_s.c"
 
-NTSTATUS dcerpc_server_lsa_init(void)
+NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
 {
        NTSTATUS ret;
 
-       ret = dcerpc_server_dssetup_init();
+       ret = dcerpc_server_dssetup_init(ctx);
        if (!NT_STATUS_IS_OK(ret)) {
                return ret;
        }
-       ret = dcerpc_server_lsarpc_init();
+       ret = dcerpc_server_lsarpc_init(ctx);
        if (!NT_STATUS_IS_OK(ret)) {
                return ret;
        }