summaryrefslogtreecommitdiff
path: root/source4/rpc_server/lsa
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2006-07-06 05:23:29 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:09:48 -0500
commitf2e8b3202c99065dafca3ba36a43450c509d0bd8 (patch)
tree4775c5023eab78b1a3f8e95bea249f40b6d8cc26 /source4/rpc_server/lsa
parent3aa8a700e6b838ffc32bb7e9aebbb197e91c4704 (diff)
downloadsamba-f2e8b3202c99065dafca3ba36a43450c509d0bd8.tar.gz
samba-f2e8b3202c99065dafca3ba36a43450c509d0bd8.tar.bz2
samba-f2e8b3202c99065dafca3ba36a43450c509d0bd8.zip
r16827: Factor out some code into common samdb functions:
- creation of ForeignSecurityPrincipals - template duplication code Rework much of the LSA server to pass the RPC-LSA test. Much of the server code was untested. In implementing the LSA Accounts feature, I have opted to have it only create entires when privilages are applied, and not to delete entries, but to delete the privilages. We skip some parts of the test, but it is much better than not testing it at all. Andrew Bartlett (This used to be commit 10eeea6da465564ed9f785d06e2d2ed06cfe29a4)
Diffstat (limited to 'source4/rpc_server/lsa')
-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);