WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
struct NetGroupAdd *r)
{
- struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
NTSTATUS status;
WERROR werr;
- POLICY_HND connect_handle, domain_handle, group_handle;
+ struct policy_handle connect_handle, domain_handle, group_handle;
struct lsa_String lsa_group_name;
struct dom_sid2 *domain_sid = NULL;
uint32_t rid = 0;
ZERO_STRUCT(domain_handle);
ZERO_STRUCT(group_handle);
- if (!r->in.buf) {
+ if (!r->in.buffer) {
return WERR_INVALID_PARAM;
}
switch (r->in.level) {
case 0:
- info0 = (struct GROUP_INFO_0 *)r->in.buf;
+ info0 = (struct GROUP_INFO_0 *)r->in.buffer;
break;
case 1:
- info1 = (struct GROUP_INFO_1 *)r->in.buf;
+ info1 = (struct GROUP_INFO_1 *)r->in.buffer;
break;
case 2:
- info2 = (struct GROUP_INFO_2 *)r->in.buf;
+ info2 = (struct GROUP_INFO_2 *)r->in.buffer;
break;
case 3:
- info3 = (struct GROUP_INFO_3 *)r->in.buf;
+ info3 = (struct GROUP_INFO_3 *)r->in.buffer;
break;
default:
werr = WERR_UNKNOWN_LEVEL;
goto done;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
&group_handle);
done:
- if (!cli) {
- return werr;
- }
-
if (is_valid_policy_hnd(&group_handle)) {
rpccli_samr_Close(pipe_cli, ctx, &group_handle);
}
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
return werr;
WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
struct NetGroupAdd *r)
{
- return NetGroupAdd_r(ctx, r);
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
}
/****************************************************************
WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
struct NetGroupDel *r)
{
- struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
NTSTATUS status;
WERROR werr;
- POLICY_HND connect_handle, domain_handle, group_handle;
+ struct policy_handle connect_handle, domain_handle, group_handle;
struct lsa_String lsa_group_name;
struct dom_sid2 *domain_sid = NULL;
int i = 0;
return WERR_INVALID_PARAM;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
werr = WERR_OK;
done:
- if (!cli) {
- return werr;
- }
-
if (is_valid_policy_hnd(&group_handle)) {
rpccli_samr_Close(pipe_cli, ctx, &group_handle);
}
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
return werr;
WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
struct NetGroupDel *r)
{
- return NetGroupDel_r(ctx, r);
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
}
/****************************************************************
WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
struct NetGroupSetInfo *r)
{
- struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
NTSTATUS status;
WERROR werr;
- POLICY_HND connect_handle, domain_handle, group_handle;
+ struct policy_handle connect_handle, domain_handle, group_handle;
struct lsa_String lsa_group_name;
struct dom_sid2 *domain_sid = NULL;
return WERR_INVALID_PARAM;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
switch (r->in.level) {
case 0:
- g0 = (struct GROUP_INFO_0 *)r->in.buf;
+ g0 = (struct GROUP_INFO_0 *)r->in.buffer;
init_lsa_String(&info.name, g0->grpi0_name);
status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
&group_handle,
&info);
break;
case 1:
- g1 = (struct GROUP_INFO_1 *)r->in.buf;
+ g1 = (struct GROUP_INFO_1 *)r->in.buffer;
init_lsa_String(&info.description, g1->grpi1_comment);
status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
&group_handle,
&info);
break;
case 2:
- g2 = (struct GROUP_INFO_2 *)r->in.buf;
+ g2 = (struct GROUP_INFO_2 *)r->in.buffer;
init_lsa_String(&info.description, g2->grpi2_comment);
status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
&group_handle,
&info);
break;
case 3:
- g3 = (struct GROUP_INFO_3 *)r->in.buf;
+ g3 = (struct GROUP_INFO_3 *)r->in.buffer;
init_lsa_String(&info.description, g3->grpi3_comment);
status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
&group_handle,
&info);
break;
case 1002:
- g1002 = (struct GROUP_INFO_1002 *)r->in.buf;
+ g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
init_lsa_String(&info.description, g1002->grpi1002_comment);
status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
&group_handle,
&info);
break;
case 1005:
- g1005 = (struct GROUP_INFO_1005 *)r->in.buf;
+ g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
info.attributes.attributes = g1005->grpi1005_attributes;
status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
&group_handle,
werr = WERR_OK;
done:
- if (!cli) {
- return werr;
- }
-
if (is_valid_policy_hnd(&group_handle)) {
rpccli_samr_Close(pipe_cli, ctx, &group_handle);
}
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
return werr;
WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
struct NetGroupSetInfo *r)
{
- return NetGroupSetInfo_r(ctx, r);
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
}
/****************************************************************
WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
struct NetGroupGetInfo *r)
{
- struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
NTSTATUS status;
WERROR werr;
- POLICY_HND connect_handle, domain_handle, group_handle;
+ struct policy_handle connect_handle, domain_handle, group_handle;
struct lsa_String lsa_group_name;
struct dom_sid2 *domain_sid = NULL;
struct samr_Ids rids;
struct samr_Ids types;
union samr_GroupInfo *info = NULL;
+ bool group_info_all = false;
ZERO_STRUCT(connect_handle);
ZERO_STRUCT(domain_handle);
return WERR_INVALID_PARAM;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
&group_handle,
GROUPINFOALL2,
&info);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
+ status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOALL,
+ &info);
+ group_info_all = true;
+ }
+
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
}
werr = map_group_info_to_buffer(ctx, r->in.level,
- &info->all2, domain_sid, rids.ids[0],
- r->out.buf);
+ group_info_all ? &info->all : &info->all2,
+ domain_sid, rids.ids[0],
+ r->out.buffer);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
done:
- if (!cli) {
- return werr;
- }
-
if (is_valid_policy_hnd(&group_handle)) {
rpccli_samr_Close(pipe_cli, ctx, &group_handle);
}
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
return werr;
WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
struct NetGroupGetInfo *r)
{
- return NetGroupGetInfo_r(ctx, r);
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
}
/****************************************************************
WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
struct NetGroupAddUser *r)
{
- struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
NTSTATUS status;
WERROR werr;
- POLICY_HND connect_handle, domain_handle, group_handle;
+ struct policy_handle connect_handle, domain_handle, group_handle;
struct lsa_String lsa_group_name, lsa_user_name;
struct dom_sid2 *domain_sid = NULL;
return WERR_INVALID_PARAM;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
werr = WERR_OK;
done:
- if (!cli) {
- return werr;
- }
-
if (is_valid_policy_hnd(&group_handle)) {
rpccli_samr_Close(pipe_cli, ctx, &group_handle);
}
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
return werr;
WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
struct NetGroupAddUser *r)
{
- return NetGroupAddUser_r(ctx, r);
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
}
/****************************************************************
WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
struct NetGroupDelUser *r)
{
- struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
NTSTATUS status;
WERROR werr;
- POLICY_HND connect_handle, domain_handle, group_handle;
+ struct policy_handle connect_handle, domain_handle, group_handle;
struct lsa_String lsa_group_name, lsa_user_name;
struct dom_sid2 *domain_sid = NULL;
return WERR_INVALID_PARAM;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
werr = WERR_OK;
done:
- if (!cli) {
- return werr;
- }
-
if (is_valid_policy_hnd(&group_handle)) {
rpccli_samr_Close(pipe_cli, ctx, &group_handle);
}
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
return werr;
WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
struct NetGroupDelUser *r)
{
- return NetGroupDelUser_r(ctx, r);
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
}
/****************************************************************
WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
struct NetGroupEnum *r)
{
- struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
struct policy_handle connect_handle;
struct dom_sid2 *domain_sid = NULL;
uint32_t total_size = 0;
uint32_t returned_size = 0;
- NTSTATUS status;
+ NTSTATUS status = NT_STATUS_OK;
WERROR werr, tmp_werr;
ZERO_STRUCT(connect_handle);
return WERR_UNKNOWN_LEVEL;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
}
if (r->out.total_entries) {
- *r->out.total_entries = domain_info->info2.num_groups;
+ *r->out.total_entries = domain_info->general.num_groups;
}
status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
goto done;
}
- if (r->out.resume_handle) {
+ if (r->out.resume_handle && info.info3.count > 0) {
*r->out.resume_handle =
info.info3.entries[info.info3.count-1].idx;
}
}
done:
- if (!cli) {
- return werr;
- }
-#if 0
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+ /* if last query */
+ if (NT_STATUS_IS_OK(status) ||
+ NT_STATUS_IS_ERR(status)) {
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
}
-#endif
+
return werr;
}
WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
struct NetGroupEnum *r)
{
- return NetGroupEnum_r(ctx, r);
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r)
+{
+ /* FIXME: this call needs to cope with large replies */
+
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids group_rids, name_types;
+ struct samr_RidTypeArray *rid_array = NULL;
+ struct lsa_Strings names;
+ struct samr_Ids member_types;
+
+ int i;
+ uint32_t entries_read = 0;
+
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &group_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_GET_MEMBERS,
+ group_rids.ids[0],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
+ &group_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_LookupRids(pipe_cli, ctx,
+ &domain_handle,
+ rid_array->count,
+ rid_array->rids,
+ &names,
+ &member_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i < names.count; i++) {
+
+ if (member_types.ids[i] != SID_NAME_USER) {
+ continue;
+ }
+
+ status = add_GROUP_USERS_INFO_X_buffer(ctx,
+ r->in.level,
+ names.names[i].string,
+ 7,
+ r->out.buffer,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ if (r->out.entries_read) {
+ *r->out.entries_read = entries_read;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries = entries_read;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ union samr_GroupInfo *group_info = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_Ids group_rids, group_types;
+ struct samr_RidTypeArray *rid_array = NULL;
+ struct lsa_String *lsa_names = NULL;
+
+ uint32_t *add_rids = NULL;
+ uint32_t *del_rids = NULL;
+ size_t num_add_rids = 0;
+ size_t num_del_rids = 0;
+
+ uint32_t *member_rids = NULL;
+ size_t num_member_rids = 0;
+
+ struct GROUP_USERS_INFO_0 *i0 = NULL;
+ struct GROUP_USERS_INFO_1 *i1 = NULL;
+
+ int i, k;
+
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &group_rids,
+ &group_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_GET_MEMBERS |
+ SAMR_GROUP_ACCESS_ADD_MEMBER |
+ SAMR_GROUP_ACCESS_REMOVE_MEMBER |
+ SAMR_GROUP_ACCESS_LOOKUP_INFO,
+ group_rids.ids[0],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &group_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
+ break;
+ case 1:
+ i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
+ break;
+ }
+
+ lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
+ if (!lsa_names) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ for (i=0; i < r->in.num_entries; i++) {
+
+ switch (r->in.level) {
+ case 0:
+ init_lsa_String(&lsa_names[i], i0->grui0_name);
+ i0++;
+ break;
+ case 1:
+ init_lsa_String(&lsa_names[i], i1->grui1_name);
+ i1++;
+ break;
+ }
+ }
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ r->in.num_entries,
+ lsa_names,
+ &user_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ member_rids = user_rids.ids;
+ num_member_rids = user_rids.count;
+
+ status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
+ &group_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ /* add list */
+
+ for (i=0; i < r->in.num_entries; i++) {
+ bool already_member = false;
+ for (k=0; k < rid_array->count; k++) {
+ if (member_rids[i] == rid_array->rids[k]) {
+ already_member = true;
+ break;
+ }
+ }
+ if (!already_member) {
+ if (!add_rid_to_array_unique(ctx,
+ member_rids[i],
+ &add_rids, &num_add_rids)) {
+ werr = WERR_GENERAL_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* del list */
+
+ for (k=0; k < rid_array->count; k++) {
+ bool keep_member = false;
+ for (i=0; i < r->in.num_entries; i++) {
+ if (member_rids[i] == rid_array->rids[k]) {
+ keep_member = true;
+ break;
+ }
+ }
+ if (!keep_member) {
+ if (!add_rid_to_array_unique(ctx,
+ rid_array->rids[k],
+ &del_rids, &num_del_rids)) {
+ werr = WERR_GENERAL_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* add list */
+
+ for (i=0; i < num_add_rids; i++) {
+ status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
+ &group_handle,
+ add_rids[i],
+ 7 /* ? */);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ /* del list */
+
+ for (i=0; i < num_del_rids; i++) {
+ status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
+ &group_handle,
+ del_rids[i]);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);
}