s3:rpcclient: Add FALL_THROUGH statements in rpcclient.c
[samba.git] / source3 / rpcclient / rpcclient.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Tim Potter 2000-2001
6    Copyright (C) Martin Pool 2003
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "../libcli/auth/netlogon_creds_cli.h"
24 #include "popt_common.h"
25 #include "rpcclient.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../librpc/gen_ndr/ndr_lsa_c.h"
28 #include "rpc_client/cli_lsarpc.h"
29 #include "../librpc/gen_ndr/ndr_netlogon.h"
30 #include "rpc_client/cli_netlogon.h"
31 #include "../libcli/smbreadline/smbreadline.h"
32 #include "../libcli/security/security.h"
33 #include "passdb.h"
34 #include "libsmb/libsmb.h"
35 #include "auth/gensec/gensec.h"
36 #include "../libcli/smb/smbXcli_base.h"
37 #include "messages.h"
38
39 enum pipe_auth_type_spnego {
40         PIPE_AUTH_TYPE_SPNEGO_NONE = 0,
41         PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
42         PIPE_AUTH_TYPE_SPNEGO_KRB5
43 };
44
45 struct dom_sid domain_sid;
46
47 static enum dcerpc_AuthType pipe_default_auth_type = DCERPC_AUTH_TYPE_NONE;
48 static enum pipe_auth_type_spnego pipe_default_auth_spnego_type = 0;
49 static enum dcerpc_AuthLevel pipe_default_auth_level = DCERPC_AUTH_LEVEL_NONE;
50 static unsigned int timeout = 0;
51 static enum dcerpc_transport_t default_transport = NCACN_NP;
52
53 struct messaging_context *rpcclient_msg_ctx;
54 struct cli_state *rpcclient_cli_state;
55 struct netlogon_creds_cli_context *rpcclient_netlogon_creds;
56 static const char *rpcclient_netlogon_domain;
57
58 /* List to hold groups of commands.
59  *
60  * Commands are defined in a list of arrays: arrays are easy to
61  * statically declare, and lists are easier to dynamically extend.
62  */
63
64 static struct cmd_list {
65         struct cmd_list *prev, *next;
66         struct cmd_set *cmd_set;
67 } *cmd_list;
68
69 /****************************************************************************
70 handle completion of commands for readline
71 ****************************************************************************/
72 static char **completion_fn(const char *text, int start, int end)
73 {
74 #define MAX_COMPLETIONS 1000
75         char **matches;
76         int i, count=0;
77         struct cmd_list *commands = cmd_list;
78
79 #if 0   /* JERRY */
80         /* FIXME!!!  -- what to do when completing argument? */
81         /* for words not at the start of the line fallback 
82            to filename completion */
83         if (start) 
84                 return NULL;
85 #endif
86
87         /* make sure we have a list of valid commands */
88         if (!commands) {
89                 return NULL;
90         }
91
92         matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
93         if (!matches) {
94                 return NULL;
95         }
96
97         matches[count++] = SMB_STRDUP(text);
98         if (!matches[0]) {
99                 SAFE_FREE(matches);
100                 return NULL;
101         }
102
103         while (commands && count < MAX_COMPLETIONS-1) {
104                 if (!commands->cmd_set) {
105                         break;
106                 }
107
108                 for (i=0; commands->cmd_set[i].name; i++) {
109                         if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
110                                 (( commands->cmd_set[i].returntype == RPC_RTYPE_NTSTATUS &&
111                         commands->cmd_set[i].ntfn ) || 
112                       ( commands->cmd_set[i].returntype == RPC_RTYPE_WERROR &&
113                         commands->cmd_set[i].wfn))) {
114                                 matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
115                                 if (!matches[count]) {
116                                         for (i = 0; i < count; i++) {
117                                                 SAFE_FREE(matches[count]);
118                                         }
119                                         SAFE_FREE(matches);
120                                         return NULL;
121                                 }
122                                 count++;
123                         }
124                 }
125                 commands = commands->next;
126         }
127
128         if (count == 2) {
129                 SAFE_FREE(matches[0]);
130                 matches[0] = SMB_STRDUP(matches[1]);
131         }
132         matches[count] = NULL;
133         return matches;
134 }
135
136 static char *next_command (char **cmdstr)
137 {
138         char *command;
139         char                    *p;
140
141         if (!cmdstr || !(*cmdstr))
142                 return NULL;
143
144         p = strchr_m(*cmdstr, ';');
145         if (p)
146                 *p = '\0';
147         command = SMB_STRDUP(*cmdstr);
148         if (p)
149                 *cmdstr = p + 1;
150         else
151                 *cmdstr = NULL;
152
153         return command;
154 }
155
156 /* Fetch the SID for this computer */
157
158 static void fetch_machine_sid(struct cli_state *cli)
159 {
160         struct policy_handle pol;
161         NTSTATUS result = NT_STATUS_OK, status;
162         static bool got_domain_sid;
163         TALLOC_CTX *mem_ctx;
164         struct rpc_pipe_client *lsapipe = NULL;
165         union lsa_PolicyInformation *info = NULL;
166         struct dcerpc_binding_handle *b;
167
168         if (got_domain_sid) return;
169
170         if (!(mem_ctx=talloc_init("fetch_machine_sid"))) {
171                 DEBUG(0,("fetch_machine_sid: talloc_init returned NULL!\n"));
172                 goto error;
173         }
174
175         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
176                                           &lsapipe);
177         if (!NT_STATUS_IS_OK(result)) {
178                 fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) );
179                 goto error;
180         }
181
182         b = lsapipe->binding_handle;
183
184         result = rpccli_lsa_open_policy(lsapipe, mem_ctx, True, 
185                                      SEC_FLAG_MAXIMUM_ALLOWED,
186                                      &pol);
187         if (!NT_STATUS_IS_OK(result)) {
188                 goto error;
189         }
190
191         status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
192                                             &pol,
193                                             LSA_POLICY_INFO_ACCOUNT_DOMAIN,
194                                             &info,
195                                             &result);
196         if (!NT_STATUS_IS_OK(status)) {
197                 result = status;
198                 goto error;
199         }
200         if (!NT_STATUS_IS_OK(result)) {
201                 goto error;
202         }
203
204         got_domain_sid = True;
205         sid_copy(&domain_sid, info->account_domain.sid);
206
207         dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
208         TALLOC_FREE(lsapipe);
209         talloc_destroy(mem_ctx);
210
211         return;
212
213  error:
214
215         if (lsapipe) {
216                 TALLOC_FREE(lsapipe);
217         }
218
219         fprintf(stderr, "could not obtain sid from server\n");
220
221         if (!NT_STATUS_IS_OK(result)) {
222                 fprintf(stderr, "error: %s\n", nt_errstr(result));
223         }
224
225         exit(1);
226 }
227
228 /* List the available commands on a given pipe */
229
230 static NTSTATUS cmd_listcommands(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
231                                  int argc, const char **argv)
232 {
233         struct cmd_list *tmp;
234         struct cmd_set *tmp_set;
235         int i;
236
237         /* Usage */
238
239         if (argc != 2) {
240                 printf("Usage: %s <pipe>\n", argv[0]);
241                 return NT_STATUS_OK;
242         }
243
244         /* Help on one command */
245
246         for (tmp = cmd_list; tmp; tmp = tmp->next) 
247         {
248                 tmp_set = tmp->cmd_set;
249
250                 if (!strcasecmp_m(argv[1], tmp_set->name))
251                 {
252                         printf("Available commands on the %s pipe:\n\n", tmp_set->name);
253
254                         i = 0;
255                         tmp_set++;
256                         while(tmp_set->name) {
257                                 printf("%30s", tmp_set->name);
258                                 tmp_set++;
259                                 i++;
260                                 if (i%3 == 0)
261                                         printf("\n");
262                         }
263
264                         /* drop out of the loop */
265                         break;
266                 }
267         }
268         printf("\n\n");
269
270         return NT_STATUS_OK;
271 }
272
273 /* Display help on commands */
274
275 static NTSTATUS cmd_help(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
276                          int argc, const char **argv)
277 {
278         struct cmd_list *tmp;
279         struct cmd_set *tmp_set;
280
281         /* Usage */
282
283         if (argc > 2) {
284                 printf("Usage: %s [command]\n", argv[0]);
285                 return NT_STATUS_OK;
286         }
287
288         /* Help on one command */
289
290         if (argc == 2) {
291                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
292
293                         tmp_set = tmp->cmd_set;
294
295                         while(tmp_set->name) {
296                                 if (strequal(argv[1], tmp_set->name)) {
297                                         if (tmp_set->usage &&
298                                             tmp_set->usage[0])
299                                                 printf("%s\n", tmp_set->usage);
300                                         else
301                                                 printf("No help for %s\n", tmp_set->name);
302
303                                         return NT_STATUS_OK;
304                                 }
305
306                                 tmp_set++;
307                         }
308                 }
309
310                 printf("No such command: %s\n", argv[1]);
311                 return NT_STATUS_OK;
312         }
313
314         /* List all commands */
315
316         for (tmp = cmd_list; tmp; tmp = tmp->next) {
317
318                 tmp_set = tmp->cmd_set;
319
320                 while(tmp_set->name) {
321
322                         printf("%15s\t\t%s\n", tmp_set->name,
323                                tmp_set->description ? tmp_set->description:
324                                "");
325
326                         tmp_set++;
327                 }
328         }
329
330         return NT_STATUS_OK;
331 }
332
333 /* Change the debug level */
334
335 static NTSTATUS cmd_debuglevel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
336                                int argc, const char **argv)
337 {
338         if (argc > 2) {
339                 printf("Usage: %s [debuglevel]\n", argv[0]);
340                 return NT_STATUS_OK;
341         }
342
343         if (argc == 2) {
344                 lp_set_cmdline("log level", argv[1]);
345         }
346
347         printf("debuglevel is %d\n", DEBUGLEVEL);
348
349         return NT_STATUS_OK;
350 }
351
352 static NTSTATUS cmd_quit(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
353                          int argc, const char **argv)
354 {
355         exit(0);
356         return NT_STATUS_OK; /* NOTREACHED */
357 }
358
359 static NTSTATUS cmd_set_ss_level(void)
360 {
361         struct cmd_list *tmp;
362
363         /* Close any existing connections not at this level. */
364
365         for (tmp = cmd_list; tmp; tmp = tmp->next) {
366                 struct cmd_set *tmp_set;
367
368                 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
369                         if (tmp_set->rpc_pipe == NULL) {
370                                 continue;
371                         }
372
373                         if ((tmp_set->rpc_pipe->auth->auth_type
374                              != pipe_default_auth_type)
375                             || (tmp_set->rpc_pipe->auth->auth_level
376                                 != pipe_default_auth_level)) {
377                                 TALLOC_FREE(tmp_set->rpc_pipe);
378                                 tmp_set->rpc_pipe = NULL;
379                         }
380                 }
381         }
382         return NT_STATUS_OK;
383 }
384
385 static NTSTATUS cmd_set_transport(void)
386 {
387         struct cmd_list *tmp;
388
389         /* Close any existing connections not at this level. */
390
391         for (tmp = cmd_list; tmp; tmp = tmp->next) {
392                 struct cmd_set *tmp_set;
393
394                 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
395                         if (tmp_set->rpc_pipe == NULL) {
396                                 continue;
397                         }
398
399                         if (tmp_set->rpc_pipe->transport->transport != default_transport) {
400                                 TALLOC_FREE(tmp_set->rpc_pipe);
401                                 tmp_set->rpc_pipe = NULL;
402                         }
403                 }
404         }
405         return NT_STATUS_OK;
406 }
407
408 static NTSTATUS cmd_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
409                          int argc, const char **argv)
410 {
411         const char *p = "[KRB5|KRB5_SPNEGO|NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]";
412         const char *type = "NTLMSSP";
413
414         pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
415         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
416
417         if (argc > 2) {
418                 printf("Usage: %s %s\n", argv[0], p);
419                 return NT_STATUS_OK;
420         }
421
422         if (argc == 2) {
423                 type = argv[1];
424                 if (strequal(type, "KRB5")) {
425                         pipe_default_auth_type = DCERPC_AUTH_TYPE_KRB5;
426                 } else if (strequal(type, "KRB5_SPNEGO")) {
427                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
428                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
429                 } else if (strequal(type, "NTLMSSP")) {
430                         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
431                 } else if (strequal(type, "NTLMSSP_SPNEGO")) {
432                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
433                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
434                 } else if (strequal(type, "SCHANNEL")) {
435                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
436                 } else {
437                         printf("unknown type %s\n", type);
438                         printf("Usage: %s %s\n", argv[0], p);
439                         return NT_STATUS_INVALID_LEVEL;
440                 }
441         }
442
443         d_printf("Setting %s - sign\n", type);
444
445         return cmd_set_ss_level();
446 }
447
448 static NTSTATUS cmd_seal(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
449                          int argc, const char **argv)
450 {
451         const char *p = "[KRB5|KRB5_SPNEGO|NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]";
452         const char *type = "NTLMSSP";
453
454         pipe_default_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
455         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
456
457         if (argc > 2) {
458                 printf("Usage: %s %s\n", argv[0], p);
459                 return NT_STATUS_OK;
460         }
461
462         if (argc == 2) {
463                 type = argv[1];
464                 if (strequal(type, "KRB5")) {
465                         pipe_default_auth_type = DCERPC_AUTH_TYPE_KRB5;
466                 } else if (strequal(type, "KRB5_SPNEGO")) {
467                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
468                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
469                 } else if (strequal(type, "NTLMSSP")) {
470                         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
471                 } else if (strequal(type, "NTLMSSP_SPNEGO")) {
472                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
473                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
474                 } else if (strequal(type, "SCHANNEL")) {
475                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
476                 } else {
477                         printf("unknown type %s\n", type);
478                         printf("Usage: %s %s\n", argv[0], p);
479                         return NT_STATUS_INVALID_LEVEL;
480                 }
481         }
482
483         d_printf("Setting %s - sign and seal\n", type);
484
485         return cmd_set_ss_level();
486 }
487
488 static NTSTATUS cmd_packet(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
489                            int argc, const char **argv)
490 {
491         const char *p = "[KRB5|KRB5_SPNEGO|NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]";
492         const char *type = "NTLMSSP";
493
494         pipe_default_auth_level = DCERPC_AUTH_LEVEL_PACKET;
495         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
496
497         if (argc > 2) {
498                 printf("Usage: %s %s\n", argv[0], p);
499                 return NT_STATUS_OK;
500         }
501
502         if (argc == 2) {
503                 type = argv[1];
504                 if (strequal(type, "KRB5")) {
505                         pipe_default_auth_type = DCERPC_AUTH_TYPE_KRB5;
506                 } else if (strequal(type, "KRB5_SPNEGO")) {
507                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
508                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
509                 } else if (strequal(type, "NTLMSSP")) {
510                         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
511                 } else if (strequal(type, "NTLMSSP_SPNEGO")) {
512                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
513                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
514                 } else if (strequal(type, "SCHANNEL")) {
515                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
516                 } else {
517                         printf("unknown type %s\n", type);
518                         printf("Usage: %s %s\n", argv[0], p);
519                         return NT_STATUS_INVALID_LEVEL;
520                 }
521         }
522
523         d_printf("Setting %s - packet\n", type);
524
525         return cmd_set_ss_level();
526 }
527
528
529 static NTSTATUS cmd_timeout(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
530                             int argc, const char **argv)
531 {
532         if (argc > 2) {
533                 printf("Usage: %s timeout\n", argv[0]);
534                 return NT_STATUS_OK;
535         }
536
537         if (argc == 2) {
538                 timeout = atoi(argv[1]);
539         }
540
541         printf("timeout is %d\n", timeout);
542
543         return NT_STATUS_OK;
544 }
545
546
547 static NTSTATUS cmd_none(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
548                          int argc, const char **argv)
549 {
550         pipe_default_auth_level = DCERPC_AUTH_LEVEL_NONE;
551         pipe_default_auth_type = DCERPC_AUTH_TYPE_NONE;
552         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
553
554         return cmd_set_ss_level();
555 }
556
557 static NTSTATUS cmd_schannel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
558                              int argc, const char **argv)
559 {
560         d_printf("Setting schannel - sign and seal\n");
561         pipe_default_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
562         pipe_default_auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
563
564         return cmd_set_ss_level();
565 }
566
567 static NTSTATUS cmd_schannel_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
568                              int argc, const char **argv)
569 {
570         d_printf("Setting schannel - sign only\n");
571         pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
572         pipe_default_auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
573
574         return cmd_set_ss_level();
575 }
576
577 static NTSTATUS cmd_choose_transport(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
578                                      int argc, const char **argv)
579 {
580         NTSTATUS status;
581
582         if (argc != 2) {
583                 printf("Usage: %s [NCACN_NP|NCACN_IP_TCP]\n", argv[0]);
584                 return NT_STATUS_OK;
585         }
586
587         if (strequal(argv[1], "NCACN_NP")) {
588                 default_transport = NCACN_NP;
589         } else if (strequal(argv[1], "NCACN_IP_TCP")) {
590                 default_transport = NCACN_IP_TCP;
591         } else {
592                 printf("transport type: %s unknown or not supported\n", argv[1]);
593                 return NT_STATUS_NOT_SUPPORTED;
594         }
595
596         status = cmd_set_transport();
597         if (!NT_STATUS_IS_OK(status)) {
598                 return status;
599         }
600
601         printf("default transport is now: %s\n", argv[1]);
602
603         return NT_STATUS_OK;
604 }
605
606 /* Built in rpcclient commands */
607
608 static struct cmd_set rpcclient_commands[] = {
609
610         { "GENERAL OPTIONS" },
611
612         { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL,     NULL, NULL,   "Get help on commands", "[command]" },
613         { "?",  RPC_RTYPE_NTSTATUS, cmd_help, NULL,       NULL, NULL,   "Get help on commands", "[command]" },
614         { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   NULL,       NULL, "Set debug level", "level" },
615         { "debug", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   NULL,    NULL, "Set debug level", "level" },
616         { "list",       RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, NULL,       NULL, "List available commands on <pipe>", "pipe" },
617         { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,   NULL,   NULL,   "Exit program", "" },
618         { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,     NULL, NULL, "Exit program", "" },
619         { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL,     NULL, NULL, "Force RPC pipe connections to be signed", "" },
620         { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL,     NULL, NULL, "Force RPC pipe connections to be sealed", "" },
621         { "packet", RPC_RTYPE_NTSTATUS, cmd_packet, NULL,         NULL, NULL, "Force RPC pipe connections with packet authentication level", "" },
622         { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL,     NULL, NULL,   "Force RPC pipe connections to be sealed with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
623         { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL,    NULL, NULL, "Force RPC pipe connections to be signed (not sealed) with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
624         { "timeout", RPC_RTYPE_NTSTATUS, cmd_timeout, NULL,       NULL, NULL, "Set timeout (in milliseconds) for RPC operations", "" },
625         { "transport", RPC_RTYPE_NTSTATUS, cmd_choose_transport, NULL,    NULL, NULL, "Choose ncacn transport for RPC operations", "" },
626         { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL,     NULL, NULL, "Force RPC pipe connections to have no special properties", "" },
627
628         { NULL }
629 };
630
631 static struct cmd_set separator_command[] = {
632         { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL,   NULL, NULL, "----------------------" },
633         { NULL }
634 };
635
636
637 /* Various pipe commands */
638
639 extern struct cmd_set lsarpc_commands[];
640 extern struct cmd_set samr_commands[];
641 extern struct cmd_set spoolss_commands[];
642 extern struct cmd_set iremotewinspool_commands[];
643 extern struct cmd_set netlogon_commands[];
644 extern struct cmd_set srvsvc_commands[];
645 extern struct cmd_set dfs_commands[];
646 extern struct cmd_set ds_commands[];
647 extern struct cmd_set echo_commands[];
648 extern struct cmd_set epmapper_commands[];
649 extern struct cmd_set shutdown_commands[];
650 extern struct cmd_set test_commands[];
651 extern struct cmd_set wkssvc_commands[];
652 extern struct cmd_set ntsvcs_commands[];
653 extern struct cmd_set drsuapi_commands[];
654 extern struct cmd_set eventlog_commands[];
655 extern struct cmd_set winreg_commands[];
656 extern struct cmd_set fss_commands[];
657 extern struct cmd_set witness_commands[];
658 extern struct cmd_set clusapi_commands[];
659
660 static struct cmd_set *rpcclient_command_list[] = {
661         rpcclient_commands,
662         lsarpc_commands,
663         ds_commands,
664         samr_commands,
665         spoolss_commands,
666         iremotewinspool_commands,
667         netlogon_commands,
668         srvsvc_commands,
669         dfs_commands,
670         echo_commands,
671         epmapper_commands,
672         shutdown_commands,
673         test_commands,
674         wkssvc_commands,
675         ntsvcs_commands,
676         drsuapi_commands,
677         eventlog_commands,
678         winreg_commands,
679         fss_commands,
680         witness_commands,
681         clusapi_commands,
682         NULL
683 };
684
685 static void add_command_set(struct cmd_set *cmd_set)
686 {
687         struct cmd_list *entry;
688
689         if (!(entry = SMB_MALLOC_P(struct cmd_list))) {
690                 DEBUG(0, ("out of memory\n"));
691                 return;
692         }
693
694         ZERO_STRUCTP(entry);
695
696         entry->cmd_set = cmd_set;
697         DLIST_ADD(cmd_list, entry);
698 }
699
700
701 /**
702  * Call an rpcclient function, passing an argv array.
703  *
704  * @param cmd Command to run, as a single string.
705  **/
706 static NTSTATUS do_cmd(struct cli_state *cli,
707                        struct user_auth_info *auth_info,
708                        struct cmd_set *cmd_entry,
709                        struct dcerpc_binding *binding,
710                        int argc, const char **argv)
711 {
712         NTSTATUS ntresult;
713         WERROR wresult;
714
715         TALLOC_CTX *mem_ctx;
716
717         /* Create mem_ctx */
718
719         if (!(mem_ctx = talloc_stackframe())) {
720                 DEBUG(0, ("talloc_init() failed\n"));
721                 return NT_STATUS_NO_MEMORY;
722         }
723
724         /* Open pipe */
725
726         if ((cmd_entry->table != NULL) && (cmd_entry->rpc_pipe == NULL)) {
727                 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
728                 switch (pipe_default_auth_type) {
729                 case DCERPC_AUTH_TYPE_NONE:
730                         ntresult = cli_rpc_pipe_open_noauth_transport(
731                                 cli, default_transport,
732                                 cmd_entry->table,
733                                 &cmd_entry->rpc_pipe);
734                         break;
735                 case DCERPC_AUTH_TYPE_SPNEGO:
736                         switch (pipe_default_auth_spnego_type) {
737                         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
738                                 use_kerberos = CRED_DONT_USE_KERBEROS;
739                                 break;
740                         case PIPE_AUTH_TYPE_SPNEGO_KRB5:
741                                 use_kerberos = CRED_MUST_USE_KERBEROS;
742                                 break;
743                         case PIPE_AUTH_TYPE_SPNEGO_NONE:
744                                 use_kerberos = CRED_AUTO_USE_KERBEROS;
745                                 break;
746                         }
747                         FALL_THROUGH;
748                 case DCERPC_AUTH_TYPE_NTLMSSP:
749                 case DCERPC_AUTH_TYPE_KRB5:
750                         ntresult = cli_rpc_pipe_open_generic_auth(
751                                 cli, cmd_entry->table,
752                                 default_transport,
753                                 use_kerberos,
754                                 pipe_default_auth_type,
755                                 pipe_default_auth_level,
756                                 smbXcli_conn_remote_name(cli->conn),
757                                 get_cmdline_auth_info_domain(auth_info),
758                                 get_cmdline_auth_info_username(auth_info),
759                                 get_cmdline_auth_info_password(auth_info),
760                                 &cmd_entry->rpc_pipe);
761                         break;
762                 case DCERPC_AUTH_TYPE_SCHANNEL:
763                         TALLOC_FREE(rpcclient_netlogon_creds);
764                         ntresult = cli_rpc_pipe_open_schannel(
765                                 cli, rpcclient_msg_ctx,
766                                 cmd_entry->table,
767                                 default_transport,
768                                 rpcclient_netlogon_domain,
769                                 &cmd_entry->rpc_pipe,
770                                 rpcclient_msg_ctx,
771                                 &rpcclient_netlogon_creds);
772                         break;
773                 default:
774                         DEBUG(0, ("Could not initialise %s. Invalid "
775                                   "auth type %u\n",
776                                   cmd_entry->table->name,
777                                   pipe_default_auth_type ));
778                         talloc_free(mem_ctx);
779                         return NT_STATUS_UNSUCCESSFUL;
780                 }
781                 if (!NT_STATUS_IS_OK(ntresult)) {
782                         DEBUG(0, ("Could not initialise %s. Error was %s\n",
783                                   cmd_entry->table->name,
784                                   nt_errstr(ntresult) ));
785                         talloc_free(mem_ctx);
786                         return ntresult;
787                 }
788
789                 if (rpcclient_netlogon_creds == NULL && cmd_entry->use_netlogon_creds) {
790                         const char *dc_name = cmd_entry->rpc_pipe->desthost;
791                         const char *domain = rpcclient_netlogon_domain;
792                         struct cli_credentials *creds = NULL;
793
794                         ntresult = pdb_get_trust_credentials(domain, NULL,
795                                                              mem_ctx, &creds);
796                         if (!NT_STATUS_IS_OK(ntresult)) {
797                                 DEBUG(0, ("Failed to fetch trust credentials for "
798                                           "%s to connect to %s: %s\n",
799                                           domain, cmd_entry->table->name,
800                                           nt_errstr(ntresult)));
801                                 TALLOC_FREE(cmd_entry->rpc_pipe);
802                                 talloc_free(mem_ctx);
803                                 return ntresult;
804                         }
805
806                         ntresult = rpccli_create_netlogon_creds_ctx(creds,
807                                                         dc_name,
808                                                         rpcclient_msg_ctx,
809                                                         rpcclient_msg_ctx,
810                                                         &rpcclient_netlogon_creds);
811                         if (!NT_STATUS_IS_OK(ntresult)) {
812                                 DEBUG(0, ("Could not initialise credentials for %s.\n",
813                                           cmd_entry->table->name));
814                                 TALLOC_FREE(cmd_entry->rpc_pipe);
815                                 TALLOC_FREE(mem_ctx);
816                                 return ntresult;
817                         }
818
819                         ntresult = rpccli_setup_netlogon_creds(
820                                 cli,
821                                 NCACN_NP,
822                                 rpcclient_netlogon_creds,
823                                 false, /* force_reauth */
824                                 creds);
825                         TALLOC_FREE(creds);
826                         if (!NT_STATUS_IS_OK(ntresult)) {
827                                 DEBUG(0, ("Could not initialise credentials for %s.\n",
828                                           cmd_entry->table->name));
829                                 TALLOC_FREE(cmd_entry->rpc_pipe);
830                                 TALLOC_FREE(rpcclient_netlogon_creds);
831                                 TALLOC_FREE(mem_ctx);
832                                 return ntresult;
833                         }
834                 }
835         }
836
837         /* Set timeout for new connections */
838         if (cmd_entry->rpc_pipe) {
839                 rpccli_set_timeout(cmd_entry->rpc_pipe, timeout);
840         }
841
842         /* Run command */
843
844         if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
845                 ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, argv);
846                 if (!NT_STATUS_IS_OK(ntresult)) {
847                         printf("result was %s\n", nt_errstr(ntresult));
848                 }
849         } else {
850                 wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, argv);
851                 /* print out the DOS error */
852                 if (!W_ERROR_IS_OK(wresult)) {
853                         printf( "result was %s\n", win_errstr(wresult));
854                 }
855                 ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
856         }
857
858         /* Cleanup */
859
860         talloc_free(mem_ctx);
861
862         return ntresult;
863 }
864
865
866 /**
867  * Process a command entered at the prompt or as part of -c
868  *
869  * @returns The NTSTATUS from running the command.
870  **/
871 static NTSTATUS process_cmd(struct user_auth_info *auth_info,
872                             struct cli_state *cli,
873                             struct dcerpc_binding *binding,
874                             char *cmd)
875 {
876         struct cmd_list *temp_list;
877         NTSTATUS result = NT_STATUS_OK;
878         int ret;
879         int argc;
880         const char **argv = NULL;
881
882         if ((ret = poptParseArgvString(cmd, &argc, &argv)) != 0) {
883                 fprintf(stderr, "rpcclient: %s\n", poptStrerror(ret));
884                 return NT_STATUS_UNSUCCESSFUL;
885         }
886
887
888         /* Walk through a dlist of arrays of commands. */
889         for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
890                 struct cmd_set *temp_set = temp_list->cmd_set;
891
892                 while (temp_set->name) {
893                         if (strequal(argv[0], temp_set->name)) {
894                                 if (!(temp_set->returntype == RPC_RTYPE_NTSTATUS && temp_set->ntfn ) &&
895                          !(temp_set->returntype == RPC_RTYPE_WERROR && temp_set->wfn )) {
896                                         fprintf (stderr, "Invalid command\n");
897                                         goto out_free;
898                                 }
899
900                                 result = do_cmd(cli, auth_info, temp_set,
901                                                 binding, argc, argv);
902
903                                 goto out_free;
904                         }
905                         temp_set++;
906                 }
907         }
908
909         if (argv[0]) {
910                 printf("command not found: %s\n", argv[0]);
911         }
912
913 out_free:
914 /* moved to do_cmd()
915         if (!NT_STATUS_IS_OK(result)) {
916                 printf("result was %s\n", nt_errstr(result));
917         }
918 */
919
920         /* NOTE: popt allocates the whole argv, including the
921          * strings, as a single block.  So a single free is
922          * enough to release it -- we don't free the
923          * individual strings.  rtfm. */
924         free(argv);
925
926         return result;
927 }
928
929
930 /* Main function */
931
932  int main(int argc, char *argv[])
933 {
934         const char **const_argv = discard_const_p(const char *, argv);
935         int                     opt;
936         static char             *cmdstr = NULL;
937         const char *server;
938         struct cli_state        *cli = NULL;
939         static char             *opt_ipaddr=NULL;
940         struct cmd_set          **cmd_set;
941         struct sockaddr_storage server_ss;
942         NTSTATUS                nt_status;
943         static int              opt_port = 0;
944         int result = 0;
945         TALLOC_CTX *frame = talloc_stackframe();
946         uint32_t flags = 0;
947         struct dcerpc_binding *binding = NULL;
948         enum dcerpc_transport_t transport;
949         uint32_t bflags = 0;
950         const char *binding_string = NULL;
951         const char *host;
952         int signing_state = SMB_SIGNING_IPC_DEFAULT;
953         struct tevent_context *ev_ctx = NULL;
954
955         /* make sure the vars that get altered (4th field) are in
956            a fixed location or certain compilers complain */
957         poptContext pc;
958         struct poptOption long_options[] = {
959                 POPT_AUTOHELP
960                 {"command",     'c', POPT_ARG_STRING,   &cmdstr, 'c', "Execute semicolon separated cmds", "COMMANDS"},
961                 {"dest-ip", 'I', POPT_ARG_STRING,   &opt_ipaddr, 'I', "Specify destination IP address", "IP"},
962                 {"port", 'p', POPT_ARG_INT,   &opt_port, 'p', "Specify port number", "PORT"},
963                 POPT_COMMON_SAMBA
964                 POPT_COMMON_CONNECTION
965                 POPT_COMMON_CREDENTIALS
966                 POPT_TABLEEND
967         };
968
969         smb_init_locale();
970
971         zero_sockaddr(&server_ss);
972
973         setlinebuf(stdout);
974
975         /* the following functions are part of the Samba debugging
976            facilities.  See lib/debug.c */
977         setup_logging("rpcclient", DEBUG_STDOUT);
978         lp_set_cmdline("log level", "0");
979
980         /* Parse options */
981
982         pc = poptGetContext("rpcclient", argc, const_argv,
983                             long_options, 0);
984
985         if (argc == 1) {
986                 poptPrintHelp(pc, stderr, 0);
987                 goto done;
988         }
989
990         while((opt = poptGetNextOpt(pc)) != -1) {
991                 switch (opt) {
992
993                 case 'I':
994                         if (!interpret_string_addr(&server_ss,
995                                                 opt_ipaddr,
996                                                 AI_NUMERICHOST)) {
997                                 fprintf(stderr, "%s not a valid IP address\n",
998                                         opt_ipaddr);
999                                 result = 1;
1000                                 goto done;
1001                         }
1002                 }
1003         }
1004
1005         /* Get server as remaining unparsed argument.  Print usage if more
1006            than one unparsed argument is present. */
1007
1008         server = poptGetArg(pc);
1009
1010         if (!server || poptGetArg(pc)) {
1011                 poptPrintHelp(pc, stderr, 0);
1012                 result = 1;
1013                 goto done;
1014         }
1015
1016         poptFreeContext(pc);
1017         popt_burn_cmdline_password(argc, argv);
1018
1019         ev_ctx = samba_tevent_context_init(frame);
1020         if (ev_ctx == NULL) {
1021                 fprintf(stderr, "Could not init event context\n");
1022                 result = 1;
1023                 goto done;
1024         }
1025
1026         nt_status = messaging_init_client(ev_ctx,
1027                                           ev_ctx,
1028                                           &rpcclient_msg_ctx);
1029         if (geteuid() != 0 &&
1030                         NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
1031                 /*
1032                  * Normal to fail to initialize messaging context
1033                  * if we're not root as we don't have ability to
1034                  * read lock directory.
1035                  */
1036                 DBG_NOTICE("Unable to initialize messaging context. "
1037                         "Must be root to do that.\n");
1038         } else if (!NT_STATUS_IS_OK(nt_status)) {
1039                 fprintf(stderr, "Could not init messaging context\n");
1040                 result = 1;
1041                 goto done;
1042         }
1043
1044         if (!init_names()) {
1045                 result = 1;
1046                 goto done;
1047         }
1048
1049         /*
1050          * Get password
1051          * from stdin if necessary
1052          */
1053
1054         if ((server[0] == '/' && server[1] == '/') ||
1055                         (server[0] == '\\' && server[1] ==  '\\')) {
1056                 server += 2;
1057         }
1058
1059         nt_status = dcerpc_parse_binding(frame, server, &binding);
1060
1061         if (!NT_STATUS_IS_OK(nt_status)) {
1062
1063                 binding_string = talloc_asprintf(frame, "ncacn_np:%s",
1064                                                  strip_hostname(server));
1065                 if (!binding_string) {
1066                         result = 1;
1067                         goto done;
1068                 }
1069
1070                 nt_status = dcerpc_parse_binding(frame, binding_string, &binding);
1071                 if (!NT_STATUS_IS_OK(nt_status)) {
1072                         result = -1;
1073                         goto done;
1074                 }
1075         }
1076
1077         transport = dcerpc_binding_get_transport(binding);
1078
1079         if (transport == NCA_UNKNOWN) {
1080                 nt_status = dcerpc_binding_set_transport(binding, NCACN_NP);
1081                 if (!NT_STATUS_IS_OK(nt_status)) {
1082                         result = -1;
1083                         goto done;
1084                 }
1085         }
1086
1087         host = dcerpc_binding_get_string_option(binding, "host");
1088
1089         bflags = dcerpc_binding_get_flags(binding);
1090         if (bflags & DCERPC_CONNECT) {
1091                 pipe_default_auth_level = DCERPC_AUTH_LEVEL_CONNECT;
1092                 pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
1093         }
1094         if (bflags & DCERPC_PACKET) {
1095                 pipe_default_auth_level = DCERPC_AUTH_LEVEL_PACKET;
1096                 pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
1097         }
1098         if (bflags & DCERPC_SIGN) {
1099                 pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1100                 pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
1101         }
1102         if (bflags & DCERPC_SEAL) {
1103                 pipe_default_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1104                 pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
1105         }
1106         if (bflags & DCERPC_AUTH_SPNEGO) {
1107                 pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
1108                 pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
1109         }
1110         if (bflags & DCERPC_AUTH_NTLM) {
1111                 if (pipe_default_auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
1112                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
1113                 } else {
1114                         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
1115                 }
1116         }
1117         if (bflags & DCERPC_AUTH_KRB5) {
1118                 if (pipe_default_auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
1119                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
1120                 } else {
1121                         pipe_default_auth_type = DCERPC_AUTH_TYPE_KRB5;
1122                 }
1123         }
1124         if (pipe_default_auth_type != DCERPC_AUTH_TYPE_NONE) {
1125                 /* If nothing is requested then default to integrity */
1126                 if (pipe_default_auth_level == DCERPC_AUTH_LEVEL_NONE) {
1127                         pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1128                 }
1129         }
1130
1131         signing_state = get_cmdline_auth_info_signing_state(
1132                         popt_get_cmdline_auth_info());
1133         switch (signing_state) {
1134         case SMB_SIGNING_OFF:
1135                 lp_set_cmdline("client ipc signing", "no");
1136                 break;
1137         case SMB_SIGNING_REQUIRED:
1138                 lp_set_cmdline("client ipc signing", "required");
1139                 break;
1140         }
1141
1142         if (get_cmdline_auth_info_use_kerberos(popt_get_cmdline_auth_info())) {
1143                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS |
1144                          CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
1145         }
1146         if (get_cmdline_auth_info_use_ccache(popt_get_cmdline_auth_info())) {
1147                 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
1148         }
1149         if (get_cmdline_auth_info_use_pw_nt_hash(
1150                         popt_get_cmdline_auth_info())) {
1151                 flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
1152         }
1153
1154         rpcclient_netlogon_domain = get_cmdline_auth_info_domain(
1155                         popt_get_cmdline_auth_info());
1156         if (rpcclient_netlogon_domain == NULL ||
1157             rpcclient_netlogon_domain[0] == '\0')
1158         {
1159                 rpcclient_netlogon_domain = lp_workgroup();
1160         }
1161
1162         nt_status = cli_full_connection(&cli, lp_netbios_name(), host,
1163                                         opt_ipaddr ? &server_ss : NULL, opt_port,
1164                                         "IPC$", "IPC",
1165                                         get_cmdline_auth_info_username(
1166                                                 popt_get_cmdline_auth_info()),
1167                                         get_cmdline_auth_info_domain(
1168                                                 popt_get_cmdline_auth_info()),
1169                                         get_cmdline_auth_info_password(
1170                                                 popt_get_cmdline_auth_info()),
1171                                         flags,
1172                                         SMB_SIGNING_IPC_DEFAULT);
1173
1174         if (!NT_STATUS_IS_OK(nt_status)) {
1175                 DEBUG(0,("Cannot connect to server.  Error was %s\n", nt_errstr(nt_status)));
1176                 result = 1;
1177                 goto done;
1178         }
1179
1180         if (get_cmdline_auth_info_smb_encrypt(popt_get_cmdline_auth_info())) {
1181                 nt_status = cli_cm_force_encryption(cli,
1182                                         get_cmdline_auth_info_username(
1183                                                 popt_get_cmdline_auth_info()),
1184                                         get_cmdline_auth_info_password(
1185                                                 popt_get_cmdline_auth_info()),
1186                                         get_cmdline_auth_info_domain(
1187                                                 popt_get_cmdline_auth_info()),
1188                                         "IPC$");
1189                 if (!NT_STATUS_IS_OK(nt_status)) {
1190                         result = 1;
1191                         goto done;
1192                 }
1193         }
1194
1195 #if 0   /* COMMENT OUT FOR TESTING */
1196         memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
1197 #endif
1198
1199         /* Load command lists */
1200         rpcclient_cli_state = cli;
1201
1202         timeout = 10000;
1203         cli_set_timeout(cli, timeout);
1204
1205         cmd_set = rpcclient_command_list;
1206
1207         while(*cmd_set) {
1208                 add_command_set(*cmd_set);
1209                 add_command_set(separator_command);
1210                 cmd_set++;
1211         }
1212
1213         default_transport = dcerpc_binding_get_transport(binding);
1214
1215         fetch_machine_sid(cli);
1216
1217        /* Do anything specified with -c */
1218         if (cmdstr && cmdstr[0]) {
1219                 char    *cmd;
1220                 char    *p = cmdstr;
1221
1222                 result = 0;
1223
1224                 while((cmd=next_command(&p)) != NULL) {
1225                         NTSTATUS cmd_result = process_cmd(
1226                                                 popt_get_cmdline_auth_info(),
1227                                                 cli, binding, cmd);
1228                         SAFE_FREE(cmd);
1229                         result = NT_STATUS_IS_ERR(cmd_result);
1230                 }
1231
1232                 goto done;
1233         }
1234
1235         /* Loop around accepting commands */
1236
1237         while(1) {
1238                 char *line = NULL;
1239
1240                 line = smb_readline("rpcclient $> ", NULL, completion_fn);
1241
1242                 if (line == NULL) {
1243                         printf("\n");
1244                         break;
1245                 }
1246
1247                 if (line[0] != '\n')
1248                         process_cmd(popt_get_cmdline_auth_info(), cli,
1249                                 binding, line);
1250                 SAFE_FREE(line);
1251         }
1252
1253 done:
1254         rpcclient_cli_state = NULL;
1255         if (cli != NULL) {
1256                 cli_shutdown(cli);
1257         }
1258         popt_free_cmdline_auth_info();
1259         netlogon_creds_cli_close_global_db();
1260         TALLOC_FREE(rpcclient_msg_ctx);
1261         TALLOC_FREE(ev_ctx);
1262         TALLOC_FREE(frame);
1263         return result;
1264 }