s3: Change sockaddr util function names for consistency
[samba.git] / source3 / utils / net.c
index 8b4fb042fcf73d928261ee4c8887251d1eb12d25..f1a5be1876b381a420d0efdc9b20a0b6b9002cf0 100644 (file)
@@ -1,30 +1,33 @@
-/* 
-   Samba Unix/Linux SMB client library 
-   Distributed SMB/CIFS Server Management Utility 
+/*
+   Samba Unix/Linux SMB client library
+   Distributed SMB/CIFS Server Management Utility
    Copyright (C) 2001 Steve French  (sfrench@us.ibm.com)
    Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
+   Copyright (C) 2008 Kai Blin (kai@samba.org)
 
    Originally written by Steve and Jim. Largely rewritten by tridge in
    November 2001.
 
    Reworked again by abartlet in December 2001
 
+   Another overhaul, moving functionality into plug-ins loaded on demand by Kai
+   in May 2008.
+
    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
+   the Free Software Foundation; either version 3 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.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
 /*****************************************************/
 /*                                                   */
 /*   Distributed SMB/CIFS Server Management Utility  */
 #include "includes.h"
 #include "utils/net.h"
 
+extern bool AllowDebugChange;
+
+#ifdef WITH_FAKE_KASERVER
+#include "utils/net_afs.h"
+#endif
+
 /***********************************************************************/
 /* Beginning of internationalization section.  Translatable constants  */
 /* should be kept in this area and referenced in the rest of the code. */
 #define YES_STRING              "Yes"
 #define NO_STRING               "No"
 
-/************************************************************************************/
-/*                       end of internationalization section                        */
-/************************************************************************************/
-
-/* Yes, these buggers are globals.... */
-const char *opt_requester_name = NULL;
-const char *opt_host = NULL; 
-const char *opt_password = NULL;
-const char *opt_user_name = NULL;
-BOOL opt_user_specified = False;
-const char *opt_workgroup = NULL;
-int opt_long_list_entries = 0;
-int opt_reboot = 0;
-int opt_force = 0;
-int opt_stdin = 0;
-int opt_port = 0;
-int opt_verbose = 0;
-int opt_maxusers = -1;
-const char *opt_comment = "";
-const char *opt_container = NULL;
-int opt_flags = -1;
-int opt_timeout = 0;
-const char *opt_target_workgroup = NULL;
-int opt_machine_pass = 0;
-BOOL opt_localgroup = False;
-BOOL opt_domaingroup = False;
-static BOOL do_talloc_report=False;
-const char *opt_newntname = "";
-int opt_rid = 0;
-int opt_acls = 0;
-int opt_attrs = 0;
-int opt_timestamps = 0;
-const char *opt_exclude = NULL;
-const char *opt_destination = NULL;
-
-BOOL opt_have_ip = False;
-struct in_addr opt_dest_ip;
-
-extern struct in_addr loopback_ip;
-extern BOOL AllowDebugChange;
-
-uint32 get_sec_channel_type(const char *param) 
+/***********************************************************************/
+/* end of internationalization section                                 */
+/***********************************************************************/
+
+uint32 get_sec_channel_type(const char *param)
 {
        if (!(param && *param)) {
                return get_default_sec_channel();
@@ -103,7 +75,7 @@ uint32 get_sec_channel_type(const char *param)
                        return SEC_CHAN_BDC;
                } else if (strequal(param, "MEMBER")) {
                        return SEC_CHAN_WKSTA;
-#if 0                  
+#if 0
                } else if (strequal(param, "DOMAIN")) {
                        return SEC_CHAN_DOMAIN;
 #endif
@@ -113,389 +85,12 @@ uint32 get_sec_channel_type(const char *param)
        }
 }
 
