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