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