r4283: adding a privilege that an account already has is not an error
[samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
index 5b3f2c9410965e2da3fa060ed2c65ef6e127221e..a4796f4356e1a5c0d9eab5edff9eb9d1e9818b71 100644 (file)
@@ -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
 */