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