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