diff options
Diffstat (limited to 'source4/rpc_server')
-rw-r--r-- | source4/rpc_server/lsa/dcesrv_lsa.c | 150 |
1 files changed, 90 insertions, 60 deletions
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 5b3f2c9410..a4796f4356 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -878,6 +878,56 @@ static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, return NT_STATUS_OK; } +/* + lsa_EnumAccountRights +*/ +static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct lsa_EnumAccountRights *r) +{ + struct dcesrv_handle *h; + struct lsa_policy_state *state; + int ret, i; + struct ldb_message **res; + const char * const attrs[] = { "privilege", NULL}; + const char *sidstr; + struct ldb_message_element *el; + + DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY); + + state = h->data; + + sidstr = dom_sid_string(mem_ctx, r->in.sid); + if (sidstr == NULL) { + return NT_STATUS_NO_MEMORY; + } + + ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, + "objectSid=%s", sidstr); + if (ret != 1) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + el = ldb_msg_find_element(res[0], "privilege"); + if (el == NULL || el->num_values == 0) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + r->out.rights->count = el->num_values; + r->out.rights->names = talloc_array_p(r->out.rights, + struct lsa_String, r->out.rights->count); + if (r->out.rights->names == NULL) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0;i<el->num_values;i++) { + r->out.rights->names[i].string = el->values[i].data; + } + + return NT_STATUS_OK; +} + + /* helper for lsa_AddAccountRights and lsa_RemoveAccountRights @@ -886,7 +936,7 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct lsa_policy_state *state, int ldb_flag, - const struct dom_sid *sid, + struct dom_sid *sid, const struct lsa_RightSet *rights) { const char *sidstr; @@ -894,6 +944,7 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, struct ldb_message_element el; int i, ret; const char *dn; + struct lsa_EnumAccountRights r2; sidstr = dom_sid_string(mem_ctx, sid); if (sidstr == NULL) { @@ -917,20 +968,52 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, if (el.name == NULL) { return NT_STATUS_NO_MEMORY; } - el.num_values = rights->count; - el.values = talloc_array_p(mem_ctx, struct ldb_val, el.num_values); + + if (ldb_flag == LDB_FLAG_MOD_ADD) { + NTSTATUS status; + + r2.in.handle = &state->handle->wire_handle; + r2.in.sid = sid; + r2.out.rights = talloc_p(mem_ctx, struct lsa_RightSet); + + status = lsa_EnumAccountRights(dce_call, mem_ctx, &r2); + if (!NT_STATUS_IS_OK(status)) { + ZERO_STRUCTP(r2.out.rights); + } + } + + el.num_values = 0; + el.values = talloc_array_p(mem_ctx, struct ldb_val, rights->count); if (el.values == NULL) { return NT_STATUS_NO_MEMORY; } - for (i=0;i<el.num_values;i++) { + for (i=0;i<rights->count;i++) { if (sec_privilege_id(rights->names[i].string) == -1) { return NT_STATUS_NO_SUCH_PRIVILEGE; } - el.values[i].length = strlen(rights->names[i].string); - el.values[i].data = talloc_strdup(mem_ctx, rights->names[i].string); - if (el.values[i].data == NULL) { + + if (ldb_flag == LDB_FLAG_MOD_ADD) { + int j; + for (j=0;j<r2.out.rights->count;j++) { + if (StrCaseCmp(r2.out.rights->names[j].string, + rights->names[i].string) == 0) { + break; + } + } + if (j != r2.out.rights->count) continue; + } + + + el.values[el.num_values].length = strlen(rights->names[i].string); + el.values[el.num_values].data = talloc_strdup(mem_ctx, rights->names[i].string); + if (el.values[el.num_values].data == NULL) { return NT_STATUS_NO_MEMORY; } + el.num_values++; + } + + if (el.num_values == 0) { + return NT_STATUS_OK; } ret = samdb_modify(state->sam_ctx, mem_ctx, &msg); @@ -944,59 +1027,6 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, return NT_STATUS_OK; } - -/* - lsa_EnumAccountRights -*/ -static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - struct lsa_EnumAccountRights *r) -{ - struct dcesrv_handle *h; - struct lsa_policy_state *state; - int ret, i; - struct ldb_message **res; - const char * const attrs[] = { "privilege", NULL}; - const char *sidstr; - struct ldb_message_element *el; - - DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY); - - state = h->data; - - sidstr = dom_sid_string(mem_ctx, r->in.sid); - if (sidstr == NULL) { - return NT_STATUS_NO_MEMORY; - } - - ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, - "objectSid=%s", sidstr); - if (ret != 1) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - el = ldb_msg_find_element(res[0], "privilege"); - if (el == NULL || el->num_values == 0) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - r->out.rights->count = el->num_values; - r->out.rights->names = talloc_array_p(r->out.rights, - struct lsa_String, r->out.rights->count); - if (r->out.rights->names == NULL) { - return NT_STATUS_NO_MEMORY; - } - - for (i=0;i<el->num_values;i++) { - r->out.rights->names[i].string = el->values[i].data; - } - - return NT_STATUS_OK; -} - - - - /* lsa_AddPrivilegesToAccount */ |