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