From 7f00878fe607901ee25fec328553d00e114d4bf3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 18 Apr 2004 20:22:31 +0000 Subject: r269: Patch from Krischan Jodies : Implement 'net rpc group delete'. Volker (This used to be commit ec321674961cc62c048b149ee19b6e36325c8eb3) --- source3/rpc_client/cli_samr.c | 92 +++++++++++++++++++ source3/utils/net.c | 3 +- source3/utils/net.h | 1 + source3/utils/net_rpc.c | 199 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 291 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index d534745d25..bcb4cb4105 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -1906,6 +1906,98 @@ NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, return result; } +/* Delete domain group */ + +NTSTATUS cli_samr_delete_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *group_pol) +{ + prs_struct qbuf, rbuf; + SAMR_Q_DELETE_DOM_GROUP q; + SAMR_R_DELETE_DOM_GROUP r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + DEBUG(10,("cli_samr_delete_dom_group\n")); + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_samr_q_delete_dom_group(&q, group_pol); + + if (!samr_io_q_delete_dom_group("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_DELETE_DOM_GROUP, &qbuf, &rbuf)) { + goto done; + } + + /* Unmarshall response */ + + if (!samr_io_r_delete_dom_group("", &r, &rbuf, 0)) { + goto done; + } + + /* Return output parameters */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Delete domain alias */ + +NTSTATUS cli_samr_delete_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *alias_pol) +{ + prs_struct qbuf, rbuf; + SAMR_Q_DELETE_DOM_ALIAS q; + SAMR_R_DELETE_DOM_ALIAS r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + DEBUG(10,("cli_samr_delete_dom_alias\n")); + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_samr_q_delete_dom_alias(&q, alias_pol); + + if (!samr_io_q_delete_dom_alias("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_DELETE_DOM_ALIAS, &qbuf, &rbuf)) { + goto done; + } + + /* Unmarshall response */ + + if (!samr_io_r_delete_dom_alias("", &r, &rbuf, 0)) { + goto done; + } + + /* Return output parameters */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + /* Delete domain user */ NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, diff --git a/source3/utils/net.c b/source3/utils/net.c index 4acb1e79b7..67b138a43b 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -66,6 +66,7 @@ int opt_long_list_entries = 0; int opt_reboot = 0; int opt_force = 0; int opt_port = 0; +int opt_verbose = 0; int opt_maxusers = -1; const char *opt_comment = ""; const char *opt_container = "cn=Users"; @@ -683,7 +684,7 @@ static struct functable net_func[] = { {"timeout", 't', POPT_ARG_INT, &opt_timeout}, {"machine-pass",'P', POPT_ARG_NONE, &opt_machine_pass}, {"myworkgroup", 'W', POPT_ARG_STRING, &opt_workgroup}, - + {"verbose", 'v', POPT_ARG_NONE, &opt_verbose}, /* Options for 'net groupmap set' */ {"local", 'L', POPT_ARG_NONE, &opt_localgroup}, {"domain", 'D', POPT_ARG_NONE, &opt_domaingroup}, diff --git a/source3/utils/net.h b/source3/utils/net.h index 62d5a74237..ba3a4e1435 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -48,6 +48,7 @@ extern const char *opt_comment; extern const char *opt_target_workgroup; extern const char *opt_workgroup; extern int opt_long_list_entries; +extern int opt_verbose; extern int opt_reboot; extern int opt_force; extern int opt_machine_pass; diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index afb94a616a..817ba912b0 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -1044,6 +1044,201 @@ static int rpc_group_usage(int argc, const char **argv) return net_help_group(argc, argv); } +/** + * Delete group on a remote RPC server + * + * All parameters are provided by the run_rpc_command function, except for + * argc, argv which are passes through. + * + * @param domain_sid The domain sid acquired from the remote server + * @param cli A cli_state connected to the server. + * @param mem_ctx Talloc context, destoyed on completion of the function. + * @param argc Standard main() style argc + * @param argv Standard main() style argv. Initial components are already + * stripped + * + * @return Normal NTSTATUS return. + **/ + +static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + POLICY_HND connect_pol, domain_pol, group_pol, user_pol; + BOOL group_is_primary = False; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + uint32 *group_rids, num_rids, *name_types, num_members, + *group_attrs, group_rid; + uint32 flags = 0x000003e8; /* Unknown */ + /* char **names; */ + int i; + /* DOM_GID *user_gids; */ + SAM_USERINFO_CTR *user_ctr; + fstring temp; + + if (argc < 1) { + d_printf("specify group\n"); + rpc_group_usage(argc,argv); + return NT_STATUS_OK; /* ok? */ + } + + result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + &connect_pol); + + if (!NT_STATUS_IS_OK(result)) { + d_printf("Request samr_connect failed\n"); + goto done; + } + + result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + MAXIMUM_ALLOWED_ACCESS, + domain_sid, &domain_pol); + + if (!NT_STATUS_IS_OK(result)) { + d_printf("Request open_domain failed\n"); + goto done; + } + + result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + flags, 1, &argv[0], + &num_rids, &group_rids, + &name_types); + + if (!NT_STATUS_IS_OK(result)) { + d_printf("Lookup of '%s' failed\n",argv[0]); + goto done; + } + + switch (name_types[0]) + { + case SID_NAME_DOM_GRP: + result = cli_samr_open_group(cli, mem_ctx, &domain_pol, + MAXIMUM_ALLOWED_ACCESS, + group_rids[0], &group_pol); + if (!NT_STATUS_IS_OK(result)) { + d_printf("Request open_group failed"); + goto done; + } + + group_rid = group_rids[0]; + + result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol, + &num_members, &group_rids, + &group_attrs); + + if (!NT_STATUS_IS_OK(result)) { + d_printf("Unable to query group members of %s",argv[0]); + goto done; + } + + if (opt_verbose) { + d_printf("Domain Group %s (rid: %d) has %d members\n", + argv[0],group_rid,num_members); + } + + /* Check if group is anyone's primary group */ + for (i = 0; i < num_members; i++) + { + result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + MAXIMUM_ALLOWED_ACCESS, + group_rids[i], &user_pol); + + if (!NT_STATUS_IS_OK(result)) { + d_printf("Unable to open group member %d\n",group_rids[i]); + goto done; + } + + ZERO_STRUCT(user_ctr); + + result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol, + 21, &user_ctr); + + if (!NT_STATUS_IS_OK(result)) { + d_printf("Unable to lookup userinfo for group member %d\n",group_rids[i]); + goto done; + } + + if (user_ctr->info.id21->group_rid == group_rid) { + unistr2_to_ascii(temp, &(user_ctr->info.id21)->uni_user_name, + sizeof(temp)-1); + if (opt_verbose) + d_printf("Group is primary group of %s\n",temp); + group_is_primary = True; + } + + cli_samr_close(cli, mem_ctx, &user_pol); + } + + if (group_is_primary) { + d_printf("Unable to delete group because some of it's " + "members have it as primary group\n"); + result = NT_STATUS_MEMBERS_PRIMARY_GROUP; + goto done; + } + + /* remove all group members */ + for (i = 0; i < num_members; i++) + { + if (opt_verbose) + d_printf("Remove group member %d...",group_rids[i]); + result = cli_samr_del_groupmem(cli, mem_ctx, &group_pol, group_rids[i]); + + if (NT_STATUS_IS_OK(result)) { + if (opt_verbose) + d_printf("ok\n"); + } else { + if (opt_verbose) + d_printf("failed\n"); + goto done; + } + } + + result = cli_samr_delete_dom_group(cli, mem_ctx, &group_pol); + + break; + /* removing a local group is easier... */ + case SID_NAME_ALIAS: + result = cli_samr_open_alias(cli, mem_ctx, &domain_pol, + MAXIMUM_ALLOWED_ACCESS, + group_rids[0], &group_pol); + + if (!NT_STATUS_IS_OK(result)) { + d_printf("Request open_alias failed\n"); + goto done; + } + + result = cli_samr_delete_dom_alias(cli, mem_ctx, &group_pol); + break; + default: + d_printf("%s is of type %s. This command is only for deleting local or global groups\n", + argv[0],sid_type_lookup(name_types[0])); + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + + if (NT_STATUS_IS_OK(result)) { + if (opt_verbose) + d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types[0]),argv[0]); + } else { + d_printf("Deleting of %s failed: %s\n",argv[0], + get_friendly_nt_error_msg(result)); + } + + done: + return result; + +} + +static int rpc_group_delete(int argc, const char **argv) +{ + return run_rpc_command(NULL, PI_SAMR, 0, rpc_group_delete_internals, + argc,argv); +} + static NTSTATUS rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name, struct cli_state *cli, @@ -2019,11 +2214,9 @@ int net_rpc_group(int argc, const char **argv) { struct functable func[] = { {"add", rpc_group_add}, + {"delete", rpc_group_delete}, {"addmem", rpc_group_addmem}, {"delmem", rpc_group_delmem}, -#if 0 - {"delete", rpc_group_delete}, -#endif {"list", rpc_group_list}, {"members", rpc_group_members}, {NULL, NULL} -- cgit