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