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