Copyright (C) Andrew Tridgell 2004
Copyright (C) Volker Lendecke 2004
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+ Copyright (C) Matthias Dieter Wallnöfer 2009
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
#include "system/time.h"
#include "lib/ldb/include/ldb.h"
#include "lib/ldb/include/ldb_errors.h"
-#include "dsdb/common/flags.h"
+#include "../libds/common/flags.h"
#include "dsdb/samdb/samdb.h"
+#include "dsdb/common/util.h"
#include "libcli/ldap/ldap_ndr.h"
#include "libcli/security/security.h"
#include "rpc_server/samr/proto.h"
#include "../lib/util/util_ldb.h"
#include "param/param.h"
+#include "lib/util/tsort.h"
/* these query macros make samr_Query[User|Group|Alias]Info a bit easier to read */
struct ldb_message_element *set_el; \
if (r->in.info->field.string == NULL) return NT_STATUS_INVALID_PARAMETER; \
if (r->in.info->field.string[0] == '\0') { \
- if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, NULL)) { \
+ if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, NULL) != LDB_SUCCESS) { \
return NT_STATUS_NO_MEMORY; \
} \
} \
- if (ldb_msg_add_string(msg, attr, r->in.info->field.string) != 0) { \
+ if (ldb_msg_add_string(msg, attr, r->in.info->field.string) != LDB_SUCCESS) { \
return NT_STATUS_NO_MEMORY; \
} \
set_el = ldb_msg_find_element(msg, attr); \
#define SET_UINT(msg, field, attr) do { \
struct ldb_message_element *set_el; \
- if (samdb_msg_add_uint(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
+ if (samdb_msg_add_uint(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != LDB_SUCCESS) { \
return NT_STATUS_NO_MEMORY; \
} \
set_el = ldb_msg_find_element(msg, attr); \
#define SET_INT64(msg, field, attr) do { \
struct ldb_message_element *set_el; \
- if (samdb_msg_add_int64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
+ if (samdb_msg_add_int64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != LDB_SUCCESS) { \
return NT_STATUS_NO_MEMORY; \
} \
set_el = ldb_msg_find_element(msg, attr); \
#define SET_UINT64(msg, field, attr) do { \
struct ldb_message_element *set_el; \
- if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
+ if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != LDB_SUCCESS) { \
return NT_STATUS_NO_MEMORY; \
} \
set_el = ldb_msg_find_element(msg, attr); \
#define SET_LHOURS(msg, field, attr) do { \
struct ldb_message_element *set_el; \
- if (samdb_msg_add_logon_hours(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
+ if (samdb_msg_add_logon_hours(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != LDB_SUCCESS) { \
return NT_STATUS_NO_MEMORY; \
} \
set_el = ldb_msg_find_element(msg, attr); \
#define SET_PARAMETERS(msg, field, attr) do { \
struct ldb_message_element *set_el; \
- if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
- return NT_STATUS_NO_MEMORY; \
+ if (r->in.info->field.length != 0) { \
+ if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != LDB_SUCCESS) { \
+ return NT_STATUS_NO_MEMORY; \
+ } \
+ set_el = ldb_msg_find_element(msg, attr); \
+ set_el->flags = LDB_FLAG_MOD_REPLACE; \
} \
- set_el = ldb_msg_find_element(msg, attr); \
- set_el->flags = LDB_FLAG_MOD_REPLACE; \
} while (0)
ZERO_STRUCTP(r->out.connect_handle);
- c_state = talloc(dce_call->conn, struct samr_connect_state);
+ c_state = talloc(mem_ctx, struct samr_connect_state);
if (!c_state) {
return NT_STATUS_NO_MEMORY;
}
/* make sure the sam database is accessible */
- c_state->sam_ctx = samdb_connect(c_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
+ c_state->sam_ctx = samdb_connect(c_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
if (c_state->sam_ctx == NULL) {
talloc_free(c_state);
return NT_STATUS_INVALID_SYSTEM_SERVICE;
struct dcesrv_handle *h;
struct dom_sid *sid;
const char * const dom_attrs[] = { "objectSid", NULL};
- const char * const ref_attrs[] = { "ncName", NULL};
struct ldb_message **dom_msgs;
- struct ldb_message **ref_msgs;
int ret;
- struct ldb_dn *partitions_basedn;
*r->out.sid = NULL;
return NT_STATUS_INVALID_PARAMETER;
}
- partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
-
if (strcasecmp(r->in.domain_name->string, "BUILTIN") == 0) {
ret = gendb_search(c_state->sam_ctx,
mem_ctx, NULL, &dom_msgs, dom_attrs,
"(objectClass=builtinDomain)");
- } else {
- ret = gendb_search(c_state->sam_ctx,
- mem_ctx, partitions_basedn, &ref_msgs, ref_attrs,
- "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
- ldb_binary_encode_string(mem_ctx, r->in.domain_name->string));
- if (ret != 1) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- ret = gendb_search_dn(c_state->sam_ctx, mem_ctx,
- samdb_result_dn(c_state->sam_ctx, mem_ctx,
- ref_msgs[0], "ncName", NULL),
+ } else if (strcasecmp_m(r->in.domain_name->string, lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx)) == 0) {
+ ret = gendb_search_dn(c_state->sam_ctx,
+ mem_ctx, ldb_get_default_basedn(c_state->sam_ctx),
&dom_msgs, dom_attrs);
+ } else {
+ return NT_STATUS_NO_SUCH_DOMAIN;
}
-
if (ret != 1) {
return NT_STATUS_NO_SUCH_DOMAIN;
}
struct samr_connect_state *c_state;
struct dcesrv_handle *h;
struct samr_SamArray *array;
- int i, start_i, ret;
- const char * const dom_attrs[] = { "cn", NULL};
- const char * const ref_attrs[] = { "nETBIOSName", NULL};
- struct ldb_result *dom_res;
- struct ldb_result *ref_res;
- struct ldb_dn *partitions_basedn;
+ uint32_t i, start_i;
*r->out.resume_handle = 0;
*r->out.sam = NULL;
c_state = h->data;
- partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
-
- ret = ldb_search(c_state->sam_ctx, mem_ctx, &dom_res, ldb_get_default_basedn(c_state->sam_ctx),
- LDB_SCOPE_SUBTREE, dom_attrs, "(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain))");
- if (ret != LDB_SUCCESS) {
- DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- *r->out.resume_handle = dom_res->count;
+ *r->out.resume_handle = 2;
start_i = *r->in.resume_handle;
- if (start_i >= dom_res->count) {
+ if (start_i >= 2) {
/* search past end of list is not an error for this call */
return NT_STATUS_OK;
}
array->count = 0;
array->entries = NULL;
- array->entries = talloc_array(mem_ctx, struct samr_SamEntry, dom_res->count - start_i);
+ array->entries = talloc_array(mem_ctx, struct samr_SamEntry, 2 - start_i);
if (array->entries == NULL) {
return NT_STATUS_NO_MEMORY;
}
- for (i=0;i<dom_res->count-start_i;i++) {
+ for (i=0;i<2-start_i;i++) {
array->entries[i].idx = start_i + i;
- /* try and find the domain */
- ret = ldb_search(c_state->sam_ctx, mem_ctx, &ref_res, partitions_basedn,
- LDB_SCOPE_SUBTREE, ref_attrs, "(&(objectClass=crossRef)(ncName=%s))",
- ldb_dn_get_linearized(dom_res->msgs[i]->dn));
-
- if (ret != LDB_SUCCESS) {
- DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- if (ref_res->count == 1) {
- array->entries[i].name.string = samdb_result_string(ref_res->msgs[0], "nETBIOSName", NULL);
+ if (i == 0) {
+ array->entries[i].name.string = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
} else {
- array->entries[i].name.string = samdb_result_string(dom_res->msgs[i], "cn", NULL);
+ array->entries[i].name.string = "BUILTIN";
}
}
struct samr_OpenDomain *r)
{
struct dcesrv_handle *h_conn, *h_domain;
- const char *domain_name;
struct samr_connect_state *c_state;
struct samr_domain_state *d_state;
const char * const dom_attrs[] = { "cn", NULL};
- const char * const ref_attrs[] = { "nETBIOSName", NULL};
struct ldb_message **dom_msgs;
- struct ldb_message **ref_msgs;
int ret;
- struct ldb_dn *partitions_basedn;
ZERO_STRUCTP(r->out.domain_handle);
return NT_STATUS_INVALID_PARAMETER;
}
- partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
+ d_state = talloc(mem_ctx, struct samr_domain_state);
+ if (!d_state) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ d_state->domain_sid = talloc_steal(d_state, r->in.sid);
+
+ if (dom_sid_equal(d_state->domain_sid, dom_sid_parse_talloc(mem_ctx, SID_BUILTIN))) {
+ d_state->builtin = true;
+ d_state->domain_name = "BUILTIN";
+ } else {
+ d_state->builtin = false;
+ d_state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
+ }
ret = gendb_search(c_state->sam_ctx,
- mem_ctx, NULL, &dom_msgs, dom_attrs,
- "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))",
+ mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), &dom_msgs, dom_attrs,
+ "(objectSid=%s)",
ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
+
if (ret == 0) {
+ talloc_free(d_state);
return NT_STATUS_NO_SUCH_DOMAIN;
} else if (ret > 1) {
+ talloc_free(d_state);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else if (ret == -1) {
+ talloc_free(d_state);
DEBUG(1, ("Failed to open domain %s: %s\n", dom_sid_string(mem_ctx, r->in.sid), ldb_errstring(c_state->sam_ctx)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
- } else {
- ret = gendb_search(c_state->sam_ctx,
- mem_ctx, partitions_basedn, &ref_msgs, ref_attrs,
- "(&(&(nETBIOSName=*)(objectclass=crossRef))(ncName=%s))",
- ldb_dn_get_linearized(dom_msgs[0]->dn));
- if (ret == 0) {
- domain_name = ldb_msg_find_attr_as_string(dom_msgs[0], "cn", NULL);
- if (domain_name == NULL) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
- } else if (ret == 1) {
-
- domain_name = ldb_msg_find_attr_as_string(ref_msgs[0], "nETBIOSName", NULL);
- if (domain_name == NULL) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
- } else {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
- }
-
- d_state = talloc(c_state, struct samr_domain_state);
- if (!d_state) {
- return NT_STATUS_NO_MEMORY;
}
- d_state->role = lp_server_role(dce_call->conn->dce_ctx->lp_ctx);
+ d_state->domain_dn = talloc_steal(d_state, dom_msgs[0]->dn);
+ d_state->role = lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx);
d_state->connect_state = talloc_reference(d_state, c_state);
d_state->sam_ctx = c_state->sam_ctx;
- d_state->domain_sid = dom_sid_dup(d_state, r->in.sid);
- d_state->domain_name = talloc_strdup(d_state, domain_name);
- d_state->domain_dn = ldb_dn_copy(d_state, dom_msgs[0]->dn);
- if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) {
- talloc_free(d_state);
- return NT_STATUS_NO_MEMORY;
- }
d_state->access_mask = r->in.access_mask;
- if (dom_sid_equal(d_state->domain_sid, dom_sid_parse_talloc(mem_ctx, SID_BUILTIN))) {
- d_state->builtin = true;
- } else {
- d_state->builtin = false;
- }
-
d_state->lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
h_domain = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_DOMAIN);
info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, dom_msgs[0], "fSMORoleOwner");
if (!info->primary.string) {
- info->primary.string = lp_netbios_name(state->lp_ctx);
+ info->primary.string = lpcfg_netbios_name(state->lp_ctx);
}
info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff",
}
/* No users in BUILTIN, and the LOCAL group types are only in builtin, and the global group type is never in BUILTIN */
- info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
+ info->num_users = samdb_search_count(state->sam_ctx, state->domain_dn,
"(objectClass=user)");
- info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
- "(&(objectClass=group)(sAMAccountType=%u))",
- ATYPE_GLOBAL_GROUP);
- info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
- "(&(objectClass=group)(sAMAccountType=%u))",
- ATYPE_LOCAL_GROUP);
+ info->num_groups = samdb_search_count(state->sam_ctx, state->domain_dn,
+ "(&(objectClass=group)(groupType=%u))",
+ GTYPE_SECURITY_GLOBAL_GROUP);
+ info->num_aliases = samdb_search_count(state->sam_ctx, state->domain_dn,
+ "(&(objectClass=group)(groupType=%u))",
+ GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
return NT_STATUS_OK;
}
dom_msgs[0], "fSMORoleOwner");
if (!info->primary.string) {
- info->primary.string = lp_netbios_name(state->lp_ctx);
+ info->primary.string = lpcfg_netbios_name(state->lp_ctx);
}
return NT_STATUS_OK;
d_state = h->data;
- info = talloc(mem_ctx, union samr_DomainInfo);
- if (!info) {
- return NT_STATUS_NO_MEMORY;
- }
-
switch (r->in.level) {
case 1:
{
- static const char * const attrs2[] = { "minPwdLength", "pwdHistoryLength",
- "pwdProperties", "maxPwdAge",
- "minPwdAge", NULL };
+ static const char * const attrs2[] = { "minPwdLength",
+ "pwdHistoryLength",
+ "pwdProperties",
+ "maxPwdAge",
+ "minPwdAge",
+ NULL };
attrs = attrs2;
break;
}
break;
}
case 9:
+ {
attrs = NULL;
- break;
+ break;
+ }
case 11:
{
- static const char * const attrs2[] = { "oEMInformation", "forceLogoff",
+ static const char * const attrs2[] = { "oEMInformation",
+ "forceLogoff",
"modifiedCount",
"lockoutDuration",
"lockOutObservationWindow",
attrs = attrs2;
break;
}
+ default:
+ {
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
}
/* some levels don't need a search */
int ret;
ret = gendb_search_dn(d_state->sam_ctx, mem_ctx,
d_state->domain_dn, &dom_msgs, attrs);
+ if (ret == 0) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
- *r->out.info = info;
+ /* allocate the info structure */
+ info = talloc_zero(mem_ctx, union samr_DomainInfo);
+ if (info == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- ZERO_STRUCTP(info);
+ *r->out.info = info;
switch (r->in.level) {
case 1:
case 13:
return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs,
&info->info13);
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
}
-
- return NT_STATUS_INVALID_INFO_CLASS;
}
return NT_STATUS_OK;
case 12:
-
+ /*
+ * It is not possible to set lockout_duration < lockout_window.
+ * (The test is the other way around since the negative numbers
+ * are stored...)
+ *
+ * TODO:
+ * This check should be moved to the backend, i.e. to some
+ * ldb module under dsdb/samdb/ldb_modules/ .
+ *
+ * This constraint is documented here for the samr rpc service:
+ * MS-SAMR 3.1.1.6 Attribute Constraints for Originating Updates
+ * http://msdn.microsoft.com/en-us/library/cc245667%28PROT.10%29.aspx
+ *
+ * And here for the ldap backend:
+ * MS-ADTS 3.1.1.5.3.2 Constraints
+ * http://msdn.microsoft.com/en-us/library/cc223462(PROT.10).aspx
+ */
+ if (r->in.info->info12.lockout_duration >
+ r->in.info->info12.lockout_window)
+ {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
SET_INT64 (msg, info12.lockout_duration, "lockoutDuration");
SET_INT64 (msg, info12.lockout_window, "lockOutObservationWindow");
SET_INT64 (msg, info12.lockout_threshold, "lockoutThreshold");
/* modify the samdb record */
ret = ldb_modify(sam_ctx, msg);
- if (ret != 0) {
+ if (ret != LDB_SUCCESS) {
DEBUG(1,("Failed to modify record %s: %s\n",
ldb_dn_get_linearized(d_state->domain_dn),
ldb_errstring(sam_ctx)));
static NTSTATUS dcesrv_samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_CreateDomainGroup *r)
{
+ NTSTATUS status;
struct samr_domain_state *d_state;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
- const char *name;
- struct ldb_message *msg;
- struct dom_sid *sid;
const char *groupname;
+ struct dom_sid *group_sid;
+ struct ldb_dn *group_dn;
struct dcesrv_handle *g_handle;
- int ret;
ZERO_STRUCTP(r->out.group_handle);
*r->out.rid = 0;
return NT_STATUS_INVALID_PARAMETER;
}
- /* check if the group already exists */
- name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
- "sAMAccountName",
- "(&(sAMAccountName=%s)(objectclass=group))",
- ldb_binary_encode_string(mem_ctx, groupname));
- if (name != NULL) {
- return NT_STATUS_GROUP_EXISTS;
- }
-
- msg = ldb_msg_new(mem_ctx);
- if (msg == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* add core elements to the ldb_message for the user */
- msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
- ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", groupname);
- if (!msg->dn) {
- return NT_STATUS_NO_MEMORY;
- }
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", groupname);
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
-
- /* create the group */
- ret = ldb_add(d_state->sam_ctx, msg);
- switch (ret) {
- case LDB_SUCCESS:
- break;
- case LDB_ERR_ENTRY_ALREADY_EXISTS:
- DEBUG(0,("Failed to create group record %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_GROUP_EXISTS;
- case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
- DEBUG(0,("Failed to create group record %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_ACCESS_DENIED;
- default:
- DEBUG(0,("Failed to create group record %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ status = dsdb_add_domain_group(d_state->sam_ctx, mem_ctx, groupname, &group_sid, &group_dn);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- a_state = talloc(d_state, struct samr_account_state);
+ a_state = talloc(mem_ctx, struct samr_account_state);
if (!a_state) {
return NT_STATUS_NO_MEMORY;
}
a_state->sam_ctx = d_state->sam_ctx;
a_state->access_mask = r->in.access_mask;
a_state->domain_state = talloc_reference(a_state, d_state);
- a_state->account_dn = talloc_steal(a_state, msg->dn);
+ a_state->account_dn = talloc_steal(a_state, group_dn);
- /* retrieve the sid for the group just created */
- sid = samdb_search_dom_sid(d_state->sam_ctx, a_state,
- msg->dn, "objectSid", NULL);
- if (sid == NULL) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- a_state->account_name = talloc_strdup(a_state, groupname);
- if (!a_state->account_name) {
- return NT_STATUS_NO_MEMORY;
- }
+ a_state->account_name = talloc_steal(a_state, groupname);
/* create the policy handle */
g_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_GROUP);
g_handle->data = talloc_steal(g_handle, a_state);
*r->out.group_handle = g_handle->wire_handle;
- *r->out.rid = sid->sub_auths[sid->num_auths-1];
+ *r->out.rid = group_sid->sub_auths[group_sid->num_auths-1];
return NT_STATUS_OK;
}
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
struct ldb_message **res;
- int ldb_cnt, count, i, first;
+ int i, ldb_cnt;
+ uint32_t first, count;
struct samr_SamEntry *entries;
- const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
+ const char * const attrs[] = { "objectSid", "sAMAccountName", NULL };
struct samr_SamArray *sam;
*r->out.resume_handle = 0;
ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
d_state->domain_dn, &res, attrs,
d_state->domain_sid,
- "(&(grouptype=%d)(objectclass=group))",
+ "(&(|(groupType=%d)(groupType=%d))(objectClass=group))",
+ GTYPE_SECURITY_UNIVERSAL_GROUP,
GTYPE_SECURITY_GLOBAL_GROUP);
- if (ldb_cnt == -1) {
+ if (ldb_cnt < 0) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
group_sid = samdb_result_dom_sid(mem_ctx, res[i],
"objectSid");
- if (group_sid == NULL)
- continue;
+ if (group_sid == NULL) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
entries[count].idx =
group_sid->sub_auths[group_sid->num_auths-1];
}
/* sort the results by rid */
- qsort(entries, count, sizeof(struct samr_SamEntry),
- (comparison_fn_t)compare_SamEntry);
+ TYPESAFE_QSORT(entries, count, compare_SamEntry);
/* find the first entry to return */
for (first=0;
first<count && entries[first].idx <= *r->in.resume_handle;
first++) ;
- /* return the rest, limit by max_size. Note that we
+ /* return the rest, limit by max_size. Note that we
use the w2k3 element size value of 54 */
*r->out.num_entries = count - first;
*r->out.num_entries = MIN(*r->out.num_entries,
*r->out.sam = sam;
+ if (first == count) {
+ return NT_STATUS_OK;
+ }
+
if (*r->out.num_entries < count - first) {
*r->out.resume_handle = entries[first+*r->out.num_entries-1].idx;
return STATUS_MORE_ENTRIES;
static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_CreateUser2 *r)
{
+ NTSTATUS status;
struct samr_domain_state *d_state;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
- const char *name;
- struct ldb_message *msg;
+ struct ldb_dn *dn;
struct dom_sid *sid;
- const char *account_name;
struct dcesrv_handle *u_handle;
- int ret;
- const char *container, *obj_class=NULL;
- char *cn_name;
- int cn_name_len;
-
- const char *attrs[] = {
- "objectSid",
- "userAccountControl",
- NULL
- };
-
- uint32_t user_account_control;
-
- struct ldb_message **msgs;
+ const char *account_name;
ZERO_STRUCTP(r->out.user_handle);
*r->out.access_granted = 0;
if (d_state->builtin) {
DEBUG(5, ("Cannot create a user in the BUILTIN domain"));
return NT_STATUS_ACCESS_DENIED;
+ } else if (r->in.acct_flags == ACB_DOMTRUST) {
+ /* Domain trust accounts must be created by the LSA calls */
+ return NT_STATUS_ACCESS_DENIED;
}
account_name = r->in.account_name->string;
return NT_STATUS_INVALID_PARAMETER;
}
- ret = ldb_transaction_start(d_state->sam_ctx);
- if (ret != 0) {
- DEBUG(0,("Failed to start a transaction for user creation: %s\n",
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- /* check if the user already exists */
- name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
- "sAMAccountName",
- "(&(sAMAccountName=%s)(objectclass=user))",
- ldb_binary_encode_string(mem_ctx, account_name));
- if (name != NULL) {
- ldb_transaction_cancel(d_state->sam_ctx);
- return NT_STATUS_USER_EXISTS;
- }
-
- msg = ldb_msg_new(mem_ctx);
- if (msg == NULL) {
- ldb_transaction_cancel(d_state->sam_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- cn_name = talloc_strdup(mem_ctx, account_name);
- if (!cn_name) {
- ldb_transaction_cancel(d_state->sam_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- cn_name_len = strlen(cn_name);
-
- /* This must be one of these values *only* */
- if (r->in.acct_flags == ACB_NORMAL) {
- container = "CN=Users";
- obj_class = "user";
-
- } else if (r->in.acct_flags == ACB_WSTRUST) {
- if (cn_name[cn_name_len - 1] != '$') {
- return NT_STATUS_FOOBAR;
- }
- cn_name[cn_name_len - 1] = '\0';
- container = "CN=Computers";
- obj_class = "computer";
- samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DOMAIN_MEMBERS);
-
- } else if (r->in.acct_flags == ACB_SVRTRUST) {
- if (cn_name[cn_name_len - 1] != '$') {
- return NT_STATUS_FOOBAR;
- }
- cn_name[cn_name_len - 1] = '\0';
- container = "OU=Domain Controllers";
- obj_class = "computer";
- samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DCS);
-
- } else if (r->in.acct_flags == ACB_DOMTRUST) {
- container = "CN=Users";
- obj_class = "user";
-
- } else {
- ldb_transaction_cancel(d_state->sam_ctx);
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* add core elements to the ldb_message for the user */
- msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
- if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s,%s", cn_name, container)) {
- ldb_transaction_cancel(d_state->sam_ctx);
- return NT_STATUS_FOOBAR;
- }
-
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", account_name);
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", obj_class);
-
- /* Start a transaction, so we can query and do a subsequent atomic modify */
-
- /* create the user */
- ret = ldb_add(d_state->sam_ctx, msg);
- switch (ret) {
- case LDB_SUCCESS:
- break;
- case LDB_ERR_ENTRY_ALREADY_EXISTS:
- ldb_transaction_cancel(d_state->sam_ctx);
- DEBUG(0,("Failed to create user record %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_USER_EXISTS;
- case LDB_ERR_UNWILLING_TO_PERFORM:
- case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
- ldb_transaction_cancel(d_state->sam_ctx);
- DEBUG(0,("Failed to create user record %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_ACCESS_DENIED;
- default:
- ldb_transaction_cancel(d_state->sam_ctx);
- DEBUG(0,("Failed to create user record %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ status = dsdb_add_user(d_state->sam_ctx, mem_ctx, account_name, r->in.acct_flags, &sid, &dn);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
-
- a_state = talloc(d_state, struct samr_account_state);
+ a_state = talloc(mem_ctx, struct samr_account_state);
if (!a_state) {
ldb_transaction_cancel(d_state->sam_ctx);
return NT_STATUS_NO_MEMORY;
a_state->sam_ctx = d_state->sam_ctx;
a_state->access_mask = r->in.access_mask;
a_state->domain_state = talloc_reference(a_state, d_state);
- a_state->account_dn = talloc_steal(a_state, msg->dn);
-
- /* retrieve the sid and account control bits for the user just created */
- ret = gendb_search_dn(d_state->sam_ctx, a_state,
- msg->dn, &msgs, attrs);
-
- if (ret != 1) {
- ldb_transaction_cancel(d_state->sam_ctx);
- DEBUG(0,("Apparently we failed to create an account record, as %s now doesn't exist\n",
- ldb_dn_get_linearized(msg->dn)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
- sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid");
- if (sid == NULL) {
- ldb_transaction_cancel(d_state->sam_ctx);
- DEBUG(0,("Apparently we failed to get the objectSid of the just created account record %s\n",
- ldb_dn_get_linearized(msg->dn)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- /* Change the account control to be the correct account type.
- * The default is for a workstation account */
- user_account_control = samdb_result_uint(msgs[0], "userAccountControl", 0);
- user_account_control = (user_account_control &
- ~(UF_NORMAL_ACCOUNT |
- UF_INTERDOMAIN_TRUST_ACCOUNT |
- UF_WORKSTATION_TRUST_ACCOUNT |
- UF_SERVER_TRUST_ACCOUNT));
- user_account_control |= samdb_acb2uf(r->in.acct_flags);
-
- talloc_free(msg);
- msg = ldb_msg_new(mem_ctx);
- if (msg == NULL) {
- ldb_transaction_cancel(d_state->sam_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- msg->dn = ldb_dn_copy(msg, a_state->account_dn);
-
- if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, msg,
- "userAccountControl",
- user_account_control) != 0) {
- ldb_transaction_cancel(d_state->sam_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- /* modify the samdb record */
- ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
- if (ret != 0) {
- DEBUG(0,("Failed to modify account record %s to set userAccountControl: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- ldb_transaction_cancel(d_state->sam_ctx);
-
- /* we really need samdb.c to return NTSTATUS */
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- ret = ldb_transaction_commit(d_state->sam_ctx);
- if (ret != 0) {
- DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
+ a_state->account_dn = talloc_steal(a_state, dn);
a_state->account_name = talloc_steal(a_state, account_name);
if (!a_state->account_name) {
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
- struct ldb_result *res;
- int ret, num_filtered_entries, i, first;
+ struct ldb_message **res;
+ int i, ldb_cnt;
+ uint32_t first, count;
struct samr_SamEntry *entries;
- const char * const attrs[] = { "objectSid", "sAMAccountName", "userAccountControl", NULL };
+ const char * const attrs[] = { "objectSid", "sAMAccountName",
+ "userAccountControl", NULL };
struct samr_SamArray *sam;
*r->out.resume_handle = 0;
d_state = h->data;
- /* don't have to worry about users in the builtin domain, as there are none */
- ret = ldb_search(d_state->sam_ctx, mem_ctx, &res, d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=user");
-
- if (ret != LDB_SUCCESS) {
- DEBUG(3, ("Failed to search for Domain Users in %s: %s\n",
- ldb_dn_get_linearized(d_state->domain_dn), ldb_errstring(d_state->sam_ctx)));
+ /* search for all domain users in this domain. This could possibly be
+ cached and resumed on resume_key */
+ ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
+ d_state->domain_dn,
+ &res, attrs,
+ d_state->domain_sid,
+ "(objectClass=user)");
+ if (ldb_cnt < 0) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/* convert to SamEntry format */
- entries = talloc_array(mem_ctx, struct samr_SamEntry, res->count);
+ entries = talloc_array(mem_ctx, struct samr_SamEntry, ldb_cnt);
if (!entries) {
return NT_STATUS_NO_MEMORY;
}
- num_filtered_entries = 0;
- for (i=0;i<res->count;i++) {
+
+ count = 0;
+
+ for (i=0;i<ldb_cnt;i++) {
/* Check if a mask has been requested */
if (r->in.acct_flags
- && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, res->msgs[i],
- d_state->domain_dn) & r->in.acct_flags) == 0)) {
+ && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
+ res[i], d_state->domain_dn) & r->in.acct_flags) == 0)) {
continue;
}
- entries[num_filtered_entries].idx = samdb_result_rid_from_sid(mem_ctx, res->msgs[i], "objectSid", 0);
- entries[num_filtered_entries].name.string = samdb_result_string(res->msgs[i], "sAMAccountName", "");
- num_filtered_entries++;
+ entries[count].idx = samdb_result_rid_from_sid(mem_ctx, res[i],
+ "objectSid", 0);
+ entries[count].name.string = samdb_result_string(res[i],
+ "sAMAccountName", "");
+ count += 1;
}
/* sort the results by rid */
- qsort(entries, num_filtered_entries, sizeof(struct samr_SamEntry),
- (comparison_fn_t)compare_SamEntry);
+ TYPESAFE_QSORT(entries, count, compare_SamEntry);
/* find the first entry to return */
for (first=0;
- first<num_filtered_entries && entries[first].idx <= *r->in.resume_handle;
+ first<count && entries[first].idx <= *r->in.resume_handle;
first++) ;
/* return the rest, limit by max_size. Note that we
use the w2k3 element size value of 54 */
- *r->out.num_entries = num_filtered_entries - first;
+ *r->out.num_entries = count - first;
*r->out.num_entries = MIN(*r->out.num_entries,
1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
*r->out.sam = sam;
- if (first == num_filtered_entries) {
+ if (first == count) {
return NT_STATUS_OK;
}
- if (*r->out.num_entries < num_filtered_entries - first) {
+ if (*r->out.num_entries < count - first) {
*r->out.resume_handle = entries[first+*r->out.num_entries-1].idx;
return STATUS_MORE_ENTRIES;
}
struct samr_domain_state *d_state;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
- const char *alias_name, *name;
- struct ldb_message *msg;
+ const char *alias_name;
struct dom_sid *sid;
struct dcesrv_handle *a_handle;
- int ret;
+ struct ldb_dn *dn;
+ NTSTATUS status;
ZERO_STRUCTP(r->out.alias_handle);
*r->out.rid = 0;
return NT_STATUS_INVALID_PARAMETER;
}
- /* Check if alias already exists */
- name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
- "sAMAccountName",
- "(sAMAccountName=%s)(objectclass=group))",
- ldb_binary_encode_string(mem_ctx, alias_name));
-
- if (name != NULL) {
- return NT_STATUS_ALIAS_EXISTS;
- }
-
- msg = ldb_msg_new(mem_ctx);
- if (msg == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* add core elements to the ldb_message for the alias */
- msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
- ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", alias_name);
- if (!msg->dn) {
- return NT_STATUS_NO_MEMORY;
- }
-
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", alias_name);
- samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
- samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "groupType", GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
-
- /* create the alias */
- ret = ldb_add(d_state->sam_ctx, msg);
- switch (ret) {
- case LDB_SUCCESS:
- break;
- case LDB_ERR_ENTRY_ALREADY_EXISTS:
- return NT_STATUS_ALIAS_EXISTS;
- case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
- return NT_STATUS_ACCESS_DENIED;
- default:
- DEBUG(0,("Failed to create alias record %s: %s\n",
- ldb_dn_get_linearized(msg->dn),
- ldb_errstring(d_state->sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ status = dsdb_add_domain_alias(d_state->sam_ctx, mem_ctx, alias_name, &sid, &dn);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- a_state = talloc(d_state, struct samr_account_state);
+ a_state = talloc(mem_ctx, struct samr_account_state);
if (!a_state) {
return NT_STATUS_NO_MEMORY;
}
a_state->sam_ctx = d_state->sam_ctx;
a_state->access_mask = r->in.access_mask;
a_state->domain_state = talloc_reference(a_state, d_state);
- a_state->account_dn = talloc_steal(a_state, msg->dn);
+ a_state->account_dn = talloc_steal(a_state, dn);
- /* retrieve the sid for the alias just created */
- sid = samdb_search_dom_sid(d_state->sam_ctx, a_state,
- msg->dn, "objectSid", NULL);
-
- a_state->account_name = talloc_strdup(a_state, alias_name);
- if (!a_state->account_name) {
- return NT_STATUS_NO_MEMORY;
- }
+ a_state->account_name = talloc_steal(a_state, alias_name);
/* create the policy handle */
a_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_ALIAS);
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
struct ldb_message **res;
- int ldb_cnt, count, i, first;
+ int i, ldb_cnt;
+ uint32_t first, count;
struct samr_SamEntry *entries;
- const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
+ const char * const attrs[] = { "objectSid", "sAMAccountName", NULL };
struct samr_SamArray *sam;
*r->out.resume_handle = 0;
d_state = h->data;
- /* search for all domain groups in this domain. This could possibly be
+ /* search for all domain aliases in this domain. This could possibly be
cached and resumed based on resume_key */
- ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
- d_state->domain_dn,
+ ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx, NULL,
&res, attrs,
d_state->domain_sid,
"(&(|(grouptype=%d)(grouptype=%d)))"
"(objectclass=group))",
GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
- if (ldb_cnt == -1) {
+ if (ldb_cnt < 0) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- if (ldb_cnt == 0) {
- return NT_STATUS_OK;
- }
/* convert to SamEntry format */
entries = talloc_array(mem_ctx, struct samr_SamEntry, ldb_cnt);
alias_sid = samdb_result_dom_sid(mem_ctx, res[i],
"objectSid");
- if (alias_sid == NULL)
- continue;
+ if (alias_sid == NULL) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
entries[count].idx =
alias_sid->sub_auths[alias_sid->num_auths-1];
}
/* sort the results by rid */
- qsort(entries, count, sizeof(struct samr_SamEntry),
- (comparison_fn_t)compare_SamEntry);
+ TYPESAFE_QSORT(entries, count, compare_SamEntry);
/* find the first entry to return */
for (first=0;
first<count && entries[first].idx <= *r->in.resume_handle;
first++) ;
- if (first == count) {
- return NT_STATUS_OK;
- }
-
+ /* return the rest, limit by max_size. Note that we
+ use the w2k3 element size value of 54 */
*r->out.num_entries = count - first;
- *r->out.num_entries = MIN(*r->out.num_entries, 1000);
+ *r->out.num_entries = MIN(*r->out.num_entries,
+ 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
sam = talloc(mem_ctx, struct samr_SamArray);
if (!sam) {
*r->out.sam = sam;
+ if (first == count) {
+ return NT_STATUS_OK;
+ }
+
if (*r->out.num_entries < count - first) {
*r->out.resume_handle =
entries[first+*r->out.num_entries-1].idx;
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
+ const char *filter;
+ const char * const attrs[] = { "objectSid", NULL };
struct ldb_message **res;
- int i, count = 0;
+ uint32_t i;
+ int count = 0;
DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
d_state = h->data;
- if (r->in.sids->num_sids > 0) {
- const char *filter;
- const char * const attrs[2] = { "objectSid", NULL };
-
- filter = talloc_asprintf(mem_ctx,
- "(&(|(grouptype=%d)(grouptype=%d))"
- "(objectclass=group)(|",
- GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
- GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
- if (filter == NULL)
- return NT_STATUS_NO_MEMORY;
-
- for (i=0; i<r->in.sids->num_sids; i++) {
- const char *memberdn;
+ filter = talloc_asprintf(mem_ctx,
+ "(&(|(grouptype=%d)(grouptype=%d))"
+ "(objectclass=group)(|",
+ GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
+ GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- memberdn =
- samdb_search_string(d_state->sam_ctx,
- mem_ctx, NULL, "distinguishedName",
- "(objectSid=%s)",
- ldap_encode_ndr_dom_sid(mem_ctx,
- r->in.sids->sids[i].sid));
+ for (i=0; i<r->in.sids->num_sids; i++) {
+ const char *memberdn;
- if (memberdn == NULL)
- continue;
+ memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
+ "distinguishedName",
+ "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx,
+ r->in.sids->sids[i].sid));
+ if (memberdn == NULL) {
+ continue;
+ }
- filter = talloc_asprintf(mem_ctx, "%s(member=%s)",
- filter, memberdn);
- if (filter == NULL)
- return NT_STATUS_NO_MEMORY;
+ filter = talloc_asprintf(mem_ctx, "%s(member=%s)", filter,
+ memberdn);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
+ }
- count = samdb_search_domain(d_state->sam_ctx, mem_ctx,
- d_state->domain_dn, &res, attrs,
- d_state->domain_sid, "%s))", filter);
- if (count < 0)
+ /* Find out if we had at least one valid member SID passed - otherwise
+ * just skip the search. */
+ if (strstr(filter, "member") != NULL) {
+ count = samdb_search_domain(d_state->sam_ctx, mem_ctx, NULL,
+ &res, attrs, d_state->domain_sid,
+ "%s))", filter);
+ if (count < 0) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
}
r->out.rids->count = 0;
struct dom_sid *alias_sid;
alias_sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
-
if (alias_sid == NULL) {
- DEBUG(0, ("Could not find objectSid\n"));
- continue;
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
r->out.rids->ids[r->out.rids->count] =
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
- int i, num_mapped;
+ uint32_t i, num_mapped;
NTSTATUS status = NT_STATUS_OK;
const char * const attrs[] = { "sAMAccountType", "objectSid", NULL };
int count;
continue;
}
- rtype = samdb_atype_map(atype);
+ rtype = ds_atype_map(atype);
if (rtype == SID_NAME_UNKNOWN) {
status = STATUS_SOME_UNMAPPED;
static NTSTATUS dcesrv_samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_LookupRids *r)
{
+ NTSTATUS status;
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
- int i, total;
- NTSTATUS status = NT_STATUS_OK;
- struct lsa_String *names;
- uint32_t *ids;
+ const char **names;
+ struct lsa_String *lsa_names;
+ enum lsa_SidType *ids;
ZERO_STRUCTP(r->out.names);
ZERO_STRUCTP(r->out.types);
if (r->in.num_rids == 0)
return NT_STATUS_OK;
- names = talloc_array(mem_ctx, struct lsa_String, r->in.num_rids);
- ids = talloc_array(mem_ctx, uint32_t, r->in.num_rids);
+ lsa_names = talloc_zero_array(mem_ctx, struct lsa_String, r->in.num_rids);
+ names = talloc_zero_array(mem_ctx, const char *, r->in.num_rids);
+ ids = talloc_zero_array(mem_ctx, enum lsa_SidType, r->in.num_rids);
- if ((names == NULL) || (ids == NULL))
+ if ((lsa_names == NULL) || (names == NULL) || (ids == NULL))
return NT_STATUS_NO_MEMORY;
- total = 0;
-
- for (i=0; i<r->in.num_rids; i++) {
- struct ldb_message **res;
- int count;
- const char * const attrs[] = { "sAMAccountType",
- "sAMAccountName", NULL };
- uint32_t atype;
- struct dom_sid *sid;
-
- ids[i] = SID_NAME_UNKNOWN;
-
- sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rids[i]);
- if (sid == NULL) {
- names[i].string = NULL;
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- count = gendb_search(d_state->sam_ctx, mem_ctx,
- d_state->domain_dn, &res, attrs,
- "(objectSid=%s)",
- ldap_encode_ndr_dom_sid(mem_ctx, sid));
- if (count != 1) {
- names[i].string = NULL;
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- names[i].string = samdb_result_string(res[0], "sAMAccountName",
- NULL);
-
- atype = samdb_result_uint(res[0], "sAMAccountType", 0);
- if (atype == 0) {
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- ids[i] = samdb_atype_map(atype);
-
- if (ids[i] == SID_NAME_UNKNOWN) {
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
- }
-
- r->out.names->names = names;
+ r->out.names->names = lsa_names;
r->out.names->count = r->in.num_rids;
- r->out.types->ids = ids;
+ r->out.types->ids = (uint32_t *) ids;
r->out.types->count = r->in.num_rids;
+ status = dsdb_lookup_rids(d_state->sam_ctx, mem_ctx, d_state->domain_sid,
+ r->in.num_rids, r->in.rids, names, ids);
+ if (NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED) || NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+ uint32_t i;
+ for (i = 0; i < r->in.num_rids; i++) {
+ lsa_names[i].string = names[i];
+ }
+ }
return status;
}
/* search for the group record */
ret = gendb_search(d_state->sam_ctx,
mem_ctx, d_state->domain_dn, &msgs, attrs,
- "(&(objectSid=%s)(objectclass=group)"
- "(grouptype=%d))",
+ "(&(objectSid=%s)(objectClass=group)"
+ "(|(groupType=%d)(groupType=%d)))",
ldap_encode_ndr_dom_sid(mem_ctx, sid),
+ GTYPE_SECURITY_UNIVERSAL_GROUP,
GTYPE_SECURITY_GLOBAL_GROUP);
if (ret == 0) {
return NT_STATUS_NO_SUCH_GROUP;
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- a_state = talloc(d_state, struct samr_account_state);
+ a_state = talloc(mem_ctx, struct samr_account_state);
if (!a_state) {
return NT_STATUS_NO_MEMORY;
}
{
struct dcesrv_handle *h;
struct samr_account_state *a_state;
- struct ldb_message *msg;
- struct ldb_result *res;
+ struct ldb_message *msg, **res;
const char * const attrs[4] = { "sAMAccountName", "description",
"numMembers", NULL };
int ret;
a_state = h->data;
- ret = ldb_search(a_state->sam_ctx, mem_ctx, &res, a_state->account_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=*");
-
- if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ /* pull all the group attributes */
+ ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
+ a_state->account_dn, &res, attrs);
+ if (ret == 0) {
return NT_STATUS_NO_SUCH_GROUP;
- } else if (ret != LDB_SUCCESS) {
- DEBUG(2, ("Error reading group info: %s\n", ldb_errstring(a_state->sam_ctx)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
-
- if (res->count != 1) {
- DEBUG(2, ("Error finding group info, got %d entries\n", res->count));
-
+ if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- msg = res->msgs[0];
+ msg = res[0];
/* allocate the info structure */
info = talloc_zero(mem_ctx, union samr_GroupInfo);
/* modify the samdb record */
ret = ldb_modify(g_state->sam_ctx, msg);
- if (ret != 0) {
+ if (ret != LDB_SUCCESS) {
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL;
}
d_state = a_state->domain_state;
membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
- if (membersid == NULL)
+ if (membersid == NULL) {
return NT_STATUS_NO_MEMORY;
+ }
- /* In native mode, AD can also nest domain groups. Not sure yet
- * whether this is also available via RPC. */
+ /* according to MS-SAMR 3.1.5.8.2 all type of accounts are accepted */
ret = ldb_search(d_state->sam_ctx, mem_ctx, &res,
- d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
- "(&(objectSid=%s)(objectclass=user))",
- ldap_encode_ndr_dom_sid(mem_ctx, membersid));
+ d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
+ "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, membersid));
- if (ret != 0) {
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
- if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
- memberdn) != 0)
+ ret = samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
+ memberdn);
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_UNSUCCESSFUL;
+ }
ret = ldb_modify(a_state->sam_ctx, mod);
switch (ret) {
case LDB_SUCCESS:
return NT_STATUS_OK;
case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
+ case LDB_ERR_ENTRY_ALREADY_EXISTS:
return NT_STATUS_MEMBER_IN_GROUP;
case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
return NT_STATUS_ACCESS_DENIED;
default:
return NT_STATUS_UNSUCCESSFUL;
}
-
}
a_state = h->data;
ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
- if (ret != 0) {
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_UNSUCCESSFUL;
}
+ talloc_free(h);
ZERO_STRUCTP(r->out.group_handle);
return NT_STATUS_OK;
d_state = a_state->domain_state;
membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
- if (membersid == NULL)
+ if (membersid == NULL) {
return NT_STATUS_NO_MEMORY;
+ }
- /* In native mode, AD can also nest domain groups. Not sure yet
- * whether this is also available via RPC. */
+ /* according to MS-SAMR 3.1.5.8.2 all type of accounts are accepted */
ret = ldb_search(d_state->sam_ctx, mem_ctx, &res,
- d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
- "(&(objectSid=%s)(objectclass=user))",
- ldap_encode_ndr_dom_sid(mem_ctx, membersid));
+ d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
+ "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, membersid));
- if (ret != 0) {
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
- if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
- memberdn) != 0) {
+ ret = samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
+ memberdn);
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_NO_MEMORY;
}
default:
return NT_STATUS_UNSUCCESSFUL;
}
-
}
{
struct dcesrv_handle *h;
struct samr_account_state *a_state;
- struct ldb_message **res;
- struct ldb_message_element *el;
+ struct samr_domain_state *d_state;
struct samr_RidTypeArray *array;
- const char * const attrs[2] = { "member", NULL };
- int ret;
+ unsigned int i, num_members;
+ struct dom_sid *members;
+ NTSTATUS status;
DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
a_state = h->data;
+ d_state = a_state->domain_state;
- /* pull the member attribute */
- ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
- a_state->account_dn, &res, attrs);
-
- if (ret != 1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ status = dsdb_enum_group_mem(d_state->sam_ctx, mem_ctx,
+ a_state->account_dn, &members,
+ &num_members);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- array = talloc(mem_ctx, struct samr_RidTypeArray);
-
- if (array == NULL)
+ array = talloc_zero(mem_ctx, struct samr_RidTypeArray);
+ if (array == NULL) {
return NT_STATUS_NO_MEMORY;
+ }
- ZERO_STRUCTP(array);
-
- el = ldb_msg_find_element(res[0], "member");
-
- if (el != NULL) {
- int i;
-
- array->count = el->num_values;
-
- array->rids = talloc_array(mem_ctx, uint32_t,
- el->num_values);
- if (array->rids == NULL)
- return NT_STATUS_NO_MEMORY;
+ if (num_members == 0) {
+ *r->out.rids = array;
- array->types = talloc_array(mem_ctx, uint32_t,
- el->num_values);
- if (array->types == NULL)
- return NT_STATUS_NO_MEMORY;
+ return NT_STATUS_OK;
+ }
- for (i=0; i<el->num_values; i++) {
- struct ldb_message **res2;
- const char * const attrs2[2] = { "objectSid", NULL };
- ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
- ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]),
- &res2, attrs2);
- if (ret != 1)
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ array->rids = talloc_array(array, uint32_t, num_members);
+ if (array->rids == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- array->rids[i] =
- samdb_result_rid_from_sid(mem_ctx, res2[0],
- "objectSid", 0);
+ array->types = talloc_array(array, uint32_t, num_members);
+ if (array->types == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- if (array->rids[i] == 0)
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ array->count = 0;
+ for (i=0; i<num_members; i++) {
+ if (!dom_sid_in_domain(d_state->domain_sid, &members[i])) {
+ continue;
+ }
- array->types[i] = 7; /* RID type of some kind, not sure what the value means. */
+ status = dom_sid_split_rid(NULL, &members[i], NULL,
+ &array->rids[array->count]);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
+
+ array->types[array->count] = 7; /* RID type of some kind, not sure what the value means. */
+ array->count++;
}
*r->out.rids = array;
return NT_STATUS_NO_MEMORY;
/* search for the group record */
- ret = gendb_search(d_state->sam_ctx,
- mem_ctx, d_state->domain_dn, &msgs, attrs,
+ ret = gendb_search(d_state->sam_ctx, mem_ctx, NULL, &msgs, attrs,
"(&(objectSid=%s)(objectclass=group)"
"(|(grouptype=%d)(grouptype=%d)))",
ldap_encode_ndr_dom_sid(mem_ctx, sid),
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- a_state = talloc(d_state, struct samr_account_state);
+ a_state = talloc(mem_ctx, struct samr_account_state);
if (!a_state) {
return NT_STATUS_NO_MEMORY;
}
/* pull all the alias attributes */
ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
- a_state->account_dn ,&res, attrs);
+ a_state->account_dn, &res, attrs);
+ if (ret == 0) {
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/* modify the samdb record */
ret = ldb_modify(a_state->sam_ctx, msg);
- if (ret != 0) {
+ if (ret != LDB_SUCCESS) {
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL;
}
a_state = h->data;
ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
- if (ret != 0) {
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_UNSUCCESSFUL;
}
+ talloc_free(h);
ZERO_STRUCTP(r->out.alias_handle);
return NT_STATUS_OK;
&msgs, attrs, "(objectsid=%s)",
ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
- if (ret == 1) {
- memberdn = msgs[0]->dn;
- } else if (ret > 1) {
- DEBUG(0,("Found %d records matching sid %s\n",
- ret, dom_sid_string(mem_ctx, r->in.sid)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ if (ret == 1) {
+ memberdn = msgs[0]->dn;
} else if (ret == 0) {
- status = samdb_create_foreign_security_principal(d_state->sam_ctx, mem_ctx,
- r->in.sid, &memberdn);
+ 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: %s\n", ret, ldb_errstring(d_state->sam_ctx)));
+ DEBUG(0,("Found %d records matching sid %s\n",
+ ret, dom_sid_string(mem_ctx, r->in.sid)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
if (memberdn == NULL) {
mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
- if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
- ldb_dn_alloc_linearized(mem_ctx, memberdn)) != 0)
+ ret = samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
+ ldb_dn_alloc_linearized(mem_ctx, memberdn));
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_UNSUCCESSFUL;
+ }
- if (ldb_modify(a_state->sam_ctx, mod) != 0)
+ ret = ldb_modify(a_state->sam_ctx, mod);
+ switch (ret) {
+ case LDB_SUCCESS:
+ return NT_STATUS_OK;
+ case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
+ case LDB_ERR_ENTRY_ALREADY_EXISTS:
+ return NT_STATUS_MEMBER_IN_GROUP;
+ case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
+ return NT_STATUS_ACCESS_DENIED;
+ default:
return NT_STATUS_UNSUCCESSFUL;
-
- return NT_STATUS_OK;
+ }
}
struct samr_domain_state *d_state;
struct ldb_message *mod;
const char *memberdn;
+ int ret;
DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
"distinguishedName", "(objectSid=%s)",
ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
-
- if (memberdn == NULL)
+ if (memberdn == NULL) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
mod = ldb_msg_new(mem_ctx);
if (mod == NULL) {
mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
- if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
- memberdn) != 0)
+ ret = samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
+ memberdn);
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_UNSUCCESSFUL;
+ }
- if (ldb_modify(a_state->sam_ctx, mod) != 0)
+ ret = ldb_modify(a_state->sam_ctx, mod);
+ switch (ret) {
+ case LDB_SUCCESS:
+ return NT_STATUS_OK;
+ case LDB_ERR_NO_SUCH_ATTRIBUTE:
+ return NT_STATUS_MEMBER_NOT_IN_GROUP;
+ case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
+ return NT_STATUS_ACCESS_DENIED;
+ default:
return NT_STATUS_UNSUCCESSFUL;
-
- return NT_STATUS_OK;
+ }
}
struct dcesrv_handle *h;
struct samr_account_state *a_state;
struct samr_domain_state *d_state;
- struct ldb_message **msgs;
- struct lsa_SidPtr *sids;
- struct ldb_message_element *el;
- const char * const attrs[2] = { "member", NULL};
- int ret;
+ struct lsa_SidPtr *array;
+ unsigned int i, num_members;
+ struct dom_sid *members;
+ NTSTATUS status;
DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
a_state = h->data;
d_state = a_state->domain_state;
- ret = gendb_search_dn(d_state->sam_ctx, mem_ctx,
- a_state->account_dn, &msgs, attrs);
-
- if (ret == -1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- } else if (ret == 0) {
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- } else if (ret != 1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ status = dsdb_enum_group_mem(d_state->sam_ctx, mem_ctx,
+ a_state->account_dn, &members,
+ &num_members);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- r->out.sids->num_sids = 0;
- r->out.sids->sids = NULL;
+ if (num_members == 0) {
+ r->out.sids->sids = NULL;
- el = ldb_msg_find_element(msgs[0], "member");
-
- if (el != NULL) {
- int i;
-
- sids = talloc_array(mem_ctx, struct lsa_SidPtr,
- el->num_values);
-
- if (sids == NULL)
- return NT_STATUS_NO_MEMORY;
-
- for (i=0; i<el->num_values; i++) {
- struct ldb_message **msgs2;
- const char * const attrs2[2] = { "objectSid", NULL };
- ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
- ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]),
- &msgs2, attrs2);
- if (ret != 1)
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ return NT_STATUS_OK;
+ }
- sids[i].sid = samdb_result_dom_sid(mem_ctx, msgs2[0],
- "objectSid");
+ array = talloc_array(mem_ctx, struct lsa_SidPtr, num_members);
+ if (array == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- if (sids[i].sid == NULL)
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
- r->out.sids->num_sids = el->num_values;
- r->out.sids->sids = sids;
+ for (i=0; i<num_members; i++) {
+ array[i].sid = &members[i];
}
+ r->out.sids->num_sids = num_members;
+ r->out.sids->sids = array;
+
return NT_STATUS_OK;
}
a_state = h->data;
ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
- if (ret != 0) {
+ if (ret != LDB_SUCCESS) {
DEBUG(1, ("Failed to delete user: %s: %s\n",
ldb_dn_get_linearized(a_state->account_dn),
ldb_errstring(a_state->sam_ctx)));
return NT_STATUS_UNSUCCESSFUL;
}
+ talloc_free(h);
ZERO_STRUCTP(r->out.user_handle);
return NT_STATUS_OK;
switch (r->in.level) {
case 1:
{
- static const char * const attrs2[] = {"sAMAccountName", "displayName",
- "primaryroupID", "description",
- "comment", NULL};
+ static const char * const attrs2[] = {"sAMAccountName",
+ "displayName",
+ "primaryroupID",
+ "description",
+ "comment",
+ NULL};
attrs = attrs2;
break;
}
case 2:
{
- static const char * const attrs2[] = {"comment", "countryCode", "codePage", NULL};
+ static const char * const attrs2[] = {"comment",
+ "countryCode",
+ "codePage",
+ NULL};
attrs = attrs2;
break;
}
"logonHours",
"badPwdCount",
"logonCount",
- "userAccountControl", NULL};
+ "userAccountControl",
+ NULL};
attrs = attrs2;
break;
}
case 4:
{
- static const char * const attrs2[] = {"logonHours", NULL};
+ static const char * const attrs2[] = {"logonHours",
+ NULL};
attrs = attrs2;
break;
}
}
case 6:
{
- static const char * const attrs2[] = {"sAMAccountName", "displayName", NULL};
+ static const char * const attrs2[] = {"sAMAccountName",
+ "displayName",
+ NULL};
attrs = attrs2;
break;
}
case 7:
{
- static const char * const attrs2[] = {"sAMAccountName", NULL};
+ static const char * const attrs2[] = {"sAMAccountName",
+ NULL};
attrs = attrs2;
break;
}
case 8:
{
- static const char * const attrs2[] = {"displayName", NULL};
+ static const char * const attrs2[] = {"displayName",
+ NULL};
attrs = attrs2;
break;
}
case 9:
{
- static const char * const attrs2[] = {"primaryGroupID", NULL};
+ static const char * const attrs2[] = {"primaryGroupID",
+ NULL};
attrs = attrs2;
break;
}
case 10:
{
- static const char * const attrs2[] = {"homeDirectory", "homeDrive", NULL};
+ static const char * const attrs2[] = {"homeDirectory",
+ "homeDrive",
+ NULL};
attrs = attrs2;
break;
}
case 11:
{
- static const char * const attrs2[] = {"scriptPath", NULL};
+ static const char * const attrs2[] = {"scriptPath",
+ NULL};
attrs = attrs2;
break;
}
case 12:
{
- static const char * const attrs2[] = {"profilePath", NULL};
+ static const char * const attrs2[] = {"profilePath",
+ NULL};
attrs = attrs2;
break;
}
case 13:
{
- static const char * const attrs2[] = {"description", NULL};
+ static const char * const attrs2[] = {"description",
+ NULL};
attrs = attrs2;
break;
}
case 14:
{
- static const char * const attrs2[] = {"userWorkstations", NULL};
+ static const char * const attrs2[] = {"userWorkstations",
+ NULL};
attrs = attrs2;
break;
}
case 16:
{
- static const char * const attrs2[] = {"userAccountControl", "pwdLastSet", NULL};
+ static const char * const attrs2[] = {"userAccountControl",
+ "pwdLastSet",
+ NULL};
attrs = attrs2;
break;
}
case 17:
{
- static const char * const attrs2[] = {"accountExpires", NULL};
+ static const char * const attrs2[] = {"accountExpires",
+ NULL};
attrs = attrs2;
break;
}
+ case 18:
+ {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
case 20:
{
- static const char * const attrs2[] = {"userParameters", NULL};
+ static const char * const attrs2[] = {"userParameters",
+ NULL};
attrs = attrs2;
break;
}
attrs = attrs2;
break;
}
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+ default:
+ {
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
}
/* pull all the user attributes */
ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
- a_state->account_dn ,&res, attrs);
+ a_state->account_dn, &res, attrs);
+ if (ret == 0) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
QUERY_RID (msg, info21.rid, "objectSid");
QUERY_UINT (msg, info21.primary_gid, "primaryGroupID");
QUERY_AFLAGS(msg, info21.acct_flags, "userAccountControl");
- info->info21.fields_present = 0x00FFFFFF;
+ info->info21.fields_present = 0x08FFFFFF;
QUERY_LHOURS(msg, info21.logon_hours, "logonHours");
QUERY_UINT (msg, info21.bad_password_count, "badPwdCount");
QUERY_UINT (msg, info21.logon_count, "logonCount");
+ if ((info->info21.acct_flags & ACB_PW_EXPIRED) != 0) {
+ info->info21.password_expired = PASS_MUST_CHANGE_AT_NEXT_LOGON;
+ } else {
+ info->info21.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;
+ }
QUERY_UINT (msg, info21.country_code, "countryCode");
QUERY_UINT (msg, info21.code_page, "codePage");
break;
break;
case 6:
+ SET_STRING(msg, info6.account_name, "samAccountName");
SET_STRING(msg, info6.full_name, "displayName");
break;
SET_UINT64(msg, info17.acct_expiry, "accountExpires");
break;
+ case 18:
+ status = samr_set_password_buffers(dce_call,
+ a_state->sam_ctx,
+ a_state->account_dn,
+ a_state->domain_state->domain_dn,
+ mem_ctx,
+ r->in.info->info18.lm_pwd_active ? r->in.info->info18.lm_pwd.hash : NULL,
+ r->in.info->info18.nt_pwd_active ? r->in.info->info18.nt_pwd.hash : NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (r->in.info->info18.password_expired > 0) {
+ struct ldb_message_element *set_el;
+ if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ set_el = ldb_msg_find_element(msg, "pwdLastSet");
+ set_el->flags = LDB_FLAG_MOD_REPLACE;
+ }
+ break;
+
case 20:
SET_PARAMETERS(msg, info20.parameters, "userParameters");
break;
case 21:
-#define IFSET(bit) if (bit & r->in.info->info21.fields_present)
+ if (r->in.info->info21.fields_present == 0)
+ return NT_STATUS_INVALID_PARAMETER;
+
+#define IFSET(bit) if (bit & r->in.info->info21.fields_present)
+ IFSET(SAMR_FIELD_LAST_LOGON)
+ SET_UINT64(msg, info21.last_logon, "lastLogon");
+ IFSET(SAMR_FIELD_LAST_LOGOFF)
+ SET_UINT64(msg, info21.last_logoff, "lastLogoff");
IFSET(SAMR_FIELD_ACCT_EXPIRY)
- SET_UINT64(msg, info21.acct_expiry, "accountExpires");
+ SET_UINT64(msg, info21.acct_expiry, "accountExpires");
IFSET(SAMR_FIELD_ACCOUNT_NAME)
SET_STRING(msg, info21.account_name, "samAccountName");
IFSET(SAMR_FIELD_FULL_NAME)
SET_STRING(msg, info21.full_name, "displayName");
- IFSET(SAMR_FIELD_DESCRIPTION)
- SET_STRING(msg, info21.description, "description");
- IFSET(SAMR_FIELD_COMMENT)
- SET_STRING(msg, info21.comment, "comment");
- IFSET(SAMR_FIELD_LOGON_SCRIPT)
- SET_STRING(msg, info21.logon_script, "scriptPath");
- IFSET(SAMR_FIELD_PROFILE_PATH)
- SET_STRING(msg, info21.profile_path, "profilePath");
IFSET(SAMR_FIELD_HOME_DIRECTORY)
SET_STRING(msg, info21.home_directory, "homeDirectory");
IFSET(SAMR_FIELD_HOME_DRIVE)
SET_STRING(msg, info21.home_drive, "homeDrive");
+ IFSET(SAMR_FIELD_LOGON_SCRIPT)
+ SET_STRING(msg, info21.logon_script, "scriptPath");
+ IFSET(SAMR_FIELD_PROFILE_PATH)
+ SET_STRING(msg, info21.profile_path, "profilePath");
+ IFSET(SAMR_FIELD_DESCRIPTION)
+ SET_STRING(msg, info21.description, "description");
IFSET(SAMR_FIELD_WORKSTATIONS)
SET_STRING(msg, info21.workstations, "userWorkstations");
- IFSET(SAMR_FIELD_LOGON_HOURS)
- SET_LHOURS(msg, info21.logon_hours, "logonHours");
- IFSET(SAMR_FIELD_ACCT_FLAGS)
- SET_AFLAGS(msg, info21.acct_flags, "userAccountControl");
+ IFSET(SAMR_FIELD_COMMENT)
+ SET_STRING(msg, info21.comment, "comment");
IFSET(SAMR_FIELD_PARAMETERS)
SET_PARAMETERS(msg, info21.parameters, "userParameters");
+ IFSET(SAMR_FIELD_PRIMARY_GID)
+ SET_UINT(msg, info21.primary_gid, "primaryGroupID");
+ IFSET(SAMR_FIELD_ACCT_FLAGS)
+ SET_AFLAGS(msg, info21.acct_flags, "userAccountControl");
+ IFSET(SAMR_FIELD_LOGON_HOURS)
+ SET_LHOURS(msg, info21.logon_hours, "logonHours");
+ IFSET(SAMR_FIELD_BAD_PWD_COUNT)
+ SET_UINT (msg, info21.bad_password_count, "badPwdCount");
+ IFSET(SAMR_FIELD_NUM_LOGONS)
+ SET_UINT (msg, info21.logon_count, "logonCount");
IFSET(SAMR_FIELD_COUNTRY_CODE)
SET_UINT (msg, info21.country_code, "countryCode");
IFSET(SAMR_FIELD_CODE_PAGE)
- SET_UINT (msg, info21.code_page, "codePage");
+ SET_UINT (msg, info21.code_page, "codePage");
+
+ /* password change fields */
+ IFSET(SAMR_FIELD_LAST_PWD_CHANGE)
+ return NT_STATUS_ACCESS_DENIED;
+
+ IFSET((SAMR_FIELD_LM_PASSWORD_PRESENT
+ | SAMR_FIELD_NT_PASSWORD_PRESENT)) {
+ uint8_t *lm_pwd_hash = NULL, *nt_pwd_hash = NULL;
+
+ if (r->in.info->info21.lm_password_set) {
+ if ((r->in.info->info21.lm_owf_password.length != 16)
+ || (r->in.info->info21.lm_owf_password.size != 16)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ lm_pwd_hash = (uint8_t *) r->in.info->info21.lm_owf_password.array;
+ }
+ if (r->in.info->info21.nt_password_set) {
+ if ((r->in.info->info21.nt_owf_password.length != 16)
+ || (r->in.info->info21.nt_owf_password.size != 16)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ nt_pwd_hash = (uint8_t *) r->in.info->info21.nt_owf_password.array;
+ }
+ status = samr_set_password_buffers(dce_call,
+ a_state->sam_ctx,
+ a_state->account_dn,
+ a_state->domain_state->domain_dn,
+ mem_ctx,
+ lm_pwd_hash,
+ nt_pwd_hash);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+
+
+ IFSET(SAMR_FIELD_EXPIRED_FLAG) {
+ NTTIME t = 0;
+ struct ldb_message_element *set_el;
+ if (r->in.info->info21.password_expired
+ == PASS_DONT_CHANGE_AT_NEXT_LOGON) {
+ unix_to_nt_time(&t, time(NULL));
+ }
+ if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg,
+ "pwdLastSet", t) != LDB_SUCCESS) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ set_el = ldb_msg_find_element(msg, "pwdLastSet");
+ set_el->flags = LDB_FLAG_MOD_REPLACE;
+ }
#undef IFSET
break;
case 23:
+ if (r->in.info->info23.info.fields_present == 0)
+ return NT_STATUS_INVALID_PARAMETER;
+
#define IFSET(bit) if (bit & r->in.info->info23.info.fields_present)
+ IFSET(SAMR_FIELD_LAST_LOGON)
+ SET_UINT64(msg, info23.info.last_logon, "lastLogon");
+ IFSET(SAMR_FIELD_LAST_LOGOFF)
+ SET_UINT64(msg, info23.info.last_logoff, "lastLogoff");
IFSET(SAMR_FIELD_ACCT_EXPIRY)
- SET_UINT64(msg, info23.info.acct_expiry, "accountExpires");
+ SET_UINT64(msg, info23.info.acct_expiry, "accountExpires");
IFSET(SAMR_FIELD_ACCOUNT_NAME)
- SET_STRING(msg, info23.info.account_name, "samAccountName");
- IFSET(SAMR_FIELD_FULL_NAME)
- SET_STRING(msg, info23.info.full_name, "displayName");
- IFSET(SAMR_FIELD_DESCRIPTION)
- SET_STRING(msg, info23.info.description, "description");
- IFSET(SAMR_FIELD_COMMENT)
- SET_STRING(msg, info23.info.comment, "comment");
- IFSET(SAMR_FIELD_LOGON_SCRIPT)
- SET_STRING(msg, info23.info.logon_script, "scriptPath");
- IFSET(SAMR_FIELD_PROFILE_PATH)
- SET_STRING(msg, info23.info.profile_path, "profilePath");
- IFSET(SAMR_FIELD_WORKSTATIONS)
- SET_STRING(msg, info23.info.workstations, "userWorkstations");
- IFSET(SAMR_FIELD_LOGON_HOURS)
- SET_LHOURS(msg, info23.info.logon_hours, "logonHours");
- IFSET(SAMR_FIELD_ACCT_FLAGS)
- SET_AFLAGS(msg, info23.info.acct_flags, "userAccountControl");
- IFSET(SAMR_FIELD_PARAMETERS)
+ SET_STRING(msg, info23.info.account_name, "samAccountName");
+ IFSET(SAMR_FIELD_FULL_NAME)
+ SET_STRING(msg, info23.info.full_name, "displayName");
+ IFSET(SAMR_FIELD_HOME_DIRECTORY)
+ SET_STRING(msg, info23.info.home_directory, "homeDirectory");
+ IFSET(SAMR_FIELD_HOME_DRIVE)
+ SET_STRING(msg, info23.info.home_drive, "homeDrive");
+ IFSET(SAMR_FIELD_LOGON_SCRIPT)
+ SET_STRING(msg, info23.info.logon_script, "scriptPath");
+ IFSET(SAMR_FIELD_PROFILE_PATH)
+ SET_STRING(msg, info23.info.profile_path, "profilePath");
+ IFSET(SAMR_FIELD_DESCRIPTION)
+ SET_STRING(msg, info23.info.description, "description");
+ IFSET(SAMR_FIELD_WORKSTATIONS)
+ SET_STRING(msg, info23.info.workstations, "userWorkstations");
+ IFSET(SAMR_FIELD_COMMENT)
+ SET_STRING(msg, info23.info.comment, "comment");
+ IFSET(SAMR_FIELD_PARAMETERS)
SET_PARAMETERS(msg, info23.info.parameters, "userParameters");
- IFSET(SAMR_FIELD_COUNTRY_CODE)
- SET_UINT (msg, info23.info.country_code, "countryCode");
- IFSET(SAMR_FIELD_CODE_PAGE)
- SET_UINT (msg, info23.info.code_page, "codePage");
+ IFSET(SAMR_FIELD_PRIMARY_GID)
+ SET_UINT(msg, info23.info.primary_gid, "primaryGroupID");
+ IFSET(SAMR_FIELD_ACCT_FLAGS)
+ SET_AFLAGS(msg, info23.info.acct_flags, "userAccountControl");
+ IFSET(SAMR_FIELD_LOGON_HOURS)
+ SET_LHOURS(msg, info23.info.logon_hours, "logonHours");
+ IFSET(SAMR_FIELD_BAD_PWD_COUNT)
+ SET_UINT (msg, info23.info.bad_password_count, "badPwdCount");
+ IFSET(SAMR_FIELD_NUM_LOGONS)
+ SET_UINT (msg, info23.info.logon_count, "logonCount");
+
+ IFSET(SAMR_FIELD_COUNTRY_CODE)
+ SET_UINT (msg, info23.info.country_code, "countryCode");
+ IFSET(SAMR_FIELD_CODE_PAGE)
+ SET_UINT (msg, info23.info.code_page, "codePage");
+
+ /* password change fields */
+ IFSET(SAMR_FIELD_LAST_PWD_CHANGE)
+ return NT_STATUS_ACCESS_DENIED;
+
IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) {
status = samr_set_password(dce_call,
a_state->sam_ctx,
a_state->account_dn,
a_state->domain_state->domain_dn,
- mem_ctx, msg,
+ mem_ctx,
&r->in.info->info23.password);
} else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) {
status = samr_set_password(dce_call,
a_state->sam_ctx,
a_state->account_dn,
a_state->domain_state->domain_dn,
- mem_ctx, msg,
+ mem_ctx,
&r->in.info->info23.password);
}
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ IFSET(SAMR_FIELD_EXPIRED_FLAG) {
+ NTTIME t = 0;
+ struct ldb_message_element *set_el;
+ if (r->in.info->info23.info.password_expired
+ == PASS_DONT_CHANGE_AT_NEXT_LOGON) {
+ unix_to_nt_time(&t, time(NULL));
+ }
+ if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg,
+ "pwdLastSet", t) != LDB_SUCCESS) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ set_el = ldb_msg_find_element(msg, "pwdLastSet");
+ set_el->flags = LDB_FLAG_MOD_REPLACE;
+ }
#undef IFSET
break;
a_state->sam_ctx,
a_state->account_dn,
a_state->domain_state->domain_dn,
- mem_ctx, msg,
+ mem_ctx,
&r->in.info->info24.password);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (r->in.info->info24.password_expired > 0) {
+ struct ldb_message_element *set_el;
+ if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ set_el = ldb_msg_find_element(msg, "pwdLastSet");
+ set_el->flags = LDB_FLAG_MOD_REPLACE;
+ }
break;
case 25:
+ if (r->in.info->info25.info.fields_present == 0)
+ return NT_STATUS_INVALID_PARAMETER;
+
#define IFSET(bit) if (bit & r->in.info->info25.info.fields_present)
+ IFSET(SAMR_FIELD_LAST_LOGON)
+ SET_UINT64(msg, info25.info.last_logon, "lastLogon");
+ IFSET(SAMR_FIELD_LAST_LOGOFF)
+ SET_UINT64(msg, info25.info.last_logoff, "lastLogoff");
IFSET(SAMR_FIELD_ACCT_EXPIRY)
- SET_UINT64(msg, info25.info.acct_expiry, "accountExpires");
+ SET_UINT64(msg, info25.info.acct_expiry, "accountExpires");
IFSET(SAMR_FIELD_ACCOUNT_NAME)
- SET_STRING(msg, info25.info.account_name, "samAccountName");
- IFSET(SAMR_FIELD_FULL_NAME)
- SET_STRING(msg, info25.info.full_name, "displayName");
- IFSET(SAMR_FIELD_DESCRIPTION)
- SET_STRING(msg, info25.info.description, "description");
- IFSET(SAMR_FIELD_COMMENT)
- SET_STRING(msg, info25.info.comment, "comment");
- IFSET(SAMR_FIELD_LOGON_SCRIPT)
- SET_STRING(msg, info25.info.logon_script, "scriptPath");
- IFSET(SAMR_FIELD_PROFILE_PATH)
- SET_STRING(msg, info25.info.profile_path, "profilePath");
- IFSET(SAMR_FIELD_WORKSTATIONS)
- SET_STRING(msg, info25.info.workstations, "userWorkstations");
- IFSET(SAMR_FIELD_LOGON_HOURS)
- SET_LHOURS(msg, info25.info.logon_hours, "logonHours");
- IFSET(SAMR_FIELD_ACCT_FLAGS)
- SET_AFLAGS(msg, info25.info.acct_flags, "userAccountControl");
- IFSET(SAMR_FIELD_PARAMETERS)
+ SET_STRING(msg, info25.info.account_name, "samAccountName");
+ IFSET(SAMR_FIELD_FULL_NAME)
+ SET_STRING(msg, info25.info.full_name, "displayName");
+ IFSET(SAMR_FIELD_HOME_DIRECTORY)
+ SET_STRING(msg, info25.info.home_directory, "homeDirectory");
+ IFSET(SAMR_FIELD_HOME_DRIVE)
+ SET_STRING(msg, info25.info.home_drive, "homeDrive");
+ IFSET(SAMR_FIELD_LOGON_SCRIPT)
+ SET_STRING(msg, info25.info.logon_script, "scriptPath");
+ IFSET(SAMR_FIELD_PROFILE_PATH)
+ SET_STRING(msg, info25.info.profile_path, "profilePath");
+ IFSET(SAMR_FIELD_DESCRIPTION)
+ SET_STRING(msg, info25.info.description, "description");
+ IFSET(SAMR_FIELD_WORKSTATIONS)
+ SET_STRING(msg, info25.info.workstations, "userWorkstations");
+ IFSET(SAMR_FIELD_COMMENT)
+ SET_STRING(msg, info25.info.comment, "comment");
+ IFSET(SAMR_FIELD_PARAMETERS)
SET_PARAMETERS(msg, info25.info.parameters, "userParameters");
- IFSET(SAMR_FIELD_COUNTRY_CODE)
- SET_UINT (msg, info25.info.country_code, "countryCode");
- IFSET(SAMR_FIELD_CODE_PAGE)
- SET_UINT (msg, info25.info.code_page, "codePage");
+ IFSET(SAMR_FIELD_PRIMARY_GID)
+ SET_UINT(msg, info25.info.primary_gid, "primaryGroupID");
+ IFSET(SAMR_FIELD_ACCT_FLAGS)
+ SET_AFLAGS(msg, info25.info.acct_flags, "userAccountControl");
+ IFSET(SAMR_FIELD_LOGON_HOURS)
+ SET_LHOURS(msg, info25.info.logon_hours, "logonHours");
+ IFSET(SAMR_FIELD_BAD_PWD_COUNT)
+ SET_UINT (msg, info25.info.bad_password_count, "badPwdCount");
+ IFSET(SAMR_FIELD_NUM_LOGONS)
+ SET_UINT (msg, info25.info.logon_count, "logonCount");
+ IFSET(SAMR_FIELD_COUNTRY_CODE)
+ SET_UINT (msg, info25.info.country_code, "countryCode");
+ IFSET(SAMR_FIELD_CODE_PAGE)
+ SET_UINT (msg, info25.info.code_page, "codePage");
+
+ /* password change fields */
+ IFSET(SAMR_FIELD_LAST_PWD_CHANGE)
+ return NT_STATUS_ACCESS_DENIED;
+
IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) {
status = samr_set_password_ex(dce_call,
a_state->sam_ctx,
a_state->account_dn,
a_state->domain_state->domain_dn,
- mem_ctx, msg,
+ mem_ctx,
&r->in.info->info25.password);
} else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) {
status = samr_set_password_ex(dce_call,
a_state->sam_ctx,
a_state->account_dn,
a_state->domain_state->domain_dn,
- mem_ctx, msg,
+ mem_ctx,
&r->in.info->info25.password);
}
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ IFSET(SAMR_FIELD_EXPIRED_FLAG) {
+ NTTIME t = 0;
+ struct ldb_message_element *set_el;
+ if (r->in.info->info25.info.password_expired
+ == PASS_DONT_CHANGE_AT_NEXT_LOGON) {
+ unix_to_nt_time(&t, time(NULL));
+ }
+ if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg,
+ "pwdLastSet", t) != LDB_SUCCESS) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ set_el = ldb_msg_find_element(msg, "pwdLastSet");
+ set_el->flags = LDB_FLAG_MOD_REPLACE;
+ }
#undef IFSET
break;
a_state->sam_ctx,
a_state->account_dn,
a_state->domain_state->domain_dn,
- mem_ctx, msg,
+ mem_ctx,
&r->in.info->info26.password);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (r->in.info->info26.password_expired > 0) {
+ struct ldb_message_element *set_el;
+ if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ set_el = ldb_msg_find_element(msg, "pwdLastSet");
+ set_el->flags = LDB_FLAG_MOD_REPLACE;
+ }
break;
-
default:
/* many info classes are not valid for SetUserInfo */
}
/* modify the samdb record */
- ret = ldb_modify(a_state->sam_ctx, msg);
- if (ret != 0) {
- DEBUG(1,("Failed to modify record %s: %s\n",
- ldb_dn_get_linearized(a_state->account_dn),
- ldb_errstring(a_state->sam_ctx)));
+ if (msg->num_elements > 0) {
+ ret = ldb_modify(a_state->sam_ctx, msg);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1,("Failed to modify record %s: %s\n",
+ ldb_dn_get_linearized(a_state->account_dn),
+ ldb_errstring(a_state->sam_ctx)));
- /* we really need samdb.c to return NTSTATUS */
- return NT_STATUS_UNSUCCESSFUL;
+ /* we really need samdb.c to return NTSTATUS */
+ return NT_STATUS_UNSUCCESSFUL;
+ }
}
return NT_STATUS_OK;
struct ldb_message **res;
const char * const attrs[2] = { "objectSid", NULL };
struct samr_RidWithAttributeArray *array;
- int count;
+ int i, count;
DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
a_state = h->data;
d_state = a_state->domain_state;
- count = samdb_search_domain(a_state->sam_ctx, mem_ctx, d_state->domain_dn, &res,
+ count = samdb_search_domain(a_state->sam_ctx, mem_ctx,
+ d_state->domain_dn, &res,
attrs, d_state->domain_sid,
"(&(member=%s)(grouptype=%d)(objectclass=group))",
ldb_dn_get_linearized(a_state->account_dn),
array->count = 0;
array->rids = NULL;
- if (count > 0) {
- int i;
- array->rids = talloc_array(mem_ctx, struct samr_RidWithAttribute,
- count);
-
- if (array->rids == NULL)
- return NT_STATUS_NO_MEMORY;
+ array->rids = talloc_array(mem_ctx, struct samr_RidWithAttribute,
+ count + 1);
+ if (array->rids == NULL)
+ return NT_STATUS_NO_MEMORY;
- for (i=0; i<count; i++) {
- struct dom_sid *group_sid;
+ /* Adds the primary group */
+ array->rids[0].rid = samdb_search_uint(a_state->sam_ctx, mem_ctx,
+ ~0, a_state->account_dn,
+ "primaryGroupID", NULL);
+ array->rids[0].attributes = SE_GROUP_MANDATORY
+ | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
+ array->count += 1;
- group_sid = samdb_result_dom_sid(mem_ctx, res[i],
- "objectSid");
- if (group_sid == NULL) {
- DEBUG(0, ("Couldn't find objectSid attrib\n"));
- continue;
- }
+ /* Adds the additional groups */
+ for (i = 0; i < count; i++) {
+ struct dom_sid *group_sid;
- array->rids[array->count].rid =
- group_sid->sub_auths[group_sid->num_auths-1];
- array->rids[array->count].attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
- array->count += 1;
+ group_sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
+ if (group_sid == NULL) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
+
+ array->rids[i + 1].rid =
+ group_sid->sub_auths[group_sid->num_auths-1];
+ array->rids[i + 1].attributes = SE_GROUP_MANDATORY
+ | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
+ array->count += 1;
}
*r->out.rids = array;
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
struct ldb_message **res;
- int ldb_cnt, count, i;
- const char * const attrs[] = { "objectSid", "sAMAccountName", "displayName",
- "description", "userAccountControl", "pwdLastSet", NULL };
+ int i, ldb_cnt;
+ uint32_t count;
+ const char * const attrs[] = { "objectSid", "sAMAccountName",
+ "displayName", "description", "userAccountControl",
+ "pwdLastSet", NULL };
struct samr_DispEntryFull *entriesFull = NULL;
struct samr_DispEntryFullGroup *entriesFullGroup = NULL;
struct samr_DispEntryAscii *entriesAscii = NULL;
- struct samr_DispEntryGeneral * entriesGeneral = NULL;
+ struct samr_DispEntryGeneral *entriesGeneral = NULL;
const char *filter;
DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
break;
case 3:
case 5:
- filter = talloc_asprintf(mem_ctx, "(&(grouptype=%d)"
- "(objectclass=group))",
+ filter = talloc_asprintf(mem_ctx,
+ "(&(|(groupType=%d)(groupType=%d))"
+ "(objectClass=group))",
+ GTYPE_SECURITY_UNIVERSAL_GROUP,
GTYPE_SECURITY_GLOBAL_GROUP);
break;
default:
switch (r->in.level) {
case 1:
entriesGeneral = talloc_array(mem_ctx,
- struct samr_DispEntryGeneral,
- ldb_cnt);
+ struct samr_DispEntryGeneral,
+ ldb_cnt);
break;
case 2:
entriesFull = talloc_array(mem_ctx,
a_state = h->data;
- r->out.info->min_password_length = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0,
- a_state->domain_state->domain_dn, "minPwdLength",
- NULL);
- r->out.info->password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0,
- a_state->account_dn,
- "pwdProperties", NULL);
+ r->out.info->min_password_length = samdb_search_uint(a_state->sam_ctx,
+ mem_ctx, 0, a_state->domain_state->domain_dn, "minPwdLength",
+ NULL);
+ r->out.info->password_properties = samdb_search_uint(a_state->sam_ctx,
+ mem_ctx, 0, a_state->account_dn, "pwdProperties", NULL);
+
return NT_STATUS_OK;
}
}
if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod,
- "member", memberdn) != 0)
+ "member", memberdn) != LDB_SUCCESS)
return NT_STATUS_NO_MEMORY;
- if (ldb_modify(d_state->sam_ctx, mod) != 0)
+ if (ldb_modify(d_state->sam_ctx, mod) != LDB_SUCCESS)
return NT_STATUS_UNSUCCESSFUL;
talloc_free(mod);
ZERO_STRUCTP(r->out.info);
- sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
+ sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
+ dce_call->conn->dce_ctx->lp_ctx,
+ dce_call->conn->auth_state.session_info);
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
ret = gendb_search_dn(sam_ctx,
mem_ctx, NULL, &msgs, attrs);
if (ret <= 0) {
+ talloc_free(sam_ctx);
+
return NT_STATUS_NO_SUCH_DOMAIN;
}
if (ret > 1) {
talloc_free(msgs);
+ talloc_free(sam_ctx);
+
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- r->out.info->min_password_length = samdb_result_uint(msgs[0], "minPwdLength", 0);
- r->out.info->password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1);
+ r->out.info->min_password_length = samdb_result_uint(msgs[0],
+ "minPwdLength", 0);
+ r->out.info->password_properties = samdb_result_uint(msgs[0],
+ "pwdProperties", 1);
talloc_free(msgs);
+ talloc_unlink(mem_ctx, sam_ctx);
- talloc_free(sam_ctx);
return NT_STATUS_OK;
}
/*
- samr_ValidatePassword
+ samr_ValidatePassword
+
+ For now the call checks the password complexity (if active) and the minimum
+ password length on level 2 and 3. Level 1 is ignored for now.
*/
-static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct samr_ValidatePassword *r)
+static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct samr_ValidatePassword *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct samr_GetDomPwInfo r2;
+ struct samr_PwInfo pwInfo;
+ DATA_BLOB password;
+ enum samr_ValidationStatus res;
+ NTSTATUS status;
+
+ (*r->out.rep) = talloc_zero(mem_ctx, union samr_ValidatePasswordRep);
+
+ r2.in.domain_name = NULL;
+ r2.out.info = &pwInfo;
+ status = dcesrv_samr_GetDomPwInfo(dce_call, mem_ctx, &r2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ switch (r->in.level) {
+ case NetValidateAuthentication:
+ /* we don't support this yet */
+ return NT_STATUS_NOT_SUPPORTED;
+ break;
+ case NetValidatePasswordChange:
+ password = data_blob_const(r->in.req->req2.password.string,
+ r->in.req->req2.password.length);
+ res = samdb_check_password(&password,
+ pwInfo.password_properties,
+ pwInfo.min_password_length);
+ (*r->out.rep)->ctr2.status = res;
+ break;
+ case NetValidatePasswordReset:
+ password = data_blob_const(r->in.req->req3.password.string,
+ r->in.req->req3.password.length);
+ res = samdb_check_password(&password,
+ pwInfo.password_properties,
+ pwInfo.min_password_length);
+ (*r->out.rep)->ctr3.status = res;
+ break;
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ return NT_STATUS_OK;
}