diff options
author | Volker Lendecke <vlendec@samba.org> | 2004-12-26 18:02:18 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:07:39 -0500 |
commit | 77529ae7926e2d299e7703c5f1b84cb849b4563b (patch) | |
tree | c5ea5655b243b8941d1aa2c1c655d133699338ef /source4 | |
parent | b29b10e48ee351c19cb7a0e9766718fa1715f747 (diff) | |
download | samba-77529ae7926e2d299e7703c5f1b84cb849b4563b.tar.gz samba-77529ae7926e2d299e7703c5f1b84cb849b4563b.tar.bz2 samba-77529ae7926e2d299e7703c5f1b84cb849b4563b.zip |
r4367: Implement samr_AddGroupMember, samr_DeleteGroupMember and
samr_QueryGroupMember.
Volker
(This used to be commit 43581c3711d2eeb901094acebea294a3b87d4c0b)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/samdb/samdb.c | 54 | ||||
-rw-r--r-- | source4/rpc_server/samr/dcesrv_samr.c | 181 |
2 files changed, 230 insertions, 5 deletions
diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c index 209599b9dc..2fcc71a8a9 100644 --- a/source4/dsdb/samdb/samdb.c +++ b/source4/dsdb/samdb/samdb.c @@ -711,6 +711,60 @@ int samdb_msg_add_delete(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg } /* + add a add attribute value to a message +*/ +int samdb_msg_add_addval(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg, + const char *attr_name, const char *value) +{ + struct ldb_wrap *sam_ctx = ctx; + struct ldb_message_element *el; + char *a, *v; + int ret; + a = talloc_strdup(mem_ctx, attr_name); + if (a == NULL) + return -1; + v = talloc_strdup(mem_ctx, value); + if (v == NULL) + return -1; + ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx); + ret = ldb_msg_add_string(sam_ctx->ldb, msg, a, v); + if (ret != 0) + return ret; + el = ldb_msg_find_element(msg, a); + if (el == NULL) + return -1; + el->flags = LDB_FLAG_MOD_ADD; + return 0; +} + +/* + add a delete attribute value to a message +*/ +int samdb_msg_add_delval(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg, + const char *attr_name, const char *value) +{ + struct ldb_wrap *sam_ctx = ctx; + struct ldb_message_element *el; + char *a, *v; + int ret; + a = talloc_strdup(mem_ctx, attr_name); + if (a == NULL) + return -1; + v = talloc_strdup(mem_ctx, value); + if (v == NULL) + return -1; + ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx); + ret = ldb_msg_add_string(sam_ctx->ldb, msg, a, v); + if (ret != 0) + return ret; + el = ldb_msg_find_element(msg, a); + if (el == NULL) + return -1; + el->flags = LDB_FLAG_MOD_DELETE; + return 0; +} + +/* add a uint_t element to a message */ int samdb_msg_add_uint(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg, diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index 2e71ad990d..5cd40184df 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -37,6 +37,15 @@ static void samr_handle_destroy(struct dcesrv_connection *conn, struct dcesrv_ha talloc_free(h->data); } +/* + This is a bad temporary hack until we have at least some kind of schema + support +*/ +static char *ldb_hexstr(TALLOC_CTX *mem_ctx, uint32 val) +{ + return talloc_asprintf(mem_ctx, "0x%.8x", val); +} + /* samr_Connect @@ -1090,8 +1099,10 @@ static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *m /* search for the group record */ ret = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &msgs, attrs, - "(&(objectSid=%s)(objectclass=group))", - sidstr); + "(&(objectSid=%s)(objectclass=group)" + "(grouptype=%s))", + sidstr, ldb_hexstr(mem_ctx, + GTYPE_SECURITY_GLOBAL_GROUP)); if (ret == 0) { return NT_STATUS_NO_SUCH_GROUP; } @@ -1297,7 +1308,54 @@ static NTSTATUS samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX static NTSTATUS samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct samr_AddGroupMember *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + struct dcesrv_handle *h; + struct samr_account_state *a_state; + struct samr_domain_state *d_state; + struct ldb_message mod; + char *membersidstr; + const char *memberdn; + struct ldb_message **msgs; + const char * const attrs[2] = { "dn", NULL }; + int ret; + + DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP); + + a_state = h->data; + d_state = a_state->domain_state; + + membersidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, + r->in.rid); + if (membersidstr == 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. */ + ret = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, + &msgs, attrs, "(&(objectSid=%s)(objectclass=user))", + membersidstr); + + if (ret == 0) + return NT_STATUS_NO_SUCH_USER; + + if (ret > 1) + return NT_STATUS_INTERNAL_DB_CORRUPTION; + + memberdn = samdb_result_string(msgs[0], "dn", NULL); + + if (memberdn == NULL) + return NT_STATUS_INTERNAL_DB_CORRUPTION; + + ZERO_STRUCT(mod); + 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) + return NT_STATUS_UNSUCCESSFUL; + + if (samdb_modify(a_state->sam_ctx, mem_ctx, &mod) != 0) + return NT_STATUS_UNSUCCESSFUL; + + return NT_STATUS_OK; } @@ -1334,7 +1392,54 @@ static NTSTATUS samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLO static NTSTATUS samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct samr_DeleteGroupMember *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + struct dcesrv_handle *h; + struct samr_account_state *a_state; + struct samr_domain_state *d_state; + struct ldb_message mod; + char *membersidstr; + const char *memberdn; + struct ldb_message **msgs; + const char * const attrs[2] = { "dn", NULL }; + int ret; + + DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP); + + a_state = h->data; + d_state = a_state->domain_state; + + membersidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, + r->in.rid); + if (membersidstr == 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. */ + ret = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, + &msgs, attrs, "(&(objectSid=%s)(objectclass=user))", + membersidstr); + + if (ret == 0) + return NT_STATUS_NO_SUCH_USER; + + if (ret > 1) + return NT_STATUS_INTERNAL_DB_CORRUPTION; + + memberdn = samdb_result_string(msgs[0], "dn", NULL); + + if (memberdn == NULL) + return NT_STATUS_INTERNAL_DB_CORRUPTION; + + ZERO_STRUCT(mod); + 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) + return NT_STATUS_UNSUCCESSFUL; + + if (samdb_modify(a_state->sam_ctx, mem_ctx, &mod) != 0) + return NT_STATUS_UNSUCCESSFUL; + + return NT_STATUS_OK; } @@ -1344,7 +1449,73 @@ static NTSTATUS samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLO static NTSTATUS samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct samr_QueryGroupMember *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + struct dcesrv_handle *h; + struct samr_account_state *a_state; + struct ldb_message **res; + struct ldb_message_element *el; + struct samr_ridArray *array; + const char * const attrs[2] = { "member", NULL }; + int ret; + + DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP); + + a_state = h->data; + + /* pull the member attribute */ + ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, attrs, + "dn=%s", a_state->account_dn); + + if (ret != 1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + array = talloc_p(mem_ctx, struct samr_ridArray); + + 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_p(mem_ctx, uint32, + el->num_values); + if (array->rids == NULL) + return NT_STATUS_NO_MEMORY; + + array->unknown = talloc_array_p(mem_ctx, uint32, + el->num_values); + if (array->unknown == NULL) + return NT_STATUS_NO_MEMORY; + + for (i=0; i<el->num_values; i++) { + struct ldb_message **res2; + const char * const attrs2[2] = { "objectSid", NULL }; + ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, + &res2, attrs2, "dn=%s", + (char *)el->values[i].data); + if (ret != 1) + return NT_STATUS_INTERNAL_DB_CORRUPTION; + + array->rids[i] = + samdb_result_rid_from_sid(mem_ctx, res2[0], + "objectSid", 0); + + if (array->rids[i] == 0) + return NT_STATUS_INTERNAL_DB_CORRUPTION; + + array->unknown[i] = 7; /* Not sure what this is.. */ + } + } + + r->out.rids = array; + + return NT_STATUS_OK; } |