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