f2d264b2b458914eb83280ee2980558b302f5026
[tprouty/samba.git] / source / nsswitch / winbindd_cm.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon connection manager
5
6    Copyright (C) Tim Potter                2001
7    Copyright (C) Andrew Bartlett           2002
8    Copyright (C) Gerald (Jerry) Carter     2003-2005.
9    Copyright (C) Volker Lendecke           2004-2005
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 /*
27    We need to manage connections to domain controllers without having to
28    mess up the main winbindd code with other issues.  The aim of the
29    connection manager is to:
30   
31        - make connections to domain controllers and cache them
32        - re-establish connections when networks or servers go down
33        - centralise the policy on connection timeouts, domain controller
34          selection etc
35        - manage re-entrancy for when winbindd becomes able to handle
36          multiple outstanding rpc requests
37   
38    Why not have connection management as part of the rpc layer like tng?
39    Good question.  This code may morph into libsmb/rpc_cache.c or something
40    like that but at the moment it's simply staying as part of winbind.  I
41    think the TNG architecture of forcing every user of the rpc layer to use
42    the connection caching system is a bad idea.  It should be an optional
43    method of using the routines.
44
45    The TNG design is quite good but I disagree with some aspects of the
46    implementation. -tpot
47
48  */
49
50 /*
51    TODO:
52
53      - I'm pretty annoyed by all the make_nmb_name() stuff.  It should be
54        moved down into another function.
55
56      - Take care when destroying cli_structs as they can be shared between
57        various sam handles.
58
59  */
60
61 #include "includes.h"
62 #include "winbindd.h"
63
64 #undef DBGC_CLASS
65 #define DBGC_CLASS DBGC_WINBIND
66
67 static void set_dc_type_and_flags( struct winbindd_domain *domain );
68
69 /****************************************************************
70  Handler triggered if we're offline to try and detect a DC.
71 ****************************************************************/
72
73 static void check_domain_online_handler(struct timed_event *te,
74                                         const struct timeval *now,
75                                         void *private_data)
76 {
77         struct winbindd_domain *domain =
78                 (struct winbindd_domain *)private_data;
79
80         DEBUG(10,("check_domain_online_handler: called for domain %s\n",
81                 domain->name ));
82
83         if (domain->check_online_event) {
84                 TALLOC_FREE(domain->check_online_event);
85         }
86
87         /* Are we still in "startup" mode ? */
88
89         if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
90                 /* No longer in "startup" mode. */
91                 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
92                         domain->name ));
93                 domain->startup = False;
94         }
95
96         /* We've been told to stay offline, so stay
97            that way. */
98
99         if (get_global_winbindd_state_offline()) {
100                 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
101                         domain->name ));
102                 return;
103         }
104
105         /* This call takes care of setting the online
106            flag to true if we connected, or re-adding
107            the offline handler if false. */
108         init_dc_connection(domain);
109 }
110
111 /****************************************************************
112  Set domain offline and also add handler to put us back online
113  if we detect a DC.
114 ****************************************************************/
115
116 void set_domain_offline(struct winbindd_domain *domain)
117 {
118         DEBUG(10,("set_domain_offline: called for domain %s\n",
119                 domain->name ));
120
121         if (domain->check_online_event) {
122                 TALLOC_FREE(domain->check_online_event);
123         }
124
125         if (domain->internal) {
126                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
127                         domain->name ));
128                 return;
129         }
130
131         domain->online = False;
132
133         /* We only add the timeout handler that checks and
134            allows us to go back online when we've not
135            been told to remain offline. */
136
137         if (get_global_winbindd_state_offline()) {
138                 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
139                         domain->name ));
140                 return;
141         }
142
143         /* If we're in statup mode, check again in 10 seconds, not in
144            lp_winbind_cache_time() seconds (which is 5 mins by default). */
145
146         domain->check_online_event = add_timed_event( NULL,
147                                                 domain->startup ?
148                                                         timeval_current_ofs(10,0) : 
149                                                         timeval_current_ofs(lp_winbind_cache_time(), 0),
150                                                 "check_domain_online_handler",
151                                                 check_domain_online_handler,
152                                                 domain);
153
154         /* The above *has* to succeed for winbindd to work. */
155         if (!domain->check_online_event) {
156                 smb_panic("set_domain_offline: failed to add online handler.\n");
157         }
158
159         DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
160                 domain->name ));
161 }
162
163 /****************************************************************
164  Set domain online - if allowed.
165 ****************************************************************/
166
167 static void set_domain_online(struct winbindd_domain *domain)
168 {
169         extern struct winbindd_methods reconnect_methods;
170         struct timeval now;
171
172         DEBUG(10,("set_domain_online: called for domain %s\n",
173                 domain->name ));
174
175         if (domain->internal) {
176                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
177                         domain->name ));
178                 return;
179         }
180
181         if (get_global_winbindd_state_offline()) {
182                 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
183                         domain->name ));
184                 return;
185         }
186
187         /* If we are waiting to get a krb5 ticket, trigger immediately. */
188         GetTimeOfDay(&now);
189         set_event_dispatch_time("krb5_ticket_gain_handler", now);
190
191         /* Ok, we're out of any startup mode now... */
192         domain->startup = False;
193
194         if (domain->online == False) {
195                 /* We were offline - now we're online. We default to
196                    using the MS-RPC backend if we started offline,
197                    and if we're going online for the first time we
198                    should really re-initialize the backends and the
199                    checks to see if we're talking to an AD or NT domain.
200                 */
201
202                 domain->initialized = False;
203
204                 /* 'reconnect_methods' is the MS-RPC backend. */
205                 if (domain->backend == &reconnect_methods) {
206                         domain->backend = NULL;
207                 }
208         }
209
210         domain->online = True;
211 }
212
213 /****************************************************************
214  Requested to set a domain online.
215 ****************************************************************/
216
217 void set_domain_online_request(struct winbindd_domain *domain)
218 {
219         DEBUG(10,("set_domain_online_request: called for domain %s\n",
220                 domain->name ));
221
222         if (get_global_winbindd_state_offline()) {
223                 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
224                         domain->name ));
225                 return;
226         }
227
228         /* We've been told it's safe to go online and
229            try and connect to a DC. But I don't believe it
230            because network manager seems to lie.
231            Wait at least 5 seconds. Heuristics suck... */
232
233         if (!domain->check_online_event) {
234                 DEBUG(5,("set_domain_online_request: no check_domain_online_handler "
235                         "registered. Were we online (%d) ?\n", (int)domain->online ));
236         } else {
237                 struct timeval tev;
238
239                 GetTimeOfDay(&tev);
240
241                 /* Go into "startup" mode again. */
242                 domain->startup_time = tev.tv_sec;
243                 domain->startup = True;
244
245                 tev.tv_sec += 5;
246                 set_event_dispatch_time("check_domain_online_handler", tev);
247         }
248 }
249
250 /****************************************************************
251  Add -ve connection cache entries for domain and realm.
252 ****************************************************************/
253
254 void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
255                                         const char *server,
256                                         NTSTATUS result)
257 {
258         add_failed_connection_entry(domain->name, server, result);
259         /* If this was the saf name for the last thing we talked to,
260            remove it. */
261         saf_delete(domain->name, server);
262         if (*domain->alt_name) {
263                 add_failed_connection_entry(domain->alt_name, server, result);
264                 saf_delete(domain->alt_name, server);
265         }
266 }
267
268 /* Choose between anonymous or authenticated connections.  We need to use
269    an authenticated connection if DCs have the RestrictAnonymous registry
270    entry set > 0, or the "Additional restrictions for anonymous
271    connections" set in the win2k Local Security Policy. 
272    
273    Caller to free() result in domain, username, password
274 */
275
276 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
277 {
278         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
279         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
280         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
281         
282         if (*username && **username) {
283
284                 if (!*domain || !**domain)
285                         *domain = smb_xstrdup(lp_workgroup());
286                 
287                 if (!*password || !**password)
288                         *password = smb_xstrdup("");
289
290                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
291                           *domain, *username));
292
293         } else {
294                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
295                 *username = smb_xstrdup("");
296                 *domain = smb_xstrdup("");
297                 *password = smb_xstrdup("");
298         }
299 }
300
301 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
302                                      fstring dcname, struct in_addr *dc_ip)
303 {
304         struct winbindd_domain *our_domain = NULL;
305         struct rpc_pipe_client *netlogon_pipe = NULL;
306         NTSTATUS result;
307         WERROR werr;
308         TALLOC_CTX *mem_ctx;
309         unsigned int orig_timeout;
310         fstring tmp;
311         char *p;
312
313         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
314          * moment.... */
315
316         if (IS_DC) {
317                 return False;
318         }
319
320         if (domain->primary) {
321                 return False;
322         }
323
324         our_domain = find_our_domain();
325
326         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
327                 return False;
328         }
329
330         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
331         if (!NT_STATUS_IS_OK(result)) {
332                 return False;
333         }
334
335         /* This call can take a long time - allow the server to time out.
336            35 seconds should do it. */
337
338         orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
339         
340         werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
341                                            domain->name, tmp);
342
343         /* And restore our original timeout. */
344         cli_set_timeout(netlogon_pipe->cli, orig_timeout);
345
346         talloc_destroy(mem_ctx);
347
348         if (!W_ERROR_IS_OK(werr)) {
349                 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
350                            dos_errstr(werr)));
351                 return False;
352         }
353
354         /* cli_netlogon_getdcname gives us a name with \\ */
355         p = tmp;
356         if (*p == '\\') {
357                 p+=1;
358         }
359         if (*p == '\\') {
360                 p+=1;
361         }
362
363         fstrcpy(dcname, p);
364
365         DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname));
366
367         if (!resolve_name(dcname, dc_ip, 0x20)) {
368                 return False;
369         }
370
371         return True;
372 }
373
374 /************************************************************************
375  Given a fd with a just-connected TCP connection to a DC, open a connection
376  to the pipe.
377 ************************************************************************/
378
379 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
380                                       const int sockfd,
381                                       const char *controller,
382                                       struct cli_state **cli,
383                                       BOOL *retry)
384 {
385         char *machine_password, *machine_krb5_principal, *machine_account;
386         char *ipc_username, *ipc_domain, *ipc_password;
387
388         BOOL got_mutex;
389
390         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
391
392         struct sockaddr peeraddr;
393         socklen_t peeraddr_len;
394
395         struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
396
397         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
398                 controller, domain->name ));
399
400         machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
401                                                           NULL);
402         
403         if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
404                 SAFE_FREE(machine_password);
405                 return NT_STATUS_NO_MEMORY;
406         }
407
408         if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
409                      lp_realm()) == -1) {
410                 SAFE_FREE(machine_account);
411                 SAFE_FREE(machine_password);
412                 return NT_STATUS_NO_MEMORY;
413         }
414
415         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
416
417         *retry = True;
418
419         got_mutex = secrets_named_mutex(controller,
420                                         WINBIND_SERVER_MUTEX_WAIT_TIME);
421
422         if (!got_mutex) {
423                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
424                          controller));
425                 result = NT_STATUS_POSSIBLE_DEADLOCK;
426                 goto done;
427         }
428
429         if ((*cli = cli_initialise()) == NULL) {
430                 DEBUG(1, ("Could not cli_initialize\n"));
431                 result = NT_STATUS_NO_MEMORY;
432                 goto done;
433         }
434
435         (*cli)->timeout = 10000;        /* 10 seconds */
436         (*cli)->fd = sockfd;
437         fstrcpy((*cli)->desthost, controller);
438         (*cli)->use_kerberos = True;
439
440         peeraddr_len = sizeof(peeraddr);
441
442         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
443             (peeraddr_len != sizeof(struct sockaddr_in)) ||
444             (peeraddr_in->sin_family != PF_INET))
445         {
446                 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
447                 result = NT_STATUS_UNSUCCESSFUL;
448                 goto done;
449         }
450
451         if (ntohs(peeraddr_in->sin_port) == 139) {
452                 struct nmb_name calling;
453                 struct nmb_name called;
454
455                 make_nmb_name(&calling, global_myname(), 0x0);
456                 make_nmb_name(&called, "*SMBSERVER", 0x20);
457
458                 if (!cli_session_request(*cli, &calling, &called)) {
459                         DEBUG(8, ("cli_session_request failed for %s\n",
460                                   controller));
461                         result = NT_STATUS_UNSUCCESSFUL;
462                         goto done;
463                 }
464         }
465
466         cli_setup_signing_state(*cli, Undefined);
467
468         if (!cli_negprot(*cli)) {
469                 DEBUG(1, ("cli_negprot failed\n"));
470                 result = NT_STATUS_UNSUCCESSFUL;
471                 goto done;
472         }
473                         
474         if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
475                 ADS_STATUS ads_status;
476
477                 if (lp_security() == SEC_ADS) {
478
479                         /* Try a krb5 session */
480
481                         (*cli)->use_kerberos = True;
482                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
483                                   "[%s]\n", controller, global_myname(),
484                                   machine_krb5_principal));
485
486                         ads_status = cli_session_setup_spnego(*cli,
487                                                               machine_krb5_principal, 
488                                                               machine_password, 
489                                                               lp_workgroup());
490
491                         if (!ADS_ERR_OK(ads_status)) {
492                                 DEBUG(4,("failed kerberos session setup with %s\n",
493                                          ads_errstr(ads_status)));
494                         }
495
496                         result = ads_ntstatus(ads_status);
497                         if (NT_STATUS_IS_OK(result)) {
498                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
499                                 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
500                                 goto session_setup_done;
501                         }
502                 }
503
504                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
505                 (*cli)->use_kerberos = False;
506
507                 DEBUG(5, ("connecting to %s from %s with username "
508                           "[%s]\\[%s]\n",  controller, global_myname(),
509                           lp_workgroup(), machine_account));
510
511                 ads_status = cli_session_setup_spnego(*cli,
512                                                       machine_account, 
513                                                       machine_password, 
514                                                       lp_workgroup());
515                 if (!ADS_ERR_OK(ads_status)) {
516                         DEBUG(4, ("authenticated session setup failed with %s\n",
517                                 ads_errstr(ads_status)));
518                 }
519
520                 result = ads_ntstatus(ads_status);
521                 if (NT_STATUS_IS_OK(result)) {
522                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
523                         cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
524                         goto session_setup_done;
525                 }
526         }
527
528         /* Fall back to non-kerberos session setup */
529
530         (*cli)->use_kerberos = False;
531
532         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
533             (strlen(ipc_username) > 0)) {
534
535                 /* Only try authenticated if we have a username */
536
537                 DEBUG(5, ("connecting to %s from %s with username "
538                           "[%s]\\[%s]\n",  controller, global_myname(),
539                           ipc_domain, ipc_username));
540
541                 if (NT_STATUS_IS_OK(cli_session_setup(
542                                             *cli, ipc_username,
543                                             ipc_password, strlen(ipc_password)+1,
544                                             ipc_password, strlen(ipc_password)+1,
545                                             ipc_domain))) {
546                         /* Successful logon with given username. */
547                         cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
548                         goto session_setup_done;
549                 } else {
550                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
551                                 ipc_domain, ipc_username ));
552                 }
553         }
554
555         /* Fall back to anonymous connection, this might fail later */
556
557         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
558                                               NULL, 0, ""))) {
559                 DEBUG(5, ("Connected anonymously\n"));
560                 cli_init_creds(*cli, "", "", "");
561                 goto session_setup_done;
562         }
563
564         result = cli_nt_error(*cli);
565
566         if (NT_STATUS_IS_OK(result))
567                 result = NT_STATUS_UNSUCCESSFUL;
568
569         /* We can't session setup */
570
571         goto done;
572
573  session_setup_done:
574
575         /* cache the server name for later connections */
576
577         saf_store( domain->name, (*cli)->desthost );
578         if (domain->alt_name && (*cli)->use_kerberos) {
579                 saf_store( domain->alt_name, (*cli)->desthost );
580         }
581
582         if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
583
584                 result = cli_nt_error(*cli);
585
586                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
587
588                 if (NT_STATUS_IS_OK(result))
589                         result = NT_STATUS_UNSUCCESSFUL;
590
591                 goto done;
592         }
593
594         secrets_named_mutex_release(controller);
595         got_mutex = False;
596         *retry = False;
597
598         /* set the domain if empty; needed for schannel connections */
599         if ( !*(*cli)->domain ) {
600                 fstrcpy( (*cli)->domain, domain->name );
601         }
602
603         result = NT_STATUS_OK;
604
605  done:
606         if (got_mutex) {
607                 secrets_named_mutex_release(controller);
608         }
609
610         SAFE_FREE(machine_account);
611         SAFE_FREE(machine_password);
612         SAFE_FREE(machine_krb5_principal);
613         SAFE_FREE(ipc_username);
614         SAFE_FREE(ipc_domain);
615         SAFE_FREE(ipc_password);
616
617         if (!NT_STATUS_IS_OK(result)) {
618                 winbind_add_failed_connection_entry(domain, controller, result);
619                 if ((*cli) != NULL) {
620                         cli_shutdown(*cli);
621                         *cli = NULL;
622                 }
623         }
624
625         return result;
626 }
627
628 struct dc_name_ip {
629         fstring name;
630         struct in_addr ip;
631 };
632
633 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
634                               const char *dcname, struct in_addr ip,
635                               struct dc_name_ip **dcs, int *num)
636 {
637         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
638                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
639                 return False;
640         }
641
642         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
643
644         if (*dcs == NULL)
645                 return False;
646
647         fstrcpy((*dcs)[*num].name, dcname);
648         (*dcs)[*num].ip = ip;
649         *num += 1;
650         return True;
651 }
652
653 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
654                                   struct in_addr ip, uint16 port,
655                                   struct sockaddr_in **addrs, int *num)
656 {
657         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
658
659         if (*addrs == NULL)
660                 return False;
661
662         (*addrs)[*num].sin_family = PF_INET;
663         putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
664         (*addrs)[*num].sin_port = htons(port);
665
666         *num += 1;
667         return True;
668 }
669
670 static void mailslot_name(struct in_addr dc_ip, fstring name)
671 {
672         fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
673 }
674
675 static BOOL send_getdc_request(struct in_addr dc_ip,
676                                const char *domain_name,
677                                const DOM_SID *sid)
678 {
679         pstring outbuf;
680         char *p;
681         fstring my_acct_name;
682         fstring my_mailslot;
683
684         mailslot_name(dc_ip, my_mailslot);
685
686         memset(outbuf, '\0', sizeof(outbuf));
687
688         p = outbuf;
689
690         SCVAL(p, 0, SAMLOGON);
691         p++;
692
693         SCVAL(p, 0, 0); /* Count pointer ... */
694         p++;
695
696         SIVAL(p, 0, 0); /* The sender's token ... */
697         p += 2;
698
699         p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
700         fstr_sprintf(my_acct_name, "%s$", global_myname());
701         p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
702
703         memcpy(p, my_mailslot, strlen(my_mailslot)+1);
704         p += strlen(my_mailslot)+1;
705
706         SIVAL(p, 0, 0x80);
707         p+=4;
708
709         SIVAL(p, 0, sid_size(sid));
710         p+=4;
711
712         p = ALIGN4(p, outbuf);
713
714         sid_linearize(p, sid_size(sid), sid);
715         p += sid_size(sid);
716
717         SIVAL(p, 0, 1);
718         SSVAL(p, 4, 0xffff);
719         SSVAL(p, 6, 0xffff);
720         p+=8;
721
722         return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
723                                  outbuf, PTR_DIFF(p, outbuf),
724                                  global_myname(), 0, domain_name, 0x1c,
725                                  dc_ip);
726 }
727
728 static BOOL receive_getdc_response(struct in_addr dc_ip,
729                                    const char *domain_name,
730                                    fstring dc_name)
731 {
732         struct packet_struct *packet;
733         fstring my_mailslot;
734         char *buf, *p;
735         fstring dcname, user, domain;
736         int len;
737
738         mailslot_name(dc_ip, my_mailslot);
739
740         packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
741
742         if (packet == NULL) {
743                 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
744                 return False;
745         }
746
747         DEBUG(5, ("Received packet for %s\n", my_mailslot));
748
749         buf = packet->packet.dgram.data;
750         len = packet->packet.dgram.datasize;
751
752         if (len < 70) {
753                 /* 70 is a completely arbitrary value to make sure
754                    the SVAL below does not read uninitialized memory */
755                 DEBUG(3, ("GetDC got short response\n"));
756                 return False;
757         }
758
759         /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
760         p = buf+SVAL(buf, smb_vwv10);
761
762         if (CVAL(p,0) != SAMLOGON_R) {
763                 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
764                 return False;
765         }
766
767         p+=2;
768         pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
769                   STR_TERMINATE|STR_NOALIGN);
770         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
771         pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
772                   STR_TERMINATE|STR_NOALIGN);
773         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
774         pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
775                   STR_TERMINATE|STR_NOALIGN);
776         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
777
778         if (!strequal(domain, domain_name)) {
779                 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
780                           domain_name, domain));
781                 return False;
782         }
783
784         p = dcname;
785         if (*p == '\\') p += 1;
786         if (*p == '\\') p += 1;
787
788         fstrcpy(dc_name, p);
789
790         DEBUG(10, ("GetDC gave name %s for domain %s\n",
791                    dc_name, domain));
792
793         return True;
794 }
795
796 /*******************************************************************
797  convert an ip to a name
798 *******************************************************************/
799
800 static BOOL dcip_to_name( const char *domainname, const char *realm, 
801                           const DOM_SID *sid, struct in_addr ip, fstring name )
802 {
803         struct ip_service ip_list;
804
805         ip_list.ip = ip;
806         ip_list.port = 0;
807
808 #ifdef WITH_ADS
809         /* For active directory servers, try to get the ldap server name.
810            None of these failures should be considered critical for now */
811
812         if (lp_security() == SEC_ADS) {
813                 ADS_STRUCT *ads;
814
815                 ads = ads_init(realm, domainname, NULL);
816                 ads->auth.flags |= ADS_AUTH_NO_BIND;
817
818                 if (ads_try_connect( ads, inet_ntoa(ip) ) )  {
819                         /* We got a cldap packet. */
820                         fstrcpy(name, ads->config.ldap_server_name);
821                         namecache_store(name, 0x20, 1, &ip_list);
822
823                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
824
825                         if ((ads->config.flags & ADS_KDC) && ads_sitename_match(ads)) {
826                                 /* We're going to use this KDC for this realm/domain.
827                                    If we are using sites, then force the krb5 libs
828                                    to use this KDC. */
829
830                                 create_local_private_krb5_conf_for_domain(realm,
831                                                                 domainname,
832                                                                 ip);
833
834                                 /* Ensure we contact this DC also. */
835                                 saf_store( domainname, name);
836                                 saf_store( realm, name);
837                         }
838
839                         ads_destroy( &ads );
840                         return True;
841                 }
842
843                 ads_destroy( &ads );
844         }
845 #endif
846
847         /* try GETDC requests next */
848         
849         if (send_getdc_request(ip, domainname, sid)) {
850                 int i;
851                 smb_msleep(100);
852                 for (i=0; i<5; i++) {
853                         if (receive_getdc_response(ip, domainname, name)) {
854                                 namecache_store(name, 0x20, 1, &ip_list);
855                                 return True;
856                         }
857                         smb_msleep(500);
858                 }
859         }
860
861         /* try node status request */
862
863         if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
864                 namecache_store(name, 0x20, 1, &ip_list);
865                 return True;
866         }
867         return False;
868 }
869
870 /*******************************************************************
871  Retreive a list of IP address for domain controllers.  Fill in 
872  the dcs[]  with results.
873 *******************************************************************/
874
875 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
876                     struct dc_name_ip **dcs, int *num_dcs)
877 {
878         fstring dcname;
879         struct  in_addr ip;
880         struct  ip_service *ip_list = NULL;
881         int     iplist_size = 0;
882         int     i;
883         BOOL    is_our_domain;
884         enum security_types sec = (enum security_types)lp_security();
885
886         is_our_domain = strequal(domain->name, lp_workgroup());
887
888         if ( !is_our_domain 
889                 && get_dc_name_via_netlogon(domain, dcname, &ip) 
890                 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
891         {
892                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
893                            dcname, inet_ntoa(ip)));
894                 return True;
895         }
896
897         if (sec == SEC_ADS) {
898                 /* We need to make sure we know the local site before
899                    doing any DNS queries, as this will restrict the
900                    get_sorted_dc_list() call below to only fetching
901                    DNS records for the correct site. */
902
903                 /* Find any DC to get the site record.
904                    We deliberately don't care about the
905                    return here. */
906                 get_dc_name(domain->name, lp_realm(), dcname, &ip);
907
908                 /* Now do the site-specific AD dns lookup. */
909                 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
910         }
911
912         /* try standard netbios queries if no ADS */
913
914         if (iplist_size==0) 
915                 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
916
917         /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
918
919         /* now add to the dc array.  We'll wait until the last minute 
920            to look up the name of the DC.  But we fill in the char* for 
921            the ip now in to make the failed connection cache work */
922
923         for ( i=0; i<iplist_size; i++ ) {
924                 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip), 
925                         ip_list[i].ip, dcs, num_dcs);
926         }
927
928         SAFE_FREE( ip_list );
929
930         return True;
931 }
932
933 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
934                         const struct winbindd_domain *domain,
935                         fstring dcname, struct sockaddr_in *addr, int *fd)
936 {
937         struct dc_name_ip *dcs = NULL;
938         int num_dcs = 0;
939
940         const char **dcnames = NULL;
941         int num_dcnames = 0;
942
943         struct sockaddr_in *addrs = NULL;
944         int num_addrs = 0;
945
946         int i, fd_index;
947
948  again:
949         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
950                 return False;
951
952         for (i=0; i<num_dcs; i++) {
953
954                 add_string_to_array(mem_ctx, dcs[i].name,
955                                     &dcnames, &num_dcnames);
956                 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
957                                       &addrs, &num_addrs);
958
959                 add_string_to_array(mem_ctx, dcs[i].name,
960                                     &dcnames, &num_dcnames);
961                 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
962                                       &addrs, &num_addrs);
963         }
964
965         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
966                 return False;
967
968         if ((addrs == NULL) || (dcnames == NULL))
969                 return False;
970
971         /* 5 second timeout. */
972         if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) 
973         {
974                 for (i=0; i<num_dcs; i++) {
975                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
976                                 "domain %s address %s. Error was %s\n",
977                                 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
978                         winbind_add_failed_connection_entry(domain,
979                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
980                 }
981                 return False;
982         }
983
984         *addr = addrs[fd_index];
985
986         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
987                 /* Ok, we've got a name for the DC */
988                 fstrcpy(dcname, dcnames[fd_index]);
989                 return True;
990         }
991
992         /* Try to figure out the name */
993         if (dcip_to_name( domain->name, domain->alt_name, &domain->sid,
994                           addr->sin_addr, dcname )) {
995                 return True;
996         }
997
998         /* We can not continue without the DC's name */
999         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
1000                                     NT_STATUS_UNSUCCESSFUL);
1001         goto again;
1002 }
1003
1004 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
1005                                    struct winbindd_cm_conn *new_conn)
1006 {
1007         TALLOC_CTX *mem_ctx;
1008         NTSTATUS result;
1009         char *saf_servername = saf_fetch( domain->name );
1010         int retries;
1011
1012         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
1013                 SAFE_FREE(saf_servername);
1014                 set_domain_offline(domain);
1015                 return NT_STATUS_NO_MEMORY;
1016         }
1017
1018         /* we have to check the server affinity cache here since 
1019            later we selecte a DC based on response time and not preference */
1020            
1021         /* Check the negative connection cache
1022            before talking to it. It going down may have
1023            triggered the reconnection. */
1024
1025         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
1026
1027                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
1028                         saf_servername, domain->name ));
1029
1030                 /* convert an ip address to a name */
1031                 if ( is_ipaddress( saf_servername ) ) {
1032                         fstring saf_name;
1033                         struct in_addr ip;
1034
1035                         ip = *interpret_addr2( saf_servername );
1036                         if (dcip_to_name( domain->name, domain->alt_name,
1037                                           &domain->sid, ip, saf_name )) {
1038                                 fstrcpy( domain->dcname, saf_name );
1039                         } else {
1040                                 winbind_add_failed_connection_entry(
1041                                         domain, saf_servername,
1042                                         NT_STATUS_UNSUCCESSFUL);
1043                         }
1044                 } else {
1045                         fstrcpy( domain->dcname, saf_servername );
1046                 }
1047
1048                 SAFE_FREE( saf_servername );
1049         }
1050
1051         for (retries = 0; retries < 3; retries++) {
1052
1053                 int fd = -1;
1054                 BOOL retry = False;
1055
1056                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1057
1058                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
1059                         domain->dcname, domain->name ));
1060
1061                 if (*domain->dcname 
1062                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
1063                         && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
1064                 {
1065                         struct sockaddr_in *addrs = NULL;
1066                         int num_addrs = 0;
1067                         int dummy = 0;
1068
1069                         add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
1070                         add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
1071
1072                         /* 5 second timeout. */
1073                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
1074                                 fd = -1;
1075                         }
1076                 }
1077
1078                 if ((fd == -1) 
1079                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
1080                 {
1081                         /* This is the one place where we will
1082                            set the global winbindd offline state
1083                            to true, if a "WINBINDD_OFFLINE" entry
1084                            is found in the winbindd cache. */
1085                         set_global_winbindd_state_offline();
1086                         break;
1087                 }
1088
1089                 new_conn->cli = NULL;
1090
1091                 result = cm_prepare_connection(domain, fd, domain->dcname,
1092                         &new_conn->cli, &retry);
1093
1094                 if (!retry)
1095                         break;
1096         }
1097
1098         if (NT_STATUS_IS_OK(result)) {
1099                 if (domain->online == False) {
1100                         /* We're changing state from offline to online. */
1101                         set_global_winbindd_state_online();
1102                 }
1103                 set_domain_online(domain);
1104         } else {
1105                 /* Ensure we setup the retry handler. */
1106                 set_domain_offline(domain);
1107         }
1108
1109         talloc_destroy(mem_ctx);
1110         return result;
1111 }
1112
1113 /* Close down all open pipes on a connection. */
1114
1115 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
1116 {
1117         /* We're closing down a possibly dead
1118            connection. Don't have impossibly long (10s) timeouts. */
1119
1120         if (conn->cli) {
1121                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
1122         }
1123
1124         if (conn->samr_pipe != NULL) {
1125                 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
1126                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1127                         if (conn->cli) {
1128                                 cli_set_timeout(conn->cli, 500);
1129                         }
1130                 }
1131                 conn->samr_pipe = NULL;
1132         }
1133
1134         if (conn->lsa_pipe != NULL) {
1135                 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
1136                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1137                         if (conn->cli) {
1138                                 cli_set_timeout(conn->cli, 500);
1139                         }
1140                 }
1141                 conn->lsa_pipe = NULL;
1142         }
1143
1144         if (conn->netlogon_pipe != NULL) {
1145                 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
1146                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
1147                         if (conn->cli) {
1148                                 cli_set_timeout(conn->cli, 500);
1149                         }
1150                 }
1151                 conn->netlogon_pipe = NULL;
1152         }
1153
1154         if (conn->cli) {
1155                 cli_shutdown(conn->cli);
1156         }
1157
1158         conn->cli = NULL;
1159 }
1160
1161 void close_conns_after_fork(void)
1162 {
1163         struct winbindd_domain *domain;
1164
1165         for (domain = domain_list(); domain; domain = domain->next) {
1166                 if (domain->conn.cli == NULL)
1167                         continue;
1168
1169                 if (domain->conn.cli->fd == -1)
1170                         continue;
1171
1172                 close(domain->conn.cli->fd);
1173                 domain->conn.cli->fd = -1;
1174         }
1175 }
1176
1177 static BOOL connection_ok(struct winbindd_domain *domain)
1178 {
1179         if (domain->conn.cli == NULL) {
1180                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
1181                           "cli!\n", domain->dcname, domain->name));
1182                 return False;
1183         }
1184
1185         if (!domain->conn.cli->initialised) {
1186                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
1187                           "initialised!\n", domain->dcname, domain->name));
1188                 return False;
1189         }
1190
1191         if (domain->conn.cli->fd == -1) {
1192                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
1193                           "never started (fd == -1)\n", 
1194                           domain->dcname, domain->name));
1195                 return False;
1196         }
1197
1198         if (domain->online == False) {
1199                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
1200                 return False;
1201         }
1202
1203         return True;
1204 }
1205
1206 /* Initialize a new connection up to the RPC BIND. */
1207
1208 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
1209 {
1210         NTSTATUS result;
1211
1212         /* Internal connections never use the network. */
1213         if (domain->internal) {
1214                 domain->initialized = True;
1215                 return NT_STATUS_OK;
1216         }
1217
1218         if (connection_ok(domain)) {
1219                 if (!domain->initialized) {
1220                         set_dc_type_and_flags(domain);
1221                 }
1222                 return NT_STATUS_OK;
1223         }
1224
1225         invalidate_cm_connection(&domain->conn);
1226
1227         result = cm_open_connection(domain, &domain->conn);
1228
1229         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
1230                 set_dc_type_and_flags(domain);
1231         }
1232
1233         return result;
1234 }
1235
1236 /******************************************************************************
1237  We can 'sense' certain things about the DC by it's replies to certain
1238  questions.
1239
1240  This tells us if this particular remote server is Active Directory, and if it
1241  is native mode.
1242 ******************************************************************************/
1243
1244 static void set_dc_type_and_flags( struct winbindd_domain *domain )
1245 {
1246         NTSTATUS                result;
1247         DS_DOMINFO_CTR          ctr;
1248         TALLOC_CTX              *mem_ctx = NULL;
1249         struct rpc_pipe_client  *cli;
1250         POLICY_HND pol;
1251
1252         char *domain_name = NULL;
1253         char *dns_name = NULL;
1254         DOM_SID *dom_sid = NULL;
1255
1256         ZERO_STRUCT( ctr );
1257         
1258         if (!connection_ok(domain)) {
1259                 return;
1260         }
1261
1262         DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
1263
1264         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
1265                                        &result);
1266
1267         if (cli == NULL) {
1268                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1269                           "PI_LSARPC_DS on domain %s: (%s)\n",
1270                           domain->name, nt_errstr(result)));
1271                 return;
1272         }
1273
1274         result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
1275                                              DsRolePrimaryDomainInfoBasic,
1276                                              &ctr);
1277         cli_rpc_pipe_close(cli);
1278
1279         if (!NT_STATUS_IS_OK(result)) {
1280                 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
1281                           "on domain %s failed: (%s)\n",
1282                           domain->name, nt_errstr(result)));
1283                 return;
1284         }
1285         
1286         if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
1287             !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
1288                 domain->native_mode = True;
1289         } else {
1290                 domain->native_mode = False;
1291         }
1292
1293         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
1294
1295         if (cli == NULL) {
1296                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
1297                           "PI_LSARPC on domain %s: (%s)\n",
1298                           domain->name, nt_errstr(result)));
1299                 cli_rpc_pipe_close(cli);
1300                 return;
1301         }
1302
1303         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
1304                               domain->name);
1305         if (!mem_ctx) {
1306                 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1307                 cli_rpc_pipe_close(cli);
1308                 return;
1309         }
1310
1311         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
1312                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
1313                 
1314         if (NT_STATUS_IS_OK(result)) {
1315                 /* This particular query is exactly what Win2k clients use 
1316                    to determine that the DC is active directory */
1317                 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
1318                                                        12, &domain_name,
1319                                                        &dns_name, NULL,
1320                                                        NULL, &dom_sid);
1321         }
1322
1323         if (NT_STATUS_IS_OK(result)) {
1324                 domain->active_directory = True;
1325
1326                 if (domain_name)
1327                         fstrcpy(domain->name, domain_name);
1328
1329                 if (dns_name)
1330                         fstrcpy(domain->alt_name, dns_name);
1331
1332                 if (dom_sid) 
1333                         sid_copy(&domain->sid, dom_sid);
1334         } else {
1335                 domain->active_directory = False;
1336
1337                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
1338                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1339                                                 &pol);
1340                         
1341                 if (!NT_STATUS_IS_OK(result))
1342                         goto done;
1343                         
1344                 result = rpccli_lsa_query_info_policy(cli, mem_ctx, 
1345                                                       &pol, 5, &domain_name, 
1346                                                       &dom_sid);
1347                         
1348                 if (NT_STATUS_IS_OK(result)) {
1349                         if (domain_name)
1350                                 fstrcpy(domain->name, domain_name);
1351
1352                         if (dom_sid) 
1353                                 sid_copy(&domain->sid, dom_sid);
1354                 }
1355         }
1356 done:
1357
1358         DEBUG(5, ("set_dc_type_and_flags: domain %s is %snative mode.\n",
1359                   domain->name, domain->native_mode ? "" : "NOT "));
1360
1361         DEBUG(5,("set_dc_type_and_flags: domain %s is %sactive directory.\n",
1362                   domain->name, domain->active_directory ? "" : "NOT "));
1363
1364         cli_rpc_pipe_close(cli);
1365         
1366         talloc_destroy(mem_ctx);
1367
1368         domain->initialized = True;
1369 }
1370
1371 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
1372                                    struct dcinfo **ppdc)
1373 {
1374         NTSTATUS result;
1375         struct rpc_pipe_client *netlogon_pipe;
1376
1377         if (lp_client_schannel() == False) {
1378                 return False;
1379         }
1380
1381         result = cm_connect_netlogon(domain, &netlogon_pipe);
1382         if (!NT_STATUS_IS_OK(result)) {
1383                 return False;
1384         }
1385
1386         /* Return a pointer to the struct dcinfo from the
1387            netlogon pipe. */
1388
1389         *ppdc = domain->conn.netlogon_pipe->dc;
1390         return True;
1391 }
1392
1393 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1394                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1395 {
1396         struct winbindd_cm_conn *conn;
1397         NTSTATUS result;
1398         fstring conn_pwd;
1399         struct dcinfo *p_dcinfo;
1400
1401         result = init_dc_connection(domain);
1402         if (!NT_STATUS_IS_OK(result)) {
1403                 return result;
1404         }
1405
1406         conn = &domain->conn;
1407
1408         if (conn->samr_pipe != NULL) {
1409                 goto done;
1410         }
1411
1412         /*
1413          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1414          * sign and sealed pipe using the machine account password by
1415          * preference. If we can't - try schannel, if that fails, try
1416          * anonymous.
1417          */
1418
1419         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1420         if ((conn->cli->user_name[0] == '\0') ||
1421             (conn->cli->domain[0] == '\0') || 
1422             (conn_pwd[0] == '\0')) {
1423                 DEBUG(10, ("cm_connect_sam: No no user available for "
1424                            "domain %s, trying schannel\n", conn->cli->domain));
1425                 goto schannel;
1426         }
1427
1428         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1429            authenticated SAMR pipe with sign & seal. */
1430         conn->samr_pipe =
1431                 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
1432                                                  PIPE_AUTH_LEVEL_PRIVACY,
1433                                                  conn->cli->domain,
1434                                                  conn->cli->user_name,
1435                                                  conn_pwd, &result);
1436
1437         if (conn->samr_pipe == NULL) {
1438                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1439                           "pipe for domain %s using NTLMSSP "
1440                           "authenticated pipe: user %s\\%s. Error was "
1441                           "%s\n", domain->name, conn->cli->domain,
1442                           conn->cli->user_name, nt_errstr(result)));
1443                 goto schannel;
1444         }
1445
1446         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1447                   "domain %s using NTLMSSP authenticated "
1448                   "pipe: user %s\\%s\n", domain->name,
1449                   conn->cli->domain, conn->cli->user_name ));
1450
1451         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1452                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1453                                      &conn->sam_connect_handle);
1454         if (NT_STATUS_IS_OK(result)) {
1455                 goto open_domain;
1456         }
1457         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1458                   "failed for domain %s, error was %s. Trying schannel\n",
1459                   domain->name, nt_errstr(result) ));
1460         cli_rpc_pipe_close(conn->samr_pipe);
1461
1462  schannel:
1463
1464         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1465
1466         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1467                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1468                            "for domain %s, trying anon\n", conn->cli->domain));
1469                 goto anonymous;
1470         }
1471         conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
1472                 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
1473                  domain->name, p_dcinfo, &result);
1474
1475         if (conn->samr_pipe == NULL) {
1476                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1477                           "domain %s using schannel. Error was %s\n",
1478                           domain->name, nt_errstr(result) ));
1479                 goto anonymous;
1480         }
1481         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1482                   "schannel.\n", domain->name ));
1483
1484         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1485                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1486                                      &conn->sam_connect_handle);
1487         if (NT_STATUS_IS_OK(result)) {
1488                 goto open_domain;
1489         }
1490         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1491                   "for domain %s, error was %s. Trying anonymous\n",
1492                   domain->name, nt_errstr(result) ));
1493         cli_rpc_pipe_close(conn->samr_pipe);
1494
1495  anonymous:
1496
1497         /* Finally fall back to anonymous. */
1498         conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
1499                                                    &result);
1500
1501         if (conn->samr_pipe == NULL) {
1502                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1503                 goto done;
1504         }
1505
1506         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1507                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
1508                                      &conn->sam_connect_handle);
1509         if (!NT_STATUS_IS_OK(result)) {
1510                 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1511                           "for domain %s Error was %s\n",
1512                           domain->name, nt_errstr(result) ));
1513                 goto done;
1514         }
1515
1516  open_domain:
1517         result = rpccli_samr_open_domain(conn->samr_pipe,
1518                                          mem_ctx,
1519                                          &conn->sam_connect_handle,
1520                                          SEC_RIGHTS_MAXIMUM_ALLOWED,
1521                                          &domain->sid,
1522                                          &conn->sam_domain_handle);
1523
1524  done:
1525
1526         if (!NT_STATUS_IS_OK(result)) {
1527                 invalidate_cm_connection(conn);
1528                 return result;
1529         }
1530
1531         *cli = conn->samr_pipe;
1532         *sam_handle = conn->sam_domain_handle;
1533         return result;
1534 }
1535
1536 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1537                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1538 {
1539         struct winbindd_cm_conn *conn;
1540         NTSTATUS result;
1541         fstring conn_pwd;
1542         struct dcinfo *p_dcinfo;
1543
1544         result = init_dc_connection(domain);
1545         if (!NT_STATUS_IS_OK(result))
1546                 return result;
1547
1548         conn = &domain->conn;
1549
1550         if (conn->lsa_pipe != NULL) {
1551                 goto done;
1552         }
1553
1554         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1555         if ((conn->cli->user_name[0] == '\0') ||
1556             (conn->cli->domain[0] == '\0') || 
1557             (conn_pwd[0] == '\0')) {
1558                 DEBUG(10, ("cm_connect_lsa: No no user available for "
1559                            "domain %s, trying schannel\n", conn->cli->domain));
1560                 goto schannel;
1561         }
1562
1563         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1564          * authenticated LSA pipe with sign & seal. */
1565         conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
1566                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1567                  conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
1568
1569         if (conn->lsa_pipe == NULL) {
1570                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1571                           "domain %s using NTLMSSP authenticated pipe: user "
1572                           "%s\\%s. Error was %s. Trying schannel.\n",
1573                           domain->name, conn->cli->domain,
1574                           conn->cli->user_name, nt_errstr(result)));
1575                 goto schannel;
1576         }
1577
1578         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1579                   "NTLMSSP authenticated pipe: user %s\\%s\n",
1580                   domain->name, conn->cli->domain, conn->cli->user_name ));
1581
1582         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1583                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1584                                         &conn->lsa_policy);
1585         if (NT_STATUS_IS_OK(result)) {
1586                 goto done;
1587         }
1588
1589         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1590                   "schannel\n"));
1591
1592         cli_rpc_pipe_close(conn->lsa_pipe);
1593
1594  schannel:
1595
1596         /* Fall back to schannel if it's a W2K pre-SP1 box. */
1597
1598         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1599                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1600                            "for domain %s, trying anon\n", conn->cli->domain));
1601                 goto anonymous;
1602         }
1603         conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
1604                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
1605                  domain->name, p_dcinfo, &result);
1606
1607         if (conn->lsa_pipe == NULL) {
1608                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1609                           "domain %s using schannel. Error was %s\n",
1610                           domain->name, nt_errstr(result) ));
1611                 goto anonymous;
1612         }
1613         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1614                   "schannel.\n", domain->name ));
1615
1616         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1617                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1618                                         &conn->lsa_policy);
1619         if (NT_STATUS_IS_OK(result)) {
1620                 goto done;
1621         }
1622
1623         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1624                   "anonymous\n"));
1625
1626         cli_rpc_pipe_close(conn->lsa_pipe);
1627
1628  anonymous:
1629
1630         conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
1631                                                   &result);
1632         if (conn->lsa_pipe == NULL) {
1633                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1634                 goto done;
1635         }
1636
1637         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1638                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
1639                                         &conn->lsa_policy);
1640  done:
1641         if (!NT_STATUS_IS_OK(result)) {
1642                 invalidate_cm_connection(conn);
1643                 return NT_STATUS_UNSUCCESSFUL;
1644         }
1645
1646         *cli = conn->lsa_pipe;
1647         *lsa_policy = conn->lsa_policy;
1648         return result;
1649 }
1650
1651 /****************************************************************************
1652  Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1653  session key stored in conn->netlogon_pipe->dc->sess_key.
1654 ****************************************************************************/
1655
1656 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1657                              struct rpc_pipe_client **cli)
1658 {
1659         struct winbindd_cm_conn *conn;
1660         NTSTATUS result;
1661
1662         uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1663         uint8  mach_pwd[16];
1664         uint32  sec_chan_type;
1665         const char *account_name;
1666         struct rpc_pipe_client *netlogon_pipe = NULL;
1667
1668         *cli = NULL;
1669
1670         result = init_dc_connection(domain);
1671         if (!NT_STATUS_IS_OK(result)) {
1672                 return result;
1673         }
1674
1675         conn = &domain->conn;
1676
1677         if (conn->netlogon_pipe != NULL) {
1678                 *cli = conn->netlogon_pipe;
1679                 return NT_STATUS_OK;
1680         }
1681
1682         if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1683                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1684         }
1685
1686         netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
1687                                                  &result);
1688         if (netlogon_pipe == NULL) {
1689                 return result;
1690         }
1691
1692         if (lp_client_schannel() != False) {
1693                 neg_flags |= NETLOGON_NEG_SCHANNEL;
1694         }
1695
1696         /* if we are a DC and this is a trusted domain, then we need to use our
1697            domain name in the net_req_auth2() request */
1698
1699         if ( IS_DC
1700                 && !strequal(domain->name, lp_workgroup())
1701                 && lp_allow_trusted_domains() ) 
1702         {
1703                 account_name = lp_workgroup();
1704         } else {
1705                 account_name = domain->primary ?
1706                         global_myname() : domain->name;
1707         }
1708
1709         if (account_name == NULL) {
1710                 cli_rpc_pipe_close(netlogon_pipe);
1711                 return NT_STATUS_NO_MEMORY;
1712         }
1713
1714         result = rpccli_netlogon_setup_creds(
1715                  netlogon_pipe,
1716                  domain->dcname, /* server name. */
1717                  domain->name,   /* domain name */
1718                  global_myname(), /* client name */
1719                  account_name,   /* machine account */
1720                  mach_pwd,       /* machine password */
1721                  sec_chan_type,  /* from get_trust_pw */
1722                  &neg_flags);
1723
1724         if (!NT_STATUS_IS_OK(result)) {
1725                 cli_rpc_pipe_close(netlogon_pipe);
1726                 return result;
1727         }
1728
1729         if ((lp_client_schannel() == True) &&
1730                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1731                 DEBUG(3, ("Server did not offer schannel\n"));
1732                 cli_rpc_pipe_close(netlogon_pipe);
1733                 return NT_STATUS_ACCESS_DENIED;
1734         }
1735
1736         if ((lp_client_schannel() == False) ||
1737                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1738                 /* We're done - just keep the existing connection to NETLOGON
1739                  * open */
1740                 conn->netlogon_pipe = netlogon_pipe;
1741                 *cli = conn->netlogon_pipe;
1742                 return NT_STATUS_OK;
1743         }
1744
1745         /* Using the credentials from the first pipe, open a signed and sealed
1746            second netlogon pipe. The session key is stored in the schannel
1747            part of the new pipe auth struct.
1748         */
1749
1750         conn->netlogon_pipe =
1751                 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1752                                                     PI_NETLOGON,
1753                                                     PIPE_AUTH_LEVEL_PRIVACY,
1754                                                     domain->name,
1755                                                     netlogon_pipe->dc,
1756                                                     &result);
1757
1758         /* We can now close the initial netlogon pipe. */
1759         cli_rpc_pipe_close(netlogon_pipe);
1760
1761         if (conn->netlogon_pipe == NULL) {
1762                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1763                           "was %s\n", nt_errstr(result)));
1764                           
1765                 /* make sure we return something besides OK */
1766                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
1767         }
1768
1769         *cli = conn->netlogon_pipe;
1770         return NT_STATUS_OK;
1771 }