1138d1984e6b3b1c929ca9faba6b46b0f11058c0
[samba.git] / source3 / utils / net.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Copyright (C) 2001 Steve French  (sfrench@us.ibm.com)
5    Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
7    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
8    Copyright (C) 2008 Kai Blin (kai@samba.org)
9
10    Originally written by Steve and Jim. Largely rewritten by tridge in
11    November 2001.
12
13    Reworked again by abartlet in December 2001
14
15    Another overhaul, moving functionality into plug-ins loaded on demand by Kai
16    in May 2008.
17
18    This program is free software; you can redistribute it and/or modify
19    it under the terms of the GNU General Public License as published by
20    the Free Software Foundation; either version 3 of the License, or
21    (at your option) any later version.
22
23    This program is distributed in the hope that it will be useful,
24    but WITHOUT ANY WARRANTY; without even the implied warranty of
25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26    GNU General Public License for more details.
27
28    You should have received a copy of the GNU General Public License
29    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
30
31 /*****************************************************/
32 /*                                                   */
33 /*   Distributed SMB/CIFS Server Management Utility  */
34 /*                                                   */
35 /*   The intent was to make the syntax similar       */
36 /*   to the NET utility (first developed in DOS      */
37 /*   with additional interesting & useful functions  */
38 /*   added in later SMB server network operating     */
39 /*   systems).                                       */
40 /*                                                   */
41 /*****************************************************/
42
43 #include "includes.h"
44 #include "popt_common_cmdline.h"
45 #include "utils/net.h"
46 #include "secrets.h"
47 #include "lib/netapi/netapi.h"
48 #include "../libcli/security/security.h"
49 #include "passdb.h"
50 #include "messages.h"
51 #include "cmdline_contexts.h"
52 #include "lib/gencache.h"
53
54 #ifdef WITH_FAKE_KASERVER
55 #include "utils/net_afs.h"
56 #endif
57
58 /***********************************************************************/
59 /* end of internationalization section                                 */
60 /***********************************************************************/
61
62 enum netr_SchannelType get_sec_channel_type(const char *param)
63 {
64         if (!(param && *param)) {
65                 return get_default_sec_channel();
66         } else {
67                 if (strequal(param, "PDC")) {
68                         return SEC_CHAN_BDC;
69                 } else if (strequal(param, "BDC")) {
70                         return SEC_CHAN_BDC;
71                 } else if (strequal(param, "MEMBER")) {
72                         return SEC_CHAN_WKSTA;
73 #if 0
74                 } else if (strequal(param, "DOMAIN")) {
75                         return SEC_CHAN_DOMAIN;
76 #endif
77                 } else {
78                         return get_default_sec_channel();
79                 }
80         }
81 }
82
83 static int net_changetrustpw(struct net_context *c, int argc, const char **argv)
84 {
85         if (net_ads_check_our_domain(c) == 0)
86                 return net_ads_changetrustpw(c, argc, argv);
87
88         return net_rpc_changetrustpw(c, argc, argv);
89 }
90
91 static void set_line_buffering(FILE *f)
92 {
93         setvbuf(f, NULL, _IOLBF, 0);
94 }
95
96 static int net_primarytrust_dumpinfo(struct net_context *c, int argc,
97                                      const char **argv)
98 {
99         int role = lp_server_role();
100         const char *domain = lp_workgroup();
101         struct secrets_domain_info1 *info = NULL;
102         bool include_secrets = c->opt_force;
103         char *str = NULL;
104         NTSTATUS status;
105
106         if (role >= ROLE_ACTIVE_DIRECTORY_DC) {
107                 d_printf(_("net primarytrust dumpinfo is only supported "
108                          "on a DOMAIN_MEMBER for now.\n"));
109                 return 1;
110         }
111
112         if (c->opt_stdin) {
113                 set_line_buffering(stdin);
114                 set_line_buffering(stdout);
115                 set_line_buffering(stderr);
116         }
117
118         status = secrets_fetch_or_upgrade_domain_info(domain,
119                                                       talloc_tos(),
120                                                       &info);
121         if (!NT_STATUS_IS_OK(status)) {
122                 d_fprintf(stderr,
123                           _("Unable to fetch the information for domain[%s] "
124                           "in the secrets database.\n"),
125                           domain);
126                 return 1;
127         }
128
129         str = secrets_domain_info_string(info, info, domain, include_secrets);
130         if (str == NULL) {
131                 d_fprintf(stderr, "secrets_domain_info_string() failed.\n");
132                 return 1;
133         }
134
135         d_printf("%s", str);
136         if (!c->opt_force) {
137                 d_printf(_("The password values are only included using "
138                          "-f flag.\n"));
139         }
140
141         TALLOC_FREE(info);
142         return 0;
143 }
144
145 /**
146  * Entrypoint for 'net primarytrust' code.
147  *
148  * @param argc Standard argc.
149  * @param argv Standard argv without initial components.
150  *
151  * @return Integer status (0 means success).
152  */
153
154 static int net_primarytrust(struct net_context *c, int argc, const char **argv)
155 {
156         struct functable func[] = {
157                 {
158                         "dumpinfo",
159                         net_primarytrust_dumpinfo,
160                         NET_TRANSPORT_LOCAL,
161                         N_("Dump the details of the workstation trust"),
162                         N_("  net [options] primarytrust dumpinfo'\n"
163                            "    Dump the details of the workstation trust "
164                            "in secrets.tdb.\n"
165                            "    Requires the -f flag to include the password values.")
166                 },
167                 {NULL, NULL, 0, NULL, NULL}
168         };
169
170         return net_run_function(c, argc, argv, "net primarytrust", func);
171 }
172
173 static int net_changesecretpw(struct net_context *c, int argc,
174                               const char **argv)
175 {
176         char *trust_pw;
177         int role = lp_server_role();
178
179         if (role != ROLE_DOMAIN_MEMBER) {
180                 d_printf(_("Machine account password change only supported on a DOMAIN_MEMBER.\n"
181                            "Do NOT use this function unless you know what it does!\n"
182                            "This function will change the ADS Domain member "
183                            "machine account password in the secrets.tdb file!\n"));
184                 return 1;
185         }
186
187         if(c->opt_force) {
188                 struct secrets_domain_info1 *info = NULL;
189                 struct secrets_domain_info1_change *prev = NULL;
190                 NTSTATUS status;
191                 struct timeval tv = timeval_current();
192                 NTTIME now = timeval_to_nttime(&tv);
193
194                 if (c->opt_stdin) {
195                         set_line_buffering(stdin);
196                         set_line_buffering(stdout);
197                         set_line_buffering(stderr);
198                 }
199
200                 trust_pw = get_pass(_("Enter machine password: "), c->opt_stdin);
201                 if (trust_pw == NULL) {
202                             d_fprintf(stderr,
203                                       _("Error in reading machine password\n"));
204                             return 1;
205                 }
206
207                 status = secrets_prepare_password_change(lp_workgroup(),
208                                                          "localhost",
209                                                          trust_pw,
210                                                          talloc_tos(),
211                                                          &info, &prev);
212                 if (!NT_STATUS_IS_OK(status)) {
213                         d_fprintf(stderr,
214                                 _("Unable to write the machine account password in the secrets database"));
215                         return 1;
216                 }
217                 if (prev != NULL) {
218                         d_fprintf(stderr,
219                                 _("Pending machine account password change found - aborting."));
220                         status = secrets_failed_password_change("localhost",
221                                                 NT_STATUS_REQUEST_NOT_ACCEPTED,
222                                                 NT_STATUS_NOT_COMMITTED,
223                                                 info);
224                         if (!NT_STATUS_IS_OK(status)) {
225                                 d_fprintf(stderr,
226                                         _("Failed to abort machine account password change"));
227                         }
228                         return 1;
229                 }
230                 status = secrets_finish_password_change("localhost", now, info);
231                 if (!NT_STATUS_IS_OK(status)) {
232                         d_fprintf(stderr,
233                                 _("Unable to write the machine account password in the secrets database"));
234                         return 1;
235                 }
236
237                 d_printf(_("Modified trust account password in secrets database\n"));
238         }
239         else {
240                 d_printf(_("Machine account password change requires the -f flag.\n"
241                            "Do NOT use this function unless you know what it does!\n"
242                            "This function will change the ADS Domain member "
243                            "machine account password in the secrets.tdb file!\n"));
244         }
245
246         return 0;
247 }
248
249 /**
250  * @brief Set the authorised user for winbindd access in secrets.tdb
251  */
252 static int net_setauthuser(struct net_context *c, int argc, const char **argv)
253 {
254         const char *password = NULL;
255
256         if (!secrets_init()) {
257                 d_fprintf(stderr, _("Failed to open secrets.tdb.\n"));
258                 return 1;
259         }
260
261         /* Delete the settings. */
262         if (argc >= 1) {
263                 if (strncmp(argv[0], "delete", 6) != 0) {
264                         d_fprintf(stderr,_("Usage:\n"));
265                         d_fprintf(stderr,
266                                   _("    net setauthuser -U user[%%password] \n"
267                                     "        Set the auth user account to user"
268                                     "password. Prompt for password if not "
269                                     "specified.\n"));
270                         d_fprintf(stderr,
271                                   _("    net setauthuser delete\n"
272                                     "        Delete the auth user setting.\n"));
273                         return 1;
274                 }
275                 secrets_delete_entry(SECRETS_AUTH_USER);
276                 secrets_delete_entry(SECRETS_AUTH_DOMAIN);
277                 secrets_delete_entry(SECRETS_AUTH_PASSWORD);
278                 return 0;
279         }
280
281         if (!c->opt_user_specified) {
282                 d_fprintf(stderr, _("Usage:\n"));
283                 d_fprintf(stderr,
284                           _("    net setauthuser -U user[%%password]\n"
285                             "        Set the auth user account to user"
286                             "password. Prompt for password if not "
287                             "specified.\n"));
288                 d_fprintf(stderr,
289                           _("    net setauthuser delete\n"
290                             "        Delete the auth user setting.\n"));
291                 return 1;
292         }
293
294         password = net_prompt_pass(c, _("the auth user"));
295         if (password == NULL) {
296                 d_fprintf(stderr,_("Failed to get the auth users password.\n"));
297                 return 1;
298         }
299
300         if (!secrets_store(SECRETS_AUTH_USER, c->opt_user_name,
301                            strlen(c->opt_user_name) + 1)) {
302                 d_fprintf(stderr, _("error storing auth user name\n"));
303                 return 1;
304         }
305
306         if (!secrets_store(SECRETS_AUTH_DOMAIN, c->opt_workgroup,
307                            strlen(c->opt_workgroup) + 1)) {
308                 d_fprintf(stderr, _("error storing auth user domain\n"));
309                 return 1;
310         }
311
312         if (!secrets_store(SECRETS_AUTH_PASSWORD, password,
313                            strlen(password) + 1)) {
314                 d_fprintf(stderr, _("error storing auth user password\n"));
315                 return 1;
316         }
317
318         return 0;
319 }
320
321 /**
322  * @brief Get the auth user settings
323  */
324 static int net_getauthuser(struct net_context *c, int argc, const char **argv)
325 {
326         char *user, *domain, *password;
327
328         /* Lift data from secrets file */
329
330         secrets_fetch_ipc_userpass(&user, &domain, &password);
331
332         if ((!user || !*user) && (!domain || !*domain ) &&
333             (!password || !*password)){
334
335                 SAFE_FREE(user);
336                 SAFE_FREE(domain);
337                 SAFE_FREE(password);
338                 d_printf(_("No authorised user configured\n"));
339                 return 0;
340         }
341
342         /* Pretty print authorised user info */
343
344         d_printf("%s%s%s%s%s\n", domain ? domain : "",
345                  domain ? lp_winbind_separator(): "", user,
346                  password ? "%" : "", password ? password : "");
347
348         SAFE_FREE(user);
349         SAFE_FREE(domain);
350         SAFE_FREE(password);
351
352         return 0;
353 }
354 /*
355  Retrieve our local SID or the SID for the specified name
356  */
357 static int net_getlocalsid(struct net_context *c, int argc, const char **argv)
358 {
359         struct dom_sid sid;
360         const char *name;
361         fstring sid_str;
362
363         if (argc >= 1) {
364                 name = argv[0];
365         }
366         else {
367                 name = lp_netbios_name();
368         }
369
370         if(!initialize_password_db(false, NULL)) {
371                 d_fprintf(stderr, _("WARNING: Could not open passdb\n"));
372                 return 1;
373         }
374
375         /* first check to see if we can even access secrets, so we don't
376            panic when we can't. */
377
378         if (!secrets_init()) {
379                 d_fprintf(stderr,
380                           _("Unable to open secrets.tdb.  Can't fetch domain "
381                             "SID for name: %s\n"), name);
382                 return 1;
383         }
384
385         /* Generate one, if it doesn't exist */
386         get_global_sam_sid();
387
388         if (!secrets_fetch_domain_sid(name, &sid)) {
389                 DEBUG(0, ("Can't fetch domain SID for name: %s\n", name));
390                 return 1;
391         }
392         sid_to_fstring(sid_str, &sid);
393         d_printf(_("SID for domain %s is: %s\n"), name, sid_str);
394         return 0;
395 }
396
397 static int net_setlocalsid(struct net_context *c, int argc, const char **argv)
398 {
399         struct dom_sid sid;
400
401         if ( (argc != 1)
402              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
403              || (!string_to_sid(&sid, argv[0]))
404              || (sid.num_auths != 4)) {
405                 d_printf(_("Usage:"));
406                 d_printf(" net setlocalsid S-1-5-21-x-y-z\n");
407                 return 1;
408         }
409
410         if (!secrets_store_domain_sid(lp_netbios_name(), &sid)) {
411                 DEBUG(0,("Can't store domain SID as a pdc/bdc.\n"));
412                 return 1;
413         }
414
415         return 0;
416 }
417
418 static int net_setdomainsid(struct net_context *c, int argc, const char **argv)
419 {
420         struct dom_sid sid;
421
422         if ( (argc != 1)
423              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
424              || (!string_to_sid(&sid, argv[0]))
425              || (sid.num_auths != 4)) {
426                 d_printf(_("Usage:"));
427                 d_printf(" net setdomainsid S-1-5-21-x-y-z\n");
428                 return 1;
429         }
430
431         if (!secrets_store_domain_sid(lp_workgroup(), &sid)) {
432                 DEBUG(0,("Can't store domain SID.\n"));
433                 return 1;
434         }
435
436         return 0;
437 }
438
439 static int net_getdomainsid(struct net_context *c, int argc, const char **argv)
440 {
441         struct dom_sid domain_sid;
442         fstring sid_str;
443
444         if (argc > 0) {
445                 d_printf(_("Usage:"));
446                 d_printf(" net getdomainsid\n");
447                 return 1;
448         }
449
450         if(!initialize_password_db(false, NULL)) {
451                 d_fprintf(stderr, _("WARNING: Could not open passdb\n"));
452                 return 1;
453         }
454
455         /* first check to see if we can even access secrets, so we don't
456            panic when we can't. */
457
458         if (!secrets_init()) {
459                 d_fprintf(stderr, _("Unable to open secrets.tdb.  Can't fetch "
460                                     "domain SID for name: %s\n"),
461                           get_global_sam_name());
462                 return 1;
463         }
464
465         /* Generate one, if it doesn't exist */
466         get_global_sam_sid();
467
468         if (!IS_DC) {
469                 if (!secrets_fetch_domain_sid(lp_netbios_name(), &domain_sid)) {
470                         d_fprintf(stderr, _("Could not fetch local SID\n"));
471                         return 1;
472                 }
473                 sid_to_fstring(sid_str, &domain_sid);
474                 d_printf(_("SID for local machine %s is: %s\n"),
475                          lp_netbios_name(), sid_str);
476         }
477         if (!secrets_fetch_domain_sid(c->opt_workgroup, &domain_sid)) {
478                 d_fprintf(stderr, _("Could not fetch domain SID\n"));
479                 return 1;
480         }
481
482         sid_to_fstring(sid_str, &domain_sid);
483         d_printf(_("SID for domain %s is: %s\n"), c->opt_workgroup, sid_str);
484
485         return 0;
486 }
487
488 static bool search_maxrid(struct pdb_search *search, const char *type,
489                           uint32_t *max_rid)
490 {
491         struct samr_displayentry *entries;
492         uint32_t i, num_entries;
493
494         if (search == NULL) {
495                 d_fprintf(stderr, _("get_maxrid: Could not search %s\n"), type);
496                 return false;
497         }
498
499         num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries);
500         for (i=0; i<num_entries; i++)
501                 *max_rid = MAX(*max_rid, entries[i].rid);
502         TALLOC_FREE(search);
503         return true;
504 }
505
506 static uint32_t get_maxrid(void)
507 {
508         uint32_t max_rid = 0;
509
510         if (!search_maxrid(pdb_search_users(talloc_tos(), 0), "users", &max_rid))
511                 return 0;
512
513         if (!search_maxrid(pdb_search_groups(talloc_tos()), "groups", &max_rid))
514                 return 0;
515
516         if (!search_maxrid(pdb_search_aliases(talloc_tos(),
517                                               get_global_sam_sid()),
518                            "aliases", &max_rid))
519                 return 0;
520
521         return max_rid;
522 }
523
524 static int net_maxrid(struct net_context *c, int argc, const char **argv)
525 {
526         uint32_t rid;
527
528         if (argc != 0) {
529                 d_fprintf(stderr, "%s net maxrid\n", _("Usage:"));
530                 return 1;
531         }
532
533         if ((rid = get_maxrid()) == 0) {
534                 d_fprintf(stderr, _("can't get current maximum rid\n"));
535                 return 1;
536         }
537
538         d_printf(_("Currently used maximum rid: %d\n"), rid);
539
540         return 0;
541 }
542
543 /* main function table */
544 static struct functable net_func[] = {
545         {
546                 "rpc",
547                 net_rpc,
548                 NET_TRANSPORT_RPC,
549                 N_("Run functions using RPC transport"),
550                 N_("  Use 'net help rpc' to get more extensive information "
551                    "about 'net rpc' commands.")
552         },
553         {
554                 "rap",
555                 net_rap,
556                 NET_TRANSPORT_RAP,
557                 N_("Run functions using RAP transport"),
558                 N_("  Use 'net help rap' to get more extensive information "
559                    "about 'net rap' commands.")
560         },
561         {
562                 "ads",
563                 net_ads,
564                 NET_TRANSPORT_ADS,
565                 N_("Run functions using ADS transport"),
566                 N_("  Use 'net help ads' to get more extensive information "
567                    "about 'net ads' commands.")
568         },
569
570         /* eventually these should auto-choose the transport ... */
571         {
572                 "file",
573                 net_file,
574                 NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
575                 N_("Functions on remote opened files"),
576                 N_("  Use 'net help file' to get more information about 'net "
577                    "file' commands.")
578         },
579         {
580                 "share",
581                 net_share,
582                 NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
583                 N_("Functions on shares"),
584                 N_("  Use 'net help share' to get more information about 'net "
585                    "share' commands.")
586         },
587         {
588                 "session",
589                 net_rap_session,
590                 NET_TRANSPORT_RAP,
591                 N_("Manage sessions"),
592                 N_("  Use 'net help session' to get more information about "
593                    "'net session' commands.")
594         },
595         {
596                 "server",
597                 net_rap_server,
598                 NET_TRANSPORT_RAP,
599                 N_("List servers in workgroup"),
600                 N_("  Use 'net help server' to get more information about 'net "
601                    "server' commands.")
602         },
603         {
604                 "domain",
605                 net_rap_domain,
606                 NET_TRANSPORT_RAP,
607                 N_("List domains/workgroups on network"),
608                 N_("  Use 'net help domain' to get more information about 'net "
609                    "domain' commands.")
610         },
611         {
612                 "printq",
613                 net_rap_printq,
614                 NET_TRANSPORT_RAP,
615                 N_("Modify printer queue"),
616                 N_("  Use 'net help printq' to get more information about 'net "
617                    "printq' commands.")
618         },
619         {
620                 "user",
621                 net_user,
622                 NET_TRANSPORT_ADS | NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
623                 N_("Manage users"),
624                 N_("  Use 'net help user' to get more information about 'net "
625                    "user' commands.")
626         },
627         {
628                 "group",
629                 net_group,
630                 NET_TRANSPORT_ADS | NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
631                 N_("Manage groups"),
632                 N_("  Use 'net help group' to get more information about 'net "
633                    "group' commands.")
634         },
635         {
636                 "groupmap",
637                 net_groupmap,
638                 NET_TRANSPORT_LOCAL,
639                 N_("Manage group mappings"),
640                 N_("  Use 'net help groupmap' to get more information about "
641                    "'net groupmap' commands.")
642         },
643         {
644                 "sam",
645                 net_sam,
646                 NET_TRANSPORT_LOCAL,
647                 N_("Functions on the SAM database"),
648                 N_("  Use 'net help sam' to get more information about 'net "
649                    "sam' commands.")
650         },
651         {
652                 "validate",
653                 net_rap_validate,
654                 NET_TRANSPORT_RAP,
655                 N_("Validate username and password"),
656                 N_("  Use 'net help validate' to get more information about "
657                    "'net validate' commands.")
658         },
659         {
660                 "groupmember",
661                 net_rap_groupmember,
662                 NET_TRANSPORT_RAP,
663                 N_("Modify group memberships"),
664                 N_("  Use 'net help groupmember' to get more information about "
665                    "'net groupmember' commands.")
666         },
667         {       "admin",
668                 net_rap_admin,
669                 NET_TRANSPORT_RAP,
670                 N_("Execute remote command on a remote OS/2 server"),
671                 N_("  Use 'net help admin' to get more information about 'net "
672                    "admin' commands.")
673         },
674         {       "service",
675                 net_rap_service,
676                 NET_TRANSPORT_RAP,
677                 N_("List/modify running services"),
678                 N_("  Use 'net help service' to get more information about "
679                    "'net service' commands.")
680         },
681         {
682                 "password",
683                 net_rap_password,
684                 NET_TRANSPORT_RAP,
685                 N_("Change user password on target server"),
686                 N_("  Use 'net help password' to get more information about "
687                    "'net password' commands.")
688         },
689         {
690                 "primarytrust",
691                 net_primarytrust,
692                 NET_TRANSPORT_RPC,
693                 N_("Run functions related to the primary workstation trust."),
694                 N_("  Use 'net help primarytrust' to get more extensive information "
695                    "about 'net primarytrust' commands.")
696         },
697         {       "changetrustpw",
698                 net_changetrustpw,
699                 NET_TRANSPORT_ADS | NET_TRANSPORT_RPC,
700                 N_("Change the trust password"),
701                 N_("  Use 'net help changetrustpw' to get more information "
702                    "about 'net changetrustpw'.")
703         },
704         {       "changesecretpw",
705                 net_changesecretpw,
706                 NET_TRANSPORT_LOCAL,
707                 N_("Change the secret password"),
708                 N_("  net [options] changesecretpw\n"
709                    "    Change the ADS domain member machine account password "
710                    "in secrets.tdb.\n"
711                    "    Do NOT use this function unless you know what it does.\n"
712                    "    Requires the -f flag to work.")
713         },
714         {
715                 "setauthuser",
716                 net_setauthuser,
717                 NET_TRANSPORT_LOCAL,
718                 N_("Set the winbind auth user"),
719                 N_("  net -U user[%%password] [-W domain] setauthuser\n"
720                    "    Set the auth user, password (and optionally domain\n"
721                    "    Will prompt for password if not given.\n"
722                    "  net setauthuser delete\n"
723                    "    Delete the existing auth user settings.")
724         },
725         {
726                 "getauthuser",
727                 net_getauthuser,
728                 NET_TRANSPORT_LOCAL,
729                 N_("Get the winbind auth user settings"),
730                 N_("  net getauthuser\n"
731                    "    Get the current winbind auth user settings.")
732         },
733         {       "time",
734                 net_time,
735                 NET_TRANSPORT_LOCAL,
736                 N_("Show/set time"),
737                 N_("  Use 'net help time' to get more information about 'net "
738                    "time' commands.")
739         },
740         {       "lookup",
741                 net_lookup,
742                 NET_TRANSPORT_LOCAL,
743                 N_("Look up host names/IP addresses"),
744                 N_("  Use 'net help lookup' to get more information about 'net "
745                    "lookup' commands.")
746         },
747         {       "g_lock",
748                 net_g_lock,
749                 NET_TRANSPORT_LOCAL,
750                 N_("Manipulate the global lock table"),
751                 N_("  Use 'net help g_lock' to get more information about "
752                    "'net g_lock' commands.")
753         },
754         {       "join",
755                 net_join,
756                 NET_TRANSPORT_ADS | NET_TRANSPORT_RPC,
757                 N_("Join a domain/AD"),
758                 N_("  Use 'net help join' to get more information about 'net "
759                    "join'.")
760         },
761         {       "dom",
762                 net_dom,
763                 NET_TRANSPORT_LOCAL,
764                 N_("Join/unjoin (remote) machines to/from a domain/AD"),
765                 N_("  Use 'net help dom' to get more information about 'net "
766                    "dom' commands.")
767         },
768         {       "cache",
769                 net_cache,
770                 NET_TRANSPORT_LOCAL,
771                 N_("Operate on the cache tdb file"),
772                 N_("  Use 'net help cache' to get more information about 'net "
773                    "cache' commands.")
774         },
775         {       "getlocalsid",
776                 net_getlocalsid,
777                 NET_TRANSPORT_LOCAL,
778                 N_("Get the SID for the local domain"),
779                 N_("  net getlocalsid")
780         },
781         {       "setlocalsid",
782                 net_setlocalsid,
783                 NET_TRANSPORT_LOCAL,
784                 N_("Set the SID for the local domain"),
785                 N_("  net setlocalsid S-1-5-21-x-y-z")
786         },
787         {       "setdomainsid",
788                 net_setdomainsid,
789                 NET_TRANSPORT_LOCAL,
790                 N_("Set domain SID on member servers"),
791                 N_("  net setdomainsid S-1-5-21-x-y-z")
792         },
793         {       "getdomainsid",
794                 net_getdomainsid,
795                 NET_TRANSPORT_LOCAL,
796                 N_("Get domain SID on member servers"),
797                 N_("  net getdomainsid")
798         },
799         {       "maxrid",
800                 net_maxrid,
801                 NET_TRANSPORT_LOCAL,
802                 N_("Display the maximum RID currently used"),
803                 N_("  net maxrid")
804         },
805         {       "idmap",
806                 net_idmap,
807                 NET_TRANSPORT_LOCAL,
808                 N_("IDmap functions"),
809                 N_("  Use 'net help idmap to get more information about 'net "
810                   "idmap' commands.")
811         },
812         {       "status",
813                 net_status,
814                 NET_TRANSPORT_LOCAL,
815                 N_("Display server status"),
816                 N_("  Use 'net help status' to get more information about 'net "
817                    "status' commands.")
818         },
819         {       "usershare",
820                 net_usershare,
821                 NET_TRANSPORT_LOCAL,
822                 N_("Manage user-modifiable shares"),
823                 N_("  Use 'net help usershare to get more information about "
824                    "'net usershare' commands.")
825         },
826         {       "usersidlist",
827                 net_usersidlist,
828                 NET_TRANSPORT_RPC,
829                 N_("Display list of all users with SID"),
830                 N_("  Use 'net help usersidlist' to get more information about "
831                    "'net usersidlist'.")
832         },
833         {       "conf",
834                 net_conf,
835                 NET_TRANSPORT_LOCAL,
836                 N_("Manage Samba registry based configuration"),
837                 N_("  Use 'net help conf' to get more information about 'net "
838                    "conf' commands.")
839         },
840         {       "registry",
841                 net_registry,
842                 NET_TRANSPORT_LOCAL,
843                 N_("Manage the Samba registry"),
844                 N_("  Use 'net help registry' to get more information about "
845                    "'net registry' commands.")
846         },
847         {       "eventlog",
848                 net_eventlog,
849                 NET_TRANSPORT_LOCAL,
850                 N_("Process Win32 *.evt eventlog files"),
851                 N_("  Use 'net help eventlog' to get more information about "
852                    "'net eventlog' commands.")
853         },
854         {       "printing",
855                 net_printing,
856                 NET_TRANSPORT_LOCAL,
857                 N_("Process tdb printer files"),
858                 N_("  Use 'net help printing' to get more information about "
859                    "'net printing' commands.")
860         },
861
862         {       "serverid",
863                 net_serverid,
864                 NET_TRANSPORT_LOCAL,
865                 N_("Manage the serverid tdb"),
866                 N_("  Use 'net help serverid' to get more information about "
867                    "'net serverid' commands.")
868         },
869
870         {       "notify",
871                 net_notify,
872                 NET_TRANSPORT_LOCAL,
873                 N_("notifyd client code"),
874                 N_("  Use 'net help notify' to get more information about "
875                    "'net notify' commands.")
876         },
877
878         {       "tdb",
879                 net_tdb,
880                 NET_TRANSPORT_LOCAL,
881                 N_("Show information from tdb records"),
882                 N_("  Use 'net help tdb' to get more information about "
883                    "'net tdb' commands.")
884         },
885
886 #ifdef WITH_FAKE_KASERVER
887         {       "afs",
888                 net_afs,
889                 NET_TRANSPORT_LOCAL,
890                 N_("Manage AFS tokens"),
891                 N_("  Use 'net help afs' to get more information about 'net "
892                    "afs' commands.")
893         },
894 #endif
895
896         {       "help",
897                 net_help,
898                 NET_TRANSPORT_LOCAL,
899                 N_("Print usage information"),
900                 N_("  Use 'net help help' to list usage information for 'net' "
901                    "commands.")
902         },
903         {NULL, NULL, 0, NULL, NULL}
904 };
905
906
907 /****************************************************************************
908   main program
909 ****************************************************************************/
910  int main(int argc, char **argv)
911 {
912         int opt,i;
913         char *p;
914         int rc = 0;
915         int argc_new = 0;
916         const char ** argv_new;
917         const char **argv_const = discard_const_p(const char *, argv);
918         poptContext pc;
919         TALLOC_CTX *frame = talloc_stackframe();
920         struct net_context *c = talloc_zero(frame, struct net_context);
921
922         struct poptOption long_options[] = {
923                 {"help",        'h', POPT_ARG_NONE,   0, 'h'},
924                 {"workgroup",   'w', POPT_ARG_STRING, &c->opt_target_workgroup},
925                 {"user",        'U', POPT_ARG_STRING, &c->opt_user_name, 'U'},
926                 {"ipaddress",   'I', POPT_ARG_STRING, 0,'I'},
927                 {"port",        'p', POPT_ARG_INT,    &c->opt_port},
928                 {"myname",      'n', POPT_ARG_STRING, &c->opt_requester_name},
929                 {"server",      'S', POPT_ARG_STRING, &c->opt_host},
930                 {"encrypt",     'e', POPT_ARG_NONE,   NULL, 'e', N_("Encrypt SMB transport") },
931                 {"container",   'c', POPT_ARG_STRING, &c->opt_container},
932                 {"comment",     'C', POPT_ARG_STRING, &c->opt_comment},
933                 {"maxusers",    'M', POPT_ARG_INT,    &c->opt_maxusers},
934                 {"flags",       'F', POPT_ARG_INT,    &c->opt_flags},
935                 {"long",        'l', POPT_ARG_NONE,   &c->opt_long_list_entries},
936                 {"reboot",      'r', POPT_ARG_NONE,   &c->opt_reboot},
937                 {"force",       'f', POPT_ARG_NONE,   &c->opt_force},
938                 {"stdin",       'i', POPT_ARG_NONE,   &c->opt_stdin},
939                 {"timeout",     't', POPT_ARG_INT,    &c->opt_timeout},
940                 {"request-timeout",0,POPT_ARG_INT,    &c->opt_request_timeout},
941                 {"machine-pass",'P', POPT_ARG_NONE,   &c->opt_machine_pass},
942                 {"kerberos",    'k', POPT_ARG_NONE,   &c->opt_kerberos},
943                 {"myworkgroup", 'W', POPT_ARG_STRING, &c->opt_workgroup},
944                 {"use-ccache",    0, POPT_ARG_NONE,   &c->opt_ccache},
945                 {"verbose",     'v', POPT_ARG_NONE,   &c->opt_verbose},
946                 {"test",        'T', POPT_ARG_NONE,   &c->opt_testmode},
947                 /* Options for 'net groupmap set' */
948                 {"local",       'L', POPT_ARG_NONE,   &c->opt_localgroup},
949                 {"domain",      'D', POPT_ARG_NONE,   &c->opt_domaingroup},
950                 {"ntname",      'N', POPT_ARG_STRING, &c->opt_newntname},
951                 {"rid",         'R', POPT_ARG_INT,    &c->opt_rid},
952                 /* Options for 'net rpc share migrate' */
953                 {"acls",        0, POPT_ARG_NONE,     &c->opt_acls},
954                 {"attrs",       0, POPT_ARG_NONE,     &c->opt_attrs},
955                 {"timestamps",  0, POPT_ARG_NONE,     &c->opt_timestamps},
956                 {"exclude",     'X', POPT_ARG_STRING, &c->opt_exclude},
957                 {"destination", 0, POPT_ARG_STRING,   &c->opt_destination},
958                 {"tallocreport", 0, POPT_ARG_NONE,    &c->do_talloc_report},
959                 /* Options for 'net rpc vampire (keytab)' */
960                 {"force-full-repl", 0, POPT_ARG_NONE, &c->opt_force_full_repl},
961                 {"single-obj-repl", 0, POPT_ARG_NONE, &c->opt_single_obj_repl},
962                 {"clean-old-entries", 0, POPT_ARG_NONE, &c->opt_clean_old_entries},
963                 /* Options for 'net idmap'*/
964                 {"db", 0, POPT_ARG_STRING, &c->opt_db},
965                 {"lock", 0, POPT_ARG_NONE,   &c->opt_lock},
966                 {"auto", 'a', POPT_ARG_NONE,   &c->opt_auto},
967                 {"repair", 0, POPT_ARG_NONE,   &c->opt_repair},
968                 /* Options for 'net registry check'*/
969                 {"reg-version", 0, POPT_ARG_INT, &c->opt_reg_version},
970                 {"output", 'o', POPT_ARG_STRING, &c->opt_output},
971                 {"wipe", 0, POPT_ARG_NONE, &c->opt_wipe},
972                 /* Options for 'net registry import' */
973                 {"precheck", 0, POPT_ARG_STRING, &c->opt_precheck},
974                 /* Options for 'net ads join or leave' */
975                 {"no-dns-updates", 0, POPT_ARG_NONE, &c->opt_no_dns_updates},
976                 {"keep-account", 0, POPT_ARG_NONE, &c->opt_keep_account},
977                 {"json", 0, POPT_ARG_NONE, &c->opt_json},
978                 POPT_COMMON_SAMBA
979                 { 0, 0, 0, 0}
980         };
981
982         zero_sockaddr(&c->opt_dest_ip);
983
984         setup_logging(argv[0], DEBUG_STDERR);
985
986         smb_init_locale();
987
988         setlocale(LC_ALL, "");
989 #if defined(HAVE_BINDTEXTDOMAIN)
990         bindtextdomain(MODULE_NAME, get_dyn_LOCALEDIR());
991 #endif
992 #if defined(HAVE_TEXTDOMAIN)
993         textdomain(MODULE_NAME);
994 #endif
995
996         /* set default debug level to 0 regardless of what smb.conf sets */
997         lp_set_cmdline("log level", "0");
998         c->private_data = net_func;
999
1000         pc = poptGetContext(NULL, argc, argv_const, long_options,
1001                             POPT_CONTEXT_KEEP_FIRST);
1002
1003         while((opt = poptGetNextOpt(pc)) != -1) {
1004                 switch (opt) {
1005                 case 'h':
1006                         c->display_usage = true;
1007                         break;
1008                 case 'e':
1009                         c->smb_encrypt = true;
1010                         break;
1011                 case 'I':
1012                         if (!interpret_string_addr(&c->opt_dest_ip,
1013                                                 poptGetOptArg(pc), 0)) {
1014                                 d_fprintf(stderr, _("\nInvalid ip address specified\n"));
1015                         } else {
1016                                 c->opt_have_ip = true;
1017                         }
1018                         break;
1019                 case 'U':
1020                         c->opt_user_specified = true;
1021                         c->opt_user_name = talloc_strdup(c, c->opt_user_name);
1022                         p = strchr(c->opt_user_name,'%');
1023                         if (p) {
1024                                 *p = 0;
1025                                 c->opt_password = p+1;
1026                         }
1027                         break;
1028                 default:
1029                         d_fprintf(stderr, _("\nInvalid option %s: %s\n"),
1030                                  poptBadOption(pc, 0), poptStrerror(opt));
1031                         net_help(c, argc, argv_const);
1032                         exit(1);
1033                 }
1034         }
1035
1036         c->msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
1037
1038         if (!lp_load_global(get_dyn_CONFIGFILE())) {
1039                 d_fprintf(stderr, "Can't load %s - run testparm to debug it\n",
1040                           get_dyn_CONFIGFILE());
1041                 exit(1);
1042         }
1043
1044 #if defined(HAVE_BIND_TEXTDOMAIN_CODESET)
1045         /* Bind our gettext results to 'unix charset'
1046            
1047            This ensures that the translations and any embedded strings are in the
1048            same charset.  It won't be the one from the user's locale (we no
1049            longer auto-detect that), but it will be self-consistent.
1050         */
1051         bind_textdomain_codeset(MODULE_NAME, lp_unix_charset());
1052 #endif
1053
1054         argv_new = (const char **)poptGetArgs(pc);
1055
1056         argc_new = argc;
1057         for (i=0; i<argc; i++) {
1058                 if (argv_new[i] == NULL) {
1059                         argc_new = i;
1060                         break;
1061                 }
1062         }
1063
1064         if (c->do_talloc_report) {
1065                 talloc_enable_leak_report();
1066         }
1067
1068         if (c->opt_requester_name) {
1069                 lp_set_cmdline("netbios name", c->opt_requester_name);
1070         }
1071
1072         if (!c->opt_user_name && getenv("LOGNAME")) {
1073                 c->opt_user_name = getenv("LOGNAME");
1074         }
1075
1076         if (!c->opt_workgroup) {
1077                 c->opt_workgroup = talloc_strdup(c, lp_workgroup());
1078         }
1079
1080         if (!c->opt_target_workgroup) {
1081                 c->opt_target_workgroup = talloc_strdup(c, lp_workgroup());
1082         }
1083
1084         if (!init_names())
1085                 exit(1);
1086
1087         load_interfaces();
1088
1089         /* this makes sure that when we do things like call scripts,
1090            that it won't assert because we are not root */
1091         sec_init();
1092
1093         if (c->opt_machine_pass) {
1094                 /* it is very useful to be able to make ads queries as the
1095                    machine account for testing purposes and for domain leave */
1096
1097                 net_use_krb_machine_account(c);
1098         }
1099
1100         if (!c->opt_password) {
1101                 c->opt_password = getenv("PASSWD");
1102         }
1103
1104         popt_burn_cmdline_password(argc, argv);
1105
1106         rc = net_run_function(c, argc_new-1, argv_new+1, "net", net_func);
1107
1108         DEBUG(2,("return code = %d\n", rc));
1109
1110         gencache_stabilize();
1111
1112         libnetapi_free(c->netapi_ctx);
1113
1114         poptFreeContext(pc);
1115
1116         TALLOC_FREE(frame);
1117         return rc;
1118 }