net: Split out "net 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_changetrustpw(struct net_context *c, int argc, const char **argv)
567 {
568         if (net_ads_check_our_domain(c) == 0)
569                 return net_ads_changetrustpw(c, argc, argv);
570
571         return net_rpc_changetrustpw(c, argc, argv);
572 }
573
574 static void set_line_buffering(FILE *f)
575 {
576         setvbuf(f, NULL, _IOLBF, 0);
577 }
578
579 static int net_changesecretpw(struct net_context *c, int argc,
580                               const char **argv)
581 {
582         char *trust_pw;
583         uint32 sec_channel_type = SEC_CHAN_WKSTA;
584
585         if(c->opt_force) {
586                 if (c->opt_stdin) {
587                         set_line_buffering(stdin);
588                         set_line_buffering(stdout);
589                         set_line_buffering(stderr);
590                 }
591
592                 trust_pw = get_pass("Enter machine password: ", c->opt_stdin);
593
594                 if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) {
595                             d_fprintf(stderr, "Unable to write the machine account password in the secrets database");
596                             return 1;
597                 }
598                 else {
599                     d_printf("Modified trust account password in secrets database\n");
600                 }
601         }
602         else {
603                 d_printf("Machine account password change requires the -f flag.\n");
604                 d_printf("Do NOT use this function unless you know what it does!\n");
605                 d_printf("This function will change the ADS Domain member machine account password in the secrets.tdb file!\n");
606         }
607
608         return 0;
609 }
610
611 static int net_share(struct net_context *c, int argc, const char **argv)
612 {
613         if (net_rpc_check(c, 0))
614                 return net_rpc_share(c, argc, argv);
615         return net_rap_share(c, argc, argv);
616 }
617
618 /*
619  Retrieve our local SID or the SID for the specified name
620  */
621 static int net_getlocalsid(struct net_context *c, int argc, const char **argv)
622 {
623         DOM_SID sid;
624         const char *name;
625         fstring sid_str;
626
627         if (argc >= 1) {
628                 name = argv[0];
629         }
630         else {
631                 name = global_myname();
632         }
633
634         if(!initialize_password_db(false, NULL)) {
635                 DEBUG(0, ("WARNING: Could not open passdb - local sid may not reflect passdb\n"
636                           "backend knowledge (such as the sid stored in LDAP)\n"));
637         }
638
639         /* first check to see if we can even access secrets, so we don't
640            panic when we can't. */
641
642         if (!secrets_init()) {
643                 d_fprintf(stderr, "Unable to open secrets.tdb.  Can't fetch domain SID for name: %s\n", name);
644                 return 1;
645         }
646
647         /* Generate one, if it doesn't exist */
648         get_global_sam_sid();
649
650         if (!secrets_fetch_domain_sid(name, &sid)) {
651                 DEBUG(0, ("Can't fetch domain SID for name: %s\n", name));
652                 return 1;
653         }
654         sid_to_fstring(sid_str, &sid);
655         d_printf("SID for domain %s is: %s\n", name, sid_str);
656         return 0;
657 }
658
659 static int net_setlocalsid(struct net_context *c, int argc, const char **argv)
660 {
661         DOM_SID sid;
662
663         if ( (argc != 1)
664              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
665              || (!string_to_sid(&sid, argv[0]))
666              || (sid.num_auths != 4)) {
667                 d_printf("usage: net setlocalsid S-1-5-21-x-y-z\n");
668                 return 1;
669         }
670
671         if (!secrets_store_domain_sid(global_myname(), &sid)) {
672                 DEBUG(0,("Can't store domain SID as a pdc/bdc.\n"));
673                 return 1;
674         }
675
676         return 0;
677 }
678
679 static int net_setdomainsid(struct net_context *c, int argc, const char **argv)
680 {
681         DOM_SID sid;
682
683         if ( (argc != 1)
684              || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
685              || (!string_to_sid(&sid, argv[0]))
686              || (sid.num_auths != 4)) {
687                 d_printf("usage: net setdomainsid S-1-5-21-x-y-z\n");
688                 return 1;
689         }
690
691         if (!secrets_store_domain_sid(lp_workgroup(), &sid)) {
692                 DEBUG(0,("Can't store domain SID.\n"));
693                 return 1;
694         }
695
696         return 0;
697 }
698
699 static int net_getdomainsid(struct net_context *c, int argc, const char **argv)
700 {
701         DOM_SID domain_sid;
702         fstring sid_str;
703
704         if (argc > 0) {
705                 d_printf("usage: net getdomainsid\n");
706                 return 1;
707         }
708
709         if(!initialize_password_db(false, NULL)) {
710                 DEBUG(0, ("WARNING: Could not open passdb - domain SID may "
711                           "not reflect passdb\n"
712                           "backend knowledge (such as the SID stored in "
713                           "LDAP)\n"));
714         }
715
716         /* first check to see if we can even access secrets, so we don't
717            panic when we can't. */
718
719         if (!secrets_init()) {
720                 d_fprintf(stderr, "Unable to open secrets.tdb.  Can't fetch domain"
721                                   "SID for name: %s\n", get_global_sam_name());
722                 return 1;
723         }
724
725         /* Generate one, if it doesn't exist */
726         get_global_sam_sid();
727
728         if (!secrets_fetch_domain_sid(global_myname(), &domain_sid)) {
729                 d_fprintf(stderr, "Could not fetch local SID\n");
730                 return 1;
731         }
732         sid_to_fstring(sid_str, &domain_sid);
733         d_printf("SID for local machine %s is: %s\n", global_myname(), sid_str);
734
735         if (!secrets_fetch_domain_sid(c->opt_workgroup, &domain_sid)) {
736                 d_fprintf(stderr, "Could not fetch domain SID\n");
737                 return 1;
738         }
739
740         sid_to_fstring(sid_str, &domain_sid);
741         d_printf("SID for domain %s is: %s\n", c->opt_workgroup, sid_str);
742
743         return 0;
744 }
745
746 #ifdef WITH_FAKE_KASERVER
747
748 int net_help_afs(struct net_context *c, int argc, const char **argv)
749 {
750         d_printf("  net afs key filename\n"
751                  "\tImports a OpenAFS KeyFile into our secrets.tdb\n\n");
752         d_printf("  net afs impersonate <user> <cell>\n"
753                  "\tCreates a token for user@cell\n\n");
754         return -1;
755 }
756
757 static int net_afs_key(struct net_context *c, int argc, const char **argv)
758 {
759         int fd;
760         struct afs_keyfile keyfile;
761
762         if (argc != 2) {
763                 d_printf("usage: 'net afs key <keyfile> cell'\n");
764                 return -1;
765         }
766
767         if (!secrets_init()) {
768                 d_fprintf(stderr, "Could not open secrets.tdb\n");
769                 return -1;
770         }
771
772         if ((fd = open(argv[0], O_RDONLY, 0)) < 0) {
773                 d_fprintf(stderr, "Could not open %s\n", argv[0]);
774                 return -1;
775         }
776
777         if (read(fd, &keyfile, sizeof(keyfile)) != sizeof(keyfile)) {
778                 d_fprintf(stderr, "Could not read keyfile\n");
779                 return -1;
780         }
781
782         if (!secrets_store_afs_keyfile(argv[1], &keyfile)) {
783                 d_fprintf(stderr, "Could not write keyfile to secrets.tdb\n");
784                 return -1;
785         }
786
787         return 0;
788 }
789
790 static int net_afs_impersonate(struct net_context *c, int argc,
791                                const char **argv)
792 {
793         char *token;
794
795         if (argc != 2) {
796                 fprintf(stderr, "Usage: net afs impersonate <user> <cell>\n");
797                 exit(1);
798         }
799
800         token = afs_createtoken_str(argv[0], argv[1]);
801
802         if (token == NULL) {
803                 fprintf(stderr, "Could not create token\n");
804                 exit(1);
805         }
806
807         if (!afs_settoken_str(token)) {
808                 fprintf(stderr, "Could not set token into kernel\n");
809                 exit(1);
810         }
811
812         printf("Success: %s@%s\n", argv[0], argv[1]);
813         return 0;
814 }
815
816 static int net_afs(struct net_context *c, int argc, const char **argv)
817 {
818         struct functable func[] = {
819                 {"key", net_afs_key},
820                 {"impersonate", net_afs_impersonate},
821                 {"help", net_help_afs},
822                 {NULL, NULL}
823         };
824         return net_run_function(c, argc, argv, func, net_help_afs);
825 }
826
827 #endif /* WITH_FAKE_KASERVER */
828
829 static bool search_maxrid(struct pdb_search *search, const char *type,
830                           uint32 *max_rid)
831 {
832         struct samr_displayentry *entries;
833         uint32 i, num_entries;
834
835         if (search == NULL) {
836                 d_fprintf(stderr, "get_maxrid: Could not search %s\n", type);
837                 return false;
838         }
839
840         num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries);
841         for (i=0; i<num_entries; i++)
842                 *max_rid = MAX(*max_rid, entries[i].rid);
843         pdb_search_destroy(search);
844         return true;
845 }
846
847 static uint32 get_maxrid(void)
848 {
849         uint32 max_rid = 0;
850
851         if (!search_maxrid(pdb_search_users(0), "users", &max_rid))
852                 return 0;
853
854         if (!search_maxrid(pdb_search_groups(), "groups", &max_rid))
855                 return 0;
856
857         if (!search_maxrid(pdb_search_aliases(get_global_sam_sid()),
858                            "aliases", &max_rid))
859                 return 0;
860
861         return max_rid;
862 }
863
864 static int net_maxrid(struct net_context *c, int argc, const char **argv)
865 {
866         uint32 rid;
867
868         if (argc != 0) {
869                 DEBUG(0, ("usage: net maxrid\n"));
870                 return 1;
871         }
872
873         if ((rid = get_maxrid()) == 0) {
874                 DEBUG(0, ("can't get current maximum rid\n"));
875                 return 1;
876         }
877
878         d_printf("Currently used maximum rid: %d\n", rid);
879
880         return 0;
881 }
882
883 /****************************************************************************
884 ****************************************************************************/
885
886 const char *net_prompt_pass(struct net_context *c, const char *user)
887 {
888         char *prompt = NULL;
889         const char *pass = NULL;
890
891         if (c->opt_password) {
892                 return c->opt_password;
893         }
894
895         if (c->opt_machine_pass) {
896                 return NULL;
897         }
898
899         asprintf(&prompt, "Enter %s's password:", user);
900         if (!prompt) {
901                 return NULL;
902         }
903
904         pass = getpass(prompt);
905         SAFE_FREE(prompt);
906
907         return pass;
908 }
909
910 /* main function table */
911 static struct functable net_func[] = {
912         {"RPC", net_rpc},
913         {"RAP", net_rap},
914         {"ADS", net_ads},
915
916         /* eventually these should auto-choose the transport ... */
917         {"FILE", net_file},
918         {"SHARE", net_share},
919         {"SESSION", net_rap_session},
920         {"SERVER", net_rap_server},
921         {"DOMAIN", net_rap_domain},
922         {"PRINTQ", net_rap_printq},
923         {"USER", net_user},
924         {"GROUP", net_group},
925         {"GROUPMAP", net_groupmap},
926         {"SAM", net_sam},
927         {"VALIDATE", net_rap_validate},
928         {"GROUPMEMBER", net_rap_groupmember},
929         {"ADMIN", net_rap_admin},
930         {"SERVICE", net_rap_service},
931         {"PASSWORD", net_rap_password},
932         {"CHANGETRUSTPW", net_changetrustpw},
933         {"CHANGESECRETPW", net_changesecretpw},
934         {"TIME", net_time},
935         {"LOOKUP", net_lookup},
936         {"JOIN", net_join},
937         {"DOM", net_dom},
938         {"CACHE", net_cache},
939         {"GETLOCALSID", net_getlocalsid},
940         {"SETLOCALSID", net_setlocalsid},
941         {"SETDOMAINSID", net_setdomainsid},
942         {"GETDOMAINSID", net_getdomainsid},
943         {"MAXRID", net_maxrid},
944         {"IDMAP", net_idmap},
945         {"STATUS", net_status},
946         {"USERSHARE", net_usershare},
947         {"USERSIDLIST", net_usersidlist},
948         {"CONF", net_conf},
949         {"REGISTRY", net_registry},
950 #ifdef WITH_FAKE_KASERVER
951         {"AFS", net_afs},
952 #endif
953
954         {"HELP", net_help},
955         {NULL, NULL}
956 };
957
958
959 /****************************************************************************
960   main program
961 ****************************************************************************/
962  int main(int argc, const char **argv)
963 {
964         int opt,i;
965         char *p;
966         int rc = 0;
967         int argc_new = 0;
968         const char ** argv_new;
969         poptContext pc;
970         TALLOC_CTX *frame = talloc_stackframe();
971         struct net_context *c = talloc_zero(frame, struct net_context);
972
973         struct poptOption long_options[] = {
974                 {"help",        'h', POPT_ARG_NONE,   0, 'h'},
975                 {"workgroup",   'w', POPT_ARG_STRING, &c->opt_target_workgroup},
976                 {"user",        'U', POPT_ARG_STRING, &c->opt_user_name, 'U'},
977                 {"ipaddress",   'I', POPT_ARG_STRING, 0,'I'},
978                 {"port",        'p', POPT_ARG_INT,    &c->opt_port},
979                 {"myname",      'n', POPT_ARG_STRING, &c->opt_requester_name},
980                 {"server",      'S', POPT_ARG_STRING, &c->opt_host},
981                 {"encrypt",     'e', POPT_ARG_NONE,   NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
982                 {"container",   'c', POPT_ARG_STRING, &c->opt_container},
983                 {"comment",     'C', POPT_ARG_STRING, &c->opt_comment},
984                 {"maxusers",    'M', POPT_ARG_INT,    &c->opt_maxusers},
985                 {"flags",       'F', POPT_ARG_INT,    &c->opt_flags},
986                 {"long",        'l', POPT_ARG_NONE,   &c->opt_long_list_entries},
987                 {"reboot",      'r', POPT_ARG_NONE,   &c->opt_reboot},
988                 {"force",       'f', POPT_ARG_NONE,   &c->opt_force},
989                 {"stdin",       'i', POPT_ARG_NONE,   &c->opt_stdin},
990                 {"timeout",     't', POPT_ARG_INT,    &c->opt_timeout},
991                 {"machine-pass",'P', POPT_ARG_NONE,   &c->opt_machine_pass},
992                 {"myworkgroup", 'W', POPT_ARG_STRING, &c->opt_workgroup},
993                 {"verbose",     'v', POPT_ARG_NONE,   &c->opt_verbose},
994                 {"test",        'T', POPT_ARG_NONE,   &c->opt_testmode},
995                 /* Options for 'net groupmap set' */
996                 {"local",       'L', POPT_ARG_NONE,   &c->opt_localgroup},
997                 {"domain",      'D', POPT_ARG_NONE,   &c->opt_domaingroup},
998                 {"ntname",      'N', POPT_ARG_STRING, &c->opt_newntname},
999                 {"rid",         'R', POPT_ARG_INT,    &c->opt_rid},
1000                 /* Options for 'net rpc share migrate' */
1001                 {"acls",        0, POPT_ARG_NONE,     &c->opt_acls},
1002                 {"attrs",       0, POPT_ARG_NONE,     &c->opt_attrs},
1003                 {"timestamps",  0, POPT_ARG_NONE,     &c->opt_timestamps},
1004                 {"exclude",     'X', POPT_ARG_STRING, &c->opt_exclude},
1005                 {"destination", 0, POPT_ARG_STRING,   &c->opt_destination},
1006                 {"tallocreport", 0, POPT_ARG_NONE,    &c->do_talloc_report},
1007
1008                 POPT_COMMON_SAMBA
1009                 { 0, 0, 0, 0}
1010         };
1011
1012
1013         zero_addr(&c->opt_dest_ip);
1014
1015         load_case_tables();
1016
1017         /* set default debug level to 0 regardless of what smb.conf sets */
1018         DEBUGLEVEL_CLASS[DBGC_ALL] = 0;
1019         dbf = x_stderr;
1020
1021         pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
1022                             POPT_CONTEXT_KEEP_FIRST);
1023
1024         while((opt = poptGetNextOpt(pc)) != -1) {
1025                 switch (opt) {
1026                 case 'h':
1027                         net_help(c, argc, argv);
1028                         exit(0);
1029                         break;
1030                 case 'e':
1031                         c->smb_encrypt = true;
1032                         break;
1033                 case 'I':
1034                         if (!interpret_string_addr(&c->opt_dest_ip,
1035                                                 poptGetOptArg(pc), 0)) {
1036                                 d_fprintf(stderr, "\nInvalid ip address specified\n");
1037                         } else {
1038                                 c->opt_have_ip = true;
1039                         }
1040                         break;
1041                 case 'U':
1042                         c->opt_user_specified = true;
1043                         c->opt_user_name = SMB_STRDUP(c->opt_user_name);
1044                         p = strchr(c->opt_user_name,'%');
1045                         if (p) {
1046                                 *p = 0;
1047                                 c->opt_password = p+1;
1048                         }
1049                         break;
1050                 default:
1051                         d_fprintf(stderr, "\nInvalid option %s: %s\n",
1052                                  poptBadOption(pc, 0), poptStrerror(opt));
1053                         net_help(c, argc, argv);
1054                         exit(1);
1055                 }
1056         }
1057
1058         /*
1059          * Don't load debug level from smb.conf. It should be
1060          * set by cmdline arg or remain default (0)
1061          */
1062         c->AllowDebugChange = false;
1063         lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
1064
1065         argv_new = (const char **)poptGetArgs(pc);
1066
1067         argc_new = argc;
1068         for (i=0; i<argc; i++) {
1069                 if (argv_new[i] == NULL) {
1070                         argc_new = i;
1071                         break;
1072                 }
1073         }
1074
1075         if (c->do_talloc_report) {
1076                 talloc_enable_leak_report();
1077         }
1078
1079         if (c->opt_requester_name) {
1080                 set_global_myname(c->opt_requester_name);
1081         }
1082
1083         if (!c->opt_user_name && getenv("LOGNAME")) {
1084                 c->opt_user_name = getenv("LOGNAME");
1085         }
1086
1087         if (!c->opt_workgroup) {
1088                 c->opt_workgroup = smb_xstrdup(lp_workgroup());
1089         }
1090
1091         if (!c->opt_target_workgroup) {
1092                 c->opt_target_workgroup = smb_xstrdup(lp_workgroup());
1093         }
1094
1095         if (!init_names())
1096                 exit(1);
1097
1098         load_interfaces();
1099
1100         /* this makes sure that when we do things like call scripts,
1101            that it won't assert becouse we are not root */
1102         sec_init();
1103
1104         if (c->opt_machine_pass) {
1105                 /* it is very useful to be able to make ads queries as the
1106                    machine account for testing purposes and for domain leave */
1107
1108                 net_use_krb_machine_account(c);
1109         }
1110
1111         if (!c->opt_password) {
1112                 c->opt_password = getenv("PASSWD");
1113         }
1114
1115         rc = net_run_function(c, argc_new-1, argv_new+1, net_func, net_help);
1116
1117         DEBUG(2,("return code = %d\n", rc));
1118
1119         libnetapi_free(c->netapi_ctx);
1120
1121         TALLOC_FREE(frame);
1122         return rc;
1123 }