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 (r->in.info->field.length != 0) { \
- if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 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); \
}
/* 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;
ret = gendb_search(c_state->sam_ctx,
mem_ctx, NULL, &dom_msgs, dom_attrs,
"(objectClass=builtinDomain)");
- } else if (strcasecmp_m(r->in.domain_name->string, lp_sam_name(dce_call->conn->dce_ctx->lp_ctx)) == 0) {
+ } 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);
for (i=0;i<2-start_i;i++) {
array->entries[i].idx = start_i + i;
if (i == 0) {
- array->entries[i].name.string = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
+ array->entries[i].name.string = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
} else {
array->entries[i].name.string = "BUILTIN";
}
d_state->domain_name = "BUILTIN";
} else {
d_state->builtin = false;
- d_state->domain_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
+ d_state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
}
ret = gendb_search(c_state->sam_ctx,
}
d_state->domain_dn = talloc_steal(d_state, dom_msgs[0]->dn);
- d_state->role = lp_server_role(dce_call->conn->dce_ctx->lp_ctx);
+ 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->access_mask = r->in.access_mask;
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",
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:
{
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:
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;
"(&(|(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];
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;
{
struct dcesrv_handle *h;
struct samr_domain_state *d_state;
- struct ldb_result *res;
- int ret;
- unsigned int i;
- uint32_t num_filtered_entries, 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 };
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 */
- TYPESAFE_QSORT(entries, num_filtered_entries, 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;
}
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];
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;
uint32_t i;
int count = 0;
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 samr_domain_state *d_state;
const char **names;
struct lsa_String *lsa_names;
- uint32_t *ids;
+ enum lsa_SidType *ids;
ZERO_STRUCTP(r->out.names);
ZERO_STRUCTP(r->out.types);
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, uint32_t, r->in.num_rids);
+ ids = talloc_zero_array(mem_ctx, enum lsa_SidType, r->in.num_rids);
if ((lsa_names == NULL) || (names == NULL) || (ids == NULL))
return NT_STATUS_NO_MEMORY;
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,
{
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);
static NTSTATUS dcesrv_samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryGroupMember *r)
{
- NTSTATUS status;
struct dcesrv_handle *h;
struct samr_account_state *a_state;
- struct samr_RidTypeArray *array;
+ struct samr_domain_state *d_state;
+ struct samr_RidAttrArray *array;
unsigned int i, num_members;
- struct dom_sid *members_as_sids;
- struct dom_sid *dom_sid;
+ 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;
- dom_sid = a_state->domain_state->domain_sid;
- status = dsdb_enum_group_mem(a_state->sam_ctx, mem_ctx, a_state->account_dn, &members_as_sids, &num_members);
-
+ 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_zero(mem_ctx, struct samr_RidTypeArray);
-
- if (array == NULL)
+ array = talloc_zero(mem_ctx, struct samr_RidAttrArray);
+ if (array == NULL) {
return NT_STATUS_NO_MEMORY;
+ }
if (num_members == 0) {
*r->out.rids = array;
return NT_STATUS_OK;
}
- array->count = 0;
- array->rids = talloc_array(array, uint32_t,
- num_members);
- if (array->rids == NULL)
+ array->rids = talloc_array(array, uint32_t, num_members);
+ if (array->rids == NULL) {
return NT_STATUS_NO_MEMORY;
+ }
- array->types = talloc_array(array, uint32_t,
- num_members);
- if (array->types == NULL)
+ array->attributes = talloc_array(array, uint32_t, num_members);
+ if (array->attributes == NULL) {
return NT_STATUS_NO_MEMORY;
+ }
+ array->count = 0;
for (i=0; i<num_members; i++) {
- if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
+ if (!dom_sid_in_domain(d_state->domain_sid, &members[i])) {
continue;
}
- status = dom_sid_split_rid(NULL, &members_as_sids[i], NULL, &array->rids[array->count]);
+
+ 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->attributes[array->count] = SE_GROUP_MANDATORY |
+ SE_GROUP_ENABLED_BY_DEFAULT |
+ SE_GROUP_ENABLED;
array->count++;
}
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),
/* 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;
}
return NT_STATUS_UNSUCCESSFUL;
}
- if (ldb_modify(a_state->sam_ctx, mod) != LDB_SUCCESS) {
+ 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;
}
return NT_STATUS_UNSUCCESSFUL;
}
- if (ldb_modify(a_state->sam_ctx, mod) != LDB_SUCCESS) {
+ 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 lsa_SidPtr *sids;
+ 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;
status = dsdb_enum_group_mem(d_state->sam_ctx, mem_ctx,
- a_state->account_dn, &members, &num_members);
+ a_state->account_dn, &members,
+ &num_members);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- r->out.sids->sids = NULL;
-
if (num_members == 0) {
+ r->out.sids->sids = NULL;
+
return NT_STATUS_OK;
}
- sids = talloc_array(mem_ctx, struct lsa_SidPtr,
- num_members);
-
- if (sids == NULL)
+ array = talloc_array(mem_ctx, struct lsa_SidPtr, num_members);
+ if (array == NULL) {
return NT_STATUS_NO_MEMORY;
+ }
for (i=0; i<num_members; i++) {
- sids[i].sid = dom_sid_dup(sids, &members[i]);
- if (sids[i].sid == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ array[i].sid = &members[i];
}
r->out.sids->num_sids = num_members;
- r->out.sids->sids = sids;
+ r->out.sids->sids = array;
return NT_STATUS_OK;
}
/* 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;
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:
+ 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");
IFSET(SAMR_FIELD_ACCOUNT_NAME)
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");
+
+ /* 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");
IFSET(SAMR_FIELD_ACCOUNT_NAME)
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,
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->domain_state->domain_dn,
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");
IFSET(SAMR_FIELD_ACCOUNT_NAME)
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,
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->domain_state->domain_dn,
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 */
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))",
+ "(&(member=%s)(|(grouptype=%d)(grouptype=%d))(objectclass=group))",
ldb_dn_get_linearized(a_state->account_dn),
- GTYPE_SECURITY_GLOBAL_GROUP);
+ GTYPE_SECURITY_GLOBAL_GROUP,
+ GTYPE_SECURITY_UNIVERSAL_GROUP);
if (count < 0)
return NT_STATUS_INTERNAL_DB_CORRUPTION;
group_sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
if (group_sid == NULL) {
- DEBUG(0, ("Couldn't find objectSid attrib\n"));
- continue;
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
array->rids[i + 1].rid =