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