c641e61c5cbd44d605d700412f361bb4779b9960
[kai/samba.git] / source3 / utils / net_util.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  Helper routines for net
4  *  Copyright (C) Volker Lendecke 2006
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #include "includes.h"
22 #include "utils/net.h"
23
24 NTSTATUS net_rpc_lookup_name(struct net_context *c,
25                              TALLOC_CTX *mem_ctx, struct cli_state *cli,
26                              const char *name, const char **ret_domain,
27                              const char **ret_name, DOM_SID *ret_sid,
28                              enum lsa_SidType *ret_type)
29 {
30         struct rpc_pipe_client *lsa_pipe;
31         POLICY_HND pol;
32         NTSTATUS result = NT_STATUS_OK;
33         const char **dom_names;
34         DOM_SID *sids;
35         enum lsa_SidType *types;
36
37         ZERO_STRUCT(pol);
38
39         lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
40         if (lsa_pipe == NULL) {
41                 d_fprintf(stderr, "Could not initialise lsa pipe\n");
42                 return result;
43         }
44
45         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
46                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
47                                         &pol);
48         if (!NT_STATUS_IS_OK(result)) {
49                 d_fprintf(stderr, "open_policy failed: %s\n",
50                           nt_errstr(result));
51                 return result;
52         }
53
54         result = rpccli_lsa_lookup_names(lsa_pipe, mem_ctx, &pol, 1,
55                                          &name, &dom_names, 1, &sids, &types);
56
57         if (!NT_STATUS_IS_OK(result)) {
58                 /* This can happen easily, don't log an error */
59                 goto done;
60         }
61
62         if (ret_domain != NULL) {
63                 *ret_domain = dom_names[0];
64         }
65         if (ret_name != NULL) {
66                 *ret_name = talloc_strdup(mem_ctx, name);
67         }
68         if (ret_sid != NULL) {
69                 sid_copy(ret_sid, &sids[0]);
70         }
71         if (ret_type != NULL) {
72                 *ret_type = types[0];
73         }
74
75  done:
76         if (is_valid_policy_hnd(&pol)) {
77                 rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
78         }
79         TALLOC_FREE(lsa_pipe);
80
81         return result;
82 }
83
84 /****************************************************************************
85  Connect to \\server\service.
86 ****************************************************************************/
87
88 NTSTATUS connect_to_service(struct net_context *c,
89                                         struct cli_state **cli_ctx,
90                                         struct sockaddr_storage *server_ss,
91                                         const char *server_name,
92                                         const char *service_name,
93                                         const char *service_type)
94 {
95         NTSTATUS nt_status;
96
97         c->opt_password = net_prompt_pass(c, c->opt_user_name);
98         if (!c->opt_password) {
99                 return NT_STATUS_NO_MEMORY;
100         }
101
102         nt_status = cli_full_connection(cli_ctx, NULL, server_name,
103                                         server_ss, c->opt_port,
104                                         service_name, service_type,
105                                         c->opt_user_name, c->opt_workgroup,
106                                         c->opt_password, 0, Undefined, NULL);
107         if (!NT_STATUS_IS_OK(nt_status)) {
108                 d_fprintf(stderr, "Could not connect to server %s\n", server_name);
109
110                 /* Display a nicer message depending on the result */
111
112                 if (NT_STATUS_V(nt_status) ==
113                     NT_STATUS_V(NT_STATUS_LOGON_FAILURE))
114                         d_fprintf(stderr, "The username or password was not correct.\n");
115
116                 if (NT_STATUS_V(nt_status) ==
117                     NT_STATUS_V(NT_STATUS_ACCOUNT_LOCKED_OUT))
118                         d_fprintf(stderr, "The account was locked out.\n");
119
120                 if (NT_STATUS_V(nt_status) ==
121                     NT_STATUS_V(NT_STATUS_ACCOUNT_DISABLED))
122                         d_fprintf(stderr, "The account was disabled.\n");
123                 return nt_status;
124         }
125
126         if (c->smb_encrypt) {
127                 nt_status = cli_force_encryption(*cli_ctx,
128                                         c->opt_user_name,
129                                         c->opt_password,
130                                         c->opt_workgroup);
131
132                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_NOT_SUPPORTED)) {
133                         d_printf("Encryption required and "
134                                 "server that doesn't support "
135                                 "UNIX extensions - failing connect\n");
136                 } else if (NT_STATUS_EQUAL(nt_status,NT_STATUS_UNKNOWN_REVISION)) {
137                         d_printf("Encryption required and "
138                                 "can't get UNIX CIFS extensions "
139                                 "version from server.\n");
140                 } else if (NT_STATUS_EQUAL(nt_status,NT_STATUS_UNSUPPORTED_COMPRESSION)) {
141                         d_printf("Encryption required and "
142                                 "share %s doesn't support "
143                                 "encryption.\n", service_name);
144                 } else if (!NT_STATUS_IS_OK(nt_status)) {
145                         d_printf("Encryption required and "
146                                 "setup failed with error %s.\n",
147                                 nt_errstr(nt_status));
148                 }
149
150                 if (!NT_STATUS_IS_OK(nt_status)) {
151                         cli_shutdown(*cli_ctx);
152                         *cli_ctx = NULL;
153                 }
154         }
155
156         return nt_status;
157 }
158
159 /****************************************************************************
160  Connect to \\server\ipc$.
161 ****************************************************************************/
162
163 NTSTATUS connect_to_ipc(struct net_context *c,
164                         struct cli_state **cli_ctx,
165                         struct sockaddr_storage *server_ss,
166                         const char *server_name)
167 {
168         return connect_to_service(c, cli_ctx, server_ss, server_name, "IPC$",
169                                   "IPC");
170 }
171
172 /****************************************************************************
173  Connect to \\server\ipc$ anonymously.
174 ****************************************************************************/
175
176 NTSTATUS connect_to_ipc_anonymous(struct net_context *c,
177                                 struct cli_state **cli_ctx,
178                                 struct sockaddr_storage *server_ss,
179                                 const char *server_name)
180 {
181         NTSTATUS nt_status;
182
183         nt_status = cli_full_connection(cli_ctx, c->opt_requester_name,
184                                         server_name, server_ss, c->opt_port,
185                                         "IPC$", "IPC",
186                                         "", "",
187                                         "", 0, Undefined, NULL);
188
189         if (NT_STATUS_IS_OK(nt_status)) {
190                 return nt_status;
191         } else {
192                 DEBUG(1,("Cannot connect to server (anonymously).  Error was %s\n", nt_errstr(nt_status)));
193                 return nt_status;
194         }
195 }
196
197 /****************************************************************************
198  Return malloced user@realm for krb5 login.
199 ****************************************************************************/
200
201 static char *get_user_and_realm(const char *username)
202 {
203         char *user_and_realm = NULL;
204
205         if (!username) {
206                 return NULL;
207         }
208         if (strchr_m(username, '@')) {
209                 user_and_realm = SMB_STRDUP(username);
210         } else {
211                 if (asprintf(&user_and_realm, "%s@%s", username, lp_realm()) == -1) {
212                         user_and_realm = NULL;
213                 }
214         }
215         return user_and_realm;
216 }
217
218 /****************************************************************************
219  Connect to \\server\ipc$ using KRB5.
220 ****************************************************************************/
221
222 NTSTATUS connect_to_ipc_krb5(struct net_context *c,
223                         struct cli_state **cli_ctx,
224                         struct sockaddr_storage *server_ss,
225                         const char *server_name)
226 {
227         NTSTATUS nt_status;
228         char *user_and_realm = NULL;
229
230         /* FIXME: Should get existing kerberos ticket if possible. */
231         c->opt_password = net_prompt_pass(c, c->opt_user_name);
232         if (!c->opt_password) {
233                 return NT_STATUS_NO_MEMORY;
234         }
235
236         user_and_realm = get_user_and_realm(c->opt_user_name);
237         if (!user_and_realm) {
238                 return NT_STATUS_NO_MEMORY;
239         }
240
241         nt_status = cli_full_connection(cli_ctx, NULL, server_name,
242                                         server_ss, c->opt_port,
243                                         "IPC$", "IPC",
244                                         user_and_realm, c->opt_workgroup,
245                                         c->opt_password,
246                                         CLI_FULL_CONNECTION_USE_KERBEROS,
247                                         Undefined, NULL);
248
249         SAFE_FREE(user_and_realm);
250
251         if (!NT_STATUS_IS_OK(nt_status)) {
252                 DEBUG(1,("Cannot connect to server using kerberos.  Error was %s\n", nt_errstr(nt_status)));
253                 return nt_status;
254         }
255
256         if (c->smb_encrypt) {
257                 nt_status = cli_cm_force_encryption(*cli_ctx,
258                                         user_and_realm,
259                                         c->opt_password,
260                                         c->opt_workgroup,
261                                         "IPC$");
262                 if (!NT_STATUS_IS_OK(nt_status)) {
263                         cli_shutdown(*cli_ctx);
264                         *cli_ctx = NULL;
265                 }
266         }
267
268         return nt_status;
269 }
270
271 /**
272  * Connect a server and open a given pipe
273  *
274  * @param cli_dst               A cli_state
275  * @param pipe                  The pipe to open
276  * @param got_pipe              boolean that stores if we got a pipe
277  *
278  * @return Normal NTSTATUS return.
279  **/
280 NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst,
281                           struct rpc_pipe_client **pp_pipe_hnd, int pipe_num)
282 {
283         NTSTATUS nt_status;
284         char *server_name = SMB_STRDUP("127.0.0.1");
285         struct cli_state *cli_tmp = NULL;
286         struct rpc_pipe_client *pipe_hnd = NULL;
287
288         if (server_name == NULL) {
289                 return NT_STATUS_NO_MEMORY;
290         }
291
292         if (c->opt_destination) {
293                 SAFE_FREE(server_name);
294                 if ((server_name = SMB_STRDUP(c->opt_destination)) == NULL) {
295                         return NT_STATUS_NO_MEMORY;
296                 }
297         }
298
299         /* make a connection to a named pipe */
300         nt_status = connect_to_ipc(c, &cli_tmp, NULL, server_name);
301         if (!NT_STATUS_IS_OK(nt_status)) {
302                 SAFE_FREE(server_name);
303                 return nt_status;
304         }
305
306         pipe_hnd = cli_rpc_pipe_open_noauth(cli_tmp, pipe_num, &nt_status);
307         if (!pipe_hnd) {
308                 DEBUG(0, ("couldn't not initialize pipe\n"));
309                 cli_shutdown(cli_tmp);
310                 SAFE_FREE(server_name);
311                 return nt_status;
312         }
313
314         *cli_dst = cli_tmp;
315         *pp_pipe_hnd = pipe_hnd;
316         SAFE_FREE(server_name);
317
318         return nt_status;
319 }
320
321 /****************************************************************************
322  Use the local machine account (krb) and password for this session.
323 ****************************************************************************/
324
325 int net_use_krb_machine_account(struct net_context *c)
326 {
327         char *user_name = NULL;
328
329         if (!secrets_init()) {
330                 d_fprintf(stderr, "ERROR: Unable to open secrets database\n");
331                 exit(1);
332         }
333
334         c->opt_password = secrets_fetch_machine_password(
335                                 c->opt_target_workgroup, NULL, NULL);
336         if (asprintf(&user_name, "%s$@%s", global_myname(), lp_realm()) == -1) {
337                 return -1;
338         }
339         c->opt_user_name = user_name;
340         return 0;
341 }
342
343 /****************************************************************************
344  Use the machine account name and password for this session.
345 ****************************************************************************/
346
347 int net_use_machine_account(struct net_context *c)
348 {
349         char *user_name = NULL;
350
351         if (!secrets_init()) {
352                 d_fprintf(stderr, "ERROR: Unable to open secrets database\n");
353                 exit(1);
354         }
355
356         c->opt_password = secrets_fetch_machine_password(
357                                 c->opt_target_workgroup, NULL, NULL);
358         if (asprintf(&user_name, "%s$", global_myname()) == -1) {
359                 return -1;
360         }
361         c->opt_user_name = user_name;
362         return 0;
363 }
364
365 bool net_find_server(struct net_context *c,
366                         const char *domain,
367                         unsigned flags,
368                         struct sockaddr_storage *server_ss,
369                         char **server_name)
370 {
371         const char *d = domain ? domain : c->opt_target_workgroup;
372
373         if (c->opt_host) {
374                 *server_name = SMB_STRDUP(c->opt_host);
375         }
376
377         if (c->opt_have_ip) {
378                 *server_ss = c->opt_dest_ip;
379                 if (!*server_name) {
380                         char addr[INET6_ADDRSTRLEN];
381                         print_sockaddr(addr, sizeof(addr), &c->opt_dest_ip);
382                         *server_name = SMB_STRDUP(addr);
383                 }
384         } else if (*server_name) {
385                 /* resolve the IP address */
386                 if (!resolve_name(*server_name, server_ss, 0x20))  {
387                         DEBUG(1,("Unable to resolve server name\n"));
388                         return false;
389                 }
390         } else if (flags & NET_FLAGS_PDC) {
391                 fstring dc_name;
392                 struct sockaddr_storage pdc_ss;
393
394                 if (!get_pdc_ip(d, &pdc_ss)) {
395                         DEBUG(1,("Unable to resolve PDC server address\n"));
396                         return false;
397                 }
398
399                 if (is_zero_addr(&pdc_ss)) {
400                         return false;
401                 }
402
403                 if (!name_status_find(d, 0x1b, 0x20, &pdc_ss, dc_name)) {
404                         return false;
405                 }
406
407                 *server_name = SMB_STRDUP(dc_name);
408                 *server_ss = pdc_ss;
409         } else if (flags & NET_FLAGS_DMB) {
410                 struct sockaddr_storage msbrow_ss;
411                 char addr[INET6_ADDRSTRLEN];
412
413                 /*  if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */
414                 if (!resolve_name(d, &msbrow_ss, 0x1B))  {
415                         DEBUG(1,("Unable to resolve domain browser via name lookup\n"));
416                         return false;
417                 }
418                 *server_ss = msbrow_ss;
419                 print_sockaddr(addr, sizeof(addr), server_ss);
420                 *server_name = SMB_STRDUP(addr);
421         } else if (flags & NET_FLAGS_MASTER) {
422                 struct sockaddr_storage brow_ss;
423                 char addr[INET6_ADDRSTRLEN];
424                 if (!resolve_name(d, &brow_ss, 0x1D))  {
425                                 /* go looking for workgroups */
426                         DEBUG(1,("Unable to resolve master browser via name lookup\n"));
427                         return false;
428                 }
429                 *server_ss = brow_ss;
430                 print_sockaddr(addr, sizeof(addr), server_ss);
431                 *server_name = SMB_STRDUP(addr);
432         } else if (!(flags & NET_FLAGS_LOCALHOST_DEFAULT_INSANE)) {
433                 if (!interpret_string_addr(server_ss,
434                                         "127.0.0.1", AI_NUMERICHOST)) {
435                         DEBUG(1,("Unable to resolve 127.0.0.1\n"));
436                         return false;
437                 }
438                 *server_name = SMB_STRDUP("127.0.0.1");
439         }
440
441         if (!*server_name) {
442                 DEBUG(1,("no server to connect to\n"));
443                 return false;
444         }
445
446         return true;
447 }
448
449 bool net_find_pdc(struct sockaddr_storage *server_ss,
450                 fstring server_name,
451                 const char *domain_name)
452 {
453         if (!get_pdc_ip(domain_name, server_ss)) {
454                 return false;
455         }
456         if (is_zero_addr(server_ss)) {
457                 return false;
458         }
459
460         if (!name_status_find(domain_name, 0x1b, 0x20, server_ss, server_name)) {
461                 return false;
462         }
463
464         return true;
465 }
466
467 NTSTATUS net_make_ipc_connection(struct net_context *c, unsigned flags,
468                                  struct cli_state **pcli)
469 {
470         return net_make_ipc_connection_ex(c, NULL, NULL, NULL, flags, pcli);
471 }
472
473 NTSTATUS net_make_ipc_connection_ex(struct net_context *c ,const char *domain,
474                                     const char *server,
475                                     struct sockaddr_storage *pss,
476                                     unsigned flags, struct cli_state **pcli)
477 {
478         char *server_name = NULL;
479         struct sockaddr_storage server_ss;
480         struct cli_state *cli = NULL;
481         NTSTATUS nt_status;
482
483         if ( !server || !pss ) {
484                 if (!net_find_server(c, domain, flags, &server_ss,
485                                      &server_name)) {
486                         d_fprintf(stderr, "Unable to find a suitable server\n");
487                         nt_status = NT_STATUS_UNSUCCESSFUL;
488                         goto done;
489                 }
490         } else {
491                 server_name = SMB_STRDUP( server );
492                 server_ss = *pss;
493         }
494
495         if (flags & NET_FLAGS_ANONYMOUS) {
496                 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
497                                                      server_name);
498         } else {
499                 nt_status = connect_to_ipc(c, &cli, &server_ss,
500                                            server_name);
501         }
502
503         /* store the server in the affinity cache if it was a PDC */
504
505         if ( (flags & NET_FLAGS_PDC) && NT_STATUS_IS_OK(nt_status) )
506                 saf_store( cli->server_domain, cli->desthost );
507
508         SAFE_FREE(server_name);
509         if (!NT_STATUS_IS_OK(nt_status)) {
510                 d_fprintf(stderr, "Connection failed: %s\n",
511                           nt_errstr(nt_status));
512                 cli = NULL;
513         }
514
515 done:
516         if (pcli != NULL) {
517                 *pcli = cli;
518         }
519         return nt_status;
520 }
521
522 /****************************************************************************
523 ****************************************************************************/
524
525 const char *net_prompt_pass(struct net_context *c, const char *user)
526 {
527         char *prompt = NULL;
528         const char *pass = NULL;
529
530         if (c->opt_password) {
531                 return c->opt_password;
532         }
533
534         if (c->opt_machine_pass) {
535                 return NULL;
536         }
537
538         asprintf(&prompt, "Enter %s's password:", user);
539         if (!prompt) {
540                 return NULL;
541         }
542
543         pass = getpass(prompt);
544         SAFE_FREE(prompt);
545
546         return pass;
547 }
548
549 /*
550   run a function from a function table. If not found then
551   call the specified usage function
552 */
553 int net_run_function(struct net_context *c, int argc, const char **argv,
554                      struct functable *table,
555                      int (*usage_fn)(struct net_context *c,
556                                      int argc, const char **argv))
557 {
558         int i;
559
560         if (argc < 1) {
561                 d_printf("\nUsage: \n");
562                 return usage_fn(c, argc, argv);
563         }
564         for (i=0; table[i].funcname; i++) {
565                 if (StrCaseCmp(argv[0], table[i].funcname) == 0)
566                         return table[i].fn(c, argc-1, argv+1);
567         }
568         d_fprintf(stderr, "No command: %s\n", argv[0]);
569         return usage_fn(c, argc, argv);
570 }
571
572 /*
573  * run a function from a function table.
574  */
575 int net_run_function2(struct net_context *c, int argc, const char **argv,
576                       const char *whoami, struct functable2 *table)
577 {
578         int i;
579
580         if (argc != 0) {
581                 for (i=0; table[i].funcname; i++) {
582                         if (StrCaseCmp(argv[0], table[i].funcname) == 0)
583                                 return table[i].fn(c, argc-1, argv+1);
584                 }
585         }
586
587         for (i=0; table[i].funcname != NULL; i++) {
588                 d_printf("%s %-15s %s\n", whoami, table[i].funcname,
589                          table[i].helptext);
590         }
591
592         return -1;
593 }
594
595 int net_run_function3(struct net_context *c, int argc, const char **argv,
596                       const char *whoami, struct functable3 *table)
597 {
598         int i;
599         if (argc != 0) {
600                 for (i=0; table[i].funcname != NULL; i++) {
601                         if (StrCaseCmp(argv[0], table[i].funcname) == 0)
602                                 return table[i].fn(c, argc-1, argv+1);
603                 }
604         }
605
606         if (c->display_usage == false) {
607                 d_fprintf(stderr, "Invalid command: %s %s\n", whoami,
608                           (argc > 0)?argv[0]:"");
609         }
610         d_printf("Usage:\n");
611         for (i=0; table[i].funcname != NULL; i++) {
612                 if(c->display_usage == false)
613                         d_printf("%s %-15s %s\n", whoami, table[i].funcname,
614                                  table[i].description);
615                 else
616                         d_printf("%s\n", table[i].usage);
617         }
618
619         return c->display_usage?0:-1;
620 }
621