net: Move net_run_function/net_run_function2 to net_util.c
[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 /* Beginning of internationalization section.  Translatable constants  */
54 /* should be kept in this area and referenced in the rest of the code. */
55 /*                                                                     */
56 /* No functions, outside of Samba or LSB (Linux Standards Base) should */
57 /* be used (if possible).                                              */
58 /***********************************************************************/
59
60 #define YES_STRING              "Yes"
61 #define NO_STRING               "No"
62
63 /***********************************************************************/
64 /* end of internationalization section                                 */
65 /***********************************************************************/
66
67 uint32 get_sec_channel_type(const char *param)
68 {
69         if (!(param && *param)) {
70                 return get_default_sec_channel();
71         } else {
72                 if (strequal(param, "PDC")) {
73                         return SEC_CHAN_BDC;
74                 } else if (strequal(param, "BDC")) {
75                         return SEC_CHAN_BDC;
76                 } else if (strequal(param, "MEMBER")) {
77                         return SEC_CHAN_WKSTA;
78 #if 0
79                 } else if (strequal(param, "DOMAIN")) {
80                         return SEC_CHAN_DOMAIN;
81 #endif
82                 } else {
83                         return get_default_sec_channel();
84                 }
85         }
86 }
87
88 static int net_changetrustpw(struct net_context *c, int argc, const char **argv)
89 {
90         if (net_ads_check_our_domain(c) == 0)
91                 return net_ads_changetrustpw(c, argc, argv);
92
93         return net_rpc_changetrustpw(c, argc, argv);
94 }
95
96 static void set_line_buffering(FILE *f)
97 {
98         setvbuf(f, NULL, _IOLBF, 0);
99 }
100
101 static int net_changesecretpw(struct net_context *c, int argc,
102                               const char **argv)
103 {
104         char *trust_pw;
105         uint32 sec_channel_type = SEC_CHAN_WKSTA;
106
107         if(c->opt_force) {
108                 if (c->opt_stdin) {
109                         set_line_buffering(stdin);
110                         set_line_buffering(stdout);
111                         set_line_buffering(stderr);
112                 }
113
114                 trust_pw = get_pass("Enter machine password: ", c->opt_stdin);
115
116                 if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) {
117                             d_fprintf(stderr, "Unable to write the machine account password in the secrets database");
118                             return 1;
119                 }
120                 else {
121                     d_printf("Modified trust account password in secrets database\n");
122                 }
123         }
124         else {
125                 d_printf("Machine account password change requires the -f flag.\n");
126                 d_printf("Do NOT use this function unless you know what it does!\n");
127                 d_printf("This function will change the ADS Domain member machine account password in the secrets.tdb file!\n");
128         }
129
130         return 0;
131 }
132
133 /*
134  Retrieve our local SID or the SID for the specified name
135  */
136 static int net_getlocalsid(struct net_context *c, int argc, const char **argv)
137 {
138         DOM_SID sid;
139         const char *name;
140         fstring sid_str;
141
142         if (argc >= 1) {
143                 name = argv[0];
144         }
145         else {
146                 name = global_myname();
147         }
148
149         if(!initialize_password_db(false, NULL)) {
150                 DEBUG(0, ("WARNING: Could not open passdb - local sid may not reflect passdb\n"
151                           "backend knowledge (such as the sid stored in LDAP)\n"));
152         }
153
154         /* first check to see if we can even access secrets, so we don't
155            panic when we can't. */
156
157         if (!secrets_init()) {
158                 d_fprintf(stderr, "Unable to open secrets.tdb.  Can't fetch domain SID for name: %s\n", name);
159                 return 1;
160         }
161
162         /* Generate one, if it doesn't exist */
163         get_global_sam_sid();
164
165         if (!secrets_fetch_domain_sid(name, &sid)) {
166                 DEBUG(0, ("Can't fetch domain SID for name: %s\n", name));
167                 return 1;
168         }
169         sid_to_fstring(sid_str, &sid);
170         d_printf("SID for domain %s is: %s\n", name, sid_str);
171         return 0;
172 }
173
174 static int net_setlocalsid(struct net_context *c, int argc, const char **argv)
175 {
176         DOM_SID sid;
177
178         if ( (argc != 1)
179              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
180              || (!string_to_sid(&sid, argv[0]))
181              || (sid.num_auths != 4)) {
182                 d_printf("usage: net setlocalsid S-1-5-21-x-y-z\n");
183                 return 1;
184         }
185
186         if (!secrets_store_domain_sid(global_myname(), &sid)) {
187                 DEBUG(0,("Can't store domain SID as a pdc/bdc.\n"));
188                 return 1;
189         }
190
191         return 0;
192 }
193
194 static int net_setdomainsid(struct net_context *c, int argc, const char **argv)
195 {
196         DOM_SID sid;
197
198         if ( (argc != 1)
199              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
200              || (!string_to_sid(&sid, argv[0]))
201              || (sid.num_auths != 4)) {
202                 d_printf("usage: net setdomainsid S-1-5-21-x-y-z\n");
203                 return 1;
204         }
205
206         if (!secrets_store_domain_sid(lp_workgroup(), &sid)) {
207                 DEBUG(0,("Can't store domain SID.\n"));
208                 return 1;
209         }
210
211         return 0;
212 }
213
214 static int net_getdomainsid(struct net_context *c, int argc, const char **argv)
215 {
216         DOM_SID domain_sid;
217         fstring sid_str;
218
219         if (argc > 0) {
220                 d_printf("usage: net getdomainsid\n");
221                 return 1;
222         }
223
224         if(!initialize_password_db(false, NULL)) {
225                 DEBUG(0, ("WARNING: Could not open passdb - domain SID may "
226                           "not reflect passdb\n"
227                           "backend knowledge (such as the SID stored in "
228                           "LDAP)\n"));
229         }
230
231         /* first check to see if we can even access secrets, so we don't
232            panic when we can't. */
233
234         if (!secrets_init()) {
235                 d_fprintf(stderr, "Unable to open secrets.tdb.  Can't fetch domain"
236                                   "SID for name: %s\n", get_global_sam_name());
237                 return 1;
238         }
239
240         /* Generate one, if it doesn't exist */
241         get_global_sam_sid();
242
243         if (!secrets_fetch_domain_sid(global_myname(), &domain_sid)) {
244                 d_fprintf(stderr, "Could not fetch local SID\n");
245                 return 1;
246         }
247         sid_to_fstring(sid_str, &domain_sid);
248         d_printf("SID for local machine %s is: %s\n", global_myname(), sid_str);
249
250         if (!secrets_fetch_domain_sid(c->opt_workgroup, &domain_sid)) {
251                 d_fprintf(stderr, "Could not fetch domain SID\n");
252                 return 1;
253         }
254
255         sid_to_fstring(sid_str, &domain_sid);
256         d_printf("SID for domain %s is: %s\n", c->opt_workgroup, sid_str);
257
258         return 0;
259 }
260
261 static bool search_maxrid(struct pdb_search *search, const char *type,
262                           uint32 *max_rid)
263 {
264         struct samr_displayentry *entries;
265         uint32 i, num_entries;
266
267         if (search == NULL) {
268                 d_fprintf(stderr, "get_maxrid: Could not search %s\n", type);
269                 return false;
270         }
271
272         num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries);
273         for (i=0; i<num_entries; i++)
274                 *max_rid = MAX(*max_rid, entries[i].rid);
275         pdb_search_destroy(search);
276         return true;
277 }
278
279 static uint32 get_maxrid(void)
280 {
281         uint32 max_rid = 0;
282
283         if (!search_maxrid(pdb_search_users(0), "users", &max_rid))
284                 return 0;
285
286         if (!search_maxrid(pdb_search_groups(), "groups", &max_rid))
287                 return 0;
288
289         if (!search_maxrid(pdb_search_aliases(get_global_sam_sid()),
290                            "aliases", &max_rid))
291                 return 0;
292
293         return max_rid;
294 }
295
296 static int net_maxrid(struct net_context *c, int argc, const char **argv)
297 {
298         uint32 rid;
299
300         if (argc != 0) {
301                 DEBUG(0, ("usage: net maxrid\n"));
302                 return 1;
303         }
304
305         if ((rid = get_maxrid()) == 0) {
306                 DEBUG(0, ("can't get current maximum rid\n"));
307                 return 1;
308         }
309
310         d_printf("Currently used maximum rid: %d\n", rid);
311
312         return 0;
313 }
314
315 /* main function table */
316 static struct functable net_func[] = {
317         {"RPC", net_rpc},
318         {"RAP", net_rap},
319         {"ADS", net_ads},
320
321         /* eventually these should auto-choose the transport ... */
322         {"FILE", net_file},
323         {"SHARE", net_share},
324         {"SESSION", net_rap_session},
325         {"SERVER", net_rap_server},
326         {"DOMAIN", net_rap_domain},
327         {"PRINTQ", net_rap_printq},
328         {"USER", net_user},
329         {"GROUP", net_group},
330         {"GROUPMAP", net_groupmap},
331         {"SAM", net_sam},
332         {"VALIDATE", net_rap_validate},
333         {"GROUPMEMBER", net_rap_groupmember},
334         {"ADMIN", net_rap_admin},
335         {"SERVICE", net_rap_service},
336         {"PASSWORD", net_rap_password},
337         {"CHANGETRUSTPW", net_changetrustpw},
338         {"CHANGESECRETPW", net_changesecretpw},
339         {"TIME", net_time},
340         {"LOOKUP", net_lookup},
341         {"JOIN", net_join},
342         {"DOM", net_dom},
343         {"CACHE", net_cache},
344         {"GETLOCALSID", net_getlocalsid},
345         {"SETLOCALSID", net_setlocalsid},
346         {"SETDOMAINSID", net_setdomainsid},
347         {"GETDOMAINSID", net_getdomainsid},
348         {"MAXRID", net_maxrid},
349         {"IDMAP", net_idmap},
350         {"STATUS", net_status},
351         {"USERSHARE", net_usershare},
352         {"USERSIDLIST", net_usersidlist},
353         {"CONF", net_conf},
354         {"REGISTRY", net_registry},
355 #ifdef WITH_FAKE_KASERVER
356         {"AFS", net_afs},
357 #endif
358
359         {"HELP", net_help},
360         {NULL, NULL}
361 };
362
363
364 /****************************************************************************
365   main program
366 ****************************************************************************/
367  int main(int argc, const char **argv)
368 {
369         int opt,i;
370         char *p;
371         int rc = 0;
372         int argc_new = 0;
373         const char ** argv_new;
374         poptContext pc;
375         TALLOC_CTX *frame = talloc_stackframe();
376         struct net_context *c = talloc_zero(frame, struct net_context);
377
378         struct poptOption long_options[] = {
379                 {"help",        'h', POPT_ARG_NONE,   0, 'h'},
380                 {"workgroup",   'w', POPT_ARG_STRING, &c->opt_target_workgroup},
381                 {"user",        'U', POPT_ARG_STRING, &c->opt_user_name, 'U'},
382                 {"ipaddress",   'I', POPT_ARG_STRING, 0,'I'},
383                 {"port",        'p', POPT_ARG_INT,    &c->opt_port},
384                 {"myname",      'n', POPT_ARG_STRING, &c->opt_requester_name},
385                 {"server",      'S', POPT_ARG_STRING, &c->opt_host},
386                 {"encrypt",     'e', POPT_ARG_NONE,   NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
387                 {"container",   'c', POPT_ARG_STRING, &c->opt_container},
388                 {"comment",     'C', POPT_ARG_STRING, &c->opt_comment},
389                 {"maxusers",    'M', POPT_ARG_INT,    &c->opt_maxusers},
390                 {"flags",       'F', POPT_ARG_INT,    &c->opt_flags},
391                 {"long",        'l', POPT_ARG_NONE,   &c->opt_long_list_entries},
392                 {"reboot",      'r', POPT_ARG_NONE,   &c->opt_reboot},
393                 {"force",       'f', POPT_ARG_NONE,   &c->opt_force},
394                 {"stdin",       'i', POPT_ARG_NONE,   &c->opt_stdin},
395                 {"timeout",     't', POPT_ARG_INT,    &c->opt_timeout},
396                 {"machine-pass",'P', POPT_ARG_NONE,   &c->opt_machine_pass},
397                 {"myworkgroup", 'W', POPT_ARG_STRING, &c->opt_workgroup},
398                 {"verbose",     'v', POPT_ARG_NONE,   &c->opt_verbose},
399                 {"test",        'T', POPT_ARG_NONE,   &c->opt_testmode},
400                 /* Options for 'net groupmap set' */
401                 {"local",       'L', POPT_ARG_NONE,   &c->opt_localgroup},
402                 {"domain",      'D', POPT_ARG_NONE,   &c->opt_domaingroup},
403                 {"ntname",      'N', POPT_ARG_STRING, &c->opt_newntname},
404                 {"rid",         'R', POPT_ARG_INT,    &c->opt_rid},
405                 /* Options for 'net rpc share migrate' */
406                 {"acls",        0, POPT_ARG_NONE,     &c->opt_acls},
407                 {"attrs",       0, POPT_ARG_NONE,     &c->opt_attrs},
408                 {"timestamps",  0, POPT_ARG_NONE,     &c->opt_timestamps},
409                 {"exclude",     'X', POPT_ARG_STRING, &c->opt_exclude},
410                 {"destination", 0, POPT_ARG_STRING,   &c->opt_destination},
411                 {"tallocreport", 0, POPT_ARG_NONE,    &c->do_talloc_report},
412
413                 POPT_COMMON_SAMBA
414                 { 0, 0, 0, 0}
415         };
416
417
418         zero_addr(&c->opt_dest_ip);
419
420         load_case_tables();
421
422         /* set default debug level to 0 regardless of what smb.conf sets */
423         DEBUGLEVEL_CLASS[DBGC_ALL] = 0;
424         dbf = x_stderr;
425
426         pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
427                             POPT_CONTEXT_KEEP_FIRST);
428
429         while((opt = poptGetNextOpt(pc)) != -1) {
430                 switch (opt) {
431                 case 'h':
432                         net_help(c, argc, argv);
433                         exit(0);
434                         break;
435                 case 'e':
436                         c->smb_encrypt = true;
437                         break;
438                 case 'I':
439                         if (!interpret_string_addr(&c->opt_dest_ip,
440                                                 poptGetOptArg(pc), 0)) {
441                                 d_fprintf(stderr, "\nInvalid ip address specified\n");
442                         } else {
443                                 c->opt_have_ip = true;
444                         }
445                         break;
446                 case 'U':
447                         c->opt_user_specified = true;
448                         c->opt_user_name = SMB_STRDUP(c->opt_user_name);
449                         p = strchr(c->opt_user_name,'%');
450                         if (p) {
451                                 *p = 0;
452                                 c->opt_password = p+1;
453                         }
454                         break;
455                 default:
456                         d_fprintf(stderr, "\nInvalid option %s: %s\n",
457                                  poptBadOption(pc, 0), poptStrerror(opt));
458                         net_help(c, argc, argv);
459                         exit(1);
460                 }
461         }
462
463         /*
464          * Don't load debug level from smb.conf. It should be
465          * set by cmdline arg or remain default (0)
466          */
467         AllowDebugChange = false;
468         lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
469
470         argv_new = (const char **)poptGetArgs(pc);
471
472         argc_new = argc;
473         for (i=0; i<argc; i++) {
474                 if (argv_new[i] == NULL) {
475                         argc_new = i;
476                         break;
477                 }
478         }
479
480         if (c->do_talloc_report) {
481                 talloc_enable_leak_report();
482         }
483
484         if (c->opt_requester_name) {
485                 set_global_myname(c->opt_requester_name);
486         }
487
488         if (!c->opt_user_name && getenv("LOGNAME")) {
489                 c->opt_user_name = getenv("LOGNAME");
490         }
491
492         if (!c->opt_workgroup) {
493                 c->opt_workgroup = smb_xstrdup(lp_workgroup());
494         }
495
496         if (!c->opt_target_workgroup) {
497                 c->opt_target_workgroup = smb_xstrdup(lp_workgroup());
498         }
499
500         if (!init_names())
501                 exit(1);
502
503         load_interfaces();
504
505         /* this makes sure that when we do things like call scripts,
506            that it won't assert becouse we are not root */
507         sec_init();
508
509         if (c->opt_machine_pass) {
510                 /* it is very useful to be able to make ads queries as the
511                    machine account for testing purposes and for domain leave */
512
513                 net_use_krb_machine_account(c);
514         }
515
516         if (!c->opt_password) {
517                 c->opt_password = getenv("PASSWD");
518         }
519
520         rc = net_run_function(c, argc_new-1, argv_new+1, net_func, net_help);
521
522         DEBUG(2,("return code = %d\n", rc));
523
524         libnetapi_free(c->netapi_ctx);
525
526         poptFreeContext(pc);
527
528         TALLOC_FREE(frame);
529         return rc;
530 }