2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
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
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.
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.
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.
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:
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
35 - manage re-entrancy for when winbindd becomes able to handle
36 multiple outstanding rpc requests
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.
45 The TNG design is quite good but I disagree with some aspects of the
53 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
54 moved down into another function.
56 - Take care when destroying cli_structs as they can be shared between
65 #define DBGC_CLASS DBGC_WINBIND
68 /* Choose between anonymous or authenticated connections. We need to use
69 an authenticated connection if DCs have the RestrictAnonymous registry
70 entry set > 0, or the "Additional restrictions for anonymous
71 connections" set in the win2k Local Security Policy.
73 Caller to free() result in domain, username, password
76 static void cm_get_ipc_userpass(char **username
, char **domain
, char **password
)
78 *username
= secrets_fetch(SECRETS_AUTH_USER
, NULL
);
79 *domain
= secrets_fetch(SECRETS_AUTH_DOMAIN
, NULL
);
80 *password
= secrets_fetch(SECRETS_AUTH_PASSWORD
, NULL
);
82 if (*username
&& **username
) {
84 if (!*domain
|| !**domain
)
85 *domain
= smb_xstrdup(lp_workgroup());
87 if (!*password
|| !**password
)
88 *password
= smb_xstrdup("");
90 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
94 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
95 *username
= smb_xstrdup("");
96 *domain
= smb_xstrdup("");
97 *password
= smb_xstrdup("");
101 static BOOL
get_dc_name_via_netlogon(const struct winbindd_domain
*domain
,
102 fstring dcname
, struct in_addr
*dc_ip
)
104 struct winbindd_domain
*our_domain
= NULL
;
105 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
112 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
119 if (domain
->primary
) {
123 our_domain
= find_our_domain();
125 if ((mem_ctx
= talloc_init("get_dc_name_via_netlogon")) == NULL
) {
129 result
= cm_connect_netlogon(our_domain
, &netlogon_pipe
);
130 if (!NT_STATUS_IS_OK(result
)) {
134 result
= rpccli_netlogon_getdcname(netlogon_pipe
, mem_ctx
, our_domain
->dcname
,
137 talloc_destroy(mem_ctx
);
139 if (!NT_STATUS_IS_OK(result
)) {
140 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
145 /* cli_netlogon_getdcname gives us a name with \\ */
156 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname
));
158 if (!resolve_name(dcname
, dc_ip
, 0x20)) {
165 /************************************************************************
166 Given a fd with a just-connected TCP connection to a DC, open a connection
168 ************************************************************************/
170 static NTSTATUS
cm_prepare_connection(const struct winbindd_domain
*domain
,
172 const char *controller
,
173 struct cli_state
**cli
,
176 char *machine_password
, *machine_krb5_principal
, *machine_account
;
177 char *ipc_username
, *ipc_domain
, *ipc_password
;
181 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
183 struct sockaddr peeraddr
;
184 socklen_t peeraddr_len
;
186 struct sockaddr_in
*peeraddr_in
= (struct sockaddr_in
*)&peeraddr
;
188 machine_password
= secrets_fetch_machine_password(lp_workgroup(), NULL
,
191 if (asprintf(&machine_account
, "%s$", global_myname()) == -1) {
192 SAFE_FREE(machine_password
);
193 return NT_STATUS_NO_MEMORY
;
196 if (asprintf(&machine_krb5_principal
, "%s$@%s", global_myname(),
198 SAFE_FREE(machine_account
);
199 SAFE_FREE(machine_password
);
200 return NT_STATUS_NO_MEMORY
;
203 cm_get_ipc_userpass(&ipc_username
, &ipc_domain
, &ipc_password
);
207 got_mutex
= secrets_named_mutex(controller
,
208 WINBIND_SERVER_MUTEX_WAIT_TIME
);
211 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
213 result
= NT_STATUS_POSSIBLE_DEADLOCK
;
217 if ((*cli
= cli_initialise(NULL
)) == NULL
) {
218 DEBUG(1, ("Could not cli_initialize\n"));
219 result
= NT_STATUS_NO_MEMORY
;
223 (*cli
)->timeout
= 10000; /* 10 seconds */
225 fstrcpy((*cli
)->desthost
, controller
);
226 (*cli
)->use_kerberos
= True
;
228 peeraddr_len
= sizeof(peeraddr
);
230 if ((getpeername((*cli
)->fd
, &peeraddr
, &peeraddr_len
) != 0) ||
231 (peeraddr_len
!= sizeof(struct sockaddr_in
)) ||
232 (peeraddr_in
->sin_family
!= PF_INET
))
234 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno
)));
235 result
= NT_STATUS_UNSUCCESSFUL
;
239 if (ntohs(peeraddr_in
->sin_port
) == 139) {
240 struct nmb_name calling
;
241 struct nmb_name called
;
243 make_nmb_name(&calling
, global_myname(), 0x0);
244 make_nmb_name(&called
, "*SMBSERVER", 0x20);
246 if (!cli_session_request(*cli
, &calling
, &called
)) {
247 DEBUG(8, ("cli_session_request failed for %s\n",
249 result
= NT_STATUS_UNSUCCESSFUL
;
254 cli_setup_signing_state(*cli
, Undefined
);
256 if (!cli_negprot(*cli
)) {
257 DEBUG(1, ("cli_negprot failed\n"));
258 result
= NT_STATUS_UNSUCCESSFUL
;
262 if ((*cli
)->protocol
>= PROTOCOL_NT1
&& (*cli
)->capabilities
& CAP_EXTENDED_SECURITY
) {
263 ADS_STATUS ads_status
;
265 if (lp_security() == SEC_ADS
) {
267 /* Try a krb5 session */
269 (*cli
)->use_kerberos
= True
;
270 DEBUG(5, ("connecting to %s from %s with kerberos principal "
271 "[%s]\n", controller
, global_myname(),
272 machine_krb5_principal
));
274 ads_status
= cli_session_setup_spnego(*cli
,
275 machine_krb5_principal
,
279 if (!ADS_ERR_OK(ads_status
)) {
280 DEBUG(4,("failed kerberos session setup with %s\n",
281 ads_errstr(ads_status
)));
284 result
= ads_ntstatus(ads_status
);
285 if (NT_STATUS_IS_OK(result
)) {
286 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
287 cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
288 goto session_setup_done
;
292 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
293 (*cli
)->use_kerberos
= False
;
295 DEBUG(5, ("connecting to %s from %s with username "
296 "[%s]\\[%s]\n", controller
, global_myname(),
297 lp_workgroup(), machine_account
));
299 ads_status
= cli_session_setup_spnego(*cli
,
303 if (!ADS_ERR_OK(ads_status
)) {
304 DEBUG(4, ("authenticated session setup failed with %s\n",
305 ads_errstr(ads_status
)));
308 result
= ads_ntstatus(ads_status
);
309 if (NT_STATUS_IS_OK(result
)) {
310 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
311 cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
312 goto session_setup_done
;
316 /* Fall back to non-kerberos session setup */
318 (*cli
)->use_kerberos
= False
;
320 if ((((*cli
)->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) != 0) &&
321 (strlen(ipc_username
) > 0)) {
323 /* Only try authenticated if we have a username */
325 DEBUG(5, ("connecting to %s from %s with username "
326 "[%s]\\[%s]\n", controller
, global_myname(),
327 ipc_domain
, ipc_username
));
329 if (cli_session_setup(*cli
, ipc_username
,
330 ipc_password
, strlen(ipc_password
)+1,
331 ipc_password
, strlen(ipc_password
)+1,
333 /* Successful logon with given username. */
334 cli_init_creds(*cli
, ipc_username
, ipc_domain
, ipc_password
);
335 goto session_setup_done
;
337 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
338 ipc_domain
, ipc_username
));
342 /* Fall back to anonymous connection, this might fail later */
344 if (cli_session_setup(*cli
, "", NULL
, 0, NULL
, 0, "")) {
345 DEBUG(5, ("Connected anonymously\n"));
346 cli_init_creds(*cli
, "", "", "");
347 goto session_setup_done
;
350 result
= cli_nt_error(*cli
);
352 if (NT_STATUS_IS_OK(result
))
353 result
= NT_STATUS_UNSUCCESSFUL
;
355 /* We can't session setup */
361 /* cache the server name for later connections */
363 saf_store( domain
->name
, (*cli
)->desthost
);
365 if (!cli_send_tconX(*cli
, "IPC$", "IPC", "", 0)) {
367 result
= cli_nt_error(*cli
);
369 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result
)));
371 if (NT_STATUS_IS_OK(result
))
372 result
= NT_STATUS_UNSUCCESSFUL
;
377 secrets_named_mutex_release(controller
);
381 /* set the domain if empty; needed for schannel connections */
382 if ( !*(*cli
)->domain
) {
383 fstrcpy( (*cli
)->domain
, domain
->name
);
386 result
= NT_STATUS_OK
;
390 secrets_named_mutex_release(controller
);
393 SAFE_FREE(machine_account
);
394 SAFE_FREE(machine_password
);
395 SAFE_FREE(machine_krb5_principal
);
396 SAFE_FREE(ipc_username
);
397 SAFE_FREE(ipc_domain
);
398 SAFE_FREE(ipc_password
);
400 if (!NT_STATUS_IS_OK(result
)) {
401 add_failed_connection_entry(domain
->name
, controller
, result
);
402 if ((*cli
) != NULL
) {
416 static BOOL
add_one_dc_unique(TALLOC_CTX
*mem_ctx
, const char *domain_name
,
417 const char *dcname
, struct in_addr ip
,
418 struct dc_name_ip
**dcs
, int *num
)
420 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name
, dcname
))) {
421 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname
));
425 *dcs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *dcs
, struct dc_name_ip
, (*num
)+1);
430 fstrcpy((*dcs
)[*num
].name
, dcname
);
431 (*dcs
)[*num
].ip
= ip
;
436 static BOOL
add_sockaddr_to_array(TALLOC_CTX
*mem_ctx
,
437 struct in_addr ip
, uint16 port
,
438 struct sockaddr_in
**addrs
, int *num
)
440 *addrs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *addrs
, struct sockaddr_in
, (*num
)+1);
445 (*addrs
)[*num
].sin_family
= PF_INET
;
446 putip((char *)&((*addrs
)[*num
].sin_addr
), (char *)&ip
);
447 (*addrs
)[*num
].sin_port
= htons(port
);
453 static void mailslot_name(struct in_addr dc_ip
, fstring name
)
455 fstr_sprintf(name
, "\\MAILSLOT\\NET\\GETDC%X", dc_ip
.s_addr
);
458 static BOOL
send_getdc_request(struct in_addr dc_ip
,
459 const char *domain_name
,
464 fstring my_acct_name
;
467 mailslot_name(dc_ip
, my_mailslot
);
469 memset(outbuf
, '\0', sizeof(outbuf
));
473 SCVAL(p
, 0, SAMLOGON
);
476 SCVAL(p
, 0, 0); /* Count pointer ... */
479 SIVAL(p
, 0, 0); /* The sender's token ... */
482 p
+= dos_PutUniCode(p
, global_myname(), sizeof(pstring
), True
);
483 fstr_sprintf(my_acct_name
, "%s$", global_myname());
484 p
+= dos_PutUniCode(p
, my_acct_name
, sizeof(pstring
), True
);
486 memcpy(p
, my_mailslot
, strlen(my_mailslot
)+1);
487 p
+= strlen(my_mailslot
)+1;
492 SIVAL(p
, 0, sid_size(sid
));
495 p
= ALIGN4(p
, outbuf
);
497 sid_linearize(p
, sid_size(sid
), sid
);
505 return cli_send_mailslot(False
, "\\MAILSLOT\\NET\\NTLOGON", 0,
506 outbuf
, PTR_DIFF(p
, outbuf
),
507 global_myname(), 0, domain_name
, 0x1c,
511 static BOOL
receive_getdc_response(struct in_addr dc_ip
,
512 const char *domain_name
,
515 struct packet_struct
*packet
;
518 fstring dcname
, user
, domain
;
521 mailslot_name(dc_ip
, my_mailslot
);
523 packet
= receive_unexpected(DGRAM_PACKET
, 0, my_mailslot
);
525 if (packet
== NULL
) {
526 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot
));
530 DEBUG(5, ("Received packet for %s\n", my_mailslot
));
532 buf
= packet
->packet
.dgram
.data
;
533 len
= packet
->packet
.dgram
.datasize
;
536 /* 70 is a completely arbitrary value to make sure
537 the SVAL below does not read uninitialized memory */
538 DEBUG(3, ("GetDC got short response\n"));
542 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
543 p
= buf
+SVAL(buf
, smb_vwv10
);
545 if (CVAL(p
,0) != SAMLOGON_R
) {
546 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p
, 0)));
551 pull_ucs2(buf
, dcname
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
552 STR_TERMINATE
|STR_NOALIGN
);
553 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
554 pull_ucs2(buf
, user
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
555 STR_TERMINATE
|STR_NOALIGN
);
556 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
557 pull_ucs2(buf
, domain
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
558 STR_TERMINATE
|STR_NOALIGN
);
559 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
561 if (!strequal(domain
, domain_name
)) {
562 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
563 domain_name
, domain
));
568 if (*p
== '\\') p
+= 1;
569 if (*p
== '\\') p
+= 1;
573 DEBUG(10, ("GetDC gave name %s for domain %s\n",
579 /*******************************************************************
580 convert an ip to a name
581 *******************************************************************/
583 static BOOL
dcip_to_name( const char *domainname
, const char *realm
,
584 const DOM_SID
*sid
, struct in_addr ip
, fstring name
)
586 struct ip_service ip_list
;
591 /* try GETDC requests first */
593 if (send_getdc_request(ip
, domainname
, sid
)) {
596 for (i
=0; i
<5; i
++) {
597 if (receive_getdc_response(ip
, domainname
, name
)) {
598 namecache_store(name
, 0x20, 1, &ip_list
);
605 /* try node status request */
607 if ( name_status_find(domainname
, 0x1c, 0x20, ip
, name
) ) {
608 namecache_store(name
, 0x20, 1, &ip_list
);
613 /* for active directory servers, try to get the ldap server name.
614 None of these failure should be considered critical for now */
616 if ( lp_security() == SEC_ADS
)
620 ads
= ads_init( realm
, domainname
, NULL
);
621 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
623 if ( !ads_try_connect( ads
, inet_ntoa(ip
) ) ) {
628 fstrcpy(name
, ads
->config
.ldap_server_name
);
629 namecache_store(name
, 0x20, 1, &ip_list
);
639 /*******************************************************************
640 Retreive a list of IP address for domain controllers. Fill in
641 the dcs[] with results.
642 *******************************************************************/
644 static BOOL
get_dcs(TALLOC_CTX
*mem_ctx
, const struct winbindd_domain
*domain
,
645 struct dc_name_ip
**dcs
, int *num_dcs
)
649 struct ip_service
*ip_list
= NULL
;
655 is_our_domain
= strequal(domain
->name
, lp_workgroup());
658 && get_dc_name_via_netlogon(domain
, dcname
, &ip
)
659 && add_one_dc_unique(mem_ctx
, domain
->name
, dcname
, ip
, dcs
, num_dcs
) )
661 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
662 dcname
, inet_ntoa(ip
)));
666 /* try standard netbios queries first */
668 get_sorted_dc_list(domain
->name
, &ip_list
, &iplist_size
, False
);
670 /* check for security = ads and use DNS if we can */
672 if ( iplist_size
==0 && lp_security() == SEC_ADS
)
673 get_sorted_dc_list(domain
->alt_name
, &ip_list
, &iplist_size
, True
);
675 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
677 /* now add to the dc array. We'll wait until the last minute
678 to look up the name of the DC. But we fill in the char* for
679 the ip now in to make the failed connection cache work */
681 for ( i
=0; i
<iplist_size
; i
++ ) {
682 add_one_dc_unique(mem_ctx
, domain
->name
, inet_ntoa(ip_list
[i
].ip
),
683 ip_list
[i
].ip
, dcs
, num_dcs
);
686 SAFE_FREE( ip_list
);
691 static BOOL
find_new_dc(TALLOC_CTX
*mem_ctx
,
692 const struct winbindd_domain
*domain
,
693 fstring dcname
, struct sockaddr_in
*addr
, int *fd
)
695 struct dc_name_ip
*dcs
= NULL
;
698 const char **dcnames
= NULL
;
701 struct sockaddr_in
*addrs
= NULL
;
707 if (!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
) || (num_dcs
== 0))
710 for (i
=0; i
<num_dcs
; i
++) {
712 add_string_to_array(mem_ctx
, dcs
[i
].name
,
713 &dcnames
, &num_dcnames
);
714 add_sockaddr_to_array(mem_ctx
, dcs
[i
].ip
, 445,
717 add_string_to_array(mem_ctx
, dcs
[i
].name
,
718 &dcnames
, &num_dcnames
);
719 add_sockaddr_to_array(mem_ctx
, dcs
[i
].ip
, 139,
723 if ((num_dcnames
== 0) || (num_dcnames
!= num_addrs
))
726 if ((addrs
== NULL
) || (dcnames
== NULL
))
729 if ( !open_any_socket_out(addrs
, num_addrs
, 10000, &fd_index
, fd
) )
731 for (i
=0; i
<num_dcs
; i
++) {
732 add_failed_connection_entry(domain
->name
,
733 dcs
[i
].name
, NT_STATUS_UNSUCCESSFUL
);
738 *addr
= addrs
[fd_index
];
740 if (*dcnames
[fd_index
] != '\0' && !is_ipaddress(dcnames
[fd_index
])) {
741 /* Ok, we've got a name for the DC */
742 fstrcpy(dcname
, dcnames
[fd_index
]);
746 /* Try to figure out the name */
747 if (dcip_to_name( domain
->name
, domain
->alt_name
, &domain
->sid
,
748 addr
->sin_addr
, dcname
)) {
752 /* We can not continue without the DC's name */
753 add_failed_connection_entry(domain
->name
, dcs
[fd_index
].name
,
754 NT_STATUS_UNSUCCESSFUL
);
758 static NTSTATUS
cm_open_connection(struct winbindd_domain
*domain
,
759 struct winbindd_cm_conn
*new_conn
)
763 char *saf_servername
= saf_fetch( domain
->name
);
766 if ((mem_ctx
= talloc_init("cm_open_connection")) == NULL
)
767 return NT_STATUS_NO_MEMORY
;
769 /* we have to check the server affinity cache here since
770 later we selecte a DC based on response time and not preference */
772 if ( saf_servername
)
774 /* convert an ip address to a name */
775 if ( is_ipaddress( saf_servername
) )
780 ip
= *interpret_addr2( saf_servername
);
781 if (dcip_to_name( domain
->name
, domain
->alt_name
,
782 &domain
->sid
, ip
, saf_name
)) {
783 fstrcpy( domain
->dcname
, saf_name
);
785 add_failed_connection_entry(
786 domain
->name
, saf_servername
,
787 NT_STATUS_UNSUCCESSFUL
);
792 fstrcpy( domain
->dcname
, saf_servername
);
795 SAFE_FREE( saf_servername
);
798 for (retries
= 0; retries
< 3; retries
++) {
803 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
805 if ((strlen(domain
->dcname
) > 0)
806 && NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, domain
->dcname
))
807 && (resolve_name(domain
->dcname
, &domain
->dcaddr
.sin_addr
, 0x20)))
809 struct sockaddr_in
*addrs
= NULL
;
813 add_sockaddr_to_array(mem_ctx
, domain
->dcaddr
.sin_addr
, 445, &addrs
, &num_addrs
);
814 add_sockaddr_to_array(mem_ctx
, domain
->dcaddr
.sin_addr
, 139, &addrs
, &num_addrs
);
816 if (!open_any_socket_out(addrs
, num_addrs
, 10000, &dummy
, &fd
)) {
817 domain
->online
= False
;
823 && !find_new_dc(mem_ctx
, domain
, domain
->dcname
, &domain
->dcaddr
, &fd
))
825 /* This is the one place where we will
826 set the global winbindd offline state
827 to true, if a "WINBINDD_OFFLINE" entry
828 is found in the winbindd cache. */
829 set_global_winbindd_state_offline();
830 domain
->online
= False
;
834 new_conn
->cli
= NULL
;
836 result
= cm_prepare_connection(domain
, fd
, domain
->dcname
,
837 &new_conn
->cli
, &retry
);
843 if (NT_STATUS_IS_OK(result
)) {
844 if (domain
->online
== False
) {
845 /* We're changing state from offline to online. */
846 set_global_winbindd_state_online();
848 domain
->online
= True
;
851 talloc_destroy(mem_ctx
);
855 /* Close down all open pipes on a connection. */
857 void invalidate_cm_connection(struct winbindd_cm_conn
*conn
)
859 if (conn
->samr_pipe
!= NULL
) {
860 cli_rpc_pipe_close(conn
->samr_pipe
);
861 conn
->samr_pipe
= NULL
;
864 if (conn
->lsa_pipe
!= NULL
) {
865 cli_rpc_pipe_close(conn
->lsa_pipe
);
866 conn
->lsa_pipe
= NULL
;
869 if (conn
->netlogon_pipe
!= NULL
) {
870 cli_rpc_pipe_close(conn
->netlogon_pipe
);
871 conn
->netlogon_pipe
= NULL
;
875 cli_shutdown(conn
->cli
);
881 void close_conns_after_fork(void)
883 struct winbindd_domain
*domain
;
885 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
886 if (domain
->conn
.cli
== NULL
)
889 if (domain
->conn
.cli
->fd
== -1)
892 close(domain
->conn
.cli
->fd
);
893 domain
->conn
.cli
->fd
= -1;
897 static BOOL
connection_ok(struct winbindd_domain
*domain
)
899 if (domain
->conn
.cli
== NULL
) {
900 DEBUG(8, ("Connection to %s for domain %s has NULL "
901 "cli!\n", domain
->dcname
, domain
->name
));
905 if (!domain
->conn
.cli
->initialised
) {
906 DEBUG(3, ("Connection to %s for domain %s was never "
907 "initialised!\n", domain
->dcname
, domain
->name
));
911 if (domain
->conn
.cli
->fd
== -1) {
912 DEBUG(3, ("Connection to %s for domain %s has died or was "
913 "never started (fd == -1)\n",
914 domain
->dcname
, domain
->name
));
921 /* Initialize a new connection up to the RPC BIND. */
923 static NTSTATUS
init_dc_connection(struct winbindd_domain
*domain
)
925 if (connection_ok(domain
))
928 invalidate_cm_connection(&domain
->conn
);
930 return cm_open_connection(domain
, &domain
->conn
);
933 /******************************************************************************
934 We can 'sense' certain things about the DC by it's replies to certain
937 This tells us if this particular remote server is Active Directory, and if it
939 ******************************************************************************/
941 void set_dc_type_and_flags( struct winbindd_domain
*domain
)
945 TALLOC_CTX
*mem_ctx
= NULL
;
946 struct rpc_pipe_client
*cli
;
949 char *domain_name
= NULL
;
950 char *dns_name
= NULL
;
951 DOM_SID
*dom_sid
= NULL
;
955 domain
->native_mode
= False
;
956 domain
->active_directory
= False
;
958 if (domain
->internal
) {
959 domain
->initialized
= True
;
963 result
= init_dc_connection(domain
);
964 if (!NT_STATUS_IS_OK(result
)) {
965 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
966 "to %s: (%s)\n", domain
->name
, nt_errstr(result
)));
967 domain
->initialized
= True
;
971 cli
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
, PI_LSARPC_DS
,
975 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
976 "PI_LSARPC_DS on domain %s: (%s)\n",
977 domain
->name
, nt_errstr(result
)));
978 domain
->initialized
= True
;
982 result
= rpccli_ds_getprimarydominfo(cli
, cli
->cli
->mem_ctx
,
983 DsRolePrimaryDomainInfoBasic
,
985 cli_rpc_pipe_close(cli
);
987 if (!NT_STATUS_IS_OK(result
)) {
988 domain
->initialized
= True
;
992 if ((ctr
.basic
->flags
& DSROLE_PRIMARY_DS_RUNNING
) &&
993 !(ctr
.basic
->flags
& DSROLE_PRIMARY_DS_MIXED_MODE
) )
994 domain
->native_mode
= True
;
996 cli
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
, PI_LSARPC
, &result
);
999 domain
->initialized
= True
;
1003 mem_ctx
= talloc_init("set_dc_type_and_flags on domain %s\n",
1006 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1007 cli_rpc_pipe_close(cli
);
1011 result
= rpccli_lsa_open_policy2(cli
, mem_ctx
, True
,
1012 SEC_RIGHTS_MAXIMUM_ALLOWED
, &pol
);
1014 if (NT_STATUS_IS_OK(result
)) {
1015 /* This particular query is exactly what Win2k clients use
1016 to determine that the DC is active directory */
1017 result
= rpccli_lsa_query_info_policy2(cli
, mem_ctx
, &pol
,
1023 if (NT_STATUS_IS_OK(result
)) {
1025 fstrcpy(domain
->name
, domain_name
);
1028 fstrcpy(domain
->alt_name
, dns_name
);
1031 sid_copy(&domain
->sid
, dom_sid
);
1033 domain
->active_directory
= True
;
1036 result
= rpccli_lsa_open_policy(cli
, mem_ctx
, True
,
1037 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1040 if (!NT_STATUS_IS_OK(result
))
1043 result
= rpccli_lsa_query_info_policy(cli
, mem_ctx
,
1044 &pol
, 5, &domain_name
,
1047 if (NT_STATUS_IS_OK(result
)) {
1049 fstrcpy(domain
->name
, domain_name
);
1052 sid_copy(&domain
->sid
, dom_sid
);
1057 cli_rpc_pipe_close(cli
);
1059 talloc_destroy(mem_ctx
);
1061 domain
->initialized
= True
;
1066 static BOOL
cm_get_schannel_dcinfo(struct winbindd_domain
*domain
,
1067 struct dcinfo
**ppdc
)
1070 struct rpc_pipe_client
*netlogon_pipe
;
1072 if (lp_client_schannel() == False
) {
1076 result
= cm_connect_netlogon(domain
, &netlogon_pipe
);
1077 if (!NT_STATUS_IS_OK(result
)) {
1081 /* Return a pointer to the struct dcinfo from the
1084 *ppdc
= domain
->conn
.netlogon_pipe
->dc
;
1088 NTSTATUS
cm_connect_sam(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
1089 struct rpc_pipe_client
**cli
, POLICY_HND
*sam_handle
)
1091 struct winbindd_cm_conn
*conn
;
1094 struct dcinfo
*p_dcinfo
;
1096 result
= init_dc_connection(domain
);
1097 if (!NT_STATUS_IS_OK(result
)) {
1101 conn
= &domain
->conn
;
1103 if (conn
->samr_pipe
!= NULL
) {
1108 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1109 * sign and sealed pipe using the machine account password by
1110 * preference. If we can't - try schannel, if that fails, try
1114 pwd_get_cleartext(&conn
->cli
->pwd
, conn_pwd
);
1115 if ((conn
->cli
->user_name
[0] == '\0') ||
1116 (conn
->cli
->domain
[0] == '\0') ||
1117 (conn_pwd
[0] == '\0')) {
1118 DEBUG(10, ("cm_connect_sam: No no user available for "
1119 "domain %s, trying schannel\n", conn
->cli
->domain
));
1123 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1124 authenticated SAMR pipe with sign & seal. */
1126 cli_rpc_pipe_open_spnego_ntlmssp(conn
->cli
, PI_SAMR
,
1127 PIPE_AUTH_LEVEL_PRIVACY
,
1129 conn
->cli
->user_name
,
1132 if (conn
->samr_pipe
== NULL
) {
1133 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1134 "pipe for domain %s using NTLMSSP "
1135 "authenticated pipe: user %s\\%s. Error was "
1136 "%s\n", domain
->name
, conn
->cli
->domain
,
1137 conn
->cli
->user_name
, nt_errstr(result
)));
1141 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1142 "domain %s using NTLMSSP authenticated "
1143 "pipe: user %s\\%s\n", domain
->name
,
1144 conn
->cli
->domain
, conn
->cli
->user_name
));
1146 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1147 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1148 &conn
->sam_connect_handle
);
1149 if (NT_STATUS_IS_OK(result
)) {
1152 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1153 "failed for domain %s, error was %s. Trying schannel\n",
1154 domain
->name
, nt_errstr(result
) ));
1155 cli_rpc_pipe_close(conn
->samr_pipe
);
1159 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1161 if (!cm_get_schannel_dcinfo(domain
, &p_dcinfo
)) {
1162 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1163 "for domain %s, trying anon\n", conn
->cli
->domain
));
1166 conn
->samr_pipe
= cli_rpc_pipe_open_schannel_with_key
1167 (conn
->cli
, PI_SAMR
, PIPE_AUTH_LEVEL_PRIVACY
,
1168 domain
->name
, p_dcinfo
, &result
);
1170 if (conn
->samr_pipe
== NULL
) {
1171 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1172 "domain %s using schannel. Error was %s\n",
1173 domain
->name
, nt_errstr(result
) ));
1176 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1177 "schannel.\n", domain
->name
));
1179 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1180 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1181 &conn
->sam_connect_handle
);
1182 if (NT_STATUS_IS_OK(result
)) {
1185 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1186 "for domain %s, error was %s. Trying anonymous\n",
1187 domain
->name
, nt_errstr(result
) ));
1188 cli_rpc_pipe_close(conn
->samr_pipe
);
1192 /* Finally fall back to anonymous. */
1193 conn
->samr_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_SAMR
,
1196 if (conn
->samr_pipe
== NULL
) {
1197 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
1201 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1202 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1203 &conn
->sam_connect_handle
);
1204 if (!NT_STATUS_IS_OK(result
)) {
1205 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1206 "for domain %s Error was %s\n",
1207 domain
->name
, nt_errstr(result
) ));
1212 result
= rpccli_samr_open_domain(conn
->samr_pipe
,
1214 &conn
->sam_connect_handle
,
1215 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1217 &conn
->sam_domain_handle
);
1221 if (!NT_STATUS_IS_OK(result
)) {
1222 invalidate_cm_connection(conn
);
1226 *cli
= conn
->samr_pipe
;
1227 *sam_handle
= conn
->sam_domain_handle
;
1231 NTSTATUS
cm_connect_lsa(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
1232 struct rpc_pipe_client
**cli
, POLICY_HND
*lsa_policy
)
1234 struct winbindd_cm_conn
*conn
;
1237 struct dcinfo
*p_dcinfo
;
1239 result
= init_dc_connection(domain
);
1240 if (!NT_STATUS_IS_OK(result
))
1243 conn
= &domain
->conn
;
1245 if (conn
->lsa_pipe
!= NULL
) {
1249 pwd_get_cleartext(&conn
->cli
->pwd
, conn_pwd
);
1250 if ((conn
->cli
->user_name
[0] == '\0') ||
1251 (conn
->cli
->domain
[0] == '\0') ||
1252 (conn_pwd
[0] == '\0')) {
1253 DEBUG(10, ("cm_connect_lsa: No no user available for "
1254 "domain %s, trying schannel\n", conn
->cli
->domain
));
1258 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1259 * authenticated LSA pipe with sign & seal. */
1260 conn
->lsa_pipe
= cli_rpc_pipe_open_spnego_ntlmssp
1261 (conn
->cli
, PI_LSARPC
, PIPE_AUTH_LEVEL_PRIVACY
,
1262 conn
->cli
->domain
, conn
->cli
->user_name
, conn_pwd
, &result
);
1264 if (conn
->lsa_pipe
== NULL
) {
1265 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1266 "domain %s using NTLMSSP authenticated pipe: user "
1267 "%s\\%s. Error was %s. Trying schannel.\n",
1268 domain
->name
, conn
->cli
->domain
,
1269 conn
->cli
->user_name
, nt_errstr(result
)));
1273 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1274 "NTLMSSP authenticated pipe: user %s\\%s\n",
1275 domain
->name
, conn
->cli
->domain
, conn
->cli
->user_name
));
1277 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
1278 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1280 if (NT_STATUS_IS_OK(result
)) {
1284 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1287 cli_rpc_pipe_close(conn
->lsa_pipe
);
1291 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1293 if (!cm_get_schannel_dcinfo(domain
, &p_dcinfo
)) {
1294 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1295 "for domain %s, trying anon\n", conn
->cli
->domain
));
1298 conn
->lsa_pipe
= cli_rpc_pipe_open_schannel_with_key
1299 (conn
->cli
, PI_LSARPC
, PIPE_AUTH_LEVEL_PRIVACY
,
1300 domain
->name
, p_dcinfo
, &result
);
1302 if (conn
->lsa_pipe
== NULL
) {
1303 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1304 "domain %s using schannel. Error was %s\n",
1305 domain
->name
, nt_errstr(result
) ));
1308 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1309 "schannel.\n", domain
->name
));
1311 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
1312 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1314 if (NT_STATUS_IS_OK(result
)) {
1318 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1321 cli_rpc_pipe_close(conn
->lsa_pipe
);
1325 conn
->lsa_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_LSARPC
,
1327 if (conn
->lsa_pipe
== NULL
) {
1328 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
1332 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
1333 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1336 if (!NT_STATUS_IS_OK(result
)) {
1337 invalidate_cm_connection(conn
);
1338 return NT_STATUS_UNSUCCESSFUL
;
1341 *cli
= conn
->lsa_pipe
;
1342 *lsa_policy
= conn
->lsa_policy
;
1346 /****************************************************************************
1347 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1348 session key stored in conn->netlogon_pipe->dc->sess_key.
1349 ****************************************************************************/
1351 NTSTATUS
cm_connect_netlogon(struct winbindd_domain
*domain
,
1352 struct rpc_pipe_client
**cli
)
1354 struct winbindd_cm_conn
*conn
;
1357 uint32 neg_flags
= NETLOGON_NEG_AUTH2_FLAGS
;
1359 uint32 sec_chan_type
;
1360 const char *account_name
;
1361 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
1365 result
= init_dc_connection(domain
);
1366 if (!NT_STATUS_IS_OK(result
)) {
1370 conn
= &domain
->conn
;
1372 if (conn
->netlogon_pipe
!= NULL
) {
1373 *cli
= conn
->netlogon_pipe
;
1374 return NT_STATUS_OK
;
1377 if (!get_trust_pw(domain
->name
, mach_pwd
, &sec_chan_type
)) {
1378 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1381 netlogon_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_NETLOGON
,
1383 if (netlogon_pipe
== NULL
) {
1387 if (lp_client_schannel() != False
) {
1388 neg_flags
|= NETLOGON_NEG_SCHANNEL
;
1391 /* if we are a DC and this is a trusted domain, then we need to use our
1392 domain name in the net_req_auth2() request */
1395 && !strequal(domain
->name
, lp_workgroup())
1396 && lp_allow_trusted_domains() )
1398 account_name
= lp_workgroup();
1400 account_name
= domain
->primary
?
1401 global_myname() : domain
->name
;
1404 if (account_name
== NULL
) {
1405 cli_rpc_pipe_close(netlogon_pipe
);
1406 return NT_STATUS_NO_MEMORY
;
1409 result
= rpccli_netlogon_setup_creds(
1411 domain
->dcname
, /* server name. */
1412 domain
->name
, /* domain name */
1413 global_myname(), /* client name */
1414 account_name
, /* machine account */
1415 mach_pwd
, /* machine password */
1416 sec_chan_type
, /* from get_trust_pw */
1419 if (!NT_STATUS_IS_OK(result
)) {
1420 cli_rpc_pipe_close(netlogon_pipe
);
1424 if ((lp_client_schannel() == True
) &&
1425 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
1426 DEBUG(3, ("Server did not offer schannel\n"));
1427 cli_rpc_pipe_close(netlogon_pipe
);
1428 return NT_STATUS_ACCESS_DENIED
;
1431 if ((lp_client_schannel() == False
) ||
1432 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
1433 /* We're done - just keep the existing connection to NETLOGON
1435 conn
->netlogon_pipe
= netlogon_pipe
;
1436 *cli
= conn
->netlogon_pipe
;
1437 return NT_STATUS_OK
;
1440 /* Using the credentials from the first pipe, open a signed and sealed
1441 second netlogon pipe. The session key is stored in the schannel
1442 part of the new pipe auth struct.
1445 conn
->netlogon_pipe
=
1446 cli_rpc_pipe_open_schannel_with_key(conn
->cli
,
1448 PIPE_AUTH_LEVEL_PRIVACY
,
1453 /* We can now close the initial netlogon pipe. */
1454 cli_rpc_pipe_close(netlogon_pipe
);
1456 if (conn
->netlogon_pipe
== NULL
) {
1457 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1458 "was %s\n", nt_errstr(result
)));
1460 /* make sure we return something besides OK */
1461 return !NT_STATUS_IS_OK(result
) ? result
: NT_STATUS_PIPE_NOT_AVAILABLE
;
1464 *cli
= conn
->netlogon_pipe
;
1465 return NT_STATUS_OK
;