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