1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-26 10:04:02 +03:00

r615: Implement samr_OpenGroup, samr_QueryGroupInfo, samr_SetGroupInfo,

samr_DeleteDomainGroup.

I've added the hidden attribute numMembers that must be maintained by
Add/DelGroupMember for the GroupInfoAll query.

Volker
(This used to be commit 945d7478605c1bd67e4162ebb0635ab7da11faaf)
This commit is contained in:
Volker Lendecke 2004-05-09 15:39:12 +00:00 committed by Gerald (Jerry) Carter
parent c041077856
commit 16f7b35a0a
3 changed files with 243 additions and 50 deletions

View File

@ -8,6 +8,7 @@ dn: @ATTRIBUTES
name: CASE_INSENSITIVE WILDCARD
sAMAccountName: CASE_INSENSITIVE WILDCARD
objectClass: CASE_INSENSITIVE
numMembers: HIDDEN
dn: @SUBCLASSES
top: domain

View File

@ -955,9 +955,133 @@ static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *
static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_OpenGroup *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
struct samr_domain_state *d_state;
struct samr_account_state *state;
struct dcesrv_handle *h;
const char *groupname, *sidstr;
TALLOC_CTX *mem_ctx2;
struct ldb_message **msgs;
struct dcesrv_handle *g_handle;
const char * const attrs[2] = { "sAMAccountName", NULL };
int ret;
ZERO_STRUCTP(r->out.acct_handle);
DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_DOMAIN);
d_state = h->data;
/* form the group SID */
sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
if (!sidstr) {
return NT_STATUS_NO_MEMORY;
}
/* search for the group record */
ret = samdb_search(d_state->sam_ctx,
mem_ctx, d_state->basedn, &msgs, attrs,
"(&(objectSid=%s)(objectclass=group))",
sidstr);
if (ret == 0) {
return NT_STATUS_NO_SUCH_GROUP;
}
if (ret != 1) {
DEBUG(1,("Found %d records matching sid %s\n", ret, sidstr));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);
if (groupname == NULL) {
DEBUG(1,("sAMAccountName field missing for sid %s\n", sidstr));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/* create group state and new policy handle */
mem_ctx2 = talloc_init("OpenGroup(%u)", r->in.rid);
if (!mem_ctx2) {
return NT_STATUS_NO_MEMORY;
}
state = talloc_p(mem_ctx2, struct samr_account_state);
if (!state) {
return NT_STATUS_NO_MEMORY;
}
state->mem_ctx = mem_ctx2;
state->sam_ctx = d_state->sam_ctx;
state->access_mask = r->in.access_mask;
state->domain_state = d_state;
state->basedn = talloc_steal(mem_ctx, mem_ctx2, msgs[0]->dn);
state->account_sid = talloc_strdup(mem_ctx2, sidstr);
state->account_name = talloc_strdup(mem_ctx2, groupname);
if (!state->account_name || !state->account_sid) {
return NT_STATUS_NO_MEMORY;
}
/* create the policy handle */
g_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_GROUP);
if (!g_handle) {
return NT_STATUS_NO_MEMORY;
}
g_handle->data = state;
g_handle->destroy = samr_Account_destroy;
/* the domain state is in use one more time */
d_state->reference_count++;
*r->out.acct_handle = g_handle->wire_handle;
return NT_STATUS_OK;
}
/* these query macros make samr_Query[User|Group]Info a bit easier to read */
#define QUERY_STRING(msg, field, attr) \
r->out.info->field = samdb_result_string(msg, attr, "");
#define QUERY_UINT(msg, field, attr) \
r->out.info->field = samdb_result_uint(msg, attr, 0);
#define QUERY_RID(msg, field, attr) \
r->out.info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
#define QUERY_NTTIME(msg, field, attr) \
r->out.info->field = samdb_result_nttime(msg, attr, 0);
#define QUERY_APASSC(msg, field, attr) \
r->out.info->field = samdb_result_allow_pwd_change(state->sam_ctx, mem_ctx, \
state->domain_state->basedn, msg, attr);
#define QUERY_FPASSC(msg, field, attr) \
r->out.info->field = samdb_result_force_pwd_change(state->sam_ctx, mem_ctx, \
state->domain_state->basedn, msg, attr);
#define QUERY_LHOURS(msg, field, attr) \
r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
#define QUERY_AFLAGS(msg, field, attr) \
r->out.info->field = samdb_result_acct_flags(msg, attr);
/* these are used to make the Set[User|Group]Info code easier to follow */
#define SET_STRING(mod, field, attr) do { \
if (r->in.info->field == NULL) return NT_STATUS_INVALID_PARAMETER; \
if (samdb_msg_add_string(state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
return NT_STATUS_NO_MEMORY; \
} \
} while (0)
#define SET_UINT(mod, field, attr) do { \
if (samdb_msg_add_uint(state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
return NT_STATUS_NO_MEMORY; \
} \
} while (0)
#define SET_AFLAGS(msg, field, attr) do { \
if (samdb_msg_add_acct_flags(state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
return NT_STATUS_NO_MEMORY; \
} \
} while (0)
#define SET_LHOURS(msg, field, attr) do { \
if (samdb_msg_add_logon_hours(state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
return NT_STATUS_NO_MEMORY; \
} \
} while (0)
/*
samr_QueryGroupInfo
@ -965,7 +1089,57 @@ static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
static NTSTATUS samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_QueryGroupInfo *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
struct dcesrv_handle *h;
struct samr_account_state *state;
struct ldb_message *msg, **res;
const char * const attrs[4] = { "sAMAccountName", "description",
"numMembers", NULL };
int ret;
r->out.info = NULL;
DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_GROUP);
state = h->data;
/* pull all the group attributes */
ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs,
"dn=%s", state->basedn);
if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
msg = res[0];
/* allocate the info structure */
r->out.info = talloc_p(mem_ctx, union samr_GroupInfo);
if (r->out.info == NULL) {
return NT_STATUS_NO_MEMORY;
}
ZERO_STRUCTP(r->out.info);
/* Fill in the level */
switch (r->in.level) {
case GroupInfoAll:
QUERY_STRING(msg, all.name.name, "sAMAccountName");
r->out.info->all.unknown = 7; /* Do like w2k3 */
QUERY_UINT (msg, all.num_members, "numMembers")
QUERY_STRING(msg, all.description.name, "description");
break;
case GroupInfoName:
QUERY_STRING(msg, name.name, "sAMAccountName");
break;
case GroupInfoX:
r->out.info->unknown.unknown = 7;
break;
case GroupInfoDescription:
QUERY_STRING(msg, description.name, "description");
break;
default:
r->out.info = NULL;
return NT_STATUS_INVALID_INFO_CLASS;
}
return NT_STATUS_OK;
}
@ -975,7 +1149,50 @@ static NTSTATUS samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_C
static NTSTATUS samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_SetGroupInfo *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
struct dcesrv_handle *h;
struct samr_account_state *state;
struct ldb_message mod, *msg = &mod;
int i, ret;
DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_GROUP);
state = h->data;
ZERO_STRUCT(mod);
mod.dn = talloc_strdup(mem_ctx, state->basedn);
if (!mod.dn) {
return NT_STATUS_NO_MEMORY;
}
switch (r->in.level) {
case GroupInfoDescription:
SET_STRING(msg, description.name, "description");
break;
case GroupInfoName:
/* On W2k3 this does not change the name, it changes the
* sAMAccountName attribute */
SET_STRING(msg, name.name, "sAMAccountName");
break;
case GroupInfoX:
/* This does not do anything obviously visible in W2k3 LDAP */
break;
default:
return NT_STATUS_INVALID_INFO_CLASS;
}
/* mark all the message elements as LDB_FLAG_MOD_REPLACE */
for (i=0;i<mod.num_elements;i++) {
mod.elements[i].flags = LDB_FLAG_MOD_REPLACE;
}
/* modify the samdb record */
ret = samdb_modify(state->sam_ctx, mem_ctx, &mod);
if (ret != 0) {
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL;
}
return NT_STATUS_OK;
}
@ -995,7 +1212,24 @@ static NTSTATUS samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_C
static NTSTATUS samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_DeleteDomainGroup *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
struct dcesrv_handle *h;
struct samr_account_state *state;
int ret;
*r->out.handle = *r->in.handle;
DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_GROUP);
state = h->data;
ret = samdb_delete(state->sam_ctx, mem_ctx, state->basedn);
if (ret != 0) {
return NT_STATUS_UNSUCCESSFUL;
}
ZERO_STRUCTP(r->out.handle);
return NT_STATUS_OK;
}
@ -1212,26 +1446,6 @@ static NTSTATUS samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *
return NT_STATUS_OK;
}
/* these query macros make samr_QueryUserInfo a bit easier to read */
#define QUERY_STRING(msg, field, attr) \
r->out.info->field = samdb_result_string(msg, attr, "");
#define QUERY_UINT(msg, field, attr) \
r->out.info->field = samdb_result_uint(msg, attr, 0);
#define QUERY_RID(msg, field, attr) \
r->out.info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
#define QUERY_NTTIME(msg, field, attr) \
r->out.info->field = samdb_result_nttime(msg, attr, 0);
#define QUERY_APASSC(msg, field, attr) \
r->out.info->field = samdb_result_allow_pwd_change(state->sam_ctx, mem_ctx, \
state->domain_state->basedn, msg, attr);
#define QUERY_FPASSC(msg, field, attr) \
r->out.info->field = samdb_result_force_pwd_change(state->sam_ctx, mem_ctx, \
state->domain_state->basedn, msg, attr);
#define QUERY_LHOURS(msg, field, attr) \
r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
#define QUERY_AFLAGS(msg, field, attr) \
r->out.info->field = samdb_result_acct_flags(msg, attr);
/*
samr_QueryUserInfo
@ -1414,32 +1628,6 @@ static NTSTATUS samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CT
}
/* these are used to make the SetUserInfo code easier to follow */
#define SET_STRING(mod, field, attr) do { \
if (r->in.info->field == NULL) return NT_STATUS_INVALID_PARAMETER; \
if (samdb_msg_add_string(state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
return NT_STATUS_NO_MEMORY; \
} \
} while (0)
#define SET_UINT(mod, field, attr) do { \
if (samdb_msg_add_uint(state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
return NT_STATUS_NO_MEMORY; \
} \
} while (0)
#define SET_AFLAGS(msg, field, attr) do { \
if (samdb_msg_add_acct_flags(state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
return NT_STATUS_NO_MEMORY; \
} \
} while (0)
#define SET_LHOURS(msg, field, attr) do { \
if (samdb_msg_add_logon_hours(state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
return NT_STATUS_NO_MEMORY; \
} \
} while (0)
/*
samr_SetUserInfo
*/

View File

@ -1615,6 +1615,10 @@ static BOOL test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
s.in.level = levels[i];
s.in.info = r.out.info;
if (s.in.level == 2) {
init_samr_Name(&s.in.info->name, "NewName");
}
if (s.in.level == 4) {
init_samr_Name(&s.in.info->description, "test description");
}