#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
*/
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
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;
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:
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;
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;
return WERR_OK;
}
default:
- return WERR_INVALID_PARAM;
+ return WERR_INVALID_PARAMETER;
}
}
(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;
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;
}
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;
* 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;
}
"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;
}
}
}
- 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;
}
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;
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;
(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;
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;
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;
}
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;
}
{
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
};
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:
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 */
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);
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);
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:
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) {
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;
}
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;
}
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;
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:
}
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;
}
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);
}
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;
}
{
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;
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);
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)
{
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);
*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);
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;
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:
/* 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;
}