-/*
-  run a function from a function table. If not found then
-  call the specified usage function 
-*/
-int net_run_function(int argc, const char **argv, struct functable *table, 
-                    int (*usage_fn)(int argc, const char **argv))
-{
-       int i;
-       
-       if (argc < 1) {
-               d_printf("\nUsage: \n");
-               return usage_fn(argc, argv);
-       }
-       for (i=0; table[i].funcname; i++) {
-               if (StrCaseCmp(argv[0], table[i].funcname) == 0)
-                       return table[i].fn(argc-1, argv+1);
-       }
-       d_fprintf(stderr, "No command: %s\n", argv[0]);
-       return usage_fn(argc, argv);
-}
-
-/*
- * run a function from a function table.
- */
-int net_run_function2(int argc, const char **argv, const char *whoami,
-                     struct functable2 *table)
-{
-       int i;
-
-       if (argc != 0) {
-               for (i=0; table[i].funcname; i++) {
-                       if (StrCaseCmp(argv[0], table[i].funcname) == 0)
-                               return table[i].fn(argc-1, argv+1);
-               }
-       }
-
-       for (i=0; table[i].funcname != NULL; i++) {
-               d_printf("%s %-15s %s\n", whoami, table[i].funcname,
-                        table[i].helptext);
-       }
-
-       return -1;
-}
-
-/****************************************************************************
-connect to \\server\service 
-****************************************************************************/
-NTSTATUS connect_to_service(struct cli_state **c, struct in_addr *server_ip,
-                                       const char *server_name, 
-                                       const char *service_name, 
-                                       const char *service_type)
+static int net_changetrustpw(struct net_context *c, int argc, const char **argv)
 {
-       NTSTATUS nt_status;
-
-       if (!opt_password && !opt_machine_pass) {
-               char *pass = getpass("Password:");
-               if (pass) {
-                       opt_password = SMB_STRDUP(pass);
-               }
-       }
-       
-       nt_status = cli_full_connection(c, NULL, server_name, 
-                                       server_ip, opt_port,
-                                       service_name, service_type,  
-                                       opt_user_name, opt_workgroup,
-                                       opt_password, 0, Undefined, NULL);
-       
-       if (NT_STATUS_IS_OK(nt_status)) {
-               return nt_status;
-       } else {
-               d_fprintf(stderr, "Could not connect to server %s\n", server_name);
-
-               /* Display a nicer message depending on the result */
-
-               if (NT_STATUS_V(nt_status) == 
-                   NT_STATUS_V(NT_STATUS_LOGON_FAILURE))
-                       d_fprintf(stderr, "The username or password was not correct.\n");
+       if (net_ads_check_our_domain(c) == 0)
+               return net_ads_changetrustpw(c, argc, argv);
 
-               if (NT_STATUS_V(nt_status) == 
-                   NT_STATUS_V(NT_STATUS_ACCOUNT_LOCKED_OUT))
-                       d_fprintf(stderr, "The account was locked out.\n");
-
-               if (NT_STATUS_V(nt_status) == 
-                   NT_STATUS_V(NT_STATUS_ACCOUNT_DISABLED))
-                       d_fprintf(stderr, "The account was disabled.\n");
-
-               return nt_status;
-       }
-}
-
-
-/****************************************************************************
-connect to \\server\ipc$  
-****************************************************************************/
-NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
-                                       const char *server_name)
-{
-       return connect_to_service(c, server_ip, server_name, "IPC$", "IPC");
-}
-
-/****************************************************************************
-connect to \\server\ipc$ anonymously
-****************************************************************************/
-NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
-                       struct in_addr *server_ip, const char *server_name)
-{
-       NTSTATUS nt_status;
-
-       nt_status = cli_full_connection(c, opt_requester_name, server_name, 
-                                       server_ip, opt_port,
-                                       "IPC$", "IPC",  
-                                       "", "",
-                                       "", 0, Undefined, NULL);
-       
-       if (NT_STATUS_IS_OK(nt_status)) {
-               return nt_status;
-       } else {
-               DEBUG(1,("Cannot connect to server (anonymously).  Error was %s\n", nt_errstr(nt_status)));
-               return nt_status;
-       }
-}
-
-/****************************************************************************
-connect to \\server\ipc$ using KRB5
-****************************************************************************/
-NTSTATUS connect_to_ipc_krb5(struct cli_state **c,
-                       struct in_addr *server_ip, const char *server_name)
-{
-       NTSTATUS nt_status;
-
-       nt_status = cli_full_connection(c, NULL, server_name, 
-                                       server_ip, opt_port,
-                                       "IPC$", "IPC",  
-                                       opt_user_name, opt_workgroup,
-                                       opt_password, CLI_FULL_CONNECTION_USE_KERBEROS, 
-                                       Undefined, NULL);
-       
-       if (NT_STATUS_IS_OK(nt_status)) {
-               return nt_status;
-       } else {
-               DEBUG(1,("Cannot connect to server using kerberos.  Error was %s\n", nt_errstr(nt_status)));
-               return nt_status;
-       }
-}
-
-/**
- * Connect a server and open a given pipe
- *
- * @param cli_dst              A cli_state 
- * @param pipe                 The pipe to open
- * @param got_pipe             boolean that stores if we got a pipe
- *
- * @return Normal NTSTATUS return.
- **/
-NTSTATUS connect_dst_pipe(struct cli_state **cli_dst, struct rpc_pipe_client **pp_pipe_hnd, int pipe_num)
-{
-       NTSTATUS nt_status;
-       char *server_name = SMB_STRDUP("127.0.0.1");
-       struct cli_state *cli_tmp = NULL;
-       struct rpc_pipe_client *pipe_hnd = NULL;
-
-       if (server_name == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (opt_destination) {
-               SAFE_FREE(server_name);
-               if ((server_name = SMB_STRDUP(opt_destination)) == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-       }
-
-       /* make a connection to a named pipe */
-       nt_status = connect_to_ipc(&cli_tmp, NULL, server_name);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               SAFE_FREE(server_name);
-               return nt_status;
-       }
-
-       pipe_hnd = cli_rpc_pipe_open_noauth(cli_tmp, pipe_num, &nt_status);
-       if (!pipe_hnd) {
-               DEBUG(0, ("couldn't not initialize pipe\n"));
-               cli_shutdown(cli_tmp);
-               SAFE_FREE(server_name);
-               return nt_status;
-       }
-
-       *cli_dst = cli_tmp;
-       *pp_pipe_hnd = pipe_hnd;
-       SAFE_FREE(server_name);
-
-       return nt_status;
-}
-
-/****************************************************************************
- Use the local machine's password for this session.
-****************************************************************************/
-
-int net_use_machine_password(void) 
-{
-       char *user_name = NULL;
-
-       if (!secrets_init()) {
-               d_fprintf(stderr, "ERROR: Unable to open secrets database\n");
-               exit(1);
-       }
-
-       user_name = NULL;
-       opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
-       if (asprintf(&user_name, "%s$@%s", global_myname(), lp_realm()) == -1) {
-               return -1;
-       }
-       opt_user_name = user_name;
-       return 0;
-}
-
-BOOL net_find_server(const char *domain, unsigned flags, struct in_addr *server_ip, char **server_name)
-{
-       const char *d = domain ? domain : opt_target_workgroup;
-
-       if (opt_host) {
-               *server_name = SMB_STRDUP(opt_host);
-       }               
-
-       if (opt_have_ip) {
-               *server_ip = opt_dest_ip;
-               if (!*server_name) {
-                       *server_name = SMB_STRDUP(inet_ntoa(opt_dest_ip));
-               }
-       } else if (*server_name) {
-               /* resolve the IP address */
-               if (!resolve_name(*server_name, server_ip, 0x20))  {
-                       DEBUG(1,("Unable to resolve server name\n"));
-                       return False;
-               }
-       } else if (flags & NET_FLAGS_PDC) {
-               struct in_addr pdc_ip;
-
-               if (get_pdc_ip(d, &pdc_ip)) {
-                       fstring dc_name;
-                       
-                       if (is_zero_ip(pdc_ip))
-                               return False;
-                       
-                       if ( !name_status_find(d, 0x1b, 0x20, pdc_ip, dc_name) )
-                               return False;
-                               
-                       *server_name = SMB_STRDUP(dc_name);
-                       *server_ip = pdc_ip;
-               }
-       } else if (flags & NET_FLAGS_DMB) {
-               struct in_addr msbrow_ip;
-               /*  if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */
-               if (!resolve_name(d, &msbrow_ip, 0x1B))  {
-                       DEBUG(1,("Unable to resolve domain browser via name lookup\n"));
-                       return False;
-               } else {
-                       *server_ip = msbrow_ip;
-               }
-               *server_name = SMB_STRDUP(inet_ntoa(opt_dest_ip));
-       } else if (flags & NET_FLAGS_MASTER) {
-               struct in_addr brow_ips;
-               if (!resolve_name(d, &brow_ips, 0x1D))  {
-                               /* go looking for workgroups */
-                       DEBUG(1,("Unable to resolve master browser via name lookup\n"));
-                       return False;
-               } else {
-                       *server_ip = brow_ips;
-               }
-               *server_name = SMB_STRDUP(inet_ntoa(opt_dest_ip));
-       } else if (!(flags & NET_FLAGS_LOCALHOST_DEFAULT_INSANE)) {
-               *server_ip = loopback_ip;
-               *server_name = SMB_STRDUP("127.0.0.1");
-       }
-
-       if (!server_name || !*server_name) {
-               DEBUG(1,("no server to connect to\n"));
-               return False;
-       }
-
-       return True;
-}
-
-
-BOOL net_find_pdc(struct in_addr *server_ip, fstring server_name, const char *domain_name)
-{
-       if (get_pdc_ip(domain_name, server_ip)) {
-               if (is_zero_ip(*server_ip))
-                       return False;
-               
-               if (!name_status_find(domain_name, 0x1b, 0x20, *server_ip, server_name))
-                       return False;
-                       
-               return True;    
-       } 
-       else
-               return False;
-}
-
-struct cli_state *net_make_ipc_connection( unsigned flags )
-{
-       return net_make_ipc_connection_ex( NULL, NULL, NULL, flags );
-}
-
-struct cli_state *net_make_ipc_connection_ex( const char *domain, const char *server,
-                                              struct in_addr *ip, unsigned flags)
-{
-       char *server_name = NULL;
-       struct in_addr server_ip;
-       struct cli_state *cli = NULL;
-       NTSTATUS nt_status;
-
-       if ( !server || !ip ) {
-               if (!net_find_server(domain, flags, &server_ip, &server_name)) {
-                       d_fprintf(stderr, "Unable to find a suitable server\n");
-                       return NULL;
-               }
-       } else {
-               server_name = SMB_STRDUP( server );
-               server_ip = *ip;
-       }
-
-       if (flags & NET_FLAGS_ANONYMOUS) {
-               nt_status = connect_to_ipc_anonymous(&cli, &server_ip, server_name);
-       } else {
-               nt_status = connect_to_ipc(&cli, &server_ip, server_name);
-       }
-
-       /* store the server in the affinity cache if it was a PDC */
-
-       if ( (flags & NET_FLAGS_PDC) && NT_STATUS_IS_OK(nt_status) )
-               saf_store( cli->server_domain, cli->desthost );
-
-       SAFE_FREE(server_name);
-       if (NT_STATUS_IS_OK(nt_status)) {
-               return cli;
-       } else {
-               d_fprintf(stderr, "Connection failed: %s\n",
-                         nt_errstr(nt_status));
-               return NULL;
-       }
-}
-
-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);
-}
-
-static int net_group(int argc, const char **argv)
-{
-       if (net_ads_check() == 0)
-               return net_ads_group(argc, argv);
-
-       if (argc == 0 && net_rpc_check(NET_FLAGS_PDC))
-               return net_rpc_group(argc, argv);
-
-       return net_rap_group(argc, argv);
-}
-
-static int net_join(int argc, const char **argv)
-{
-       if (net_ads_check() == 0) {
-               if (net_ads_join(argc, argv) == 0)
-                       return 0;
-               else
-                       d_fprintf(stderr, "ADS join did not work, falling back to RPC...\n");
-       }
-       return net_rpc_join(argc, argv);
-}
-
-static int net_changetrustpw(int argc, const char **argv)
-{
-       if (net_ads_check() == 0)
-               return net_ads_changetrustpw(argc, argv);
-
-       return net_rpc_changetrustpw(argc, argv);
+       return net_rpc_changetrustpw(c, argc, argv);
 }
 
 static void set_line_buffering(FILE *f)
