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