rpc: Don't crash if npa_accept fails
[ambi/samba-autobuild/.git] / source3 / utils / net.c
index a6a9ec0119de1d0dc22e50c3e2b4893a650b03ed..7c5b6a05be74b228b814b13137c928f37b99548b 100644 (file)
 /*****************************************************/
 
 #include "includes.h"
-#include "popt_common.h"
+#include "popt_common_cmdline.h"
 #include "utils/net.h"
 #include "secrets.h"
 #include "lib/netapi/netapi.h"
 #include "../libcli/security/security.h"
 #include "passdb.h"
 #include "messages.h"
+#include "cmdline_contexts.h"
+#include "lib/gencache.h"
+#include "auth/credentials/credentials.h"
 
 #ifdef WITH_FAKE_KASERVER
 #include "utils/net_afs.h"
@@ -91,13 +94,110 @@ static void set_line_buffering(FILE *f)
        setvbuf(f, NULL, _IOLBF, 0);
 }
 
+static int net_primarytrust_dumpinfo(struct net_context *c, int argc,
+                                    const char **argv)
+{
+       int role = lp_server_role();
+       const char *domain = lp_workgroup();
+       struct secrets_domain_info1 *info = NULL;
+       bool include_secrets = c->opt_force;
+       char *str = NULL;
+       NTSTATUS status;
+
+       if (role >= ROLE_ACTIVE_DIRECTORY_DC) {
+               d_printf(_("net primarytrust dumpinfo is only supported "
+                        "on a DOMAIN_MEMBER for now.\n"));
+               return 1;
+       }
+
+       if (c->opt_stdin) {
+               set_line_buffering(stdin);
+               set_line_buffering(stdout);
+               set_line_buffering(stderr);
+       }
+
+       status = secrets_fetch_or_upgrade_domain_info(domain,
+                                                     talloc_tos(),
+                                                     &info);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr,
+                         _("Unable to fetch the information for domain[%s] "
+                         "in the secrets database.\n"),
+                         domain);
+               return 1;
+       }
+
+       str = secrets_domain_info_string(info, info, domain, include_secrets);
+       if (str == NULL) {
+               d_fprintf(stderr, "secrets_domain_info_string() failed.\n");
+               return 1;
+       }
+
+       d_printf("%s", str);
+       if (!c->opt_force) {
+               d_printf(_("The password values are only included using "
+                        "-f flag.\n"));
+       }
+
+       TALLOC_FREE(info);
+       return 0;
+}
+
+/**
+ * Entrypoint for 'net primarytrust' code.
+ *
+ * @param argc Standard argc.
+ * @param argv Standard argv without initial components.
+ *
+ * @return Integer status (0 means success).
+ */
+
+static int net_primarytrust(struct net_context *c, int argc, const char **argv)
+{
+       struct functable func[] = {
+               {
+                       .funcname         = "dumpinfo",
+                       .fn               = net_primarytrust_dumpinfo,
+                       .valid_transports = NET_TRANSPORT_LOCAL,
+                       .description      = N_("Dump the details of the "
+                                              "workstation trust"),
+                       .usage            = N_("  net [options] primarytrust "
+                                              "dumpinfo'\n"
+                                              "    Dump the details of the "
+                                              "workstation trust in "
+                                              "secrets.tdb.\n"
+                                              "    Requires the -f flag to "
+                                              "include the password values."),
+               },
+               {
+                       .funcname = NULL,
+               },
+       };
+
+       return net_run_function(c, argc, argv, "net primarytrust", func);
+}
+
 static int net_changesecretpw(struct net_context *c, int argc,
                              const char **argv)
 {
         char *trust_pw;
-        enum netr_SchannelType sec_channel_type = SEC_CHAN_WKSTA;
+       int role = lp_server_role();
+
+       if (role != ROLE_DOMAIN_MEMBER) {
+               d_printf(_("Machine account password change only supported on a DOMAIN_MEMBER.\n"
+                          "Do NOT use this function unless you know what it does!\n"
+                          "This function will change the ADS Domain member "
+                          "machine account password in the secrets.tdb file!\n"));
+               return 1;
+       }
 
        if(c->opt_force) {
+               struct secrets_domain_info1 *info = NULL;
+               struct secrets_domain_info1_change *prev = NULL;
+               NTSTATUS status;
+               struct timeval tv = timeval_current();
+               NTTIME now = timeval_to_nttime(&tv);
+
                if (c->opt_stdin) {
                        set_line_buffering(stdin);
                        set_line_buffering(stdout);
@@ -111,14 +211,37 @@ static int net_changesecretpw(struct net_context *c, int argc,
                            return 1;
                }
 
-               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"));
-                           return 1;
+               status = secrets_prepare_password_change(lp_workgroup(),
+                                                        "localhost",
+                                                        trust_pw,
+                                                        talloc_tos(),
+                                                        &info, &prev);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_fprintf(stderr,
+                               _("Unable to write the machine account password in the secrets database"));
+                       return 1;
                }
-               else {
-                   d_printf(_("Modified trust account password in secrets database\n"));
+               if (prev != NULL) {
+                       d_fprintf(stderr,
+                               _("Pending machine account password change found - aborting."));
+                       status = secrets_failed_password_change("localhost",
+                                               NT_STATUS_REQUEST_NOT_ACCEPTED,
+                                               NT_STATUS_NOT_COMMITTED,
+                                               info);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               d_fprintf(stderr,
+                                       _("Failed to abort machine account password change"));
+                       }
+                       return 1;
+               }
+               status = secrets_finish_password_change("localhost", now, info);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_fprintf(stderr,
+                               _("Unable to write the machine account password in the secrets database"));
+                       return 1;
                }
+
+               d_printf(_("Modified trust account password in secrets database\n"));
        }
        else {
                d_printf(_("Machine account password change requires the -f flag.\n"
@@ -156,9 +279,9 @@ static int net_setauthuser(struct net_context *c, int argc, const char **argv)
                                    "        Delete the auth user setting.\n"));
                        return 1;
                }
