c677e3a9ba551b1ed735c1fe479f3472df2181ef
[kai/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 "utils/net.h"
45
46 extern bool AllowDebugChange;
47
48 #ifdef WITH_FAKE_KASERVER
49 #include "utils/net_afs.h"
50 #endif
51
52 /***********************************************************************/
53 /* end of internationalization section                                 */
54 /***********************************************************************/
55
56 enum netr_SchannelType get_sec_channel_type(const char *param)
57 {
58         if (!(param && *param)) {
59                 return get_default_sec_channel();
60         } else {
61                 if (strequal(param, "PDC")) {
62                         return SEC_CHAN_BDC;
63                 } else if (strequal(param, "BDC")) {
64                         return SEC_CHAN_BDC;
65                 } else if (strequal(param, "MEMBER")) {
66                         return SEC_CHAN_WKSTA;
67 #if 0
68                 } else if (strequal(param, "DOMAIN")) {
69                         return SEC_CHAN_DOMAIN;
70 #endif
71                 } else {
72                         return get_default_sec_channel();
73                 }
74         }
75 }
76
77 static int net_changetrustpw(struct net_context *c, int argc, const char **argv)
78 {
79         if (net_ads_check_our_domain(c) == 0)
80                 return net_ads_changetrustpw(c, argc, argv);
81
82         return net_rpc_changetrustpw(c, argc, argv);
83 }
84
85 static void set_line_buffering(FILE *f)
86 {
87         setvbuf(f, NULL, _IOLBF, 0);
88 }
89
90 static int net_changesecretpw(struct net_context *c, int argc,
91                               const char **argv)
92 {
93         char *trust_pw;
94         enum netr_SchannelType sec_channel_type = SEC_CHAN_WKSTA;
95
96         if(c->opt_force) {
97                 if (c->opt_stdin) {
98                         set_line_buffering(stdin);
99                         set_line_buffering(stdout);
100                         set_line_buffering(stderr);
101                 }
102
103                 trust_pw = get_pass(_("Enter machine password: "), c->opt_stdin);
104
105                 if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) {
106                             d_fprintf(stderr,
107                                       _("Unable to write the machine account password in the secrets database"));
108                             return 1;
109                 }
110                 else {
111                     d_printf(_("Modified trust account password in secrets database\n"));
112                 }
113         }
114         else {
115                 d_printf(_("Machine account password change requires the -f flag.\n"
116                            "Do NOT use this function unless you know what it does!\n"
117                            "This function will change the ADS Domain member "
118                            "machine account password in the secrets.tdb file!\n"));
119         }
120
121         return 0;
122 }
123
124 /**
125  * @brief Set the authorised user for winbindd access in secrets.tdb
126  */
127 static int net_setauthuser(struct net_context *c, int argc, const char **argv)
128 {
129         const char *password = NULL;
130
131         if (!secrets_init()) {
132                 d_fprintf(stderr, _("Failed to open secrets.tdb.\n"));
133                 return 1;
134         }
135
136         /* Delete the settings. */
137         if (argc >= 1) {
138                 if (strncmp(argv[0], "delete", 6) != 0) {
139                         d_fprintf(stderr,_("Usage:\n"));
140                         d_fprintf(stderr,
141                                   _("    net setauthuser -U user[%%password] \n"
142                                     "        Set the auth user account to user"
143                                     "password. Prompt for password if not "
144                                     "specified.\n"));
145                         d_fprintf(stderr,
146                                   _("    net setauthuser delete\n"
147                                     "        Delete the auth user setting.\n"));
148                         return 1;
149                 }
150                 secrets_delete(SECRETS_AUTH_USER);
151                 secrets_delete(SECRETS_AUTH_DOMAIN);
152                 secrets_delete(SECRETS_AUTH_PASSWORD);
153                 return 0;
154         }
155
156         if (!c->opt_user_specified) {
157                 d_fprintf(stderr, _("Usage:\n"));
158                 d_fprintf(stderr,
159                           _("    net setauthuser -U user[%%password]\n"
160                             "        Set the auth user account to user"
161                             "password. Prompt for password if not "
162                             "specified.\n"));
163                 d_fprintf(stderr,
164                           _("    net setauthuser delete\n"
165                             "        Delete the auth user setting.\n"));
166                 return 1;
167         }
168
169         password = net_prompt_pass(c, _("the auth user"));
170         if (password == NULL) {
171                 d_fprintf(stderr,_("Failed to get the auth users password.\n"));
172                 return 1;
173         }
174
175         if (!secrets_store(SECRETS_AUTH_USER, c->opt_user_name,
176                            strlen(c->opt_user_name) + 1)) {
177                 d_fprintf(stderr, _("error storing auth user name\n"));
178                 return 1;
179         }
180
181         if (!secrets_store(SECRETS_AUTH_DOMAIN, c->opt_workgroup,
182                            strlen(c->opt_workgroup) + 1)) {
183                 d_fprintf(stderr, _("error storing auth user domain\n"));
184                 return 1;
185         }
186
187         if (!secrets_store(SECRETS_AUTH_PASSWORD, password,
188                            strlen(password) + 1)) {
189                 d_fprintf(stderr, _("error storing auth user password\n"));
190                 return 1;
191         }
192
193         return 0;
194 }
195
196 /**
197  * @brief Get the auth user settings
198  */
199 static int net_getauthuser(struct net_context *c, int argc, const char **argv)
200 {
201         char *user, *domain, *password;
202
203         /* Lift data from secrets file */
204
205         secrets_fetch_ipc_userpass(&user, &domain, &password);
206
207         if ((!user || !*user) && (!domain || !*domain ) &&
208             (!password || !*password)){
209
210                 SAFE_FREE(user);
211                 SAFE_FREE(domain);
212                 SAFE_FREE(password);
213                 d_printf(_("No authorised user configured\n"));
214                 return 0;
215         }
216
217         /* Pretty print authorised user info */
218
219         d_printf("%s%s%s%s%s\n", domain ? domain : "",
220                  domain ? lp_winbind_separator(): "", user,
221                  password ? "%" : "", password ? password : "");
222
223         SAFE_FREE(user);
224         SAFE_FREE(domain);
225         SAFE_FREE(password);
226
227         return 0;
228 }
229 /*
230  Retrieve our local SID or the SID for the specified name
231  */
232 static int net_getlocalsid(struct net_context *c, int argc, const char **argv)
233 {
234         struct dom_sid sid;
235         const char *name;
236         fstring sid_str;
237
238         if (argc >= 1) {
239                 name = argv[0];
240         }
241         else {
242                 name = global_myname();
243         }
244
245         if(!initialize_password_db(false, NULL)) {
246                 DEBUG(0, ("WARNING: Could not open passdb - local sid may not reflect passdb\n"
247                           "backend knowledge (such as the sid stored in LDAP)\n"));
248         }
249
250         /* first check to see if we can even access secrets, so we don't
251            panic when we can't. */
252
253         if (!secrets_init()) {
254                 d_fprintf(stderr,
255                           _("Unable to open secrets.tdb.  Can't fetch domain "
256                             "SID for name: %s\n"), name);
257                 return 1;
258         }
259
260         /* Generate one, if it doesn't exist */
261         get_global_sam_sid();
262
263         if (!secrets_fetch_domain_sid(name, &sid)) {
264                 DEBUG(0, ("Can't fetch domain SID for name: %s\n", name));
265                 return 1;
266         }
267         sid_to_fstring(sid_str, &sid);
268         d_printf(_("SID for domain %s is: %s\n"), name, sid_str);
269         return 0;
270 }
271
272 static int net_setlocalsid(struct net_context *c, int argc, const char **argv)
273 {
274         struct dom_sid sid;
275
276         if ( (argc != 1)
277              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
278              || (!string_to_sid(&sid, argv[0]))
279              || (sid.num_auths != 4)) {
280                 d_printf(_("Usage:"));
281                 d_printf(" net setlocalsid S-1-5-21-x-y-z\n");
282                 return 1;
283         }
284
285         if (!secrets_store_domain_sid(global_myname(), &sid)) {
286                 DEBUG(0,("Can't store domain SID as a pdc/bdc.\n"));
287                 return 1;
288         }
289
290         return 0;
291 }
292
293 static int net_setdomainsid(struct net_context *c, int argc, const char **argv)
294 {
295         struct dom_sid sid;
296
297         if ( (argc != 1)
298              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
299              || (!string_to_sid(&sid, argv[0]))
300              || (sid.num_auths != 4)) {
301                 d_printf(_("Usage:"));
302                 d_printf(" net setdomainsid S-1-5-21-x-y-z\n");
303                 return 1;
304         }
305
306         if (!secrets_store_domain_sid(lp_workgroup(), &sid)) {
307                 DEBUG(0,("Can't store domain SID.\n"));
308                 return 1;
309         }
310
311         return 0;
312 }
313
314 static int net_getdomainsid(struct net_context *c, int argc, const char **argv)
315 {
316         struct dom_sid domain_sid;
317         fstring sid_str;
318
319         if (argc > 0) {
320                 d_printf(_("Usage:"));
321                 d_printf(" net getdomainsid\n");
322                 return 1;
323         }
324
325         if(!initialize_password_db(false, NULL)) {
326                 DEBUG(0, ("WARNING: Could not open passdb - domain SID may "
327                           "not reflect passdb\n"
328                           "backend knowledge (such as the SID stored in "
329                           "LDAP)\n"));
330         }
331
332         /* first check to see if we can even access secrets, so we don't
333            panic when we can't. */
334
335         if (!secrets_init()) {
336                 d_fprintf(stderr, _("Unable to open secrets.tdb.  Can't fetch "
337                                     "domain SID for name: %s\n"),
338                           get_global_sam_name());
339                 return 1;
340         }
341
342         /* Generate one, if it doesn't exist */
343         get_global_sam_sid();
344
345         if (!secrets_fetch_domain_sid(global_myname(), &domain_sid)) {
346                 d_fprintf(stderr, _("Could not fetch local SID\n"));
347                 return 1;
348         }
349         sid_to_fstring(sid_str, &domain_sid);
350         d_printf(_("SID for local machine %s is: %s\n"),
351                  global_myname(), sid_str);
352
353         if (!secrets_fetch_domain_sid(c->opt_workgroup, &domain_sid)) {
354                 d_fprintf(stderr, _("Could not fetch domain SID\n"));
355                 return 1;
356         }
357
358         sid_to_fstring(sid_str, &domain_sid);
359         d_printf(_("SID for domain %s is: %s\n"), c->opt_workgroup, sid_str);
360
361         return 0;
362 }
363
364 static bool search_maxrid(struct pdb_search *search, const char *type,
365                           uint32 *max_rid)
366 {
367         struct samr_displayentry *entries;
368         uint32 i, num_entries;
369
370         if (search == NULL) {
371                 d_fprintf(stderr, _("get_maxrid: Could not search %s\n"), type);
372                 return false;
373         }
374
375         num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries);
376         for (i=0; i<num_entries; i++)
377                 *max_rid = MAX(*max_rid, entries[i].rid);
378         TALLOC_FREE(search);
379         return true;
380 }
381
382 static uint32 get_maxrid(void)
383 {
384         uint32 max_rid = 0;
385
386         if (!search_maxrid(pdb_search_users(talloc_tos(), 0), "users", &max_rid))
387                 return 0;
388
389         if (!search_maxrid(pdb_search_groups(talloc_tos()), "groups", &max_rid))
390                 return 0;
391
392         if (!search_maxrid(pdb_search_aliases(talloc_tos(),
393                                               get_global_sam_sid()),
394                            "aliases", &max_rid))
395                 return 0;
396
397         return max_rid;
398 }
399
400 static int net_maxrid(struct net_context *c, int argc, const char **argv)
401 {
402         uint32 rid;
403
404         if (argc != 0) {
405                 d_fprintf(stderr, "%s net maxrid\n", _("Usage:"));
406                 return 1;
407         }
408
409         if ((rid = get_maxrid()) == 0) {
410                 d_fprintf(stderr, _("can't get current maximum rid\n"));
411                 return 1;
412         }
413
414         d_printf(_("Currently used maximum rid: %d\n"), rid);
415
416         return 0;
417 }
418
419 /* main function table */
420 static struct functable net_func[] = {
421         {
422                 "rpc",
423                 net_rpc,
424                 NET_TRANSPORT_RPC,
425                 N_("Run functions using RPC transport"),
426                 N_("  Use 'net help rpc' to get more extensive information "
427                    "about 'net rpc' commands.")
428         },
429         {
430                 "rap",
431                 net_rap,
432                 NET_TRANSPORT_RAP,
433                 N_("Run functions using RAP transport"),
434                 N_("  Use 'net help rap' to get more extensive information "
435                    "about 'net rap' commands.")
436         },
437         {
438                 "ads",
439                 net_ads,
440                 NET_TRANSPORT_ADS,
441                 N_("Run functions using ADS transport"),
442                 N_("  Use 'net help ads' to get more extensive information "
443                    "about 'net ads' commands.")
444         },
445
446         /* eventually these should auto-choose the transport ... */
447         {
448                 "file",
449                 net_file,
450                 NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
451                 N_("Functions on remote opened files"),
452                 N_("  Use 'net help file' to get more information about 'net "
453                    "file' commands.")
454         },
455         {
456                 "share",
457                 net_share,
458                 NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
459                 N_("Functions on shares"),
460                 N_("  Use 'net help share' to get more information about 'net "
461                    "share' commands.")
462         },
463         {
464                 "session",
465                 net_rap_session,
466                 NET_TRANSPORT_RAP,
467                 N_("Manage sessions"),
468                 N_("  Use 'net help session' to get more information about "
469                    "'net session' commands.")
470         },
471         {
472                 "server",
473                 net_rap_server,
474                 NET_TRANSPORT_RAP,
475                 N_("List servers in workgroup"),
476                 N_("  Use 'net help server' to get more information about 'net "
477                    "server' commands.")
478         },
479         {
480                 "domain",
481                 net_rap_domain,
482                 NET_TRANSPORT_RAP,
483                 N_("List domains/workgroups on network"),
484                 N_("  Use 'net help domain' to get more information about 'net "
485                    "domain' commands.")
486         },
487         {
488                 "printq",
489                 net_rap_printq,
490                 NET_TRANSPORT_RAP,
491                 N_("Modify printer queue"),
492                 N_("  Use 'net help printq' to get more information about 'net "
493                    "printq' commands.")
494         },
495         {
496                 "user",
497                 net_user,
498                 NET_TRANSPORT_ADS | NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
499                 N_("Manage users"),
500                 N_("  Use 'net help user' to get more information about 'net "
501                    "user' commands.")
502         },
503         {
504                 "group",
505                 net_group,
506                 NET_TRANSPORT_ADS | NET_TRANSPORT_RPC | NET_TRANSPORT_RAP,
507                 N_("Manage groups"),
508                 N_("  Use 'net help group' to get more information about 'net "
509                    "group' commands.")
510         },
511         {
512                 "groupmap",
513                 net_groupmap,
514                 NET_TRANSPORT_LOCAL,
515                 N_("Manage group mappings"),
516                 N_("  Use 'net help groupmap' to get more information about "
517                    "'net groupmap' commands.")
518         },
519         {
520                 "sam",
521                 net_sam,
522                 NET_TRANSPORT_LOCAL,
523                 N_("Functions on the SAM database"),
524                 N_("  Use 'net help sam' to get more information about 'net "
525                    "sam' commands.")
526         },
527         {
528                 "validate",
529                 net_rap_validate,
530                 NET_TRANSPORT_RAP,
531                 N_("Validate username and password"),
532                 N_("  Use 'net help validate' to get more information about "
533                    "'net validate' commands.")
534         },
535         {
536                 "groupmember",
537                 net_rap_groupmember,
538                 NET_TRANSPORT_RAP,
539                 N_("Modify group memberships"),
540                 N_("  Use 'net help groupmember' to get more information about "
541                    "'net groupmember' commands.")
542         },
543         {       "admin",
544                 net_rap_admin,
545                 NET_TRANSPORT_RAP,
546                 N_("Execute remote command on a remote OS/2 server"),
547                 N_("  Use 'net help admin' to get more information about 'net "
548                    "admin' commands.")
549         },
550         {       "service",
551                 net_rap_service,
552                 NET_TRANSPORT_RAP,
553                 N_("List/modify running services"),
554                 N_("  Use 'net help service' to get more information about "
555                    "'net service' commands.")
556         },
557         {
558                 "password",
559                 net_rap_password,
560                 NET_TRANSPORT_RAP,
561                 N_("Change user password on target server"),
562                 N_("  Use 'net help password' to get more information about "
563                    "'net password' commands.")
564         },
565         {       "changetrustpw",
566                 net_changetrustpw,
567                 NET_TRANSPORT_ADS | NET_TRANSPORT_RPC,
568                 N_("Change the trust password"),
569                 N_("  Use 'net help changetrustpw' to get more information "
570                    "about 'net changetrustpw'.")
571         },
572         {       "changesecretpw",
573                 net_changesecretpw,
574                 NET_TRANSPORT_LOCAL,
575                 N_("Change the secret password"),
576                 N_("  net [options] changesecretpw\n"
577                    "    Change the ADS domain member machine account password "
578                    "in secrets.tdb.\n"
579                    "    Do NOT use this function unless you know what it does.\n"
580                    "    Requires the -f flag to work.")
581         },
582         {
583                 "setauthuser",
584                 net_setauthuser,
585                 NET_TRANSPORT_LOCAL,
586                 N_("Set the winbind auth user"),
587                 N_("  net -U user[%%password] [-W domain] setauthuser\n"
588                    "    Set the auth user, password (and optionally domain\n"
589                    "    Will prompt for password if not given.\n"
590                    "  net setauthuser delete\n"
591                    "    Delete the existing auth user settings.")
592         },
593         {
594                 "getauthuser",
595                 net_getauthuser,
596                 NET_TRANSPORT_LOCAL,
597                 N_("Get the winbind auth user settings"),
598                 N_("  net getauthuser\n"
599                    "    Get the current winbind auth user settings.")
600         },
601         {       "time",
602                 net_time,
603                 NET_TRANSPORT_LOCAL,
604                 N_("Show/set time"),
605                 N_("  Use 'net help time' to get more information about 'net "
606                    "time' commands.")
607         },
608         {       "lookup",
609                 net_lookup,
610                 NET_TRANSPORT_LOCAL,
611                 N_("Look up host names/IP addresses"),
612                 N_("  Use 'net help lookup' to get more information about 'net "
613                    "lookup' commands.")
614         },
615         {       "g_lock",
616                 net_g_lock,
617                 NET_TRANSPORT_LOCAL,
618                 N_("Manipulate the global lock table"),
619                 N_("  Use 'net help g_lock' to get more information about "
620                    "'net g_lock' commands.")
621         },
622         {       "join",
623                 net_join,
624                 NET_TRANSPORT_ADS | NET_TRANSPORT_RPC,
625                 N_("Join a domain/AD"),
626                 N_("  Use 'net help join' to get more information about 'net "
627                    "join'.")
628         },
629         {       "dom",
630                 net_dom,
631                 NET_TRANSPORT_LOCAL,
632                 N_("Join/unjoin (remote) machines to/from a domain/AD"),
633                 N_("  Use 'net help dom' to get more information about 'net "
634                    "dom' commands.")
635         },
636         {       "cache",
637                 net_cache,
638                 NET_TRANSPORT_LOCAL,
639                 N_("Operate on the cache tdb file"),
640                 N_("  Use 'net help cache' to get more information about 'net "
641                    "cache' commands.")
642         },
643         {       "getlocalsid",
644                 net_getlocalsid,
645                 NET_TRANSPORT_LOCAL,
646                 N_("Get the SID for the local domain"),
647                 N_("  net getlocalsid")
648         },
649         {       "setlocalsid",
650                 net_setlocalsid,
651                 NET_TRANSPORT_LOCAL,
652                 N_("Set the SID for the local domain"),
653                 N_("  net setlocalsid S-1-5-21-x-y-z")
654         },
655         {       "setdomainsid",
656                 net_setdomainsid,
657                 NET_TRANSPORT_LOCAL,
658                 N_("Set domain SID on member servers"),
659                 N_("  net setdomainsid S-1-5-21-x-y-z")
660         },
661         {       "getdomainsid",
662                 net_getdomainsid,
663                 NET_TRANSPORT_LOCAL,
664                 N_("Get domain SID on member servers"),
665                 N_("  net getdomainsid")
666         },
667         {       "maxrid",
668                 net_maxrid,
669                 NET_TRANSPORT_LOCAL,
670                 N_("Display the maximul RID currently used"),
671                 N_("  net maxrid")
672         },
673         {       "idmap",
674                 net_idmap,
675                 NET_TRANSPORT_LOCAL,
676                 N_("IDmap functions"),
677                 N_("  Use 'net help idmap to get more information about 'net "
678                   "idmap' commands.")
679         },
680         {       "status",
681                 net_status,
682                 NET_TRANSPORT_LOCAL,
683                 N_("Display server status"),
684                 N_("  Use 'net help status' to get more information about 'net "
685                    "status' commands.")
686         },
687         {       "usershare",
688                 net_usershare,
689                 NET_TRANSPORT_LOCAL,
690                 N_("Manage user-modifiable shares"),
691                 N_("  Use 'net help usershare to get more information about "
692                    "'net usershare' commands.")
693         },
694         {       "usersidlist",
695                 net_usersidlist,
696                 NET_TRANSPORT_RPC,
697                 N_("Display list of all users with SID"),
698                 N_("  Use 'net help usersidlist' to get more information about "
699                    "'net usersidlist'.")
700         },
701         {       "conf",
702                 net_conf,
703                 NET_TRANSPORT_LOCAL,
704                 N_("Manage Samba registry based configuration"),
705                 N_("  Use 'net help conf' to get more information about 'net "
706                    "conf' commands.")
707         },
708         {       "registry",
709                 net_registry,
710                 NET_TRANSPORT_LOCAL,
711                 N_("Manage the Samba registry"),
712                 N_("  Use 'net help registry' to get more information about "
713                    "'net registry' commands.")
714         },
715         {       "eventlog",
716                 net_eventlog,
717                 NET_TRANSPORT_LOCAL,
718                 N_("Process Win32 *.evt eventlog files"),
719                 N_("  Use 'net help eventlog' to get more information about "
720                    "'net eventlog' commands.")
721         },
722         {       "printing",
723                 net_printing,
724                 NET_TRANSPORT_LOCAL,
725                 N_("Process tdb printer files"),
726                 N_("  Use 'net help printing' to get more information about "
727                    "'net printing' commands.")
728         },
729
730         {       "serverid",
731                 net_serverid,
732                 NET_TRANSPORT_LOCAL,
733                 N_("Manage the serverid tdb"),
734                 N_("  Use 'net help serverid' to get more information about "
735                    "'net serverid' commands.")
736         },
737
738 #ifdef WITH_FAKE_KASERVER
739         {       "afs",
740                 net_afs,
741                 NET_TRANSPORT_LOCAL,
742                 N_("Manage AFS tokens"),
743                 N_("  Use 'net help afs' to get more information about 'net "
744                    "afs' commands.")
745         },
746 #endif
747
748         {       "help",
749                 net_help,
750                 NET_TRANSPORT_LOCAL,
751                 N_("Print usage information"),
752                 N_("  Use 'net help help' to list usage information for 'net' "
753                    "commands.")
754         },
755         {NULL, NULL, 0, NULL, NULL}
756 };
757
758
759 /****************************************************************************
760   main program
761 ****************************************************************************/
762  int main(int argc, const char **argv)
763 {
764         int opt,i;
765         char *p;
766         int rc = 0;
767         int argc_new = 0;
768         const char ** argv_new;
769         poptContext pc;
770         TALLOC_CTX *frame = talloc_stackframe();
771         struct net_context *c = talloc_zero(frame, struct net_context);
772
773         struct poptOption long_options[] = {
774                 {"help",        'h', POPT_ARG_NONE,   0, 'h'},
775                 {"workgroup",   'w', POPT_ARG_STRING, &c->opt_target_workgroup},
776                 {"user",        'U', POPT_ARG_STRING, &c->opt_user_name, 'U'},
777                 {"ipaddress",   'I', POPT_ARG_STRING, 0,'I'},
778                 {"port",        'p', POPT_ARG_INT,    &c->opt_port},
779                 {"myname",      'n', POPT_ARG_STRING, &c->opt_requester_name},
780                 {"server",      'S', POPT_ARG_STRING, &c->opt_host},
781                 {"encrypt",     'e', POPT_ARG_NONE,   NULL, 'e', N_("Encrypt SMB transport (UNIX extended servers only)") },
782                 {"container",   'c', POPT_ARG_STRING, &c->opt_container},
783                 {"comment",     'C', POPT_ARG_STRING, &c->opt_comment},
784                 {"maxusers",    'M', POPT_ARG_INT,    &c->opt_maxusers},
785                 {"flags",       'F', POPT_ARG_INT,    &c->opt_flags},
786                 {"long",        'l', POPT_ARG_NONE,   &c->opt_long_list_entries},
787                 {"reboot",      'r', POPT_ARG_NONE,   &c->opt_reboot},
788                 {"force",       'f', POPT_ARG_NONE,   &c->opt_force},
789                 {"stdin",       'i', POPT_ARG_NONE,   &c->opt_stdin},
790                 {"timeout",     't', POPT_ARG_INT,    &c->opt_timeout},
791                 {"request-timeout",0,POPT_ARG_INT,    &c->opt_request_timeout},
792                 {"machine-pass",'P', POPT_ARG_NONE,   &c->opt_machine_pass},
793                 {"kerberos",    'k', POPT_ARG_NONE,   &c->opt_kerberos},
794                 {"myworkgroup", 'W', POPT_ARG_STRING, &c->opt_workgroup},
795                 {"use-ccache",    0, POPT_ARG_NONE,   &c->opt_ccache},
796                 {"verbose",     'v', POPT_ARG_NONE,   &c->opt_verbose},
797                 {"test",        'T', POPT_ARG_NONE,   &c->opt_testmode},
798                 /* Options for 'net groupmap set' */
799                 {"local",       'L', POPT_ARG_NONE,   &c->opt_localgroup},
800                 {"domain",      'D', POPT_ARG_NONE,   &c->opt_domaingroup},
801                 {"ntname",      'N', POPT_ARG_STRING, &c->opt_newntname},
802                 {"rid",         'R', POPT_ARG_INT,    &c->opt_rid},
803                 /* Options for 'net rpc share migrate' */
804                 {"acls",        0, POPT_ARG_NONE,     &c->opt_acls},
805                 {"attrs",       0, POPT_ARG_NONE,     &c->opt_attrs},
806                 {"timestamps",  0, POPT_ARG_NONE,     &c->opt_timestamps},
807                 {"exclude",     'X', POPT_ARG_STRING, &c->opt_exclude},
808                 {"destination", 0, POPT_ARG_STRING,   &c->opt_destination},
809                 {"tallocreport", 0, POPT_ARG_NONE,    &c->do_talloc_report},
810                 /* Options for 'net rpc vampire (keytab)' */
811                 {"force-full-repl", 0, POPT_ARG_NONE, &c->opt_force_full_repl},
812                 {"single-obj-repl", 0, POPT_ARG_NONE, &c->opt_single_obj_repl},
813                 {"clean-old-entries", 0, POPT_ARG_NONE, &c->opt_clean_old_entries},
814
815                 POPT_COMMON_SAMBA
816                 { 0, 0, 0, 0}
817         };
818
819         zero_sockaddr(&c->opt_dest_ip);
820
821         load_case_tables();
822
823         setlocale(LC_ALL, "");
824 #if defined(HAVE_BINDTEXTDOMAIN)
825         bindtextdomain(MODULE_NAME, dyn_LOCALEDIR);
826 #endif
827 #if defined(HAVE_TEXTDOMAIN)
828         textdomain(MODULE_NAME);
829 #endif
830
831         /* set default debug level to 0 regardless of what smb.conf sets */
832         DEBUGLEVEL_CLASS[DBGC_ALL] = 0;
833         dbf = x_stderr;
834         c->private_data = net_func;
835
836         pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
837                             POPT_CONTEXT_KEEP_FIRST);
838
839         while((opt = poptGetNextOpt(pc)) != -1) {
840                 switch (opt) {
841                 case 'h':
842                         c->display_usage = true;
843                         break;
844                 case 'e':
845                         c->smb_encrypt = true;
846                         break;
847                 case 'I':
848                         if (!interpret_string_addr(&c->opt_dest_ip,
849                                                 poptGetOptArg(pc), 0)) {
850                                 d_fprintf(stderr, _("\nInvalid ip address specified\n"));
851                         } else {
852                                 c->opt_have_ip = true;
853                         }
854                         break;
855                 case 'U':
856                         c->opt_user_specified = true;
857                         c->opt_user_name = SMB_STRDUP(c->opt_user_name);
858                         p = strchr(c->opt_user_name,'%');
859                         if (p) {
860                                 *p = 0;
861                                 c->opt_password = p+1;
862                         }
863                         break;
864                 default:
865                         d_fprintf(stderr, _("\nInvalid option %s: %s\n"),
866                                  poptBadOption(pc, 0), poptStrerror(opt));
867                         net_help(c, argc, argv);
868                         exit(1);
869                 }
870         }
871
872         /*
873          * Don't load debug level from smb.conf. It should be
874          * set by cmdline arg or remain default (0)
875          */
876         AllowDebugChange = false;
877         lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
878
879         argv_new = (const char **)poptGetArgs(pc);
880
881         argc_new = argc;
882         for (i=0; i<argc; i++) {
883                 if (argv_new[i] == NULL) {
884                         argc_new = i;
885                         break;
886                 }
887         }
888
889         if (c->do_talloc_report) {
890                 talloc_enable_leak_report();
891         }
892
893         if (c->opt_requester_name) {
894                 set_global_myname(c->opt_requester_name);
895         }
896
897         if (!c->opt_user_name && getenv("LOGNAME")) {
898                 c->opt_user_name = getenv("LOGNAME");
899         }
900
901         if (!c->opt_workgroup) {
902                 c->opt_workgroup = smb_xstrdup(lp_workgroup());
903         }
904
905         if (!c->opt_target_workgroup) {
906                 c->opt_target_workgroup = smb_xstrdup(lp_workgroup());
907         }
908
909         if (!init_names())
910                 exit(1);
911
912         load_interfaces();
913
914         /* this makes sure that when we do things like call scripts,
915            that it won't assert because we are not root */
916         sec_init();
917
918         if (c->opt_machine_pass) {
919                 /* it is very useful to be able to make ads queries as the
920                    machine account for testing purposes and for domain leave */
921
922                 net_use_krb_machine_account(c);
923         }
924
925         if (!c->opt_password) {
926                 c->opt_password = getenv("PASSWD");
927         }
928
929         rc = net_run_function(c, argc_new-1, argv_new+1, "net", net_func);
930
931         DEBUG(2,("return code = %d\n", rc));
932
933         gencache_stabilize();
934
935         libnetapi_free(c->netapi_ctx);
936
937         poptFreeContext(pc);
938
939         TALLOC_FREE(frame);
940         return rc;
941 }