net: Move "net join" handling into a separate file.
[Samba.git] / source / utils / net.c
blobcc038e21782046a9eccbda34b62d194303778d3c
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)
10 Originally written by Steve and Jim. Largely rewritten by tridge in
11 November 2001.
13 Reworked again by abartlet in December 2001
15 Another overhaul, moving functionality into plug-ins loaded on demand by Kai
16 in May 2008.
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.
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.
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/>. */
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 /*****************************************************/
43 #include "includes.h"
44 #include "utils/net.h"
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 /***********************************************************************/
54 #define YES_STRING "Yes"
55 #define NO_STRING "No"
57 /***********************************************************************/
58 /* end of internationalization section */
59 /***********************************************************************/
61 uint32 get_sec_channel_type(const char *param)
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();
83 run a function from a function table. If not found then
84 call the specified usage function
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))
91 int i;
93 if (argc < 1) {
94 d_printf("\nUsage: \n");
95 return usage_fn(c, argc, argv);
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);
101 d_fprintf(stderr, "No command: %s\n", argv[0]);
102 return usage_fn(c, argc, argv);
106 * run a function from a function table.
108 int net_run_function2(struct net_context *c, int argc, const char **argv,
109 const char *whoami, struct functable2 *table)
111 int i;
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);
120 for (i=0; table[i].funcname != NULL; i++) {
121 d_printf("%s %-15s %s\n", whoami, table[i].funcname,
122 table[i].helptext);
125 return -1;
128 /****************************************************************************
129 Connect to \\server\service.
130 ****************************************************************************/
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)
139 NTSTATUS nt_status;
141 c->opt_password = net_prompt_pass(c, c->opt_user_name);
142 if (!c->opt_password) {
143 return NT_STATUS_NO_MEMORY;
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);
154 /* Display a nicer message depending on the result */
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");
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");
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;
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);
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));
194 if (!NT_STATUS_IS_OK(nt_status)) {
195 cli_shutdown(*cli_ctx);
196 *cli_ctx = NULL;
200 return nt_status;
203 /****************************************************************************
204 Connect to \\server\ipc$.
205 ****************************************************************************/
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)
212 return connect_to_service(c, cli_ctx, server_ss, server_name, "IPC$",
213 "IPC");
216 /****************************************************************************
217 Connect to \\server\ipc$ anonymously.
218 ****************************************************************************/
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)
225 NTSTATUS nt_status;
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);
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;
241 /****************************************************************************
242 Return malloced user@realm for krb5 login.
243 ****************************************************************************/
245 static char *get_user_and_realm(const char *username)
247 char *user_and_realm = NULL;
249 if (!username) {
250 return NULL;
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;
259 return user_and_realm;
262 /****************************************************************************
263 Connect to \\server\ipc$ using KRB5.
264 ****************************************************************************/
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)
271 NTSTATUS nt_status;
272 char *user_and_realm = NULL;
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;
280 user_and_realm = get_user_and_realm(c->opt_user_name);
281 if (!user_and_realm) {
282 return NT_STATUS_NO_MEMORY;
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);
293 SAFE_FREE(user_and_realm);
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;
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;
312 return nt_status;
316 * Connect a server and open a given pipe
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
322 * @return Normal NTSTATUS return.
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)
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;
332 if (server_name == NULL) {
333 return NT_STATUS_NO_MEMORY;
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;
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;
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;
358 *cli_dst = cli_tmp;
359 *pp_pipe_hnd = pipe_hnd;
360 SAFE_FREE(server_name);
362 return nt_status;
365 /****************************************************************************
366 Use the local machine account (krb) and password for this session.
367 ****************************************************************************/
369 int net_use_krb_machine_account(struct net_context *c)
371 char *user_name = NULL;
373 if (!secrets_init()) {
374 d_fprintf(stderr, "ERROR: Unable to open secrets database\n");
375 exit(1);
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;
383 c->opt_user_name = user_name;
384 return 0;
387 /****************************************************************************
388 Use the machine account name and password for this session.
389 ****************************************************************************/
391 int net_use_machine_account(struct net_context *c)
393 char *user_name = NULL;
395 if (!secrets_init()) {
396 d_fprintf(stderr, "ERROR: Unable to open secrets database\n");
397 exit(1);
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;
405 c->opt_user_name = user_name;
406 return 0;
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)
415 const char *d = domain ? domain : c->opt_target_workgroup;
417 if (c->opt_host) {
418 *server_name = SMB_STRDUP(c->opt_host);
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);
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;
434 } else if (flags & NET_FLAGS_PDC) {
435 fstring dc_name;
436 struct sockaddr_storage pdc_ss;
438 if (!get_pdc_ip(d, &pdc_ss)) {
439 DEBUG(1,("Unable to resolve PDC server address\n"));
440 return false;
443 if (is_zero_addr(&pdc_ss)) {
444 return false;
447 if (!name_status_find(d, 0x1b, 0x20, &pdc_ss, dc_name)) {
448 return false;
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];
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;
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;
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;
482 *server_name = SMB_STRDUP("127.0.0.1");
485 if (!*server_name) {
486 DEBUG(1,("no server to connect to\n"));
487 return false;
490 return true;
493 bool net_find_pdc(struct sockaddr_storage *server_ss,
494 fstring server_name,
495 const char *domain_name)
497 if (!get_pdc_ip(domain_name, server_ss)) {
498 return false;
500 if (is_zero_addr(server_ss)) {
501 return false;
504 if (!name_status_find(domain_name, 0x1b, 0x20, server_ss, server_name)) {
505 return false;
508 return true;
511 NTSTATUS net_make_ipc_connection(struct net_context *c, unsigned flags,
512 struct cli_state **pcli)
514 return net_make_ipc_connection_ex(c, NULL, NULL, NULL, flags, pcli);
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)
522 char *server_name = NULL;
523 struct sockaddr_storage server_ss;
524 struct cli_state *cli = NULL;
525 NTSTATUS nt_status;
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;
534 } else {
535 server_name = SMB_STRDUP( server );
536 server_ss = *pss;
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);
547 /* store the server in the affinity cache if it was a PDC */
549 if ( (flags & NET_FLAGS_PDC) && NT_STATUS_IS_OK(nt_status) )
550 saf_store( cli->server_domain, cli->desthost );
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;
559 done:
560 if (pcli != NULL) {
561 *pcli = cli;
563 return nt_status;
566 static int net_user(struct net_context *c, int argc, const char **argv)
568 if (net_ads_check(c) == 0)
569 return net_ads_user(c, argc, argv);
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);
575 return net_rap_user(c, argc, argv);
578 static int net_group(struct net_context *c, int argc, const char **argv)
580 if (net_ads_check(c) == 0)
581 return net_ads_group(c, argc, argv);
583 if (argc == 0 && net_rpc_check(c, NET_FLAGS_PDC))
584 return net_rpc_group(c,argc, argv);
586 return net_rap_group(c, argc, argv);
589 static int net_changetrustpw(struct net_context *c, int argc, const char **argv)
591 if (net_ads_check_our_domain(c) == 0)
592 return net_ads_changetrustpw(c, argc, argv);
594 return net_rpc_changetrustpw(c, argc, argv);
597 static void set_line_buffering(FILE *f)
599 setvbuf(f, NULL, _IOLBF, 0);
602 static int net_changesecretpw(struct net_context *c, int argc,
603 const char **argv)
605 char *trust_pw;
606 uint32 sec_channel_type = SEC_CHAN_WKSTA;
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);
615 trust_pw = get_pass("Enter machine password: ", c->opt_stdin);
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;
621 else {
622 d_printf("Modified trust account password in secrets database\n");
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");
631 return 0;
634 static int net_share(struct net_context *c, int argc, const char **argv)
636 if (net_rpc_check(c, 0))
637 return net_rpc_share(c, argc, argv);
638 return net_rap_share(c, argc, argv);
641 static int net_file(struct net_context *c, int argc, const char **argv)
643 if (net_rpc_check(c, 0))
644 return net_rpc_file(c, argc, argv);
645 return net_rap_file(c, argc, argv);
649 Retrieve our local SID or the SID for the specified name
651 static int net_getlocalsid(struct net_context *c, int argc, const char **argv)
653 DOM_SID sid;
654 const char *name;
655 fstring sid_str;
657 if (argc >= 1) {
658 name = argv[0];
660 else {
661 name = global_myname();
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"));
669 /* first check to see if we can even access secrets, so we don't
670 panic when we can't. */
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;
677 /* Generate one, if it doesn't exist */
678 get_global_sam_sid();
680 if (!secrets_fetch_domain_sid(name, &sid)) {
681 DEBUG(0, ("Can't fetch domain SID for name: %s\n", name));
682 return 1;
684 sid_to_fstring(sid_str, &sid);
685 d_printf("SID for domain %s is: %s\n", name, sid_str);
686 return 0;
689 static int net_setlocalsid(struct net_context *c, int argc, const char **argv)
691 DOM_SID sid;
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;
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;
706 return 0;
709 static int net_setdomainsid(struct net_context *c, int argc, const char **argv)
711 DOM_SID sid;
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;
721 if (!secrets_store_domain_sid(lp_workgroup(), &sid)) {
722 DEBUG(0,("Can't store domain SID.\n"));
723 return 1;
726 return 0;
729 static int net_getdomainsid(struct net_context *c, int argc, const char **argv)
731 DOM_SID domain_sid;
732 fstring sid_str;
734 if (argc > 0) {
735 d_printf("usage: net getdomainsid\n");
736 return 1;
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"));
746 /* first check to see if we can even access secrets, so we don't
747 panic when we can't. */
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;
755 /* Generate one, if it doesn't exist */
756 get_global_sam_sid();
758 if (!secrets_fetch_domain_sid(global_myname(), &domain_sid)) {
759 d_fprintf(stderr, "Could not fetch local SID\n");
760 return 1;
762 sid_to_fstring(sid_str, &domain_sid);
763 d_printf("SID for local machine %s is: %s\n", global_myname(), sid_str);
765 if (!secrets_fetch_domain_sid(c->opt_workgroup, &domain_sid)) {
766 d_fprintf(stderr, "Could not fetch domain SID\n");
767 return 1;
770 sid_to_fstring(sid_str, &domain_sid);
771 d_printf("SID for domain %s is: %s\n", c->opt_workgroup, sid_str);
773 return 0;
776 #ifdef WITH_FAKE_KASERVER
778 int net_help_afs(struct net_context *c, int argc, const char **argv)
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;
787 static int net_afs_key(struct net_context *c, int argc, const char **argv)
789 int fd;
790 struct afs_keyfile keyfile;
792 if (argc != 2) {
793 d_printf("usage: 'net afs key <keyfile> cell'\n");
794 return -1;
797 if (!secrets_init()) {
798 d_fprintf(stderr, "Could not open secrets.tdb\n");
799 return -1;
802 if ((fd = open(argv[0], O_RDONLY, 0)) < 0) {
803 d_fprintf(stderr, "Could not open %s\n", argv[0]);
804 return -1;
807 if (read(fd, &keyfile, sizeof(keyfile)) != sizeof(keyfile)) {
808 d_fprintf(stderr, "Could not read keyfile\n");
809 return -1;
812 if (!secrets_store_afs_keyfile(argv[1], &keyfile)) {
813 d_fprintf(stderr, "Could not write keyfile to secrets.tdb\n");
814 return -1;
817 return 0;
820 static int net_afs_impersonate(struct net_context *c, int argc,
821 const char **argv)
823 char *token;
825 if (argc != 2) {
826 fprintf(stderr, "Usage: net afs impersonate <user> <cell>\n");
827 exit(1);
830 token = afs_createtoken_str(argv[0], argv[1]);
832 if (token == NULL) {
833 fprintf(stderr, "Could not create token\n");
834 exit(1);
837 if (!afs_settoken_str(token)) {
838 fprintf(stderr, "Could not set token into kernel\n");
839 exit(1);
842 printf("Success: %s@%s\n", argv[0], argv[1]);
843 return 0;
846 static int net_afs(struct net_context *c, int argc, const char **argv)
848 struct functable func[] = {
849 {"key", net_afs_key},
850 {"impersonate", net_afs_impersonate},
851 {"help", net_help_afs},
852 {NULL, NULL}
854 return net_run_function(c, argc, argv, func, net_help_afs);
857 #endif /* WITH_FAKE_KASERVER */
859 static bool search_maxrid(struct pdb_search *search, const char *type,
860 uint32 *max_rid)
862 struct samr_displayentry *entries;
863 uint32 i, num_entries;
865 if (search == NULL) {
866 d_fprintf(stderr, "get_maxrid: Could not search %s\n", type);
867 return false;
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;
877 static uint32 get_maxrid(void)
879 uint32 max_rid = 0;
881 if (!search_maxrid(pdb_search_users(0), "users", &max_rid))
882 return 0;
884 if (!search_maxrid(pdb_search_groups(), "groups", &max_rid))
885 return 0;
887 if (!search_maxrid(pdb_search_aliases(get_global_sam_sid()),
888 "aliases", &max_rid))
889 return 0;
891 return max_rid;
894 static int net_maxrid(struct net_context *c, int argc, const char **argv)
896 uint32 rid;
898 if (argc != 0) {
899 DEBUG(0, ("usage: net maxrid\n"));
900 return 1;
903 if ((rid = get_maxrid()) == 0) {
904 DEBUG(0, ("can't get current maximum rid\n"));
905 return 1;
908 d_printf("Currently used maximum rid: %d\n", rid);
910 return 0;
913 /****************************************************************************
914 ****************************************************************************/
916 const char *net_prompt_pass(struct net_context *c, const char *user)
918 char *prompt = NULL;
919 const char *pass = NULL;
921 if (c->opt_password) {
922 return c->opt_password;
925 if (c->opt_machine_pass) {
926 return NULL;
929 asprintf(&prompt, "Enter %s's password:", user);
930 if (!prompt) {
931 return NULL;
934 pass = getpass(prompt);
935 SAFE_FREE(prompt);
937 return pass;
940 /* main function table */
941 static struct functable net_func[] = {
942 {"RPC", net_rpc},
943 {"RAP", net_rap},
944 {"ADS", net_ads},
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
984 {"HELP", net_help},
985 {NULL, NULL}
989 /****************************************************************************
990 main program
991 ****************************************************************************/
992 int main(int argc, const char **argv)
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);
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},
1038 POPT_COMMON_SAMBA
1039 { 0, 0, 0, 0}
1043 zero_addr(&c->opt_dest_ip);
1045 load_case_tables();
1047 /* set default debug level to 0 regardless of what smb.conf sets */
1048 DEBUGLEVEL_CLASS[DBGC_ALL] = 0;
1049 dbf = x_stderr;
1051 pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
1052 POPT_CONTEXT_KEEP_FIRST);
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;
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;
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);
1089 * Don't load debug level from smb.conf. It should be
1090 * set by cmdline arg or remain default (0)
1092 c->AllowDebugChange = false;
1093 lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
1095 argv_new = (const char **)poptGetArgs(pc);
1097 argc_new = argc;
1098 for (i=0; i<argc; i++) {
1099 if (argv_new[i] == NULL) {
1100 argc_new = i;
1101 break;
1105 if (c->do_talloc_report) {
1106 talloc_enable_leak_report();
1109 if (c->opt_requester_name) {
1110 set_global_myname(c->opt_requester_name);
1113 if (!c->opt_user_name && getenv("LOGNAME")) {
1114 c->opt_user_name = getenv("LOGNAME");
1117 if (!c->opt_workgroup) {
1118 c->opt_workgroup = smb_xstrdup(lp_workgroup());
1121 if (!c->opt_target_workgroup) {
1122 c->opt_target_workgroup = smb_xstrdup(lp_workgroup());
1125 if (!init_names())
1126 exit(1);
1128 load_interfaces();
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();
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 */
1138 net_use_krb_machine_account(c);
1141 if (!c->opt_password) {
1142 c->opt_password = getenv("PASSWD");
1145 rc = net_run_function(c, argc_new-1, argv_new+1, net_func, net_help);
1147 DEBUG(2,("return code = %d\n", rc));
1149 libnetapi_free(c->netapi_ctx);
1151 TALLOC_FREE(frame);
1152 return rc;