r8796: disable schannel on the lsa client pipe for now to deal with Windows 2003...
[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 /* Global list of connections.  Initially a DLIST but can become a hash
68    table or whatever later. */
69
70 /* Choose between anonymous or authenticated connections.  We need to use
71    an authenticated connection if DCs have the RestrictAnonymous registry
72    entry set > 0, or the "Additional restrictions for anonymous
73    connections" set in the win2k Local Security Policy. 
74    
75    Caller to free() result in domain, username, password
76 */
77
78 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
79 {
80         *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
81         *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
82         *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
83         
84         if (*username && **username) {
85
86                 if (!*domain || !**domain)
87                         *domain = smb_xstrdup(lp_workgroup());
88                 
89                 if (!*password || !**password)
90                         *password = smb_xstrdup("");
91
92                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
93                           *domain, *username));
94
95         } else {
96                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
97                 *username = smb_xstrdup("");
98                 *domain = smb_xstrdup("");
99                 *password = smb_xstrdup("");
100         }
101 }
102
103 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
104                                      fstring dcname, struct in_addr *dc_ip)
105 {
106         struct winbindd_domain *our_domain;
107         NTSTATUS result;
108         struct rpc_pipe_client *cli;
109         TALLOC_CTX *mem_ctx;
110
111         fstring tmp;
112         char *p;
113
114         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
115          * moment.... */
116
117         if (IS_DC)
118                 return False;
119
120         if (domain->primary)
121                 return False;
122
123         our_domain = find_our_domain();
124
125         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL)
126                 return False;
127
128         {
129                 /* These var's can be ignored -- we're not requesting
130                    anything in the credential chain here */
131                 unsigned char *session_key;
132                 DOM_CRED *creds;
133                 result = cm_connect_netlogon(our_domain, mem_ctx, &cli,
134                                              &session_key, &creds);
135         }
136
137         if (!NT_STATUS_IS_OK(result))
138                 return False;
139
140         result = rpccli_netlogon_getdcname(cli, mem_ctx, domain->dcname,
141                                            domain->name, tmp);
142
143         talloc_destroy(mem_ctx);
144
145         if (!NT_STATUS_IS_OK(result))
146                 return False;
147
148         /* cli_netlogon_getdcname gives us a name with \\ */
149         p = tmp;
150         if (*p == '\\') p+=1;
151         if (*p == '\\') p+=1;
152
153         fstrcpy(dcname, p);
154
155         if (!resolve_name(dcname, dc_ip, 0x20))
156                 return False;
157
158         return True;
159 }
160
161 /************************************************************************
162  Given a fd with a just-connected TCP connection to a DC, open a connection
163  to the pipe.
164 ************************************************************************/
165
166 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
167                                       const int sockfd,
168                                       const char *controller,
169                                       struct cli_state **cli,
170                                       BOOL *retry)
171 {
172         char *machine_password, *machine_krb5_principal;
173         char *ipc_username, *ipc_domain, *ipc_password;
174
175         BOOL got_mutex;
176         BOOL add_failed_connection = True;
177
178         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
179
180         struct sockaddr peeraddr;
181         socklen_t peeraddr_len;
182
183         struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
184
185         machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
186                                                           NULL);
187         
188         if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
189                      lp_realm()) == -1) {
190                 SAFE_FREE(machine_password);
191                 return NT_STATUS_NO_MEMORY;
192         }
193
194         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
195
196         *retry = True;
197
198         got_mutex = secrets_named_mutex(controller,
199                                         WINBIND_SERVER_MUTEX_WAIT_TIME);
200
201         if (!got_mutex) {
202                 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n",
203                          controller));
204                 result = NT_STATUS_POSSIBLE_DEADLOCK;
205                 goto done;
206         }
207
208         if ((*cli = cli_initialise(NULL)) == NULL) {
209                 DEBUG(1, ("Could not cli_initialize\n"));
210                 result = NT_STATUS_NO_MEMORY;
211                 goto done;
212         }
213
214         (*cli)->timeout = 10000;        /* 10 seconds */
215         (*cli)->fd = sockfd;
216         fstrcpy((*cli)->desthost, controller);
217         (*cli)->use_kerberos = True;
218
219         peeraddr_len = sizeof(peeraddr);
220
221         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
222             (peeraddr_len != sizeof(struct sockaddr_in)) ||
223             (peeraddr_in->sin_family != PF_INET))
224         {
225                 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
226                 goto done;
227         }
228
229         if (ntohs(peeraddr_in->sin_port) == 139) {
230                 struct nmb_name calling;
231                 struct nmb_name called;
232
233                 make_nmb_name(&calling, global_myname(), 0x0);
234                 make_nmb_name(&called, "*SMBSERVER", 0x20);
235
236                 if (!cli_session_request(*cli, &calling, &called)) {
237                         DEBUG(8, ("cli_session_request failed for %s\n",
238                                   controller));
239                         goto done;
240                 }
241         }
242
243         cli_setup_signing_state(*cli, Undefined);
244
245         if (!cli_negprot(*cli)) {
246                 DEBUG(1, ("cli_negprot failed\n"));
247                 cli_shutdown(*cli);
248                 goto done;
249         }
250
251         /* Krb5 session */
252                         
253         if ((lp_security() == SEC_ADS) 
254             && ((*cli)->protocol >= PROTOCOL_NT1 &&
255                 (*cli)->capabilities & CAP_EXTENDED_SECURITY)) {
256
257                 ADS_STATUS ads_status;
258                 (*cli)->use_kerberos = True;
259                 DEBUG(5, ("connecting to %s from %s with kerberos principal "
260                           "[%s]\n", controller, global_myname(),
261                           machine_krb5_principal));
262
263                 ads_status = cli_session_setup_spnego(*cli,
264                                                       machine_krb5_principal, 
265                                                       machine_password, 
266                                                       lp_workgroup());
267
268                 if (!ADS_ERR_OK(ads_status))
269                         DEBUG(4,("failed kerberos session setup with %s\n",
270                                  ads_errstr(ads_status)));
271
272                 result = ads_ntstatus(ads_status);
273         }
274
275         if (NT_STATUS_IS_OK(result))
276                 goto session_setup_done;
277
278         /* Fall back to non-kerberos session setup */
279
280         (*cli)->use_kerberos = False;
281
282         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
283             (strlen(ipc_username) > 0)) {
284
285                 /* Only try authenticated if we have a username */
286
287                 DEBUG(5, ("connecting to %s from %s with username "
288                           "[%s]\\[%s]\n",  controller, global_myname(),
289                           ipc_domain, ipc_username));
290
291                 if (cli_session_setup(*cli, ipc_username,
292                                       ipc_password, strlen(ipc_password)+1,
293                                       ipc_password, strlen(ipc_password)+1,
294                                       ipc_domain)) {
295                         DEBUG(5, ("authenticated session setup failed\n"));
296                         goto session_setup_done;
297                 }
298         }
299
300         /* Fall back to anonymous connection, this might fail later */
301
302         if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
303                 DEBUG(5, ("Connected anonymously\n"));
304                 goto session_setup_done;
305         }
306
307         result = cli_nt_error(*cli);
308
309         if (NT_STATUS_IS_OK(result))
310                 result = NT_STATUS_UNSUCCESSFUL;
311
312         /* We can't session setup */
313
314         goto done;
315
316  session_setup_done:
317
318         if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
319
320                 result = cli_nt_error(*cli);
321
322                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
323
324                 if (NT_STATUS_IS_OK(result))
325                         result = NT_STATUS_UNSUCCESSFUL;
326
327                 cli_shutdown(*cli);
328                 goto done;
329         }
330
331         secrets_named_mutex_release(controller);
332         got_mutex = False;
333         *retry = False;
334
335         /* set the domain if empty; needed for schannel connections */
336         if ( !*(*cli)->domain )
337                 fstrcpy( (*cli)->domain, domain->name );
338
339         (*cli)->pipe_auth_flags = 0;
340
341         result = NT_STATUS_OK;
342         add_failed_connection = False;
343
344  done:
345         if (got_mutex)
346                 secrets_named_mutex_release(controller);
347
348         SAFE_FREE(machine_password);
349         SAFE_FREE(machine_krb5_principal);
350         SAFE_FREE(ipc_username);
351         SAFE_FREE(ipc_domain);
352         SAFE_FREE(ipc_password);
353
354         if (add_failed_connection)
355                 add_failed_connection_entry(domain->name, controller, result);
356
357         return result;
358 }
359
360 struct dc_name_ip {
361         fstring name;
362         struct in_addr ip;
363 };
364
365 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
366                               const char *dcname, struct in_addr ip,
367                               struct dc_name_ip **dcs, int *num)
368 {
369         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname)))
370                 return False;
371
372         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
373
374         if (*dcs == NULL)
375                 return False;
376
377         fstrcpy((*dcs)[*num].name, dcname);
378         (*dcs)[*num].ip = ip;
379         *num += 1;
380         return True;
381 }
382
383 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
384                                   struct in_addr ip, uint16 port,
385                                   struct sockaddr_in **addrs, int *num)
386 {
387         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
388
389         if (*addrs == NULL)
390                 return False;
391
392         (*addrs)[*num].sin_family = PF_INET;
393         putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
394         (*addrs)[*num].sin_port = htons(port);
395
396         *num += 1;
397         return True;
398 }
399
400 static void mailslot_name(struct in_addr dc_ip, fstring name)
401 {
402         fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
403 }
404
405 static BOOL send_getdc_request(struct in_addr dc_ip,
406                                const char *domain_name,
407                                const DOM_SID *sid)
408 {
409         pstring outbuf;
410         char *p;
411         fstring my_acct_name;
412         fstring my_mailslot;
413
414         mailslot_name(dc_ip, my_mailslot);
415
416         memset(outbuf, '\0', sizeof(outbuf));
417
418         p = outbuf;
419
420         SCVAL(p, 0, SAMLOGON);
421         p++;
422
423         SCVAL(p, 0, 0); /* Count pointer ... */
424         p++;
425
426         SIVAL(p, 0, 0); /* The sender's token ... */
427         p += 2;
428
429         p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
430         fstr_sprintf(my_acct_name, "%s$", global_myname());
431         p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
432
433         memcpy(p, my_mailslot, strlen(my_mailslot)+1);
434         p += strlen(my_mailslot)+1;
435
436         SIVAL(p, 0, 0x80);
437         p+=4;
438
439         SIVAL(p, 0, sid_size(sid));
440         p+=4;
441
442         p = ALIGN4(p, outbuf);
443
444         sid_linearize(p, sid_size(sid), sid);
445         p += sid_size(sid);
446
447         SIVAL(p, 0, 1);
448         SSVAL(p, 4, 0xffff);
449         SSVAL(p, 6, 0xffff);
450         p+=8;
451
452         return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
453                                  outbuf, PTR_DIFF(p, outbuf),
454                                  global_myname(), 0, domain_name, 0x1c,
455                                  dc_ip);
456 }
457
458 static BOOL receive_getdc_response(struct in_addr dc_ip,
459                                    const char *domain_name,
460                                    fstring dc_name)
461 {
462         struct packet_struct *packet;
463         fstring my_mailslot;
464         char *buf, *p;
465         fstring dcname, user, domain;
466         int len;
467
468         mailslot_name(dc_ip, my_mailslot);
469
470         packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
471
472         if (packet == NULL) {
473                 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
474                 return False;
475         }
476
477         DEBUG(5, ("Received packet for %s\n", my_mailslot));
478
479         buf = packet->packet.dgram.data;
480         len = packet->packet.dgram.datasize;
481
482         if (len < 70) {
483                 /* 70 is a completely arbitrary value to make sure
484                    the SVAL below does not read uninitialized memory */
485                 DEBUG(3, ("GetDC got short response\n"));
486                 return False;
487         }
488
489         /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
490         p = buf+SVAL(buf, smb_vwv10);
491
492         if (CVAL(p,0) != SAMLOGON_R) {
493                 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
494                 return False;
495         }
496
497         p+=2;
498         pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
499                   STR_TERMINATE|STR_NOALIGN);
500         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
501         pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
502                   STR_TERMINATE|STR_NOALIGN);
503         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
504         pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
505                   STR_TERMINATE|STR_NOALIGN);
506         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
507
508         if (!strequal(domain, domain_name)) {
509                 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
510                           domain_name, domain));
511                 return False;
512         }
513
514         p = dcname;
515         if (*p == '\\') p += 1;
516         if (*p == '\\') p += 1;
517
518         fstrcpy(dc_name, p);
519
520         DEBUG(10, ("GetDC gave name %s for domain %s\n",
521                    dc_name, domain));
522
523         return True;
524 }
525
526 /*******************************************************************
527  convert an ip to a name
528 *******************************************************************/
529
530 static void dcip_to_name( const char *domainname, const char *realm, 
531                           const DOM_SID *sid, struct in_addr ip, fstring name )
532 {
533         int i;
534
535         /* try GETDC requests first */
536         
537         send_getdc_request(ip, domainname, sid);
538         smb_msleep(100);
539
540         for (i=0; i<5; i++) {
541                 if (receive_getdc_response(ip, domainname, name))
542                         return;
543                 smb_msleep(500);
544         }
545
546         /* try node status request */
547
548         if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
549                 return;
550
551         /* backup in case the netbios stuff fails */
552
553         fstrcpy( name, inet_ntoa(ip) );
554
555 #ifdef WITH_ADS
556         /* for active directory servers, try to get the ldap server name.
557            None of these failure should be considered critical for now */
558
559         if ( lp_security() == SEC_ADS ) 
560         {
561                 ADS_STRUCT *ads;
562                 ADS_STATUS status;
563
564                 ads = ads_init( realm, domainname, NULL );
565                 ads->auth.flags |= ADS_AUTH_NO_BIND;
566
567                 if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) )  {
568                         ads_destroy( &ads );
569                         return;
570                 }
571
572                 status = ads_server_info(ads);
573                 if ( !ADS_ERR_OK(status) ) {
574                         ads_destroy( &ads );
575                         return;
576                 }
577
578                 fstrcpy(name, ads->config.ldap_server_name);
579
580                 ads_destroy( &ads );
581         }
582 #endif
583
584         return;
585 }
586
587 /*******************************************************************
588  Retreive a list of IP address for domain controllers.  Fill in 
589  the dcs[]  with results.
590 *******************************************************************/
591
592 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
593                     struct dc_name_ip **dcs, int *num_dcs)
594 {
595         fstring dcname;
596         struct  in_addr ip;
597         struct  ip_service *ip_list = NULL;
598         int     iplist_size = 0;
599         int     i;
600         BOOL    is_our_domain;
601
602
603         is_our_domain = strequal(domain->name, lp_workgroup());
604
605         if ( !is_our_domain 
606                 && get_dc_name_via_netlogon(domain, dcname, &ip) 
607                 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
608         {
609                 return True;
610         }
611
612         if ( is_our_domain 
613                 && must_use_pdc(domain->name) 
614                 && get_pdc_ip(domain->name, &ip)) 
615         {
616                 if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs)) 
617                         return True;
618         }
619
620         /* try standard netbios queries first */
621
622         get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
623
624         /* check for security = ads and use DNS if we can */
625
626         if ( iplist_size==0 && lp_security() == SEC_ADS ) 
627                 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
628
629         /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
630
631         /* now add to the dc array.  We'll wait until the last minute 
632            to look up the name of the DC.  But we fill in the char* for 
633            the ip now in to make the failed connection cache work */
634
635         for ( i=0; i<iplist_size; i++ ) {
636                 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip), 
637                         ip_list[i].ip, dcs, num_dcs);
638         }
639
640         SAFE_FREE( ip_list );
641
642         return True;
643 }
644
645 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
646                         const struct winbindd_domain *domain,
647                         fstring dcname, struct sockaddr_in *addr, int *fd)
648 {
649         struct dc_name_ip *dcs = NULL;
650         int num_dcs = 0;
651
652         const char **dcnames = NULL;
653         int num_dcnames = 0;
654
655         struct sockaddr_in *addrs = NULL;
656         int num_addrs = 0;
657
658         int i, fd_index;
659
660         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
661                 return False;
662
663         for (i=0; i<num_dcs; i++) {
664
665                 add_string_to_array(mem_ctx, dcs[i].name,
666                                     &dcnames, &num_dcnames);
667                 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
668                                       &addrs, &num_addrs);
669
670                 add_string_to_array(mem_ctx, dcs[i].name,
671                                     &dcnames, &num_dcnames);
672                 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
673                                       &addrs, &num_addrs);
674         }
675
676         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
677                 return False;
678
679         if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) ) 
680         {
681                 for (i=0; i<num_dcs; i++) {
682                         add_failed_connection_entry(domain->name,
683                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
684                 }
685                 return False;
686         }
687
688         *addr = addrs[fd_index];
689
690         /* if we have no name on the server or just an IP address for 
691            the name, now try to get the name */
692
693         if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
694                 dcip_to_name( domain->name, domain->alt_name, &domain->sid, addr->sin_addr, dcname );
695         else
696                 fstrcpy(dcname, dcnames[fd_index]);
697
698         return True;
699 }
700
701 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
702                                    struct winbindd_cm_conn *new_conn)
703 {
704         TALLOC_CTX *mem_ctx;
705         NTSTATUS result;
706
707         int retries;
708
709         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
710                 return NT_STATUS_NO_MEMORY;
711
712         for (retries = 0; retries < 3; retries++) {
713
714                 int fd = -1;
715                 BOOL retry;
716
717                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
718
719                 if ((strlen(domain->dcname) > 0) &&
720                     NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
721                                                               domain->dcname))) {
722                         int dummy;
723                         if (!open_any_socket_out(&domain->dcaddr, 1, 10000,
724                                                  &dummy, &fd)) {
725                                 fd = -1;
726                         }
727                 }
728
729                 if ((fd == -1) &&
730                     !find_new_dc(mem_ctx, domain, domain->dcname,
731                                  &domain->dcaddr, &fd))
732                         break;
733
734                 new_conn->cli = NULL;
735
736                 result = cm_prepare_connection(domain, fd, domain->dcname,
737                         &new_conn->cli, &retry);
738
739                 if (!retry)
740                         break;
741         }
742
743         talloc_destroy(mem_ctx);
744         return result;
745 }
746
747 /* Return true if a connection is still alive */
748
749 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
750 {
751         if (conn->samr_pipe != NULL) {
752                 cli_rpc_close(conn->samr_pipe);
753                 conn->samr_pipe = NULL;
754         }
755
756         if (conn->lsa_pipe != NULL) {
757                 cli_rpc_close(conn->lsa_pipe);
758                 conn->lsa_pipe = NULL;
759         }
760
761         if (conn->netlogon_auth2_pipe != NULL) {
762                 cli_rpc_close(conn->netlogon_auth2_pipe);
763                 conn->netlogon_auth2_pipe = NULL;
764         }
765
766         if (conn->netlogon_pipe != NULL) {
767                 cli_rpc_close(conn->netlogon_pipe);
768                 conn->netlogon_pipe = NULL;
769         }
770
771         if (conn->cli)
772                 cli_shutdown(conn->cli);
773
774         conn->cli = NULL;
775 }
776
777 void close_conns_after_fork(void)
778 {
779         struct winbindd_domain *domain;
780
781         for (domain = domain_list(); domain; domain = domain->next) {
782                 if (domain->conn.cli == NULL)
783                         continue;
784
785                 if (domain->conn.cli->fd == -1)
786                         continue;
787
788                 close(domain->conn.cli->fd);
789                 domain->conn.cli->fd = -1;
790         }
791 }
792
793 static BOOL connection_ok(struct winbindd_domain *domain)
794 {
795         if (domain->conn.cli == NULL) {
796                 DEBUG(8, ("Connection to %s for domain %s has NULL "
797                           "cli!\n", domain->dcname, domain->name));
798                 return False;
799         }
800
801         if (!domain->conn.cli->initialised) {
802                 DEBUG(3, ("Connection to %s for domain %s was never "
803                           "initialised!\n", domain->dcname, domain->name));
804                 return False;
805         }
806
807         if (domain->conn.cli->fd == -1) {
808                 DEBUG(3, ("Connection to %s for domain %s has died or was "
809                           "never started (fd == -1)\n", 
810                           domain->dcname, domain->name));
811                 return False;
812         }
813
814         return True;
815 }
816         
817 /* Initialize a new connection up to the RPC BIND. */
818
819 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
820 {
821         if (connection_ok(domain))
822                 return NT_STATUS_OK;
823
824         invalidate_cm_connection(&domain->conn);
825
826         return cm_open_connection(domain, &domain->conn);
827 }
828
829 /**********************************************************************************
830  We can 'sense' certain things about the DC by it's replies to certain questions.
831
832  This tells us if this particular remote server is Active Directory, and if it is
833  native mode.
834 **********************************************************************************/
835
836 void set_dc_type_and_flags( struct winbindd_domain *domain )
837 {
838         NTSTATUS                result;
839         DS_DOMINFO_CTR          ctr;
840         TALLOC_CTX              *mem_ctx = NULL;
841         struct rpc_pipe_client  *cli;
842         POLICY_HND pol;
843         
844         char *domain_name = NULL;
845         char *dns_name = NULL;
846         DOM_SID *dom_sid = NULL;
847
848         ZERO_STRUCT( ctr );
849         
850         domain->native_mode = False;
851         domain->active_directory = False;
852
853         if (domain->internal) {
854                 domain->initialized = True;
855                 return;
856         }
857
858         result = init_dc_connection(domain);
859         if (!NT_STATUS_IS_OK(result)) {
860                 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
861                           "to %s: (%s)\n", domain->name, nt_errstr(result)));
862                 domain->initialized = True;
863                 return;
864         }
865
866         cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC_DS);
867
868         if (cli == NULL) {
869                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
870                           "PI_LSARPC_DS on domain %s: (%s)\n",
871                           domain->name, nt_errstr(result)));
872                 domain->initialized = True;
873                 return;
874         }
875
876         result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
877                                              DsRolePrimaryDomainInfoBasic,
878                                              &ctr);
879         cli_rpc_close(cli);
880
881         if (!NT_STATUS_IS_OK(result)) {
882                 domain->initialized = True;
883                 return;
884         }
885         
886         if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
887             !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
888                 domain->native_mode = True;
889
890         cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC);
891
892         if (cli == NULL) {
893                 domain->initialized = True;
894                 return;
895         }
896
897         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
898                               domain->name);
899         if (!mem_ctx) {
900                 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
901                 return;
902         }
903
904         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
905                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
906                 
907         if (NT_STATUS_IS_OK(result)) {
908                 /* This particular query is exactly what Win2k clients use 
909                    to determine that the DC is active directory */
910                 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
911                                                        12, &domain_name,
912                                                        &dns_name, NULL,
913                                                        NULL, &dom_sid);
914         }
915
916         if (NT_STATUS_IS_OK(result)) {
917                 if (domain_name)
918                         fstrcpy(domain->name, domain_name);
919
920                 if (dns_name)
921                         fstrcpy(domain->alt_name, dns_name);
922
923                 if (dom_sid) 
924                         sid_copy(&domain->sid, dom_sid);
925
926                 domain->active_directory = True;
927         } else {
928                 
929                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
930                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
931                                                 &pol);
932                         
933                 if (!NT_STATUS_IS_OK(result))
934                         goto done;
935                         
936                 result = rpccli_lsa_query_info_policy(cli, mem_ctx, 
937                                                       &pol, 5, &domain_name, 
938                                                       &dom_sid);
939                         
940                 if (NT_STATUS_IS_OK(result)) {
941                         if (domain_name)
942                                 fstrcpy(domain->name, domain_name);
943
944                         if (dom_sid) 
945                                 sid_copy(&domain->sid, dom_sid);
946                 }
947         }
948 done:
949
950         cli_rpc_close(cli);
951         
952         talloc_destroy(mem_ctx);
953
954         domain->initialized = True;
955         
956         return;
957 }
958
959 static BOOL cm_get_schannel_key(struct winbindd_domain *domain,
960                                 TALLOC_CTX *mem_ctx,
961                                 unsigned char **session_key)
962 {
963         struct rpc_pipe_client *cli;
964         DOM_CRED *credentials;
965
966         if (lp_client_schannel() == False)
967                 return False;
968
969         return NT_STATUS_IS_OK(cm_connect_netlogon(domain, mem_ctx,
970                                                    &cli, session_key,
971                                                    &credentials));
972 }
973
974 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
975                         struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
976 {
977         struct winbindd_cm_conn *conn;
978         NTSTATUS result;
979
980         result = init_dc_connection(domain);
981         if (!NT_STATUS_IS_OK(result))
982                 return result;
983
984         conn = &domain->conn;
985
986         if (conn->samr_pipe == NULL) {
987                 unsigned char *session_key;
988
989                 if (cm_get_schannel_key(domain, mem_ctx, &session_key))
990                         conn->samr_pipe = cli_rpc_open_schannel(conn->cli,
991                                                                 PI_SAMR,
992                                                                 session_key,
993                                                                 domain->name);
994                 else
995                         conn->samr_pipe = cli_rpc_open_noauth(conn->cli,
996                                                               PI_SAMR);
997
998                 if (conn->samr_pipe == NULL) {
999                         result = NT_STATUS_PIPE_NOT_AVAILABLE;
1000                         goto done;
1001                 }
1002
1003                 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1004                                              SEC_RIGHTS_MAXIMUM_ALLOWED,
1005                                              &conn->sam_connect_handle);
1006                 if (!NT_STATUS_IS_OK(result))
1007                         goto done;
1008
1009                 result = rpccli_samr_open_domain(conn->samr_pipe,
1010                                                  mem_ctx,
1011                                                  &conn->sam_connect_handle,
1012                                                  SEC_RIGHTS_MAXIMUM_ALLOWED,
1013                                                  &domain->sid,
1014                                                  &conn->sam_domain_handle);
1015         }
1016
1017  done:
1018         if (!NT_STATUS_IS_OK(result)) {
1019                 invalidate_cm_connection(conn);
1020                 return NT_STATUS_UNSUCCESSFUL;
1021         }
1022
1023         *cli = conn->samr_pipe;
1024         *sam_handle = conn->sam_domain_handle;
1025         return result;
1026 }
1027
1028 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1029                         struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1030 {
1031         struct winbindd_cm_conn *conn;
1032         NTSTATUS result;
1033
1034         result = init_dc_connection(domain);
1035         if (!NT_STATUS_IS_OK(result))
1036                 return result;
1037
1038         conn = &domain->conn;
1039
1040         if (conn->lsa_pipe == NULL) {
1041 #if 0
1042                 /* disabling schannl on the LSA pipe for now since 
1043                    both Win2K-SP4 SR1 & Win2K3-SP1 fail the open_policy() 
1044                    call (return codes 0xc0020042 and 0xc0020041 respectively).
1045                    We really need to fix this soon.  --jerry  */
1046
1047                 unsigned char *session_key;
1048
1049                 if (cm_get_schannel_key(domain, mem_ctx, &session_key))
1050                         conn->lsa_pipe = cli_rpc_open_schannel(conn->cli,
1051                                                                PI_LSARPC,
1052                                                                session_key,
1053                                                                domain->name);
1054                 else
1055 #endif
1056                         conn->lsa_pipe = cli_rpc_open_noauth(conn->cli,
1057                                                              PI_LSARPC);
1058
1059                 if (conn->lsa_pipe == NULL) {
1060                         result = NT_STATUS_PIPE_NOT_AVAILABLE;
1061                         goto done;
1062                 }
1063
1064                 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1065                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
1066                                                 &conn->lsa_policy);
1067         }
1068
1069  done:
1070         if (!NT_STATUS_IS_OK(result)) {
1071                 invalidate_cm_connection(conn);
1072                 return NT_STATUS_UNSUCCESSFUL;
1073         }
1074
1075         *cli = conn->lsa_pipe;
1076         *lsa_policy = conn->lsa_policy;
1077         return result;
1078 }
1079
1080 /*******************************************************************
1081  wrapper around retrieving the trust account password
1082 *******************************************************************/
1083
1084 static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16],
1085                          uint32 *channel)
1086 {
1087         DOM_SID sid;
1088         char *pwd;
1089         time_t last_set_time;
1090
1091         /* if we are a DC and this is not our domain, then lookup an account
1092            for the domain trust */
1093
1094         if ( IS_DC && !strequal(domain, lp_workgroup()) &&
1095              lp_allow_trusted_domains() ) {
1096
1097                 if (!secrets_fetch_trusted_domain_password(domain, &pwd, &sid,
1098                                                            &last_set_time)) {
1099                         DEBUG(0, ("get_trust_pw: could not fetch trust "
1100                                   "account password for trusted domain %s\n",
1101                                   domain));
1102                         return False;
1103                 }
1104
1105                 *channel = SEC_CHAN_DOMAIN;
1106                 E_md4hash(pwd, ret_pwd);
1107                 SAFE_FREE(pwd);
1108
1109                 return True;
1110         }
1111
1112         /* Just get the account for the requested domain. In the future this
1113          * might also cover to be member of more than one domain. */
1114
1115         if (secrets_fetch_trust_account_password(domain, ret_pwd,
1116                                                  &last_set_time, channel))
1117                 return True;
1118
1119         DEBUG(5, ("get_trust_pw: could not fetch trust account "
1120                   "password for domain %s\n", domain));
1121         return False;
1122 }
1123
1124 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1125                              TALLOC_CTX *mem_ctx,
1126                              struct rpc_pipe_client **cli,
1127                              unsigned char **session_key,
1128                              DOM_CRED **credentials)
1129 {
1130         struct winbindd_cm_conn *conn;
1131         NTSTATUS result;
1132
1133         uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1134         uint8  mach_pwd[16];
1135         uint32  sec_chan_type;
1136         DOM_CHAL clnt_chal, srv_chal, rcv_chal;
1137         const char *server_name;
1138         const char *account_name;
1139         UTIME zerotime;
1140
1141         result = init_dc_connection(domain);
1142         if (!NT_STATUS_IS_OK(result))
1143                 return result;
1144
1145         conn = &domain->conn;
1146
1147         if (conn->netlogon_pipe != NULL) {
1148                 *cli = conn->netlogon_pipe;
1149                 *session_key = (unsigned char *)&conn->sess_key;
1150                 *credentials = &conn->clnt_cred;
1151                 return NT_STATUS_OK;
1152         }
1153
1154         if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type))
1155                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1156
1157         conn->netlogon_auth2_pipe = cli_rpc_open_noauth(conn->cli,
1158                                                         PI_NETLOGON);
1159         if (conn->netlogon_auth2_pipe == NULL)
1160                 return NT_STATUS_UNSUCCESSFUL;
1161
1162         if (lp_client_schannel() != False)
1163                 neg_flags |= NETLOGON_NEG_SCHANNEL;
1164
1165         generate_random_buffer(clnt_chal.data, 8);
1166
1167         server_name = talloc_asprintf(mem_ctx, "\\\\%s", domain->dcname);
1168
1169         /* if we are a DC and this is a trusted domain, then we need to use our
1170            domain name in the net_req_auth2() request */
1171
1172         if ( IS_DC ) {
1173                 account_name = talloc_asprintf( mem_ctx, "%s$", lp_workgroup() );
1174         }
1175         else {
1176                 account_name = talloc_asprintf(mem_ctx, "%s$", 
1177                         domain->primary ?  global_myname() : domain->name);
1178         }
1179
1180         if ((server_name == NULL) || (account_name == NULL))
1181                 return NT_STATUS_NO_MEMORY;
1182
1183         result = rpccli_net_req_chal(conn->netlogon_auth2_pipe, server_name,
1184                                      global_myname(), &clnt_chal, &srv_chal);
1185         if (!NT_STATUS_IS_OK(result))
1186                 return result;
1187
1188         /**************** Long-term Session key **************/
1189
1190         /* calculate the session key */
1191         cred_session_key(&clnt_chal, &srv_chal, mach_pwd, conn->sess_key);
1192         memset((char *)conn->sess_key+8, '\0', 8);
1193
1194         /* calculate auth2 credentials */
1195         zerotime.time = 0;
1196         cred_create(conn->sess_key, &clnt_chal, zerotime,
1197                     &conn->clnt_cred.challenge);
1198
1199         result = rpccli_net_auth2(conn->netlogon_auth2_pipe, server_name,
1200                                   account_name, sec_chan_type, global_myname(),
1201                                   &conn->clnt_cred.challenge, &neg_flags,
1202                                   &rcv_chal);
1203
1204         if (!NT_STATUS_IS_OK(result))
1205                 return result;
1206
1207         zerotime.time = 0;
1208         if (!cred_assert(&rcv_chal, conn->sess_key, &srv_chal, zerotime)) {
1209                 DEBUG(0, ("Server replied with bad credential\n"));
1210                 return NT_STATUS_ACCESS_DENIED;
1211         }
1212
1213         if ((lp_client_schannel() == True) &&
1214             ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1215                 DEBUG(3, ("Server did not offer schannel\n"));
1216                 cli_rpc_close(conn->netlogon_auth2_pipe);
1217                 conn->netlogon_auth2_pipe = NULL;
1218                 return NT_STATUS_ACCESS_DENIED;
1219         }
1220
1221         if ((lp_client_schannel() == False) ||
1222             ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1223                 /* keep the existing connection to NETLOGON open */
1224                 conn->netlogon_pipe = conn->netlogon_auth2_pipe;
1225                 conn->netlogon_auth2_pipe = NULL;
1226                 *cli = conn->netlogon_pipe;
1227                 *session_key = (unsigned char *)&conn->sess_key;
1228                 *credentials = &conn->clnt_cred;
1229                 return NT_STATUS_OK;
1230         }
1231
1232         conn->netlogon_pipe = cli_rpc_open_schannel(conn->cli, PI_NETLOGON,
1233                                                     conn->sess_key,
1234                                                     domain->name);
1235
1236         if (conn->netlogon_pipe == NULL) {
1237                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe\n"));
1238                 cli_rpc_close(conn->netlogon_auth2_pipe);
1239                 conn->netlogon_auth2_pipe = NULL;
1240                 return NT_STATUS_ACCESS_DENIED;
1241         }
1242
1243         *cli = conn->netlogon_pipe;
1244         *session_key = (unsigned char *)&conn->sess_key;
1245         *credentials = &conn->clnt_cred;
1246                 
1247         return NT_STATUS_OK;
1248 }