-               secrets_delete(SECRETS_AUTH_USER);
-               secrets_delete(SECRETS_AUTH_DOMAIN);
-               secrets_delete(SECRETS_AUTH_PASSWORD);
+               secrets_delete_entry(SECRETS_AUTH_USER);
+               secrets_delete_entry(SECRETS_AUTH_DOMAIN);
+               secrets_delete_entry(SECRETS_AUTH_PASSWORD);
                return 0;
        }
 
@@ -242,7 +365,7 @@ static int net_getlocalsid(struct net_context *c, int argc, const char **argv)
 {
         struct dom_sid sid;
        const char *name;
-       fstring sid_str;
+       struct dom_sid_buf sid_str;
 
        if (argc >= 1) {
                name = argv[0];
@@ -273,8 +396,9 @@ static int net_getlocalsid(struct net_context *c, int argc, const char **argv)
                DEBUG(0, ("Can't fetch domain SID for name: %s\n", name));
                return 1;
        }
-       sid_to_fstring(sid_str, &sid);
-       d_printf(_("SID for domain %s is: %s\n"), name, sid_str);
+       d_printf(_("SID for domain %s is: %s\n"),
+                name,
+                dom_sid_str_buf(&sid, &sid_str));
        return 0;
 }
 
@@ -323,7 +447,7 @@ static int net_setdomainsid(struct net_context *c, int argc, const char **argv)
 static int net_getdomainsid(struct net_context *c, int argc, const char **argv)
 {
        struct dom_sid domain_sid;
-       fstring sid_str;
+       struct dom_sid_buf sid_str;
 
        if (argc > 0) {
                d_printf(_("Usage:"));
@@ -354,26 +478,27 @@ static int net_getdomainsid(struct net_context *c, int argc, const char **argv)
                        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"),
-                        lp_netbios_name(), sid_str);
+                        lp_netbios_name(),
+                        dom_sid_str_buf(&domain_sid, &sid_str));
        }
        if (!secrets_fetch_domain_sid(c->opt_workgroup, &domain_sid)) {
                d_fprintf(stderr, _("Could not fetch domain SID\n"));
                return 1;
        }
 
