summaryrefslogtreecommitdiff
path: root/source4/rpc_server/lsa/dcesrv_lsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/rpc_server/lsa/dcesrv_lsa.c')
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c197
1 files changed, 149 insertions, 48 deletions
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index 17f9754c3b..9a76926375 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -27,6 +27,7 @@
#include "auth/auth.h"
#include "dsdb/samdb/samdb.h"
#include "libcli/ldap/ldap.h"
+#include "lib/ldb/include/ldb_errors.h"
#include "libcli/security/security.h"
#include "libcli/auth/libcli_auth.h"
#include "passdb/secrets.h"
@@ -66,7 +67,6 @@ struct lsa_account_state {
struct lsa_policy_state *policy;
uint32_t access_mask;
struct dom_sid *account_sid;
- const struct ldb_dn *account_dn;
};
@@ -90,6 +90,17 @@ struct lsa_trusted_domain_state {
const struct ldb_dn *trusted_domain_dn;
};
+static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_EnumAccountRights *r);
+
+static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_policy_state *state,
+ int ldb_flag,
+ struct dom_sid *sid,
+ const struct lsa_RightSet *rights);
+
/*
lsa_Close
*/
@@ -139,6 +150,41 @@ static NTSTATUS lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_c
}
return NT_STATUS_OK;
+ } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
+ struct lsa_RightSet *rights;
+ struct lsa_account_state *astate;
+ struct lsa_EnumAccountRights r2;
+ NTSTATUS status;
+
+ rights = talloc(mem_ctx, struct lsa_RightSet);
+
+ DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
+
+ astate = h->data;
+
+ r2.in.handle = &astate->policy->handle->wire_handle;
+ r2.in.sid = astate->account_sid;
+ r2.out.rights = rights;
+
+ status = lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ return NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
+ LDB_FLAG_MOD_DELETE, astate->account_sid,
+ r2.out.rights);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ return NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
}
return NT_STATUS_INVALID_HANDLE;
@@ -458,7 +504,42 @@ static NTSTATUS lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX
static NTSTATUS lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_CreateAccount *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct lsa_account_state *astate;
+
+ struct lsa_policy_state *state;
+ struct dcesrv_handle *h, *ah;
+
+ ZERO_STRUCTP(r->out.acct_handle);
+
+ DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+
+ state = h->data;
+
+ astate = talloc(dce_call->conn, struct lsa_account_state);
+ if (astate == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ astate->account_sid = dom_sid_dup(astate, r->in.sid);
+ if (astate->account_sid == NULL) {
+ talloc_free(astate);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ astate->policy = talloc_reference(astate, state);
+ astate->access_mask = r->in.access_mask;
+
+ ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
+ if (!ah) {
+ talloc_free(astate);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ah->data = talloc_steal(ah, astate);
+
+ *r->out.acct_handle = ah->wire_handle;
+
+ return NT_STATUS_OK;
}
@@ -479,9 +560,12 @@ static NTSTATUS lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX
state = h->data;
- ret = gendb_search(state->sam_ldb, mem_ctx, state->builtin_dn, &res, attrs,
- "(|(privilege=*)(objectSid=*))");
- if (ret <= 0) {
+ /* NOTE: This call must only return accounts that have at least
+ one privilege set
+ */
+ ret = gendb_search(state->sam_ldb, mem_ctx, samdb_base_dn(mem_ctx), &res, attrs,
+ "(&(objectSid=*)(privilege=*))");
+ if (ret < 0) {
return NT_STATUS_NO_SUCH_USER;
}
@@ -1298,15 +1382,6 @@ static NTSTATUS lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *
return NT_STATUS_NO_MEMORY;
}
- /* check it really exists */
- astate->account_dn = samdb_search_dn(state->sam_ldb, astate,
- NULL, "(&(objectSid=%s)(objectClass=group))",
- ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid));
- if (astate->account_dn == NULL) {
- talloc_free(astate);
- return NT_STATUS_NO_SUCH_USER;
- }
-
astate->policy = talloc_reference(astate, state);
astate->access_mask = r->in.access_mask;
@@ -1337,6 +1412,7 @@ static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
struct ldb_message **res;
const char * const attrs[] = { "privilege", NULL};
struct ldb_message_element *el;
+ const char *sidstr;
DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
@@ -1347,8 +1423,13 @@ static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
r->out.privs->unknown = 0;
r->out.privs->set = NULL;
- ret = gendb_search_dn(astate->policy->sam_ldb, mem_ctx,
- astate->account_dn, &res, attrs);
+ sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
+ if (sidstr == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = gendb_search(astate->policy->sam_ldb, mem_ctx, samdb_base_dn(mem_ctx), &res, attrs,
+ "objectSid=%s", sidstr);
if (ret != 1) {
return NT_STATUS_OK;
}
@@ -1359,7 +1440,7 @@ static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
}
r->out.privs->set = talloc_array(r->out.privs,
- struct lsa_LUIDAttribute, el->num_values);
+ struct lsa_LUIDAttribute, el->num_values);
if (r->out.privs->set == NULL) {
return NT_STATUS_NO_MEMORY;
}
@@ -1403,11 +1484,20 @@ static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
return NT_STATUS_NO_MEMORY;
}
- ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
- "objectSid=%s", sidstr);
- if (ret != 1) {
+ ret = gendb_search(state->sam_ldb, mem_ctx, samdb_base_dn(mem_ctx), &res, attrs,
+ "(&(objectSid=%s)(privilege=*))", sidstr);
+ if (ret == 0) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ if (ret > 1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (ret == -1) {
+ DEBUG(3, ("searching for account rights for SID: %s failed: %s",
+ dom_sid_string(mem_ctx, r->in.sid),
+ ldb_errstring(state->sam_ldb)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
el = ldb_msg_find_element(res[0], "privilege");
if (el == NULL || el->num_values == 0) {
@@ -1442,7 +1532,7 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
{
const char *sidstr;
struct ldb_message *msg;
- struct ldb_message_element el;
+ struct ldb_message_element *el;
int i, ret;
struct lsa_EnumAccountRights r2;
@@ -1456,8 +1546,18 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
return NT_STATUS_NO_MEMORY;
}
- msg->dn = samdb_search_dn(state->sam_ldb, mem_ctx, NULL, "objectSid=%s", sidstr);
+ msg->dn = samdb_search_dn(state->sam_ldb, mem_ctx,
+ samdb_base_dn(mem_ctx), "objectSid=%s", sidstr);
if (msg->dn == NULL) {
+ NTSTATUS status;
+ if (ldb_flag == LDB_FLAG_MOD_DELETE) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ status = samdb_create_foreign_security_principal(state->sam_ldb, mem_ctx,
+ sid, &msg->dn);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
return NT_STATUS_NO_SUCH_USER;
}
@@ -1478,11 +1578,6 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
}
}
- el.num_values = 0;
- el.values = talloc_array(mem_ctx, struct ldb_val, rights->count);
- if (el.values == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
for (i=0;i<rights->count;i++) {
if (sec_privilege_id(rights->names[i].string) == -1) {
return NT_STATUS_NO_SUCH_PRIVILEGE;
@@ -1499,24 +1594,25 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
if (j != r2.out.rights->count) continue;
}
-
- el.values[el.num_values].length = strlen(rights->names[i].string);
- el.values[el.num_values].data = (uint8_t *)talloc_strdup(mem_ctx, rights->names[i].string);
- if (el.values[el.num_values].data == NULL) {
+ ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_NO_MEMORY;
}
- el.num_values++;
}
- if (el.num_values == 0) {
+ el = ldb_msg_find_element(msg, "privilege");
+ if (!el) {
return NT_STATUS_OK;
}
ret = samdb_modify(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- if (ldb_flag == LDB_FLAG_MOD_DELETE) {
+ if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ DEBUG(3, ("Could not %s attributes from %s: %s",
+ ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
+ ldb_dn_linearize(mem_ctx, msg->dn), ldb_errstring(state->sam_ldb)));
return NT_STATUS_UNEXPECTED_IO_ERROR;
}
@@ -1721,9 +1817,9 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- if (ret < 0 || ret > 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret,
- ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
+ if (ret == -1) {
+ DEBUG(0,("Failure searching for CN=%s: %s\n",
+ name2, ldb_errstring(secret_state->sam_ldb)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -1753,9 +1849,9 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- if (ret < 0 || ret > 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret,
- ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
+ if (ret == -1) {
+ DEBUG(0,("Failure searching for CN=%s: %s\n",
+ name, ldb_errstring(secret_state->sam_ldb)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -1764,10 +1860,11 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
}
/* pull in all the template attributes. Note this is always from the global samdb */
- ret = samdb_copy_template(secret_state->policy->sam_ldb, mem_ctx, msg,
- "(&(name=TemplateSecret)(objectclass=secretTemplate))");
+ ret = samdb_copy_template(secret_state->policy->sam_ldb, msg,
+ "(&(cn=TemplateSecret)(objectclass=secretTemplate))");
if (ret != 0) {
- DEBUG(0,("Failed to load TemplateSecret from samdb\n"));
+ DEBUG(0,("Failed to load TemplateSecret from samdb: %s\n",
+ ldb_errstring(secret_state->policy->sam_ldb)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -1778,8 +1875,9 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
/* create the secret */
ret = samdb_add(secret_state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to create secret record %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn)));
+ DEBUG(0,("Failed to create secret record %s: %s\n",
+ ldb_dn_linearize(mem_ctx, msg->dn),
+ ldb_errstring(secret_state->sam_ldb)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -2314,10 +2412,13 @@ static NTSTATUS lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call
return NT_STATUS_NO_SUCH_PRIVILEGE;
}
- ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
+ ret = gendb_search(state->sam_ldb, mem_ctx, samdb_base_dn(mem_ctx), &res, attrs,
"privilege=%s", privname);
- if (ret <= 0) {
- return NT_STATUS_NO_SUCH_USER;
+ if (ret == -1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (ret == 0) {
+ return NT_STATUS_NO_MORE_ENTRIES;
}
r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);