diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/utils/net.c | 92 | ||||
-rw-r--r-- | source3/utils/net_ads.c | 11 | ||||
-rw-r--r-- | source3/utils/net_help.c | 125 | ||||
-rw-r--r-- | source3/utils/net_rap.c | 15 | ||||
-rw-r--r-- | source3/utils/net_rpc.c | 344 |
5 files changed, 470 insertions, 117 deletions
diff --git a/source3/utils/net.c b/source3/utils/net.c index e33691ea5e..b81e37c0af 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -78,27 +78,6 @@ struct in_addr opt_dest_ip; extern pstring global_myname; -int net_common_flags_usage(int argc, const char **argv) -{ - - d_printf("Valid targets: choose one (none defaults to localhost)\n"); - d_printf("\t-S or --server=<server>\t\tserver name\n"); - d_printf("\t-I or --ipaddress=<ipaddr>\taddress of target server\n"); - d_printf("\t-w or --workgroup=<wg>\t\ttarget workgroup or domain\n"); - - d_printf("\n"); - d_printf("Valid miscellaneous options are:\n"); /* misc options */ - d_printf("\t-p or --port=<port>\tconnection port on target server\n"); - d_printf("\t-W or --myworkgroup=<wg>\tclient workgroup\n"); - d_printf("\t-d or --debug=<level>\t\tdebug level (0-10)\n"); - d_printf("\t-n or --myname=<name>\t\tclient name\n"); - d_printf("\t-U or --user=<name>\t\tuser name\n"); - d_printf("\t-s or --conf=<path>\t\tpathname of smb.conf file\n"); - d_printf("\t-l or --long\t\t\tDisplay full information\n"); - return -1; -} - - /* run a function from a function table. If not found then call the specified usage function @@ -180,7 +159,7 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c, } } -static BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_name) +BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_name) { if (opt_host) { @@ -300,11 +279,17 @@ struct cli_state *net_make_ipc_connection(unsigned flags) return cli; } + + static int net_user(int argc, const char **argv) { if (net_ads_check() == 0) return net_ads_user(argc, argv); + /* if server is not specified, default to PDC? */ + if (net_rpc_check(NET_FLAGS_PDC)) + return net_rpc_user(argc, argv); + return net_rap_user(argc, argv); } @@ -320,63 +305,6 @@ static int net_join(int argc, const char **argv) return net_rpc_join(argc, argv); } -static int net_usage(int argc, const char **argv) -{ - d_printf(" net time\t\t to view or set time information\n"\ - " net lookup\t\t to lookup host name or ip address\n"\ - "\n"\ - " net ads [command]\tto run ADS commands\n"\ - " net rap [command]\tto run RAP (pre-RPC) commands\n"\ - " net rpc [command]\tto run RPC commands\n"\ - "\n"\ - "Type \"net help <option>\" to get more information on that option\n"); - return -1; -} - -static int help_usage(int argc, const char **argv) -{ - d_printf( -"\n"\ -"Usage: net help <function>\n"\ -"\n"\ -"Valid functions are:\n"\ -" RPC RAP ADS FILE SHARE SESSION SERVER DOMAIN PRINTQ USER GROUP VALIDATE\n"\ -" GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP\n"); - return -1; -} - -/* - handle "net help *" subcommands -*/ -static int net_help(int argc, const char **argv) -{ - struct functable func[] = { - {"ADS", net_ads_help}, - {"RAP", net_rap_help}, - {"RPC", net_rpc_help}, - - {"FILE", net_rap_file_usage}, - {"SHARE", net_rap_share_usage}, - {"SESSION", net_rap_session_usage}, - {"SERVER", net_rap_server_usage}, - {"DOMAIN", net_rap_domain_usage}, - {"PRINTQ", net_rap_printq_usage}, - {"USER", net_rap_user_usage}, - {"GROUP", net_rap_group_usage}, - {"VALIDATE", net_rap_validate_usage}, - {"GROUPMEMBER", net_rap_groupmember_usage}, - {"ADMIN", net_rap_admin_usage}, - {"SERVICE", net_rap_service_usage}, - {"PASSWORD", net_rap_password_usage}, - {"TIME", net_time_usage}, - {"LOOKUP", net_lookup_usage}, - - {"HELP", help_usage}, - {NULL, NULL}}; - - return net_run_function(argc, argv, func, net_usage); -} - /* main function table */ static struct functable net_func[] = { {"RPC", net_rpc}, @@ -453,7 +381,7 @@ static struct functable net_func[] = { while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case 'h': - net_usage(argc, argv); + net_help(argc, argv); exit(0); break; case 'I': @@ -474,7 +402,7 @@ static struct functable net_func[] = { break; default: d_printf("\nInvalid option %c (%d)\n", (char)opt, opt); - net_usage(argc, argv); + net_help(argc, argv); } } @@ -523,7 +451,7 @@ static struct functable net_func[] = { load_interfaces(); - rc = net_run_function(argc_new-1, argv_new+1, net_func, net_usage); + rc = net_run_function(argc_new-1, argv_new+1, net_func, net_help); DEBUG(2,("return code = %d\n", rc)); return rc; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 2696152b12..260f49ee76 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -162,16 +162,7 @@ static void usergrp_display(char *field, void **values, void *data_area) static int net_ads_user_usage(int argc, const char **argv) { - d_printf("\nnet ads user \n\tList users\n"); - d_printf("\nnet ads user DELETE <name>"\ - "\n\tDelete specified user\n"); - d_printf("\nnet ads user INFO <name>"\ - "\n\tList the domain groups of the specified user\n"); - d_printf("\nnet ads user ADD <name> [-F user flags]"\ - "\n\tAdd specified user\n"); - net_common_flags_usage(argc, argv); - - return -1; + return net_help_user(argc, argv); } static int ads_user_add(int argc, const char **argv) diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c new file mode 100644 index 0000000000..38b1aa2b28 --- /dev/null +++ b/source3/utils/net_help.c @@ -0,0 +1,125 @@ +/* + Samba Unix/Linux SMB client library + net help commands + Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +int net_common_methods_usage(int argc, const char**argv) +{ + d_printf("Valid methods: (auto-detected if not specified)\n"); + d_printf("\tads\t\t\t\tActive Directory (LDAP/Kerberos)\n"); + d_printf("\trpc\t\t\t\tDCE-RPC\n"); + d_printf("\trap\t\t\t\tRAP (older systems)\n"); + d_printf("\n"); +} + +int net_common_flags_usage(int argc, const char **argv) +{ + d_printf("Valid targets: choose one (none defaults to localhost)\n"); + d_printf("\t-S or --server=<server>\t\tserver name\n"); + d_printf("\t-I or --ipaddress=<ipaddr>\taddress of target server\n"); + d_printf("\t-w or --workgroup=<wg>\t\ttarget workgroup or domain\n"); + + d_printf("\n"); + d_printf("Valid miscellaneous options are:\n"); /* misc options */ + d_printf("\t-p or --port=<port>\t\tconnection port on target\n"); + d_printf("\t-W or --myworkgroup=<wg>\tclient workgroup\n"); + d_printf("\t-d or --debug=<level>\t\tdebug level (0-10)\n"); + d_printf("\t-n or --myname=<name>\t\tclient name\n"); + d_printf("\t-U or --user=<name>\t\tuser name\n"); + d_printf("\t-s or --conf=<path>\t\tpathname of smb.conf file\n"); + d_printf("\t-l or --long\t\t\tDisplay full information\n"); + return -1; +} + +static int help_usage(int argc, const char **argv) +{ + d_printf( +"\n"\ +"Usage: net help <function>\n"\ +"\n"\ +"Valid functions are:\n"\ +" RPC RAP ADS FILE SHARE SESSION SERVER DOMAIN PRINTQ USER GROUP VALIDATE\n"\ +" GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP\n"); + return -1; +} + +int net_help_user(int argc, const char **argv) +{ + d_printf("\nnet [method] user [misc. options] [targets]\n\tList users\n"); + d_printf("\nnet [method] user DELETE <name> [misc. options] [targets]"\ + "\n\tDelete specified user\n"); + d_printf("\nnet [method] user INFO <name> [misc. options] [targets]"\ + "\n\tList the domain groups of the specified user\n"); + d_printf("\nnet [method] user ADD <name> [-F user flags] [misc. options]"\ + " [targets]\n\tAdd specified user\n"); + + net_common_methods_usage(argc, argv); + net_common_flags_usage(argc, argv); + d_printf( + "\t-C or --comment=<comment>\tdescriptive comment (for add only)\n"); + return -1; +} + +static int net_usage(int argc, const char **argv) +{ + d_printf(" net time\t\tto view or set time information\n"\ + " net lookup\t\tto lookup host name or ip address\n"\ + " net user\t\tto manage users\n"\ + " net join\t\tto join a domain\n"\ + "\n"\ + " net ads [command]\tto run ADS commands\n"\ + " net rap [command]\tto run RAP (pre-RPC) commands\n"\ + " net rpc [command]\tto run RPC commands\n"\ + "\n"\ + "Type \"net help <option>\" to get more information on that option\n"); + return -1; +} + +/* + handle "net help *" subcommands +*/ +int net_help(int argc, const char **argv) +{ + struct functable func[] = { + {"ADS", net_ads_help}, + {"RAP", net_rap_help}, + {"RPC", net_rpc_help}, + + {"FILE", net_rap_file_usage}, + {"SHARE", net_rap_share_usage}, + {"SESSION", net_rap_session_usage}, + {"SERVER", net_rap_server_usage}, + {"DOMAIN", net_rap_domain_usage}, + {"PRINTQ", net_rap_printq_usage}, + {"USER", net_help_user}, + {"GROUP", net_rap_group_usage}, + {"VALIDATE", net_rap_validate_usage}, + {"GROUPMEMBER", net_rap_groupmember_usage}, + {"ADMIN", net_rap_admin_usage}, + {"SERVICE", net_rap_service_usage}, + {"PASSWORD", net_rap_password_usage}, + {"TIME", net_time_usage}, + {"LOOKUP", net_lookup_usage}, + + {"HELP", help_usage}, + {NULL, NULL}}; + + return net_run_function(argc, argv, func, net_usage); +} diff --git a/source3/utils/net_rap.c b/source3/utils/net_rap.c index 13180c47c5..a6b199fd88 100644 --- a/source3/utils/net_rap.c +++ b/source3/utils/net_rap.c @@ -605,20 +605,9 @@ int net_rap_printq(int argc, const char **argv) } -int net_rap_user_usage(int argc, const char **argv) +static int net_rap_user_usage(int argc, const char **argv) { - d_printf("\nnet rap user [misc. options] [targets]\n\tList users\n"); - d_printf("\nnet rap user DELETE <name> [misc. options] [targets]"\ - "\n\tDelete specified user\n"); - d_printf("\nnet rap user INFO <name> [misc. options] [targets]"\ - "\n\tList the domain groups of the specified user\n"); - d_printf("\nnet rap user ADD <name> [-F user flags] [misc. options]"\ - " [targets]\n\tAdd specified user\n"); - - net_common_flags_usage(argc, argv); - d_printf( - "\t-C or --comment=<comment>\tdescriptive comment (for add only)\n"); - return -1; + return net_help_user(argc, argv); } static void user_fn(const char *user_name, const char *comment, diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 6200d6f914..19e2c63ecc 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -20,6 +20,8 @@ #include "includes.h" #include "../utils/net.h" +extern pstring global_myname; + /** * @file net_rpc.c * @@ -296,6 +298,17 @@ int net_rpc_join(int argc, const char **argv) /****************************************************************************/ +/** + * Basic usage function for 'net rpc user' + * @param argc Standard main() style argc. + * @param argv Standard main() style argv. Initial components are already + * stripped. + **/ + +static int rpc_user_usage(int argc, const char **argv) +{ + return net_help_user(argc, argv); +} /** * Add a new user to a remote RPC server @@ -307,7 +320,7 @@ int net_rpc_join(int argc, const char **argv) * @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 argc Standard main() style argv. Initial components are already + * @param argv Standard main() style argv. Initial components are already * stripped * * @return Normal NTSTATUS return. @@ -323,7 +336,8 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_sta uint32 unknown, user_rid; if (argc != 1) { - d_printf("Usage: net rpc user add username\n"); + d_printf("User must be specified\n"); + rpc_user_usage(argc, argv); return NT_STATUS_OK; } @@ -372,7 +386,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_sta * Add a new user to a remote RPC server * * @param argc Standard main() style argc - * @param argc Standard main() style argv. Initial components are already + * @param argv Standard main() style argv. Initial components are already * stripped * * @return A shell status integer (0 for success) @@ -385,16 +399,277 @@ static int rpc_user_add(int argc, const char **argv) } /** - * Basic usage function for 'net rpc user' + * Delete a user from a remote RPC server + * + * All paramaters are provided by the run_rpc_command funcion, 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 argc Standard main() style argv. Initial components are already + * @param argv Standard main() style argv. Initial components are already * stripped + * + * @return Normal NTSTATUS return. **/ -static int rpc_user_usage(int argc, const char **argv) +static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, + struct cli_state *cli, + TALLOC_CTX *mem_ctx, + int argc, const char **argv) { - d_printf(" net rpc user add \t to add a user\n"); - return -1; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + POLICY_HND connect_pol, domain_pol, user_pol; + + if (argc < 1) { + d_printf("User must be specified\n"); + rpc_user_usage(argc, argv); + return NT_STATUS_OK; + } + /* Get sam policy and domain handles */ + + result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + &connect_pol); + + if (!NT_STATUS_IS_OK(result)) { + 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)) { + goto done; + } + + /* Get handle on user */ + + { + uint32 *user_rids, num_rids, *name_types; + uint32 flags = 0x000003e8; /* Unknown */ + + result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + flags, 1, (char **) &argv[0], + &num_rids, &user_rids, + &name_types); + + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + MAXIMUM_ALLOWED_ACCESS, + user_rids[0], &user_pol); + + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + } + + /* Delete user */ + + result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol); + + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + /* Display results */ + + done: + return result; + +} + +/** + * Delete a user from a remote RPC server + * + * @param argc Standard main() style argc + * @param argv Standard main() style argv. Initial components are already + * stripped + * + * @return A shell status integer (0 for success) + **/ + +static int rpc_user_delete(int argc, const char **argv) +{ + return run_rpc_command(PIPE_SAMR, 0, rpc_user_del_internals, + argc, argv); +} + +/** + * List user's groups on a remote RPC server + * + * All paramaters are provided by the run_rpc_command funcion, 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_user_info_internals(const DOM_SID *domain_sid, struct cli_state *cli, + TALLOC_CTX *mem_ctx, int argc, const char **argv) +{ + POLICY_HND connect_pol, domain_pol, user_pol; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 *rids, num_rids, *name_types, num_names; + uint32 flags = 0x000003e8; /* Unknown */ + int i; + char **names; + DOM_GID *user_gids; + + if (argc < 1) { + d_printf("User must be specified\n"); + rpc_user_usage(argc, argv); + return NT_STATUS_OK; + } + /* Get sam policy handle */ + + result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + &connect_pol); + if (!NT_STATUS_IS_OK(result)) goto done; + + /* Get domain policy handle */ + + result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + MAXIMUM_ALLOWED_ACCESS, + domain_sid, &domain_pol); + if (!NT_STATUS_IS_OK(result)) goto done; + + /* Get handle on user */ + + result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + flags, 1, (char **) &argv[0], + &num_rids, &rids, &name_types); + + if (!NT_STATUS_IS_OK(result)) goto done; + + result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + MAXIMUM_ALLOWED_ACCESS, + rids[0], &user_pol); + if (!NT_STATUS_IS_OK(result)) goto done; + + result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol, + &num_rids, &user_gids); + + /* Look up rids */ + + rids = (uint32 *)talloc(mem_ctx, sizeof(uint32) * num_rids); + + for (i = 0; i < num_rids; i++) + rids[i] = user_gids[i].g_rid; + + result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol, + flags, num_rids, rids, + &num_names, &names, &name_types); + + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + /* Display results */ + + for (i = 0; i < num_names; i++) + printf("%s\n", names[i]); + + done: + return result; +} + +/** + * List a user's groups from a remote RPC server + * + * @param argc Standard main() style argc + * @param argv Standard main() style argv. Initial components are already + * stripped + * + * @return A shell status integer (0 for success) + **/ + +static int rpc_user_info(int argc, const char **argv) +{ + return run_rpc_command(PIPE_SAMR, 0, rpc_user_info_internals, + argc, argv); +} + +/** + * List users on a remote RPC server + * + * All paramaters are provided by the run_rpc_command funcion, 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_user_list_internals(const DOM_SID *domain_sid, struct cli_state *cli, + TALLOC_CTX *mem_ctx, int argc, const char **argv) +{ + POLICY_HND connect_pol, domain_pol; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 start_idx=0, max_entries=250, num_entries, i; + SAM_DISPINFO_CTR ctr; + SAM_DISPINFO_1 info1; + + /* Get sam policy handle */ + + result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + &connect_pol); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + /* Get domain policy handle */ + + result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + MAXIMUM_ALLOWED_ACCESS, + domain_sid, &domain_pol); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + /* Query domain users */ + ZERO_STRUCT(ctr); + ZERO_STRUCT(info1); + ctr.sam.info1 = &info1; + if (opt_long_list_entries) + d_printf("\nUser name Comment"\ + "\n-----------------------------\n"); + do { + fstring user, desc; + result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol, + &start_idx, 1, &num_entries, + max_entries, &ctr); + for (i = 0; i < num_entries; i++) { + unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1); + if (opt_long_list_entries) + unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1); + + if (opt_long_list_entries) + printf("%-21.21s %-50.50s\n", user, desc); + else + printf("%-21.21s\n", user); + } + } while (!NT_STATUS_IS_OK(result)); + + done: + return result; } /** @@ -404,15 +679,22 @@ static int rpc_user_usage(int argc, const char **argv) * stripped **/ -static int rpc_user(int argc, const char **argv) +int net_rpc_user(int argc, const char **argv) { struct functable func[] = { {"add", rpc_user_add}, + {"info", rpc_user_info}, + {"delete", rpc_user_delete}, {NULL, NULL} }; if (argc == 0) { - return rpc_user_usage(argc, argv); + if (opt_long_list_entries) { + } else { + } + return run_rpc_command(PIPE_SAMR, 0, + rpc_user_list_internals, + argc, argv); } return net_run_function(argc, argv, func, rpc_user_usage); @@ -928,6 +1210,44 @@ static int rpc_trustdom(int argc, const char **argv) return (net_run_function(argc, argv, func, rpc_user_usage)); } +/** + * Check if a server will take rpc commands + * @param flags Type of server to connect to (PDC, DMB, localhost) + * if the host is not explicitly specified + * @return BOOL (true means rpc supported) + */ +BOOL net_rpc_check(unsigned flags) +{ + struct cli_state cli; + BOOL ret = False; + struct in_addr server_ip; + char *server_name = NULL; + + /* flags (i.e. server type) may depend on command */ + if (!net_find_server(flags, &server_ip, &server_name)) + goto done; + + ZERO_STRUCT(cli); + if (cli_initialise(&cli) == False) + return False; + + if (!cli_connect(&cli, server_name, &server_ip)) + goto done; + if (!attempt_netbios_session_request(&cli, global_myname, + server_name, &server_ip)) + goto done; + if (!cli_negprot(&cli)) + goto done; + if (cli.protocol < PROTOCOL_NT1) + goto done; + + ret = True; + done: + cli_shutdown(&cli); + return ret; +} + + /****************************************************************************/ @@ -968,7 +1288,7 @@ int net_rpc_help(int argc, const char **argv) { struct functable func[] = { {"join", rpc_join_usage}, - {"user", rpc_user_usage}, + {"user", net_help_user}, /*{"changetrustpw", rpc_changetrustpw_usage}, */ {"trustdom", rpc_trustdom_usage}, /*{"abortshutdown", rpc_shutdown_abort_usage},*/ @@ -996,7 +1316,7 @@ int net_rpc(int argc, const char **argv) { struct functable func[] = { {"join", net_rpc_join}, - {"user", rpc_user}, + {"user", net_rpc_user}, {"changetrustpw", rpc_changetrustpw}, {"trustdom", rpc_trustdom}, {"abortshutdown", rpc_shutdown_abort}, |