summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c173
-rw-r--r--source4/dsdb/samdb/samdb.c182
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c197
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c56
-rw-r--r--source4/torture/rpc/lsa.c37
5 files changed, 365 insertions, 280 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 2f0c6f2d17..c95fb70820 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -45,45 +45,6 @@
int samldb_notice_sid(struct ldb_module *module,
TALLOC_CTX *mem_ctx, const struct dom_sid *sid);
-/* if value is not null also check for attribute to have exactly that value */
-static struct ldb_message_element *samldb_find_attribute(const struct ldb_message *msg, const char *name, const char *value)
-{
- int j;
- struct ldb_message_element *el = ldb_msg_find_element(msg, name);
- if (!el) {
- return NULL;
- }
-
- if (!value) {
- return el;
- }
-
- for (j = 0; j < el->num_values; j++) {
- if (strcasecmp(value,
- (char *)el->values[j].data) == 0) {
- return el;
- }
- }
-
- return NULL;
-}
-
-static BOOL samldb_msg_add_string(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *value)
-{
- char *aval = talloc_strdup(msg, value);
-
- if (aval == NULL) {
- ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_msg_add_string: talloc_strdup failed!\n");
- return False;
- }
-
- if (ldb_msg_add_string(msg, name, aval) != 0) {
- return False;
- }
-
- return True;
-}
-
static BOOL samldb_msg_add_sid(struct ldb_module *module, struct ldb_message *msg, const char *name, const struct dom_sid *sid)
{
struct ldb_val v;
@@ -96,34 +57,6 @@ static BOOL samldb_msg_add_sid(struct ldb_module *module, struct ldb_message *ms
return (ldb_msg_add_value(msg, name, &v) == 0);
}
-static BOOL samldb_find_or_add_value(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *value, const char *set_value)
-{
- if (msg == NULL || name == NULL || value == NULL || set_value == NULL) {
- return False;
- }
-
- if (samldb_find_attribute(msg, name, value) == NULL) {
- return samldb_msg_add_string(module, msg, name, set_value);
- }
- return True;
-}
-
-static BOOL samldb_find_or_add_attribute(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *set_value)
-{
- struct ldb_message_element *el;
-
- if (msg == NULL || name == NULL || set_value == NULL) {
- return False;
- }
-
- el = ldb_msg_find_element(msg, name);
- if (el) {
- return True;
- }
-
- return samldb_msg_add_string(module, msg, name, set_value);
-}
-
/*
allocate a new id, attempting to do it atomically
return 0 on failure, the id on success
@@ -484,69 +417,6 @@ static char *samldb_generate_samAccountName(struct ldb_module *module, TALLOC_CT
} while (1);
}
-static int samldb_copy_template(struct ldb_module *module, struct ldb_message *msg, const char *filter)
-{
- struct ldb_result *res;
- struct ldb_message *t;
- int ret, i, j;
-
- struct ldb_dn *basedn = ldb_dn_explode(msg, "cn=Templates");
-
- /* pull the template record */
- ret = ldb_search(module->ldb, basedn, LDB_SCOPE_SUBTREE, filter, NULL, &res);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- if (res->count != 1) {
- ldb_set_errstring(module->ldb, talloc_asprintf(module, "samldb_copy_template: ERROR: template '%s' matched %d records, expected 1\n", filter,
- res->count));
- return LDB_ERR_OPERATIONS_ERROR;
- }
- t = res->msgs[0];
-
- for (i = 0; i < t->num_elements; i++) {
- struct ldb_message_element *el = &t->elements[i];
- /* some elements should not be copied from the template */
- if (strcasecmp(el->name, "cn") == 0 ||
- strcasecmp(el->name, "name") == 0 ||
- strcasecmp(el->name, "sAMAccountName") == 0 ||
- strcasecmp(el->name, "objectGUID") == 0) {
- continue;
- }
- for (j = 0; j < el->num_values; j++) {
- if (strcasecmp(el->name, "objectClass") == 0) {
- if (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
- strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "foreignSecurityPrincipalTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "secretTemplate") == 0) {
- continue;
- }
- if ( ! samldb_find_or_add_value(module, msg, el->name,
- (char *)el->values[j].data,
- (char *)el->values[j].data)) {
- ldb_set_errstring(module->ldb, talloc_asprintf(module, "Adding objectClass %s failed.\n", el->values[j].data));
- talloc_free(res);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- } else {
- if ( ! samldb_find_or_add_attribute(module, msg, el->name,
- (char *)el->values[j].data)) {
- ldb_set_errstring(module->ldb, talloc_asprintf(module, "Adding attribute %s failed.\n", el->name));
- talloc_free(res);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- }
- }
- }
-
- talloc_free(res);
-
- return LDB_SUCCESS;
-}
-
static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_message *msg,
struct ldb_message **ret_msg)
{
@@ -567,7 +437,7 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = samldb_copy_template(module, msg2, "(&(CN=TemplateGroup)(objectclass=groupTemplate))");
+ ret = samdb_copy_template(module->ldb, msg2, "(&(CN=TemplateGroup)(objectclass=groupTemplate))");
if (ret != 0) {
talloc_free(mem_ctx);
return ret;
@@ -588,9 +458,10 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
- if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", name)) {
+ ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name);
+ if (ret) {
talloc_free(mem_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
}
@@ -625,9 +496,9 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
return LDB_ERR_OPERATIONS_ERROR;
}
- if (samldb_find_attribute(msg, "objectclass", "computer") != NULL) {
+ if (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL) {
- ret = samldb_copy_template(module, msg2, "(&(CN=TemplateComputer)(objectclass=userTemplate))");
+ ret = samdb_copy_template(module->ldb, msg2, "(&(CN=TemplateComputer)(objectclass=userTemplate))");
if (ret) {
ldb_debug(module->ldb, LDB_DEBUG_WARNING, "samldb_fill_user_or_computer_object: Error copying computer template!\n");
talloc_free(mem_ctx);
@@ -635,26 +506,29 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
}
/* readd user and then computer objectclasses */
- if ( ! samldb_find_or_add_value(module, msg2, "objectclass", "user", "user")) {
+ ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "user");
+ if (ret) {
talloc_free(mem_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
- if ( ! samldb_find_or_add_value(module, msg2, "objectclass", "computer", "computer")) {
+ ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "computer");
+ if (ret) {
talloc_free(mem_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
} else {
- ret = samldb_copy_template(module, msg2, "(&(CN=TemplateUser)(objectclass=userTemplate))");
+ ret = samdb_copy_template(module->ldb, msg2, "(&(CN=TemplateUser)(objectclass=userTemplate))");
if (ret) {
ldb_debug(module->ldb, LDB_DEBUG_WARNING, "samldb_fill_user_or_computer_object: Error copying user template!\n");
talloc_free(mem_ctx);
return ret;
}
/* readd user objectclass */
- if ( ! samldb_find_or_add_value(module, msg2, "objectclass", "user", "user")) {
+ ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "user");
+ if (ret) {
talloc_free(mem_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
}
@@ -672,9 +546,10 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
- if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", name)) {
+ ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name);
+ if (ret) {
talloc_free(mem_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
}
@@ -719,7 +594,7 @@ static int samldb_fill_foreignSecurityPrincipal_object(struct ldb_module *module
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = samldb_copy_template(module, msg2, "(&(CN=TemplateForeignSecurityPrincipal)(objectclass=foreignSecurityPrincipalTemplate))");
+ ret = samdb_copy_template(module->ldb, msg2, "(&(CN=TemplateForeignSecurityPrincipal)(objectclass=foreignSecurityPrincipalTemplate))");
if (ret != 0) {
ldb_debug(module->ldb, LDB_DEBUG_WARNING, "samldb_fill_foreignSecurityPrincipal_object: Error copying template!\n");
talloc_free(mem_ctx);
@@ -815,8 +690,8 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
}
/* is user or computer? */
- if ((samldb_find_attribute(msg, "objectclass", "user") != NULL) ||
- (samldb_find_attribute(msg, "objectclass", "computer") != NULL)) {
+ if ((samdb_find_attribute(module->ldb, msg, "objectclass", "user") != NULL) ||
+ (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL)) {
/* add all relevant missing objects */
ret = samldb_fill_user_or_computer_object(module, msg, &msg2);
if (ret) {
@@ -826,7 +701,7 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
/* is group? add all relevant missing objects */
if ( ! msg2 ) {
- if (samldb_find_attribute(msg, "objectclass", "group") != NULL) {
+ if (samdb_find_attribute(module->ldb, msg, "objectclass", "group") != NULL) {
ret = samldb_fill_group_object(module, msg, &msg2);
if (ret) {
return ret;
@@ -836,7 +711,7 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
/* perhaps a foreignSecurityPrincipal? */
if ( ! msg2 ) {
- if (samldb_find_attribute(msg, "objectclass", "foreignSecurityPrincipal") != NULL) {
+ if (samdb_find_attribute(module->ldb, msg, "objectclass", "foreignSecurityPrincipal") != NULL) {
ret = samldb_fill_foreignSecurityPrincipal_object(module, msg, &msg2);
if (ret) {
return ret;
diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c
index ba73a039af..2136294661 100644
--- a/source4/dsdb/samdb/samdb.c
+++ b/source4/dsdb/samdb/samdb.c
@@ -4,7 +4,9 @@
interface functions for the sam database
Copyright (C) Andrew Tridgell 2004
-
+ Copyright (C) Volker Lendecke 2004
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -25,6 +27,7 @@
#include "librpc/gen_ndr/ndr_misc.h"
#include "librpc/gen_ndr/ndr_security.h"
#include "lib/ldb/include/ldb.h"
+#include "lib/ldb/include/ldb_private.h"
#include "lib/ldb/include/ldb_errors.h"
#include "libcli/security/security.h"
#include "auth/credentials/credentials.h"
@@ -621,51 +624,121 @@ uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
return samdb_uf2acb(userAccountControl);
}
+
+/* Find an attribute, with a particular value */
+struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb,
+ const struct ldb_message *msg,
+ const char *name, const char *value)
+{
+ int i;
+ struct ldb_message_element *el = ldb_msg_find_element(msg, name);
+ struct ldb_val v;
+
+ v.data = discard_const_p(uint8_t, value);
+ v.length = strlen(value);
+
+ if (!el) {
+ return NULL;
+ }
+
+ for (i=0;i<el->num_values;i++) {
+ if (strcasecmp(value, (char *)el->values[i].data) == 0) {
+ return el;
+ }
+ }
+
+ return NULL;
+}
+
+int samdb_find_or_add_value(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
+{
+ if (samdb_find_attribute(ldb, msg, name, set_value) == NULL) {
+ return samdb_msg_add_string(ldb, msg, msg, name, set_value);
+ }
+ return LDB_SUCCESS;
+}
+
+int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
+{
+ struct ldb_message_element *el;
+
+ el = ldb_msg_find_element(msg, name);
+ if (el) {
+ return LDB_SUCCESS;
+ }
+
+ return samdb_msg_add_string(ldb, msg, msg, name, set_value);
+}
+
+
/*
copy from a template record to a message
*/
-int samdb_copy_template(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
- struct ldb_message *msg, const char *expression)
+int samdb_copy_template(struct ldb_context *ldb,
+ struct ldb_message *msg, const char *filter)
{
- struct ldb_message **res, *t;
+ struct ldb_result *res;
+ struct ldb_message *t;
int ret, i, j;
- struct ldb_dn *basedn = ldb_dn_explode(msg, "cn=Templates");
+ struct ldb_dn *basedn = ldb_dn_explode(ldb, "cn=Templates");
/* pull the template record */
- ret = gendb_search(sam_ldb, mem_ctx, basedn, &res, NULL, "%s", expression);
- if (ret != 1) {
- DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n",
- expression, ret));
- return -1;
+ ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, filter, NULL, &res);
+ talloc_free(basedn);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ if (res->count != 1) {
+ ldb_set_errstring(ldb, talloc_asprintf(ldb, "samdb_copy_template: ERROR: template '%s' matched %d records, expected 1\n", filter,
+ res->count));
+ talloc_free(res);
+ return LDB_ERR_OPERATIONS_ERROR;
}
- t = res[0];
+ t = res->msgs[0];
- for (i=0;i<t->num_elements;i++) {
+ for (i = 0; i < t->num_elements; i++) {
struct ldb_message_element *el = &t->elements[i];
/* some elements should not be copied from the template */
if (strcasecmp(el->name, "cn") == 0 ||
strcasecmp(el->name, "name") == 0 ||
- strcasecmp(el->name, "sAMAccountName") == 0) {
+ strcasecmp(el->name, "sAMAccountName") == 0 ||
+ strcasecmp(el->name, "objectGUID") == 0) {
continue;
}
- for (j=0;j<el->num_values;j++) {
- if (strcasecmp(el->name, "objectClass") == 0 &&
- (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
- strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "foreignSecurityTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 ||
- strcasecmp((char *)el->values[j].data, "secretTemplate") == 0)) {
- continue;
+ for (j = 0; j < el->num_values; j++) {
+ if (strcasecmp(el->name, "objectClass") == 0) {
+ if (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
+ strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
+ strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
+ strcasecmp((char *)el->values[j].data, "foreignSecurityPrincipalTemplate") == 0 ||
+ strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 ||
+ strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 ||
+ strcasecmp((char *)el->values[j].data, "secretTemplate") == 0) {
+ continue;
+ }
+ ret = samdb_find_or_add_value(ldb, msg, el->name,
+ (char *)el->values[j].data);
+ if (ret) {
+ ldb_set_errstring(ldb, talloc_asprintf(ldb, "Adding objectClass %s failed.\n", el->values[j].data));
+ talloc_free(res);
+ return ret;
+ }
+ } else {
+ ret = samdb_find_or_add_attribute(ldb, msg, el->name,
+ (char *)el->values[j].data);
+ if (ret) {
+ ldb_set_errstring(ldb, talloc_asprintf(ldb, "Adding attribute %s failed.\n", el->name));
+ talloc_free(res);
+ return ret;
+ }
}
- samdb_msg_add_string(sam_ldb, mem_ctx, msg, el->name,
- (char *)el->values[j].data);
}
}
- return 0;
+ talloc_free(res);
+
+ return LDB_SUCCESS;
}
@@ -678,7 +751,7 @@ int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc
char *s = talloc_strdup(mem_ctx, str);
char *a = talloc_strdup(mem_ctx, attr_name);
if (s == NULL || a == NULL) {
- return -1;
+ return LDB_ERR_OPERATIONS_ERROR;
}
return ldb_msg_add_string(msg, a, s);
}
@@ -1446,3 +1519,58 @@ NTSTATUS security_token_create(TALLOC_CTX *mem_ctx,
}
+NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
+ struct dom_sid *sid, struct ldb_dn **ret_dn)
+{
+ struct ldb_message *msg;
+ struct ldb_dn *basedn;
+ const char *sidstr;
+ int ret;
+
+ sidstr = dom_sid_string(mem_ctx, sid);
+ NT_STATUS_HAVE_NO_MEMORY(sidstr);
+
+ /* We might have to create a ForeignSecurityPrincipal, even if this user
+ * is in our own domain */
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* TODO: Hmmm. This feels wrong. How do I find the base dn to
+ * put the ForeignSecurityPrincipals? d_state->domain_dn does
+ * not work, this is wrong for the Builtin domain, there's no
+ * cn=For...,cn=Builtin,dc={BASEDN}. -- vl
+ */
+
+ basedn = samdb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(mem_ctx),
+ "(&(objectClass=container)(cn=ForeignSecurityPrincipals))");
+
+ if (basedn == NULL) {
+ DEBUG(0, ("Failed to find DN for "
+ "ForeignSecurityPrincipal container\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ /* add core elements to the ldb_message for the alias */
+ msg->dn = ldb_dn_build_child(mem_ctx, "CN", sidstr, basedn);
+ if (msg->dn == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ samdb_msg_add_string(sam_ctx, mem_ctx, msg,
+ "objectClass",
+ "foreignSecurityPrincipal");
+
+ /* create the alias */
+ ret = samdb_add(sam_ctx, mem_ctx, msg);
+ if (ret != 0) {
+ DEBUG(0,("Failed to create foreignSecurityPrincipal "
+ "record %s: %s\n",
+ ldb_dn_linearize(mem_ctx, msg->dn),
+ ldb_errstring(sam_ctx)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ *ret_dn = msg->dn;
+ return NT_STATUS_OK;
+}
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);
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 40d562fc0c..e36c0e96ea 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -2527,6 +2527,7 @@ static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_C
const char * const attrs[] = { NULL };
struct ldb_dn *memberdn = NULL;
int ret;
+ NTSTATUS status;
DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
@@ -2544,58 +2545,13 @@ static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_C
ret, dom_sid_string(mem_ctx, r->in.sid)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else if (ret == 0) {
- struct ldb_message *msg;
- struct ldb_dn *basedn;
- const char *sidstr;
-
- sidstr = dom_sid_string(mem_ctx, r->in.sid);
- NT_STATUS_HAVE_NO_MEMORY(sidstr);
-
- /* We might have to create a ForeignSecurityPrincipal, even if this user
- * is in our own domain */
-
- msg = ldb_msg_new(mem_ctx);
- if (msg == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* TODO: Hmmm. This feels wrong. How do I find the base dn to
- * put the ForeignSecurityPrincipals? d_state->domain_dn does
- * not work, this is wrong for the Builtin domain, there's no
- * cn=For...,cn=Builtin,dc={BASEDN}. -- vl
- */
-
- basedn = samdb_search_dn(d_state->sam_ctx, mem_ctx, samdb_base_dn(mem_ctx),
- "(&(objectClass=container)(cn=ForeignSecurityPrincipals))");
-
- if (basedn == NULL) {
- DEBUG(0, ("Failed to find DN for "
- "ForeignSecurityPrincipal container\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- /* add core elements to the ldb_message for the alias */
- msg->dn = ldb_dn_build_child(mem_ctx, "CN", sidstr, basedn);
- if (msg->dn == NULL)
- return NT_STATUS_NO_MEMORY;
-
- memberdn = msg->dn;
-
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg,
- "objectClass",
- "foreignSecurityPrincipal");
-
- /* create the alias */
- ret = samdb_add(d_state->sam_ctx, mem_ctx, msg);
- if (ret != 0) {
- DEBUG(0,("Failed to create foreignSecurityPrincipal "
- "record %s: %s\n",
- ldb_dn_linearize(mem_ctx, msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ status = samdb_create_foreign_security_principal(d_state->sam_ctx, mem_ctx,
+ r->in.sid, &memberdn);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
} else {
- DEBUG(0, ("samdb_search returned %d\n", ret));
+ DEBUG(0, ("samdb_search returned %d: %s\n", ret, ldb_errstring(d_state->sam_ctx)));
}
if (memberdn == NULL) {
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 24f7bbbd01..099dd41430 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -1178,7 +1178,8 @@ static BOOL test_EnumAccountRights(struct dcerpc_pipe *p,
status = dcerpc_lsa_EnumAccountRights(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("EnumAccountRights failed - %s\n", nt_errstr(status));
+ printf("EnumAccountRights of %s failed - %s\n",
+ dom_sid_string(mem_ctx, sid), nt_errstr(status));
return False;
}
@@ -1194,6 +1195,11 @@ static BOOL test_QuerySecurity(struct dcerpc_pipe *p,
NTSTATUS status;
struct lsa_QuerySecurity r;
+ if (lp_parm_bool(-1, "target", "samba4", False)) {
+ printf("skipping QuerySecurity test against Samba4\n");
+ return True;
+ }
+
printf("Testing QuerySecurity\n");
r.in.handle = acct_handle;
@@ -1250,6 +1256,7 @@ static BOOL test_EnumAccounts(struct dcerpc_pipe *p,
struct lsa_SidArray sids1, sids2;
uint32_t resume_handle = 0;
int i;
+ BOOL ret = True;
printf("\ntesting EnumAccounts\n");
@@ -1284,14 +1291,14 @@ static BOOL test_EnumAccounts(struct dcerpc_pipe *p,
printf("testing all accounts\n");
for (i=0;i<sids1.num_sids;i++) {
- test_OpenAccount(p, mem_ctx, handle, sids1.sids[i].sid);
- test_EnumAccountRights(p, mem_ctx, handle, sids1.sids[i].sid);
+ ret &= test_OpenAccount(p, mem_ctx, handle, sids1.sids[i].sid);
+ ret &= test_EnumAccountRights(p, mem_ctx, handle, sids1.sids[i].sid);
}
printf("\n");
}
if (sids1.num_sids < 3) {
- return True;
+ return ret;
}
printf("trying EnumAccounts partial listing (asking for 1 at 2)\n");
@@ -1580,8 +1587,12 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p,
return False;
}
- ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains);
-
+ if (lp_parm_bool(-1, "target", "samba4", False)) {
+ printf("skipping 'each' Trusted Domains tests against Samba4\n");
+ } else {
+ ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains);
+ }
+
} while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)));
return ret;
@@ -1666,6 +1677,11 @@ static BOOL test_QueryDomainInfoPolicy(struct dcerpc_pipe *p,
NTSTATUS status;
int i;
BOOL ret = True;
+ if (lp_parm_bool(-1, "target", "samba4", False)) {
+ printf("skipping QueryDomainInformationPolicy test against Samba4\n");
+ return True;
+ }
+
printf("\nTesting QueryDomainInformationPolicy\n");
for (i=2;i<4;i++) {
@@ -1697,6 +1713,11 @@ static BOOL test_QueryInfoPolicy(struct dcerpc_pipe *p,
BOOL ret = True;
printf("\nTesting QueryInfoPolicy\n");
+ if (lp_parm_bool(-1, "target", "samba4", False)) {
+ printf("skipping QueryInfoPolicy2 against Samba4\n");
+ return True;
+ }
+
for (i=1;i<13;i++) {
r.in.handle = handle;
r.in.level = i;
@@ -1730,6 +1751,10 @@ static BOOL test_QueryInfoPolicy2(struct dcerpc_pipe *p,
int i;
BOOL ret = True;
printf("\nTesting QueryInfoPolicy2\n");
+ if (lp_parm_bool(-1, "target", "samba4", False)) {
+ printf("skipping QueryInfoPolicy2 against Samba4\n");
+ return True;
+ }
for (i=1;i<13;i++) {
r.in.handle = handle;