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