-       sid_to_fstring(sid_str, &domain_sid);
-       d_printf(_("SID for domain %s is: %s\n"), c->opt_workgroup, sid_str);
+       d_printf(_("SID for domain %s is: %s\n"),
+                c->opt_workgroup,
+                dom_sid_str_buf(&domain_sid, &sid_str));
 
        return 0;
 }
 
 static bool search_maxrid(struct pdb_search *search, const char *type,
-                         uint32 *max_rid)
+                         uint32_t *max_rid)
 {
        struct samr_displayentry *entries;
-       uint32 i, num_entries;
+       uint32_t i, num_entries;
 
        if (search == NULL) {
                d_fprintf(stderr, _("get_maxrid: Could not search %s\n"), type);
@@ -387,9 +512,9 @@ static bool search_maxrid(struct pdb_search *search, const char *type,
        return true;
 }
 
-static uint32 get_maxrid(void)
+static uint32_t get_maxrid(void)
 {
-       uint32 max_rid = 0;
+       uint32_t max_rid = 0;
 
        if (!search_maxrid(pdb_search_users(talloc_tos(), 0), "users", &max_rid))
                return 0;
@@ -407,7 +532,7 @@ static uint32 get_maxrid(void)
 
 static int net_maxrid(struct net_context *c, int argc, const char **argv)
 {
-       uint32 rid;
+       uint32_t rid;
 
        if (argc != 0) {
                d_fprintf(stderr, "%s net maxrid\n", _("Usage:"));
@@ -570,6 +695,14 @@ static struct functable net_func[] = {
                N_("  Use 'net help password' to get more information about "
                   "'net password' commands.")
        },
+       {
+               "primarytrust",
+               net_primarytrust,
+               NET_TRANSPORT_RPC,
+               N_("Run functions related to the primary workstation trust."),
+               N_("  Use 'net help primarytrust' to get more extensive information "
+                  "about 'net primarytrust' commands.")
+       },
        {       "changetrustpw",
                net_changetrustpw,
                NET_TRANSPORT_ADS | NET_TRANSPORT_RPC,
@@ -743,6 +876,22 @@ static struct functable net_func[] = {
                   "'net serverid' commands.")
        },
 
+       {       "notify",
+               net_notify,
+               NET_TRANSPORT_LOCAL,
+               N_("notifyd client code"),
+               N_("  Use 'net help notify' to get more information about "
+                  "'net notify' commands.")
+       },
+
+       {       "tdb",
+               net_tdb,
+               NET_TRANSPORT_LOCAL,
+               N_("Show information from tdb records"),
+               N_("  Use 'net help tdb' to get more information about "
+                  "'net tdb' commands.")
+       },
+
 #ifdef WITH_FAKE_KASERVER
        {       "afs",
                net_afs,
@@ -764,6 +913,26 @@ static struct functable net_func[] = {
 };
 
 
+static void get_credentials_file(struct net_context *c,
+                                const char *file)
+{
+       struct cli_credentials *cred = cli_credentials_init(c);
+
+       if (cred == NULL) {
+               d_printf("ERROR: Unable to allocate memory!\n");
+               exit(-1);
+       }
+
+       if (!cli_credentials_parse_file(cred, file, CRED_GUESS_FILE)) {
+               exit(-1);
+       }
+
+       c->opt_user_name = cli_credentials_get_username(cred);
+       c->opt_user_specified = (c->opt_user_name != NULL);
+       c->opt_password = cli_credentials_get_password(cred);
+       c->opt_target_workgroup = cli_credentials_get_domain(cred);
+}
+
 /****************************************************************************
   main program
 ****************************************************************************/
@@ -780,66 +949,323 @@ static struct functable net_func[] = {
        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, &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,    &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', N_("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},
-               {"request-timeout",0,POPT_ARG_INT,    &c->opt_request_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},
-               {"use-ccache",    0, POPT_ARG_NONE,   &c->opt_ccache},
-               {"verbose",     'v', POPT_ARG_NONE,   &c->opt_verbose},
-               {"test",        'T', POPT_ARG_NONE,   &c->opt_testmode},
+               {
+                       .longName   = "help",
+                       .shortName  = 'h',
+                       .argInfo    = POPT_ARG_NONE,
+                       .val        = 'h',
+               },
+               {
+                       .longName   = "workgroup",
+                       .shortName  = 'w',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_target_workgroup,
+               },
+               {
+                       .longName   = "user",
+                       .shortName  = 'U',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_user_name,
+                       .val        = 'U',
+               },
+               {
+                       .longName   = "authentication-file",
+                       .shortName  = 'A',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_user_name,
+                       .val        = 'A',
+                       .descrip    = "Get the credentials from a file",
+                       .argDescrip = "FILE",
+               },
+               {
+                       .longName   = "ipaddress",
+                       .shortName  = 'I',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = 0,
+                       .val        = 'I',
+               },
+               {
+                       .longName   = "port",
+                       .shortName  = 'p',
+                       .argInfo    = POPT_ARG_INT,
+                       .arg        = &c->opt_port,
+               },
+               {
+                       .longName   = "myname",
+                       .shortName  = 'n',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_requester_name,
+               },
+               {
+                       .longName   = "server",
+                       .shortName  = 'S',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_host,
+               },
+               {
+                       .longName   = "encrypt",
+                       .shortName  = 'e',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = NULL,
+                       .val        = 'e',
+                       .descrip    = N_("Encrypt SMB transport"),
+               },
+               {
+                       .longName   = "container",
+                       .shortName  = 'c',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_container,
+               },
+               {
+                       .longName   = "comment",
+                       .shortName  = 'C',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_comment,
+               },
+               {
+                       .longName   = "maxusers",
+                       .shortName  = 'M',
+                       .argInfo    = POPT_ARG_INT,
+                       .arg        = &c->opt_maxusers,
+               },
+               {
+                       .longName   = "flags",
+                       .shortName  = 'F',
+                       .argInfo    = POPT_ARG_INT,
+                       .arg        = &c->opt_flags,
+               },
+               {
+                       .longName   = "long",
+                       .shortName  = 'l',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_long_list_entries,
+               },
+               {
+                       .longName   = "reboot",
+                       .shortName  = 'r',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_reboot,
+               },
+               {
+                       .longName   = "force",
+                       .shortName  = 'f',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_force,
+               },
+               {
+                       .longName   = "stdin",
+                       .shortName  = 'i',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_stdin,
+               },
+               {
+                       .longName   = "timeout",
+                       .shortName  = 't',
+                       .argInfo    = POPT_ARG_INT,
+                       .arg        = &c->opt_timeout,
+               },
+               {
+                       .longName   = "request-timeout",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_INT,
+                       .arg        = &c->opt_request_timeout,
+               },
+               {
+                       .longName   = "machine-pass",
+                       .shortName  = 'P',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_machine_pass,
+               },
+               {
+                       .longName   = "kerberos",
+                       .shortName  = 'k',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_kerberos,
+               },
+               {
+                       .longName   = "myworkgroup",
+                       .shortName  = 'W',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_workgroup,
+               },
+               {
+                       .longName   = "use-ccache",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_ccache,
+               },
+               {
+                       .longName   = "verbose",
+                       .shortName  = 'v',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_verbose,
+               },
+               {
+                       .longName   = "test",
+                       .shortName  = 'T',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_testmode,
+               },
                /* Options for 'net groupmap set' */
-               {"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},
+               {
+                       .longName   = "local",
+                       .shortName  = 'L',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_localgroup,
+               },
+               {
+                       .longName   = "domain",
+                       .shortName  = 'D',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_domaingroup,
+               },
+               {
+                       .longName   = "ntname",
+                       .shortName  = 'N',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_newntname,
+               },
+               {
+                       .longName   = "rid",
+                       .shortName  = 'R',
+                       .argInfo    = POPT_ARG_INT,
+                       .arg        = &c->opt_rid,
+               },
                /* Options for 'net rpc share migrate' */
-               {"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},
+               {
+                       .longName   = "acls",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_acls,
+               },
+               {
+                       .longName   = "attrs",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_attrs,
+               },
+               {
+                       .longName   = "timestamps",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_timestamps,
+               },
+               {
+                       .longName   = "exclude",
+                       .shortName  = 'X',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_exclude,
+               },
+               {
+                       .longName   = "destination",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_destination,
+               },
+               {
+                       .longName   = "tallocreport",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &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},
+               {
+                       .longName   = "force-full-repl",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_force_full_repl,
+               },
+               {
+                       .longName   = "single-obj-repl",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_single_obj_repl,
+               },
+               {
+                       .longName   = "clean-old-entries",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_clean_old_entries,
+               },
                /* Options for 'net idmap'*/
-               {"db", 0, POPT_ARG_STRING, &c->opt_db},
-               {"lock", 0, POPT_ARG_NONE,   &c->opt_lock},
-               {"auto", 'a', POPT_ARG_NONE,   &c->opt_auto},
-               {"repair", 0, POPT_ARG_NONE,   &c->opt_repair},
+               {
+                       .longName   = "db",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_db,
+               },
+               {
+                       .longName   = "lock",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        =   &c->opt_lock,
+               },
+               {
+                       .longName   = "auto",
+                       .shortName  = 'a',
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_auto,
+               },
+               {
+                       .longName   = "repair",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        =   &c->opt_repair,
+               },
                /* Options for 'net registry check'*/
-               {"reg-version", 0, POPT_ARG_INT, &c->opt_reg_version},
-               {"output", 'o', POPT_ARG_STRING, &c->opt_output},
-               {"wipe", 0, POPT_ARG_NONE, &c->opt_wipe},
+               {
+                       .longName   = "reg-version",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_INT,
+                       .arg        = &c->opt_reg_version,
+               },
+               {
+                       .longName   = "output",
+                       .shortName  = 'o',
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_output,
+               },
+               {
+                       .longName   = "wipe",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_wipe,
+               },
                /* Options for 'net registry import' */
-               {"precheck", 0, POPT_ARG_STRING, &c->opt_precheck},
+               {
+                       .longName   = "precheck",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_STRING,
+                       .arg        = &c->opt_precheck,
+               },
+               /* Options for 'net ads join or leave' */
+               {
+                       .longName   = "no-dns-updates",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_no_dns_updates,
+               },
+               {
+                       .longName   = "keep-account",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_keep_account,
+               },
+               {
+                       .longName   = "json",
+                       .shortName  = 0,
+                       .argInfo    = POPT_ARG_NONE,
+                       .arg        = &c->opt_json,
+               },
                POPT_COMMON_SAMBA
-               { 0, 0, 0, 0}
+               POPT_TABLEEND
        };
 
        zero_sockaddr(&c->opt_dest_ip);
 
        setup_logging(argv[0], DEBUG_STDERR);
 
-       load_case_tables();
+       smb_init_locale();
 
        setlocale(LC_ALL, "");
 #if defined(HAVE_BINDTEXTDOMAIN)
@@ -881,6 +1307,9 @@ static struct functable net_func[] = {
                                c->opt_password = p+1;
                        }
                        break;
+               case 'A':
+                       get_credentials_file(c, c->opt_user_name);
+                       break;
                default:
                        d_fprintf(stderr, _("\nInvalid option %s: %s\n"),
                                 poptBadOption(pc, 0), poptStrerror(opt));
@@ -889,7 +1318,13 @@ static struct functable net_func[] = {
                }
        }
 
-       lp_load_global(get_dyn_CONFIGFILE());
+       c->msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
+
+       if (!lp_load_global(get_dyn_CONFIGFILE())) {
+               d_fprintf(stderr, "Can't load %s - run testparm to debug it\n",
+                         get_dyn_CONFIGFILE());
+               exit(1);
+       }
 
 #if defined(HAVE_BIND_TEXTDOMAIN_CODESET)
        /* Bind our gettext results to 'unix charset'
@@ -924,11 +1359,11 @@ static struct functable net_func[] = {
        }
 
        if (!c->opt_workgroup) {
-               c->opt_workgroup = smb_xstrdup(lp_workgroup());
+               c->opt_workgroup = talloc_strdup(c, lp_workgroup());
        }
 
        if (!c->opt_target_workgroup) {
-               c->opt_target_workgroup = smb_xstrdup(lp_workgroup());
+               c->opt_target_workgroup = talloc_strdup(c, lp_workgroup());
        }
 
        if (!init_names())
@@ -953,17 +1388,10 @@ static struct functable net_func[] = {
 
        popt_burn_cmdline_password(argc, argv);
 
-       /* Failing to init the msg_ctx isn't a fatal error. Only
-          root-level things (joining/leaving domains etc.) will be denied. */
-
-       c->msg_ctx = messaging_init(c, samba_tevent_context_init(c));
-
        rc = net_run_function(c, argc_new-1, argv_new+1, "net", net_func);
 
        DEBUG(2,("return code = %d\n", rc));
 
-       gencache_stabilize();
-
        libnetapi_free(c->netapi_ctx);
 
        poptFreeContext(pc);