net: Move "net join" handling into a separate file.
[ira/wip.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 /***********************************************************************/
47 /* Beginning of internationalization section.  Translatable constants  */
48 /* should be kept in this area and referenced in the rest of the code. */
49 /*                                                                     */
50 /* No functions, outside of Samba or LSB (Linux Standards Base) should */
51 /* be used (if possible).                                              */
52 /***********************************************************************/
53
54 #define YES_STRING              "Yes"
55 #define NO_STRING               "No"
56
57 /***********************************************************************/
58 /* end of internationalization section                                 */
59 /***********************************************************************/
60
61 uint32 get_sec_channel_type(const char *param)
62 {
63         if (!(param && *param)) {
64                 return get_default_sec_channel();
65         } else {
66                 if (strequal(param, "PDC")) {
67                         return SEC_CHAN_BDC;
68                 } else if (strequal(param, "BDC")) {
69                         return SEC_CHAN_BDC;
70                 } else if (strequal(param, "MEMBER")) {
71                         return SEC_CHAN_WKSTA;
72 #if 0
73                 } else if (strequal(param, "DOMAIN")) {
74                         return SEC_CHAN_DOMAIN;
75 #endif
76                 } else {
77                         return get_default_sec_channel();
78                 }
79         }
80 }
81
82 /*
83   run a function from a function table. If not found then
84   call the specified usage function
85 */
86 int net_run_function(struct net_context *c, int argc, const char **argv,
87                      struct functable *table,
88                      int (*usage_fn)(struct net_context *c,
89                                      int argc, const char **argv))
90 {
91         int i;
92
93         if (argc < 1) {
94                 d_printf("\nUsage: \n");
95                 return usage_fn(c, argc, argv);
96         }
97         for (i=0; table[i].funcname; i++) {
98                 if (StrCaseCmp(argv[0], table[i].funcname) == 0)
99                         return table[i].fn(c, argc-1, argv+1);
100         }
101         d_fprintf(stderr, "No command: %s\n", argv[0]);
102         return usage_fn(c, argc, argv);
103 }
104
105 /*
106  * run a function from a function table.
107  */
108 int net_run_function2(struct net_context *c, int argc, const char **argv,
109                       const char *whoami, struct functable2 *table)
110 {
111         int i;
112
113         if (argc != 0) {
114                 for (i=0; table[i].funcname; i++) {
115                         if (StrCaseCmp(argv[0], table[i].funcname) == 0)
116                                 return table[i].fn(c, argc-1, argv+1);
117                 }
118         }
119
120         for (i=0; table[i].funcname != NULL; i++) {
121                 d_printf("%s %-15s %s\n", whoami, table[i].funcname,
122                          table[i].helptext);
123         }
124
125         return -1;
126 }
127
128 /****************************************************************************
129  Connect to \\server\service.
130 ****************************************************************************/
131
132 NTSTATUS connect_to_service(struct net_context *c,
133                                         struct cli_state **cli_ctx,
134                                         struct sockaddr_storage *server_ss,
135                                         const char *server_name,
136                                         const char *service_name,
137                                         const char *service_type)
138 {
139         NTSTATUS nt_status;
140
141         c->opt_password = net_prompt_pass(c, c->opt_user_name);
142         if (!c->opt_password) {
143                 return NT_STATUS_NO_MEMORY;
144         }
145
146         nt_status = cli_full_connection(cli_ctx, NULL, server_name,
147                                         server_ss, c->opt_port,
148                                         service_name, service_type,
149                                         c->opt_user_name, c->opt_workgroup,
150                                         c->opt_password, 0, Undefined, NULL);
151         if (!NT_STATUS_IS_OK(nt_status)) {
152                 d_fprintf(stderr, "Could not connect to server %s\n", server_name);
153
154                 /* Display a nicer message depending on the result */
155
156                 if (NT_STATUS_V(nt_status) ==
157                     NT_STATUS_V(NT_STATUS_LOGON_FAILURE))
158                         d_fprintf(stderr, "The username or password was not correct.\n");
159
160                 if (NT_STATUS_V(nt_status) ==
161                     NT_STATUS_V(NT_STATUS_ACCOUNT_LOCKED_OUT))
162                         d_fprintf(stderr, "The account was locked out.\n");
163
164                 if (NT_STATUS_V(nt_status) ==
165                     NT_STATUS_V(NT_STATUS_ACCOUNT_DISABLED))
166                         d_fprintf(stderr, "The account was disabled.\n");
167                 return nt_status;
168         }
169
170         if (c->smb_encrypt) {
171                 nt_status = cli_force_encryption(*cli_ctx,
172                                         c->opt_user_name,
173                                         c->opt_password,
174                                         c->opt_workgroup);
175
176                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_NOT_SUPPORTED)) {
177                         d_printf("Encryption required and "
178                                 "server that doesn't support "
179                                 "UNIX extensions - failing connect\n");
180                 } else if (NT_STATUS_EQUAL(nt_status,NT_STATUS_UNKNOWN_REVISION)) {
181                         d_printf("Encryption required and "
182                                 "can't get UNIX CIFS extensions "
183                                 "version from server.\n");
184                 } else if (NT_STATUS_EQUAL(nt_status,NT_STATUS_UNSUPPORTED_COMPRESSION)) {
185                         d_printf("Encryption required and "
186                                 "share %s doesn't support "
187                                 "encryption.\n", service_name);
188                 } else if (!NT_STATUS_IS_OK(nt_status)) {
189                         d_printf("Encryption required and "
190                                 "setup failed with error %s.\n",
191                                 nt_errstr(nt_status));
192                 }
193
194                 if (!NT_STATUS_IS_OK(nt_status)) {
195                         cli_shutdown(*cli_ctx);
196                         *cli_ctx = NULL;
197                 }
198         }
199
200         return nt_status;
201 }
202
203 /****************************************************************************
204  Connect to \\server\ipc$.
205 ****************************************************************************/
206
207 NTSTATUS connect_to_ipc(struct net_context *c,
208                         struct cli_state **cli_ctx,
209                         struct sockaddr_storage *server_ss,
210                         const char *server_name)
211 {
212         return connect_to_service(c, cli_ctx, server_ss, server_name, "IPC$",
213                                   "IPC");
214 }
215
216 /****************************************************************************
217  Connect to \\server\ipc$ anonymously.
218 ****************************************************************************/
219
220 NTSTATUS connect_to_ipc_anonymous(struct net_context *c,
221                                 struct cli_state **cli_ctx,
222                                 struct sockaddr_storage *server_ss,
223                                 const char *server_name)
224 {
225         NTSTATUS nt_status;
226
227         nt_status = cli_full_connection(cli_ctx, c->opt_requester_name,
228                                         server_name, server_ss, c->opt_port,
229                                         "IPC$", "IPC",
230                                         "", "",
231                                         "", 0, Undefined, NULL);
232
233         if (NT_STATUS_IS_OK(nt_status)) {
234                 return nt_status;
235         } else {
236                 DEBUG(1,("Cannot connect to server (anonymously).  Error was %s\n", nt_errstr(nt_status)));
237                 return nt_status;
238         }
239 }
240
241 /****************************************************************************
242  Return malloced user@realm for krb5 login.
243 ****************************************************************************/
244
245 static char *get_user_and_realm(const char *username)
246 {
247         char *user_and_realm = NULL;
248
249         if (!username) {
250                 return NULL;
251         }
252         if (strchr_m(username, '@')) {
253                 user_and_realm = SMB_STRDUP(username);
254         } else {
255                 if (asprintf(&user_and_realm, "%s@%s", username, lp_realm()) == -1) {
256                         user_and_realm = NULL;
257                 }
258         }
259         return user_and_realm;
260 }
261
262 /****************************************************************************
263  Connect to \\server\ipc$ using KRB5.
264 ****************************************************************************/
265
266 NTSTATUS connect_to_ipc_krb5(struct net_context *c,
267                         struct cli_state **cli_ctx,
268                         struct sockaddr_storage *server_ss,
269                         const char *server_name)
270 {
271         NTSTATUS nt_status;
272         char *user_and_realm = NULL;
273
274         /* FIXME: Should get existing kerberos ticket if possible. */
275         c->opt_password = net_prompt_pass(c, c->opt_user_name);
276         if (!c->opt_password) {
277                 return NT_STATUS_NO_MEMORY;
278         }
279
280         user_and_realm = get_user_and_realm(c->opt_user_name);
281         if (!user_and_realm) {
282                 return NT_STATUS_NO_MEMORY;
283         }
284
285         nt_status = cli_full_connection(cli_ctx, NULL, server_name,
286                                         server_ss, c->opt_port,
287                                         "IPC$", "IPC",
288                                         user_and_realm, c->opt_workgroup,
289                                         c->opt_password,
290                                         CLI_FULL_CONNECTION_USE_KERBEROS,
291                                         Undefined, NULL);
292
293         SAFE_FREE(user_and_realm);
294
295         if (!NT_STATUS_IS_OK(nt_status)) {
296                 DEBUG(1,("Cannot connect to server using kerberos.  Error was %s\n", nt_errstr(nt_status)));
297                 return nt_status;
298         }
299
300         if (c->smb_encrypt) {
301                 nt_status = cli_cm_force_encryption(*cli_ctx,
302                                         user_and_realm,
303                                         c->opt_password,
304                                         c->opt_workgroup,
305                                         "IPC$");
306                 if (!NT_STATUS_IS_OK(nt_status)) {
307                         cli_shutdown(*cli_ctx);
308                         *cli_ctx = NULL;
309                 }
310         }
311
312         return nt_status;
313 }
314
315 /**
316  * Connect a server and open a given pipe
317  *
318  * @param cli_dst               A cli_state
319  * @param pipe                  The pipe to open
320  * @param got_pipe              boolean that stores if we got a pipe
321  *
322  * @return Normal NTSTATUS return.
323  **/
324 NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst,
325                           struct rpc_pipe_client **pp_pipe_hnd, int pipe_num)
326 {
327         NTSTATUS nt_status;
328         char *server_name = SMB_STRDUP("127.0.0.1");
329         struct cli_state *cli_tmp = NULL;
330         struct rpc_pipe_client *pipe_hnd = NULL;
331
332         if (server_name == NULL) {
333                 return NT_STATUS_NO_MEMORY;
334         }
335
336         if (c->opt_destination) {
337                 SAFE_FREE(server_name);
338                 if ((server_name = SMB_STRDUP(c->opt_destination)) == NULL) {
339                         return NT_STATUS_NO_MEMORY;
340                 }
341         }
342
343         /* make a connection to a named pipe */
344         nt_status = connect_to_ipc(c, &cli_tmp, NULL, server_name);
345         if (!NT_STATUS_IS_OK(nt_status)) {
346                 SAFE_FREE(server_name);
347                 return nt_status;
348         }
349
350         pipe_hnd = cli_rpc_pipe_open_noauth(cli_tmp, pipe_num, &nt_status);
351         if (!pipe_hnd) {
352                 DEBUG(0, ("couldn't not initialize pipe\n"));
353                 cli_shutdown(cli_tmp);
354                 SAFE_FREE(server_name);
355                 return nt_status;
356         }
357
358         *cli_dst = cli_tmp;
359         *pp_pipe_hnd = pipe_hnd;
360         SAFE_FREE(server_name);
361
362         return nt_status;
363 }
364
365 /****************************************************************************
366  Use the local machine account (krb) and password for this session.
367 ****************************************************************************/
368
369 int net_use_krb_machine_account(struct net_context *c)
370 {
371         char *user_name = NULL;
372
373         if (!secrets_init()) {
374                 d_fprintf(stderr, "ERROR: Unable to open secrets database\n");
375                 exit(1);
376         }
377
378         c->opt_password = secrets_fetch_machine_password(
379                                 c->opt_target_workgroup, NULL, NULL);
380         if (asprintf(&user_name, "%s$@%s", global_myname(), lp_realm()) == -1) {
381                 return -1;
382         }
383         c->opt_user_name = user_name;
384         return 0;
385 }
386
387 /****************************************************************************
388  Use the machine account name and password for this session.
389 ****************************************************************************/
390
391 int net_use_machine_account(struct net_context *c)
392 {
393         char *user_name = NULL;
394
395         if (!secrets_init()) {
396                 d_fprintf(stderr, "ERROR: Unable to open secrets database\n");
397                 exit(1);
398         }
399
400         c->opt_password = secrets_fetch_machine_password(
401                                 c->opt_target_workgroup, NULL, NULL);
402         if (asprintf(&user_name, "%s$", global_myname()) == -1) {
403                 return -1;
404         }
405         c->opt_user_name = user_name;
406         return 0;
407 }
408
409 bool net_find_server(struct net_context *c,
410                         const char *domain,
411                         unsigned flags,
412                         struct sockaddr_storage *server_ss,
413                         char **server_name)
414 {
415         const char *d = domain ? domain : c->opt_target_workgroup;
416
417         if (c->opt_host) {
418                 *server_name = SMB_STRDUP(c->opt_host);
419         }
420
421         if (c->opt_have_ip) {
422                 *server_ss = c->opt_dest_ip;
423                 if (!*server_name) {
424                         char addr[INET6_ADDRSTRLEN];
425                         print_sockaddr(addr, sizeof(addr), &c->opt_dest_ip);
426                         *server_name = SMB_STRDUP(addr);
427                 }
428         } else if (*server_name) {
429                 /* resolve the IP address */
430                 if (!resolve_name(*server_name, server_ss, 0x20))  {
431                         DEBUG(1,("Unable to resolve server name\n"));
432                         return false;
433                 }
434         } else if (flags & NET_FLAGS_PDC) {
435                 fstring dc_name;
436                 struct sockaddr_storage pdc_ss;
437
438                 if (!get_pdc_ip(d, &pdc_ss)) {
439                         DEBUG(1,("Unable to resolve PDC server address\n"));
440                         return false;
441                 }
442
443                 if (is_zero_addr(&pdc_ss)) {
444                         return false;
445                 }
446
447                 if (!name_status_find(d, 0x1b, 0x20, &pdc_ss, dc_name)) {
448                         return false;
449                 }
450
451                 *server_name = SMB_STRDUP(dc_name);
452                 *server_ss = pdc_ss;
453         } else if (flags & NET_FLAGS_DMB) {
454                 struct sockaddr_storage msbrow_ss;
455                 char addr[INET6_ADDRSTRLEN];
456
457                 /*  if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */
458                 if (!resolve_name(d, &msbrow_ss, 0x1B))  {
459                         DEBUG(1,("Unable to resolve domain browser via name lookup\n"));
460                         return false;
461                 }
462                 *server_ss = msbrow_ss;
463                 print_sockaddr(addr, sizeof(addr), server_ss);
464                 *server_name = SMB_STRDUP(addr);
465         } else if (flags & NET_FLAGS_MASTER) {
466                 struct sockaddr_storage brow_ss;
467                 char addr[INET6_ADDRSTRLEN];
468                 if (!resolve_name(d, &brow_ss, 0x1D))  {
469                                 /* go looking for workgroups */
470                         DEBUG(1,("Unable to resolve master browser via name lookup\n"));
471                         return false;
472                 }
473                 *server_ss = brow_ss;
474                 print_sockaddr(addr, sizeof(addr), server_ss);
475                 *server_name = SMB_STRDUP(addr);
476         } else if (!(flags & NET_FLAGS_LOCALHOST_DEFAULT_INSANE)) {
477                 if (!interpret_string_addr(server_ss,
478                                         "127.0.0.1", AI_NUMERICHOST)) {
479                         DEBUG(1,("Unable to resolve 127.0.0.1\n"));
480                         return false;
481                 }
482                 *server_name = SMB_STRDUP("127.0.0.1");
483         }
484
485         if (!*server_name) {
486                 DEBUG(1,("no server to connect to\n"));
487                 return false;
488         }
489
490         return true;
491 }
492
493 bool net_find_pdc(struct sockaddr_storage *server_ss,
494                 fstring server_name,
495                 const char *domain_name)
496 {
497         if (!get_pdc_ip(domain_name, server_ss)) {
498                 return false;
499         }
500         if (is_zero_addr(server_ss)) {
501                 return false;
502         }
503
504         if (!name_status_find(domain_name, 0x1b, 0x20, server_ss, server_name)) {
505                 return false;
506         }
507
508         return true;
509 }
510
511 NTSTATUS net_make_ipc_connection(struct net_context *c, unsigned flags,
512                                  struct cli_state **pcli)
513 {
514         return net_make_ipc_connection_ex(c, NULL, NULL, NULL, flags, pcli);
515 }
516
517 NTSTATUS net_make_ipc_connection_ex(struct net_context *c ,const char *domain,
518                                     const char *server,
519                                     struct sockaddr_storage *pss,
520                                     unsigned flags, struct cli_state **pcli)
521 {
522         char *server_name = NULL;
523         struct sockaddr_storage server_ss;
524         struct cli_state *cli = NULL;
525         NTSTATUS nt_status;
526
527         if ( !server || !pss ) {
528                 if (!net_find_server(c, domain, flags, &server_ss,
529                                      &server_name)) {
530                         d_fprintf(stderr, "Unable to find a suitable server\n");
531                         nt_status = NT_STATUS_UNSUCCESSFUL;
532                         goto done;
533                 }
534         } else {
535                 server_name = SMB_STRDUP( server );
536                 server_ss = *pss;
537         }
538
539         if (flags & NET_FLAGS_ANONYMOUS) {
540                 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
541                                                      server_name);
542         } else {
543                 nt_status = connect_to_ipc(c, &cli, &server_ss,
544                                            server_name);
545         }
546
547         /* store the server in the affinity cache if it was a PDC */
548
549         if ( (flags & NET_FLAGS_PDC) && NT_STATUS_IS_OK(nt_status) )
550                 saf_store( cli->server_domain, cli->desthost );
551
552         SAFE_FREE(server_name);
553         if (!NT_STATUS_IS_OK(nt_status)) {
554                 d_fprintf(stderr, "Connection failed: %s\n",
555                           nt_errstr(nt_status));
556                 cli = NULL;
557         }
558
559 done:
560         if (pcli != NULL) {
561                 *pcli = cli;
562         }
563         return nt_status;
564 }
565
566 static int net_user(struct net_context *c, int argc, const char **argv)
567 {
568         if (net_ads_check(c) == 0)
569                 return net_ads_user(c, argc, argv);
570
571         /* if server is not specified, default to PDC? */
572         if (net_rpc_check(c, NET_FLAGS_PDC))
573                 return net_rpc_user(c, argc, argv);
574
575         return net_rap_user(c, argc, argv);
576 }
577
578 static int net_group(struct net_context *c, int argc, const char **argv)
579 {
580         if (net_ads_check(c) == 0)
581                 return net_ads_group(c, argc, argv);
582
583         if (argc == 0 && net_rpc_check(c, NET_FLAGS_PDC))
584                 return net_rpc_group(c,argc, argv);
585
586         return net_rap_group(c, argc, argv);
587 }
588
589 static int net_changetrustpw(struct net_context *c, int argc, const char **argv)
590 {
591         if (net_ads_check_our_domain(c) == 0)
592                 return net_ads_changetrustpw(c, argc, argv);
593
594         return net_rpc_changetrustpw(c, argc, argv);
595 }
596
597 static void set_line_buffering(FILE *f)
598 {
599         setvbuf(f, NULL, _IOLBF, 0);
600 }
601
602 static int net_changesecretpw(struct net_context *c, int argc,
603                               const char **argv)
604 {
605         char *trust_pw;
606         uint32 sec_channel_type = SEC_CHAN_WKSTA;
607
608         if(c->opt_force) {
609                 if (c->opt_stdin) {
610                         set_line_buffering(stdin);
611                         set_line_buffering(stdout);
612                         set_line_buffering(stderr);
613                 }
614
615                 trust_pw = get_pass("Enter machine password: ", c->opt_stdin);
616
617                 if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) {
618                             d_fprintf(stderr, "Unable to write the machine account password in the secrets database");
619                             return 1;
620                 }
621                 else {
622                     d_printf("Modified trust account password in secrets database\n");
623                 }
624         }
625         else {
626                 d_printf("Machine account password change requires the -f flag.\n");
627                 d_printf("Do NOT use this function unless you know what it does!\n");
628                 d_printf("This function will change the ADS Domain member machine account password in the secrets.tdb file!\n");
629         }
630
631         return 0;
632 }
633
634 static int net_share(struct net_context *c, int argc, const char **argv)
635 {
636         if (net_rpc_check(c, 0))
637                 return net_rpc_share(c, argc, argv);
638         return net_rap_share(c, argc, argv);
639 }
640
641 static int net_file(struct net_context *c, int argc, const char **argv)
642 {
643         if (net_rpc_check(c, 0))
644                 return net_rpc_file(c, argc, argv);
645         return net_rap_file(c, argc, argv);
646 }
647
648 /*
649  Retrieve our local SID or the SID for the specified name
650  */
651 static int net_getlocalsid(struct net_context *c, int argc, const char **argv)
652 {
653         DOM_SID sid;
654         const char *name;
655         fstring sid_str;
656
657         if (argc >= 1) {
658                 name = argv[0];
659         }
660         else {
661                 name = global_myname();
662         }
663
664         if(!initialize_password_db(false, NULL)) {
665                 DEBUG(0, ("WARNING: Could not open passdb - local sid may not reflect passdb\n"
666                           "backend knowledge (such as the sid stored in LDAP)\n"));
667         }
668
669         /* first check to see if we can even access secrets, so we don't
670            panic when we can't. */
671
672         if (!secrets_init()) {
673                 d_fprintf(stderr, "Unable to open secrets.tdb.  Can't fetch domain SID for name: %s\n", name);
674                 return 1;
675         }
676
677         /* Generate one, if it doesn't exist */
678         get_global_sam_sid();
679
680         if (!secrets_fetch_domain_sid(name, &sid)) {
681                 DEBUG(0, ("Can't fetch domain SID for name: %s\n", name));
682                 return 1;
683         }
684         sid_to_fstring(sid_str, &sid);
685         d_printf("SID for domain %s is: %s\n", name, sid_str);
686         return 0;
687 }
688
689 static int net_setlocalsid(struct net_context *c, int argc, const char **argv)
690 {
691         DOM_SID sid;
692
693         if ( (argc != 1)
694              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
695              || (!string_to_sid(&sid, argv[0]))
696              || (sid.num_auths != 4)) {
697                 d_printf("usage: net setlocalsid S-1-5-21-x-y-z\n");
698                 return 1;
699         }
700
701         if (!secrets_store_domain_sid(global_myname(), &sid)) {
702                 DEBUG(0,("Can't store domain SID as a pdc/bdc.\n"));
703                 return 1;
704         }
705
706         return 0;
707 }
708
709 static int net_setdomainsid(struct net_context *c, int argc, const char **argv)
710 {
711         DOM_SID sid;
712
713         if ( (argc != 1)
714              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
715              || (!string_to_sid(&sid, argv[0]))
716              || (sid.num_auths != 4)) {
717                 d_printf("usage: net setdomainsid S-1-5-21-x-y-z\n");
718                 return 1;
719         }
720
721         if (!secrets_store_domain_sid(lp_workgroup(), &sid)) {
722                 DEBUG(0,("Can't store domain SID.\n"));
723                 return 1;
724         }
725
726         return 0;
727 }
728
729 static int net_getdomainsid(struct net_context *c, int argc, const char **argv)
730 {
731         DOM_SID domain_sid;
732         fstring sid_str;
733
734         if (argc > 0) {
735                 d_printf("usage: net getdomainsid\n");
736                 return 1;
737         }
738
739         if(!initialize_password_db(false, NULL)) {
740                 DEBUG(0, ("WARNING: Could not open passdb - domain SID may "
741                           "not reflect passdb\n"
742                           "backend knowledge (such as the SID stored in "
743                           "LDAP)\n"));
744         }
745
746         /* first check to see if we can even access secrets, so we don't
747            panic when we can't. */
748
749         if (!secrets_init()) {
750                 d_fprintf(stderr, "Unable to open secrets.tdb.  Can't fetch domain"
751                                   "SID for name: %s\n", get_global_sam_name());
752                 return 1;
753         }
754
755         /* Generate one, if it doesn't exist */
756         get_global_sam_sid();
757
758         if (!secrets_fetch_domain_sid(global_myname(), &domain_sid)) {
759                 d_fprintf(stderr, "Could not fetch local SID\n");
760                 return 1;
761         }
762         sid_to_fstring(sid_str, &domain_sid);
763         d_printf("SID for local machine %s is: %s\n", global_myname(), sid_str);
764
765         if (!secrets_fetch_domain_sid(c->opt_workgroup, &domain_sid)) {
766                 d_fprintf(stderr, "Could not fetch domain SID\n");
767                 return 1;
768         }
769
770         sid_to_fstring(sid_str, &domain_sid);
771         d_printf("SID for domain %s is: %s\n", c->opt_workgroup, sid_str);
772
773         return 0;
774 }
775
776 #ifdef WITH_FAKE_KASERVER
777
778 int net_help_afs(struct net_context *c, int argc, const char **argv)
779 {
780         d_printf("  net afs key filename\n"
781                  "\tImports a OpenAFS KeyFile into our secrets.tdb\n\n");
782         d_printf("  net afs impersonate <user> <cell>\n"
783                  "\tCreates a token for user@cell\n\n");
784         return -1;
785 }
786
787 static int net_afs_key(struct net_context *c, int argc, const char **argv)
788 {
789         int fd;
790         struct afs_keyfile keyfile;
791
792         if (argc != 2) {
793                 d_printf("usage: 'net afs key <keyfile> cell'\n");
794                 return -1;
795         }
796
797         if (!secrets_init()) {
798                 d_fprintf(stderr, "Could not open secrets.tdb\n");
799                 return -1;
800         }
801
802         if ((fd = open(argv[0], O_RDONLY, 0)) < 0) {
803                 d_fprintf(stderr, "Could not open %s\n", argv[0]);
804                 return -1;
805         }
806
807         if (read(fd, &keyfile, sizeof(keyfile)) != sizeof(keyfile)) {
808                 d_fprintf(stderr, "Could not read keyfile\n");
809                 return -1;
810         }
811
812         if (!secrets_store_afs_keyfile(argv[1], &keyfile)) {
813                 d_fprintf(stderr, "Could not write keyfile to secrets.tdb\n");
814                 return -1;
815         }
816
817         return 0;
818 }
819
820 static int net_afs_impersonate(struct net_context *c, int argc,
821                                const char **argv)
822 {
823         char *token;
824
825         if (argc != 2) {
826                 fprintf(stderr, "Usage: net afs impersonate <user> <cell>\n");
827                 exit(1);
828         }
829
830         token = afs_createtoken_str(argv[0], argv[1]);
831
832         if (token == NULL) {
833                 fprintf(stderr, "Could not create token\n");
834                 exit(1);
835         }
836
837         if (!afs_settoken_str(token)) {
838                 fprintf(stderr, "Could not set token into kernel\n");
839                 exit(1);
840         }
841
842         printf("Success: %s@%s\n", argv[0], argv[1]);
843         return 0;
844 }
845
846 static int net_afs(struct net_context *c, int argc, const char **argv)
847 {
848         struct functable func[] = {
849                 {"key", net_afs_key},
850                 {"impersonate", net_afs_impersonate},
851                 {"help", net_help_afs},
852                 {NULL, NULL}
853         };
854         return net_run_function(c, argc, argv, func, net_help_afs);
855 }
856
857 #endif /* WITH_FAKE_KASERVER */
858
859 static bool search_maxrid(struct pdb_search *search, const char *type,
860                           uint32 *max_rid)
861 {
862         struct samr_displayentry *entries;
863         uint32 i, num_entries;
864
865         if (search == NULL) {
866                 d_fprintf(stderr, "get_maxrid: Could not search %s\n", type);
867                 return false;
868         }
869
870         num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries);
871         for (i=0; i<num_entries; i++)
872                 *max_rid = MAX(*max_rid, entries[i].rid);
873         pdb_search_destroy(search);
874         return true;
875 }
876
877 static uint32 get_maxrid(void)
878 {
879         uint32 max_rid = 0;
880
881         if (!search_maxrid(pdb_search_users(0), "users", &max_rid))
882                 return 0;
883
884         if (!search_maxrid(pdb_search_groups(), "groups", &max_rid))
885                 return 0;
886
887         if (!search_maxrid(pdb_search_aliases(get_global_sam_sid()),
888                            "aliases", &max_rid))
889                 return 0;
890
891         return max_rid;
892 }
893
894 static int net_maxrid(struct net_context *c, int argc, const char **argv)
895 {
896         uint32 rid;
897
898         if (argc != 0) {
899                 DEBUG(0, ("usage: net maxrid\n"));
900                 return 1;
901         }
902
903         if ((rid = get_maxrid()) == 0) {
904                 DEBUG(0, ("can't get current maximum rid\n"));
905                 return 1;
906         }
907
908         d_printf("Currently used maximum rid: %d\n", rid);
909
910         return 0;
911 }
912
913 /****************************************************************************
914 ****************************************************************************/
915
916 const char *net_prompt_pass(struct net_context *c, const char *user)
917 {
918         char *prompt = NULL;
919         const char *pass = NULL;
920
921         if (c->opt_password) {
922                 return c->opt_password;
923         }
924
925         if (c->opt_machine_pass) {
926                 return NULL;
927         }
928
929         asprintf(&prompt, "Enter %s's password:", user);
930         if (!prompt) {
931                 return NULL;
932         }
933
934         pass = getpass(prompt);
935         SAFE_FREE(prompt);
936
937         return pass;
938 }
939
940 /* main function table */
941 static struct functable net_func[] = {
942         {"RPC", net_rpc},
943         {"RAP", net_rap},
944         {"ADS", net_ads},
945
946         /* eventually these should auto-choose the transport ... */
947         {"FILE", net_file},
948         {"SHARE", net_share},
949         {"SESSION", net_rap_session},
950         {"SERVER", net_rap_server},
951         {"DOMAIN", net_rap_domain},
952         {"PRINTQ", net_rap_printq},
953         {"USER", net_user},
954         {"GROUP", net_group},
955         {"GROUPMAP", net_groupmap},
956         {"SAM", net_sam},
957         {"VALIDATE", net_rap_validate},
958         {"GROUPMEMBER", net_rap_groupmember},
959         {"ADMIN", net_rap_admin},
960         {"SERVICE", net_rap_service},
961         {"PASSWORD", net_rap_password},
962         {"CHANGETRUSTPW", net_changetrustpw},
963         {"CHANGESECRETPW", net_changesecretpw},
964         {"TIME", net_time},
965         {"LOOKUP", net_lookup},
966         {"JOIN", net_join},
967         {"DOM", net_dom},
968         {"CACHE", net_cache},
969         {"GETLOCALSID", net_getlocalsid},
970         {"SETLOCALSID", net_setlocalsid},
971         {"SETDOMAINSID", net_setdomainsid},
972         {"GETDOMAINSID", net_getdomainsid},
973         {"MAXRID", net_maxrid},
974         {"IDMAP", net_idmap},
975         {"STATUS", net_status},
976         {"USERSHARE", net_usershare},
977         {"USERSIDLIST", net_usersidlist},
978         {"CONF", net_conf},
979         {"REGISTRY", net_registry},
980 #ifdef WITH_FAKE_KASERVER
981         {"AFS", net_afs},
982 #endif
983
984         {"HELP", net_help},
985         {NULL, NULL}
986 };
987
988
989 /****************************************************************************
990   main program
991 ****************************************************************************/
992  int main(int argc, const char **argv)
993 {
994         int opt,i;
995         char *p;
996         int rc = 0;
997         int argc_new = 0;
998         const char ** argv_new;
999         poptContext pc;
1000         TALLOC_CTX *frame = talloc_stackframe();
1001         struct net_context *c = talloc_zero(frame, struct net_context);
1002
1003         struct poptOption long_options[] = {
1004                 {"help",        'h', POPT_ARG_NONE,   0, 'h'},
1005                 {"workgroup",   'w', POPT_ARG_STRING, &c->opt_target_workgroup},
1006                 {"user",        'U', POPT_ARG_STRING, &c->opt_user_name, 'U'},
1007                 {"ipaddress",   'I', POPT_ARG_STRING, 0,'I'},
1008                 {"port",        'p', POPT_ARG_INT,    &c->opt_port},
1009                 {"myname",      'n', POPT_ARG_STRING, &c->opt_requester_name},
1010                 {"server",      'S', POPT_ARG_STRING, &c->opt_host},
1011                 {"encrypt",     'e', POPT_ARG_NONE,   NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
1012                 {"container",   'c', POPT_ARG_STRING, &c->opt_container},
1013                 {"comment",     'C', POPT_ARG_STRING, &c->opt_comment},
1014                 {"maxusers",    'M', POPT_ARG_INT,    &c->opt_maxusers},
1015                 {"flags",       'F', POPT_ARG_INT,    &c->opt_flags},
1016                 {"long",        'l', POPT_ARG_NONE,   &c->opt_long_list_entries},
1017                 {"reboot",      'r', POPT_ARG_NONE,   &c->opt_reboot},
1018                 {"force",       'f', POPT_ARG_NONE,   &c->opt_force},
1019                 {"stdin",       'i', POPT_ARG_NONE,   &c->opt_stdin},
1020                 {"timeout",     't', POPT_ARG_INT,    &c->opt_timeout},
1021                 {"machine-pass",'P', POPT_ARG_NONE,   &c->opt_machine_pass},
1022                 {"myworkgroup", 'W', POPT_ARG_STRING, &c->opt_workgroup},
1023                 {"verbose",     'v', POPT_ARG_NONE,   &c->opt_verbose},
1024                 {"test",        'T', POPT_ARG_NONE,   &c->opt_testmode},
1025                 /* Options for 'net groupmap set' */
1026                 {"local",       'L', POPT_ARG_NONE,   &c->opt_localgroup},
1027                 {"domain",      'D', POPT_ARG_NONE,   &c->opt_domaingroup},
1028                 {"ntname",      'N', POPT_ARG_STRING, &c->opt_newntname},
1029                 {"rid",         'R', POPT_ARG_INT,    &c->opt_rid},
1030                 /* Options for 'net rpc share migrate' */
1031                 {"acls",        0, POPT_ARG_NONE,     &c->opt_acls},
1032                 {"attrs",       0, POPT_ARG_NONE,     &c->opt_attrs},
1033                 {"timestamps",  0, POPT_ARG_NONE,     &c->opt_timestamps},
1034                 {"exclude",     'X', POPT_ARG_STRING, &c->opt_exclude},
1035                 {"destination", 0, POPT_ARG_STRING,   &c->opt_destination},
1036                 {"tallocreport", 0, POPT_ARG_NONE,    &c->do_talloc_report},
1037
1038                 POPT_COMMON_SAMBA
1039                 { 0, 0, 0, 0}
1040         };
1041
1042
1043         zero_addr(&c->opt_dest_ip);
1044
1045         load_case_tables();
1046
1047         /* set default debug level to 0 regardless of what smb.conf sets */
1048         DEBUGLEVEL_CLASS[DBGC_ALL] = 0;
1049         dbf = x_stderr;
1050
1051         pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
1052                             POPT_CONTEXT_KEEP_FIRST);
1053
1054         while((opt = poptGetNextOpt(pc)) != -1) {
1055                 switch (opt) {
1056                 case 'h':
1057                         net_help(c, argc, argv);
1058                         exit(0);
1059                         break;
1060                 case 'e':
1061                         c->smb_encrypt = true;
1062                         break;
1063                 case 'I':
1064                         if (!interpret_string_addr(&c->opt_dest_ip,
1065                                                 poptGetOptArg(pc), 0)) {
1066                                 d_fprintf(stderr, "\nInvalid ip address specified\n");
1067                         } else {
1068                                 c->opt_have_ip = true;
1069                         }
1070                         break;
1071                 case 'U':
1072                         c->opt_user_specified = true;
1073                         c->opt_user_name = SMB_STRDUP(c->opt_user_name);
1074                         p = strchr(c->opt_user_name,'%');
1075                         if (p) {
1076                                 *p = 0;
1077                                 c->opt_password = p+1;
1078                         }
1079                         break;
1080                 default:
1081                         d_fprintf(stderr, "\nInvalid option %s: %s\n",
1082                                  poptBadOption(pc, 0), poptStrerror(opt));
1083                         net_help(c, argc, argv);
1084                         exit(1);
1085                 }
1086         }
1087
1088         /*
1089          * Don't load debug level from smb.conf. It should be
1090          * set by cmdline arg or remain default (0)
1091          */
1092         c->AllowDebugChange = false;
1093         lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
1094
1095         argv_new = (const char **)poptGetArgs(pc);
1096
1097         argc_new = argc;
1098         for (i=0; i<argc; i++) {
1099                 if (argv_new[i] == NULL) {
1100                         argc_new = i;
1101                         break;
1102                 }
1103         }
1104
1105         if (c->do_talloc_report) {
1106                 talloc_enable_leak_report();
1107         }
1108
1109         if (c->opt_requester_name) {
1110                 set_global_myname(c->opt_requester_name);
1111         }
1112
1113         if (!c->opt_user_name && getenv("LOGNAME")) {
1114                 c->opt_user_name = getenv("LOGNAME");
1115         }
1116
1117         if (!c->opt_workgroup) {
1118                 c->opt_workgroup = smb_xstrdup(lp_workgroup());
1119         }
1120
1121         if (!c->opt_target_workgroup) {
1122                 c->opt_target_workgroup = smb_xstrdup(lp_workgroup());
1123         }
1124
1125         if (!init_names())
1126                 exit(1);
1127
1128         load_interfaces();
1129
1130         /* this makes sure that when we do things like call scripts,
1131            that it won't assert becouse we are not root */
1132         sec_init();
1133
1134         if (c->opt_machine_pass) {
1135                 /* it is very useful to be able to make ads queries as the
1136                    machine account for testing purposes and for domain leave */
1137
1138                 net_use_krb_machine_account(c);
1139         }
1140
1141         if (!c->opt_password) {
1142                 c->opt_password = getenv("PASSWD");
1143         }
1144
1145         rc = net_run_function(c, argc_new-1, argv_new+1, net_func, net_help);
1146
1147         DEBUG(2,("return code = %d\n", rc));
1148
1149         libnetapi_free(c->netapi_ctx);
1150
1151         TALLOC_FREE(frame);
1152         return rc;
1153 }