@@ -503,19 +98,20 @@ static void set_line_buffering(FILE *f)
        setvbuf(f, NULL, _IOLBF, 0);
 }
 
-static int net_changesecretpw(int argc, const char **argv)
+static int net_changesecretpw(struct net_context *c, int argc,
+                             const char **argv)
 {
         char *trust_pw;
         uint32 sec_channel_type = SEC_CHAN_WKSTA;
 
-       if(opt_force) {
-               if (opt_stdin) {
+       if(c->opt_force) {
+               if (c->opt_stdin) {
                        set_line_buffering(stdin);
                        set_line_buffering(stdout);
                        set_line_buffering(stderr);
                }
 
-               trust_pw = get_pass("Enter machine password: ", opt_stdin);
+               trust_pw = get_pass("Enter machine password: ", c->opt_stdin);
 
                if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) {
                            d_fprintf(stderr, "Unable to write the machine account password in the secrets database");
@@ -534,24 +130,10 @@ static int net_changesecretpw(int argc, const char **argv)
         return 0;
 }
 
-static int net_share(int argc, const char **argv)
-{
-       if (net_rpc_check(0))
-               return net_rpc_share(argc, argv);
-       return net_rap_share(argc, argv);
-}
-
-static int net_file(int argc, const char **argv)
-{
-       if (net_rpc_check(0))
-               return net_rpc_file(argc, argv);
-       return net_rap_file(argc, argv);
-}
-
 /*
  Retrieve our local SID or the SID for the specified name
  */
-static int net_getlocalsid(int argc, const char **argv)
+static int net_getlocalsid(struct net_context *c, int argc, const char **argv)
 {
         DOM_SID sid;
        const char *name;
@@ -564,9 +146,9 @@ static int net_getlocalsid(int argc, const char **argv)
                name = global_myname();
        }
 
-       if(!initialize_password_db(False)) {
+       if(!initialize_password_db(false, NULL)) {
                DEBUG(0, ("WARNING: Could not open passdb - local sid may not reflect passdb\n"
-                         "backend knowlege (such as the sid stored in LDAP)\n"));
+                         "backend knowledge (such as the sid stored in LDAP)\n"));
        }
 
        /* first check to see if we can even access secrets, so we don't
@@ -584,12 +166,12 @@ static int net_getlocalsid(int argc, const char **argv)
                DEBUG(0, ("Can't fetch domain SID for name: %s\n", name));
                return 1;
        }
-       sid_to_string(sid_str, &sid);
+       sid_to_fstring(sid_str, &sid);
        d_printf("SID for domain %s is: %s\n", name, sid_str);
        return 0;
 }
 
-static int net_setlocalsid(int argc, const char **argv)
+static int net_setlocalsid(struct net_context *c, int argc, const char **argv)
 {
        DOM_SID sid;
 
@@ -609,7 +191,7 @@ static int net_setlocalsid(int argc, const char **argv)
        return 0;
 }
 
-static int net_setdomainsid(int argc, const char **argv)
+static int net_setdomainsid(struct net_context *c, int argc, const char **argv)
 {
        DOM_SID sid;
 
@@ -629,120 +211,54 @@ static int net_setdomainsid(int argc, const char **argv)
        return 0;
 }
 
-static int net_getdomainsid(int argc, const char **argv)
+static int net_getdomainsid(struct net_context *c, int argc, const char **argv)
 {
        DOM_SID domain_sid;
        fstring sid_str;
 
-       if(!initialize_password_db(False)) {
-               DEBUG(0, ("WARNING: Could not open passdb - domain sid may not reflect passdb\n"
-                         "backend knowlege (such as the sid stored in LDAP)\n"));
-       }
-
-       /* Generate one, if it doesn't exist */
-       get_global_sam_sid();
-
-       if (!secrets_fetch_domain_sid(global_myname(), &domain_sid)) {
-               d_fprintf(stderr, "Could not fetch local SID\n");
+       if (argc > 0) {
+               d_printf("usage: net getdomainsid\n");
                return 1;
        }
-       sid_to_string(sid_str, &domain_sid);
-       d_printf("SID for domain %s is: %s\n", global_myname(), sid_str);
 
-       if (!secrets_fetch_domain_sid(opt_workgroup, &domain_sid)) {
-               d_fprintf(stderr, "Could not fetch domain SID\n");
-               return 1;
+       if(!initialize_password_db(false, NULL)) {
+               DEBUG(0, ("WARNING: Could not open passdb - domain SID may "
+                         "not reflect passdb\n"
+                         "backend knowledge (such as the SID stored in "
+                         "LDAP)\n"));
        }
 
-       sid_to_string(sid_str, &domain_sid);
-       d_printf("SID for domain %s is: %s\n", opt_workgroup, sid_str);
-
-       return 0;
-}
-
-#ifdef WITH_FAKE_KASERVER
-
-int net_help_afs(int argc, const char **argv)
-{
-       d_printf("  net afs key filename\n"
-                "\tImports a OpenAFS KeyFile into our secrets.tdb\n\n");
-       d_printf("  net afs impersonate <user> <cell>\n"
-                "\tCreates a token for user@cell\n\n");
-       return -1;
-}
-
-static int net_afs_key(int argc, const char **argv)
-{
-       int fd;
-       struct afs_keyfile keyfile;
-
-       if (argc != 2) {
-               d_printf("usage: 'net afs key <keyfile> cell'\n");
-               return -1;
-       }
+       /* first check to see if we can even access secrets, so we don't
+          panic when we can't. */
 
        if (!secrets_init()) {
-               d_fprintf(stderr, "Could not open secrets.tdb\n");
-               return -1;
-       }
-
-       if ((fd = open(argv[0], O_RDONLY, 0)) < 0) {
-               d_fprintf(stderr, "Could not open %s\n", argv[0]);
-               return -1;
-       }
-
-       if (read(fd, &keyfile, sizeof(keyfile)) != sizeof(keyfile)) {
-               d_fprintf(stderr, "Could not read keyfile\n");
-               return -1;
-       }
-
-       if (!secrets_store_afs_keyfile(argv[1], &keyfile)) {
-               d_fprintf(stderr, "Could not write keyfile to secrets.tdb\n");
-               return -1;
+               d_fprintf(stderr, "Unable to open secrets.tdb.  Can't fetch domain"
+                                 "SID for name: %s\n", get_global_sam_name());
+               return 1;
        }
 
-       return 0;
-}
-
-static int net_afs_impersonate(int argc, const char **argv)
-{
-       char *token;
+       /* Generate one, if it doesn't exist */
+       get_global_sam_sid();
 
-       if (argc != 2) {
-               fprintf(stderr, "Usage: net afs impersonate <user> <cell>\n");
-               exit(1);
+       if (!secrets_fetch_domain_sid(global_myname(), &domain_sid)) {
+               d_fprintf(stderr, "Could not fetch local SID\n");
+               return 1;
        }
+       sid_to_fstring(sid_str, &domain_sid);
+       d_printf("SID for local machine %s is: %s\n", global_myname(), sid_str);
 
-       token = afs_createtoken_str(argv[0], argv[1]);
-
-       if (token == NULL) {
-               fprintf(stderr, "Could not create token\n");
-               exit(1);
+       if (!secrets_fetch_domain_sid(c->opt_workgroup, &domain_sid)) {
+               d_fprintf(stderr, "Could not fetch domain SID\n");
+               return 1;
        }
 
-       if (!afs_settoken_str(token)) {
-               fprintf(stderr, "Could not set token into kernel\n");
-               exit(1);
-       }
+       sid_to_fstring(sid_str, &domain_sid);
+       d_printf("SID for domain %s is: %s\n", c->opt_workgroup, sid_str);
 
-       printf("Success: %s@%s\n", argv[0], argv[1]);
        return 0;
 }
 
-static int net_afs(int argc, const char **argv)
-{
-       struct functable func[] = {
-               {"key", net_afs_key},
-               {"impersonate", net_afs_impersonate},
-               {"help", net_help_afs},
-               {NULL, NULL}
-       };
-       return net_run_function(argc, argv, func, net_help_afs);
-}
-
-#endif /* WITH_FAKE_KASERVER */
-
-static BOOL search_maxrid(struct pdb_search *search, const char *type,
+static bool search_maxrid(struct pdb_search *search, const char *type,
                          uint32 *max_rid)
 {
        struct samr_displayentry *entries;
@@ -750,14 +266,14 @@ static BOOL search_maxrid(struct pdb_search *search, const char *type,
 
        if (search == NULL) {
                d_fprintf(stderr, "get_maxrid: Could not search %s\n", type);
-               return False;
+               return false;
        }
 
        num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries);
        for (i=0; i<num_entries; i++)
                *max_rid = MAX(*max_rid, entries[i].rid);
        pdb_search_destroy(search);
-       return True;
+       return true;
 }
 
 static uint32 get_maxrid(void)
@@ -773,11 +289,11 @@ static uint32 get_maxrid(void)
        if (!search_maxrid(pdb_search_aliases(get_global_sam_sid()),
                           "aliases", &max_rid))
                return 0;
-       
+
        return max_rid;
 }
 
-static int net_maxrid(int argc, const char **argv)
+static int net_maxrid(struct net_context *c, int argc, const char **argv)
 {
        uint32 rid;
 
@@ -798,47 +314,292 @@ static int net_maxrid(int argc, const char **argv)
 
 /* main function table */
 static struct functable net_func[] = {
-       {"RPC", net_rpc},
-       {"RAP", net_rap},
-       {"ADS", net_ads},
+       {
+               "rpc",
+               net_rpc,
+               NET_TRANSPORT_RPC,
+               "Run functions using RPC transport",
+               "  Use 'net help rpc' to get more extensive information about "
+               "'net rpc' commands."
+       },
+       {
+               "rap",
+               net_rap,
+               NET_TRANSPORT_RAP,
+               "Run functions using RAP transport",
+               "  Use 'net help rap' to get more extensive information about "
+               "'net rap' commands."
+       },
+       {
+               "ads",
+               net_ads,
+               NET_TRANSPORT_ADS,
+               "Run functions using ADS transport",
+               "  Use 'net help ads' to get more extensive information about "
+               "'net ads' commands."
+       },
 
        /* eventually these should auto-choose the transport ... */
-       {"FILE", net_file},
-       {"SHARE", net_share},
-       {"SESSION", net_rap_session},
-       {"SERVER", net_rap_server},
-       {"DOMAIN", net_rap_domain},
-       {"PRINTQ", net_rap_printq},
-       {"USER", net_user},
-       {"GROUP", net_group},
-       {"GROUPMAP", net_groupmap},
-       {"SAM", net_sam},
-       {"VALIDATE", net_rap_validate},
-       {"GROUPMEMBER", net_rap_groupmember},
-       {"ADMIN", net_rap_admin},
-       {"SERVICE", net_rap_service},   
-       {"PASSWORD", net_rap_password},
-       {"CHANGETRUSTPW", net_changetrustpw},
-       {"CHANGESECRETPW", net_changesecretpw},
-       {"TIME", net_time},
-       {"LOOKUP", net_lookup},
-       {"JOIN", net_join},
-       {"CACHE", net_cache},
-       {"GETLOCALSID", net_getlocalsid},
-       {"SETLOCALSID", net_setlocalsid},
-       {"SETDOMAINSID", net_setdomainsid},
-       {"GETDOMAINSID", net_getdomainsid},
-       {"MAXRID", net_maxrid},
-       {"IDMAP", net_idmap},
-       {"STATUS", net_status},
-       {"USERSHARE", net_usershare},
-       {"USERSIDLIST", net_usersidlist},
+       {
+               "file",
+               net_file,
+               NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
+               "Functions on remote opened files",
+               "  Use 'net help file' to get more information about 'net "
+               "file' commands."
+       },
+       {
+               "share",
+               net_share,
+               NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
+               "Functions on shares",
+               "  Use 'net help share' to get more information about 'net "
+               "share' commands."
+       },
+       {
+               "session",
+               net_rap_session,
+               NET_TRANSPORT_RAP,
+               "Manage sessions",
+               "  Use 'net help session' to get more information about 'net "
+               "session' commands."
+       },
+       {
+               "server",
+               net_rap_server,
+               NET_TRANSPORT_RAP,
+               "List servers in workgroup",
+               "  Use 'net help server' to get more information about 'net "
+               "server' commands."
+       },
+       {
+               "domain",
+               net_rap_domain,
+               NET_TRANSPORT_RAP,
+               "List domains/workgroups on network",
+               "  Use 'net help domain' to get more information about 'net "
+               "domain' commands."
+       },
+       {
+               "printq",
+               net_rap_printq,
+               NET_TRANSPORT_RAP,
+               "Modify printer queue",
+               "  Use 'net help printq' to get more information about 'net "
+               "printq' commands."
+       },
+       {
+               "user",
+               net_user,
+               NET_TRANSPORT_ADS | NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
+               "Manage users",
+               "  Use 'net help user' to get more information about 'net "
+               "user' commands."
+       },
+       {
+               "group",
+               net_group,
+               NET_TRANSPORT_ADS | NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
+               "Manage groups",
+               "  Use 'net help group' to get more information about 'net "
+               "group' commands."
+       },
+       {
+               "groupmap",
+               net_groupmap,
+               NET_TRANSPORT_LOCAL,
+               "Manage group mappings",
+               "  Use 'net help groupmap' to get more information about 'net "
+               "groupmap' commands."
+       },
+       {
+               "sam",
+               net_sam,
+               NET_TRANSPORT_LOCAL,
+               "Functions on the SAM database",
+               "  Use 'net help sam' to get more information about 'net sam' "
+               "commands."
+       },
+       {
+               "validate",
+               net_rap_validate,
+               NET_TRANSPORT_RAP,
+               "Validate username and password",
+               "  Use 'net help validate' to get more information about 'net "
+               "validate' commands."
+       },
+       {
+               "groupmember",
+               net_rap_groupmember,
+               NET_TRANSPORT_RAP,
+               "Modify group memberships",
+               "  Use 'net help groupmember' to get more information about "
+               "'net groupmember' commands."
+       },
+       {       "admin",
+               net_rap_admin,
+               NET_TRANSPORT_RAP,
+               "Execute remote command on a remote OS/2 server",
+               "  Use 'net help admin' to get more information about 'net "
+               "admin' commands."
+       },
+       {       "service",
+               net_rap_service,
+               NET_TRANSPORT_RAP,
+               "List/modify running services",
+               "  Use 'net help service' to get more information about 'net "
+               "service' commands."
+       },
+       {
+               "password",
+               net_rap_password,
+               NET_TRANSPORT_RAP,
+               "Change user password on target server",
+               "  Use 'net help password' to get more information about 'net "
+               "password' commands."
+       },
+       {       "changetrustpw",
+               net_changetrustpw,
+               NET_TRANSPORT_ADS | NET_TRANSPORT_RPC,
+               "Change the trust password",
+               "  Use 'net help changetrustpw' to get more information about "
+               "'net changetrustpw'."
+       },
+       {       "changesecretpw",
+               net_changesecretpw,
+               NET_TRANSPORT_LOCAL,
+               "Change the secret password",
+               "  net [options] changesecretpw\n"
+               "    Change the ADS domain member machine account password in "
+               "secrets.tdb.\n"
+               "    Do NOT use this function unless you know what it does.\n"
+               "    Requires the -f flag to work."
+       },
+       {       "time",
+               net_time,
+               NET_TRANSPORT_LOCAL,
+               "Show/set time",
+               "  Use 'net help time' to get more information about 'net "
+               "time' commands."
+       },
+       {       "lookup",
+               net_lookup,
+               NET_TRANSPORT_LOCAL,
+               "Look up host names/IP addresses",
+               "  Use 'net help lookup' to get more information about 'net "
+               "lookup' commands."
+       },
+       {       "join",
+               net_join,
+               NET_TRANSPORT_ADS | NET_TRANSPORT_RPC,
+               "Join a domain/AD",
+               "  Use 'net help join' to get more information about 'net "
+               "join'."
+       },
+       {       "dom",
+               net_dom,
+               NET_TRANSPORT_LOCAL,
+               "Join/unjoin (remote) machines to/from a domain/AD",
+               "  Use 'net help dom' to get more information about 'net dom' "
+               "commands."
+       },
+       {       "cache",
+               net_cache,
+               NET_TRANSPORT_LOCAL,
+               "Operate on the cache tdb file",
+               "  Use 'net help cache' to get more information about 'net "
+               "cache' commands."
+       },
+       {       "getlocalsid",
+               net_getlocalsid,
+               NET_TRANSPORT_LOCAL,
+               "Get the SID for the local domain",
+               "  net getlocalsid"
+       },
+       {       "setlocalsid",
+               net_setlocalsid,
+               NET_TRANSPORT_LOCAL,
+               "Set the SID for the local domain",
+               "  net setlocalsid S-1-5-21-x-y-z"
+       },
+       {       "setdomainsid",
+               net_setdomainsid,
+               NET_TRANSPORT_LOCAL,
+               "Set domain SID on member servers",
+               "  net setdomainsid S-1-5-21-x-y-z"
+       },
+       {       "getdomainsid",
+               net_getdomainsid,
+               NET_TRANSPORT_LOCAL,
+               "Get domain SID on member servers",
+               "  net getdomainsid"
+       },
+       {       "maxrid",
+               net_maxrid,
+               NET_TRANSPORT_LOCAL,
+               "Display the maximul RID currently used",
+               "  net maxrid"
+       },
+       {       "idmap",
+               net_idmap,
+               NET_TRANSPORT_LOCAL,
+               "IDmap functions",
+               "  Use 'net help idmap to get more information about 'net "
+               "idmap' commands."
+       },
+       {       "status",
+               net_status,
+               NET_TRANSPORT_LOCAL,
+               "Display server status",
+               "  Use 'net help status' to get more information about 'net "
+               "status' commands."
+       },
+       {       "usershare",
+               net_usershare,
+               NET_TRANSPORT_LOCAL,
+               "Manage user-modifiable shares",
+               "  Use 'net help usershare to get more information about 'net "
+               "usershare' commands."
+       },
+       {       "usersidlist",
+               net_usersidlist,
+               NET_TRANSPORT_RPC,
+               "Display list of all users with SID",
+               "  Use 'net help usersidlist' to get more information about "
+               "'net usersidlist'."
+       },
+       {       "conf",
+               net_conf,
+               NET_TRANSPORT_LOCAL,
+               "Manage Samba registry based configuration",
+               "  Use 'net help conf' to get more information about 'net "
+               "conf' commands."
+       },
+       {       "registry",
+               net_registry,
+               NET_TRANSPORT_LOCAL,
+               "Manage the Samba registry",
+               "  Use 'net help registry' to get more information about 'net "
+               "registry' commands."
+       },
 #ifdef WITH_FAKE_KASERVER
-       {"AFS", net_afs},
+       {       "afs",
+               net_afs,
+               NET_TRANSPORT_LOCAL,
+               "Manage AFS tokens",
+               "  Use 'net help afs' to get more information about 'net afs' "
+               "commands."
+       },
 #endif
 
-       {"HELP", net_help},
-       {NULL, NULL}
+       {       "help",
+               net_help,
+               NET_TRANSPORT_LOCAL,
+               "Print usage information",
+               "  Use 'net help help' to list usage information for 'net' "
+               "commands."
+       },
+       {NULL, NULL, 0, NULL, NULL}
 };
 
 
@@ -853,92 +614,106 @@ static struct functable net_func[] = {
        int argc_new = 0;
        const char ** argv_new;
        poptContext pc;
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct net_context *c = talloc_zero(frame, struct net_context);
 
        struct poptOption long_options[] = {
                {"help",        'h', POPT_ARG_NONE,   0, 'h'},
-               {"workgroup",   'w', POPT_ARG_STRING, &opt_target_workgroup},
-               {"user",        'U', POPT_ARG_STRING, &opt_user_name, 'U'},
+               {"workgroup",   'w', POPT_ARG_STRING, &c->opt_target_workgroup},
+               {"user",        'U', POPT_ARG_STRING, &c->opt_user_name, 'U'},
                {"ipaddress",   'I', POPT_ARG_STRING, 0,'I'},
-               {"port",        'p', POPT_ARG_INT,    &opt_port},
-               {"myname",      'n', POPT_ARG_STRING, &opt_requester_name},
-               {"server",      'S', POPT_ARG_STRING, &opt_host},
-               {"container",   'c', POPT_ARG_STRING, &opt_container},
-               {"comment",     'C', POPT_ARG_STRING, &opt_comment},
-               {"maxusers",    'M', POPT_ARG_INT,    &opt_maxusers},
-               {"flags",       'F', POPT_ARG_INT,    &opt_flags},
-               {"long",        'l', POPT_ARG_NONE,   &opt_long_list_entries},
-               {"reboot",      'r', POPT_ARG_NONE,   &opt_reboot},
-               {"force",       'f', POPT_ARG_NONE,   &opt_force},
-               {"stdin",       'i', POPT_ARG_NONE,   &opt_stdin},
-               {"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},
+               {"port",        'p', POPT_ARG_INT,    &c->opt_port},
+               {"myname",      'n', POPT_ARG_STRING, &c->opt_requester_name},
+               {"server",      'S', POPT_ARG_STRING, &c->opt_host},
+               {"encrypt",     'e', POPT_ARG_NONE,   NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
+               {"container",   'c', POPT_ARG_STRING, &c->opt_container},
+               {"comment",     'C', POPT_ARG_STRING, &c->opt_comment},
+               {"maxusers",    'M', POPT_ARG_INT,    &c->opt_maxusers},
+               {"flags",       'F', POPT_ARG_INT,    &c->opt_flags},
+               {"long",        'l', POPT_ARG_NONE,   &c->opt_long_list_entries},
+               {"reboot",      'r', POPT_ARG_NONE,   &c->opt_reboot},
+               {"force",       'f', POPT_ARG_NONE,   &c->opt_force},
+               {"stdin",       'i', POPT_ARG_NONE,   &c->opt_stdin},
+               {"timeout",     't', POPT_ARG_INT,    &c->opt_timeout},
+               {"machine-pass",'P', POPT_ARG_NONE,   &c->opt_machine_pass},
+               {"kerberos",    'k', POPT_ARG_NONE,   &c->opt_kerberos},
+               {"myworkgroup", 'W', POPT_ARG_STRING, &c->opt_workgroup},
+               {"verbose",     'v', POPT_ARG_NONE,   &c->opt_verbose},
+               {"test",        'T', POPT_ARG_NONE,   &c->opt_testmode},
                /* Options for 'net groupmap set' */
-               {"local",       'L', POPT_ARG_NONE,   &opt_localgroup},
-               {"domain",      'D', POPT_ARG_NONE,   &opt_domaingroup},
-               {"ntname",      'N', POPT_ARG_STRING, &opt_newntname},
-               {"rid",         'R', POPT_ARG_INT,    &opt_rid},
+               {"local",       'L', POPT_ARG_NONE,   &c->opt_localgroup},
+               {"domain",      'D', POPT_ARG_NONE,   &c->opt_domaingroup},
+               {"ntname",      'N', POPT_ARG_STRING, &c->opt_newntname},
+               {"rid",         'R', POPT_ARG_INT,    &c->opt_rid},
                /* Options for 'net rpc share migrate' */
-               {"acls",        0, POPT_ARG_NONE,     &opt_acls},
-               {"attrs",       0, POPT_ARG_NONE,     &opt_attrs},
-               {"timestamps",  0, POPT_ARG_NONE,     &opt_timestamps},
-               {"exclude",     'e', POPT_ARG_STRING, &opt_exclude},
-               {"destination", 0, POPT_ARG_STRING,   &opt_destination},
-               {"tallocreport", 0, POPT_ARG_NONE, &do_talloc_report},
+               {"acls",        0, POPT_ARG_NONE,     &c->opt_acls},
+               {"attrs",       0, POPT_ARG_NONE,     &c->opt_attrs},
+               {"timestamps",  0, POPT_ARG_NONE,     &c->opt_timestamps},
+               {"exclude",     'X', POPT_ARG_STRING, &c->opt_exclude},
+               {"destination", 0, POPT_ARG_STRING,   &c->opt_destination},
+               {"tallocreport", 0, POPT_ARG_NONE,    &c->do_talloc_report},
+               /* Options for 'net rpc vampire (keytab)' */
+               {"force-full-repl", 0, POPT_ARG_NONE, &c->opt_force_full_repl},
+               {"single-obj-repl", 0, POPT_ARG_NONE, &c->opt_single_obj_repl},
+               {"clean-old-entries", 0, POPT_ARG_NONE, &c->opt_clean_old_entries},
 
                POPT_COMMON_SAMBA
                { 0, 0, 0, 0}
        };
 
-       zero_ip(&opt_dest_ip);
+
+       zero_sockaddr(&c->opt_dest_ip);
 
        load_case_tables();
 
        /* set default debug level to 0 regardless of what smb.conf sets */
        DEBUGLEVEL_CLASS[DBGC_ALL] = 0;
        dbf = x_stderr;
-       
-       pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
+       c->private_data = net_func;
+
+       pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
                            POPT_CONTEXT_KEEP_FIRST);
-       
+
        while((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case 'h':
-                       net_help(argc, argv);
-                       exit(0);
+                       c->display_usage = true;
+                       break;
+               case 'e':
+                       c->smb_encrypt = true;
                        break;
                case 'I':
-                       opt_dest_ip = *interpret_addr2(poptGetOptArg(pc));
-                       if (is_zero_ip(opt_dest_ip))
+                       if (!interpret_string_addr(&c->opt_dest_ip,
+                                               poptGetOptArg(pc), 0)) {
                                d_fprintf(stderr, "\nInvalid ip address specified\n");
-                       else
-                               opt_have_ip = True;
+                       } else {
+                               c->opt_have_ip = true;
+                       }
                        break;
                case 'U':
-                       opt_user_specified = True;
-                       opt_user_name = SMB_STRDUP(opt_user_name);
-                       p = strchr(opt_user_name,'%');
+                       c->opt_user_specified = true;
+                       c->opt_user_name = SMB_STRDUP(c->opt_user_name);
+                       p = strchr(c->opt_user_name,'%');
                        if (p) {
                                *p = 0;
-                               opt_password = p+1;
+                               c->opt_password = p+1;
                        }
                        break;
                default:
-                       d_fprintf(stderr, "\nInvalid option %s: %s\n", 
+                       d_fprintf(stderr, "\nInvalid option %s: %s\n",
                                 poptBadOption(pc, 0), poptStrerror(opt));
-                       net_help(argc, argv);
+                       net_help(c, argc, argv);
                        exit(1);
                }
        }
-       
+
        /*
         * Don't load debug level from smb.conf. It should be
         * set by cmdline arg or remain default (0)
         */
-       AllowDebugChange = False;
-       lp_load(dyn_CONFIGFILE,True,False,False,True);
-       
+       AllowDebugChange = false;
+       lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
+
        argv_new = (const char **)poptGetArgs(pc);
 
        argc_new = argc;
@@ -949,48 +724,54 @@ static struct functable net_func[] = {
                }
        }
 
-       if (do_talloc_report) {
+       if (c->do_talloc_report) {
                talloc_enable_leak_report();
        }
 
-       if (opt_requester_name) {
-               set_global_myname(opt_requester_name);
+       if (c->opt_requester_name) {
+               set_global_myname(c->opt_requester_name);
        }
 
-       if (!opt_user_name && getenv("LOGNAME")) {
-               opt_user_name = getenv("LOGNAME");
+       if (!c->opt_user_name && getenv("LOGNAME")) {
+               c->opt_user_name = getenv("LOGNAME");
        }
 
-       if (!opt_workgroup) {
-               opt_workgroup = smb_xstrdup(lp_workgroup());
+       if (!c->opt_workgroup) {
+               c->opt_workgroup = smb_xstrdup(lp_workgroup());
        }
-       
-       if (!opt_target_workgroup) {
-               opt_target_workgroup = smb_xstrdup(lp_workgroup());
+
+       if (!c->opt_target_workgroup) {
+               c->opt_target_workgroup = smb_xstrdup(lp_workgroup());
        }
-       
+
        if (!init_names())
                exit(1);
 
        load_interfaces();
-       
-       /* this makes sure that when we do things like call scripts, 
+
+       /* this makes sure that when we do things like call scripts,
           that it won't assert becouse we are not root */
        sec_init();
 
-       if (opt_machine_pass) {
+       if (c->opt_machine_pass) {
                /* it is very useful to be able to make ads queries as the
                   machine account for testing purposes and for domain leave */
 
-               net_use_machine_password();
+               net_use_krb_machine_account(c);
        }
 
-       if (!opt_password) {
-               opt_password = getenv("PASSWD");
+       if (!c->opt_password) {
+               c->opt_password = getenv("PASSWD");
        }
-        
-       rc = net_run_function(argc_new-1, argv_new+1, net_func, net_help);
-       
+
+       rc = net_run_function(c, argc_new-1, argv_new+1, "net", net_func);
+
        DEBUG(2,("return code = %d\n", rc));
+
+       libnetapi_free(c->netapi_ctx);
+
+       poptFreeContext(pc);
+
+       TALLOC_FREE(frame);
        return rc;
 }