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
;
113 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
120 if (domain
->primary
) {
124 our_domain
= find_our_domain();
126 if ((mem_ctx
= talloc_init("get_dc_name_via_netlogon")) == NULL
) {
130 result
= cm_connect_netlogon(our_domain
, &netlogon_pipe
);
131 if (!NT_STATUS_IS_OK(result
)) {
135 werr
= rpccli_netlogon_getdcname(netlogon_pipe
, mem_ctx
, our_domain
->dcname
,
138 talloc_destroy(mem_ctx
);
140 if (!W_ERROR_IS_OK(werr
)) {
141 DEBUG(10, ("rpccli_netlogon_getdcname failed: %s\n",
146 /* cli_netlogon_getdcname gives us a name with \\ */
157 DEBUG(10, ("rpccli_netlogon_getdcname returned %s\n", dcname
));
159 if (!resolve_name(dcname
, dc_ip
, 0x20)) {
166 /************************************************************************
167 Given a fd with a just-connected TCP connection to a DC, open a connection
169 ************************************************************************/
171 static NTSTATUS
cm_prepare_connection(const struct winbindd_domain
*domain
,
173 const char *controller
,
174 struct cli_state
**cli
,
177 char *machine_password
, *machine_krb5_principal
, *machine_account
;
178 char *ipc_username
, *ipc_domain
, *ipc_password
;
182 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
184 struct sockaddr peeraddr
;
185 socklen_t peeraddr_len
;
187 struct sockaddr_in
*peeraddr_in
= (struct sockaddr_in
*)&peeraddr
;
189 machine_password
= secrets_fetch_machine_password(lp_workgroup(), NULL
,
192 if (asprintf(&machine_account
, "%s$", global_myname()) == -1) {
193 SAFE_FREE(machine_password
);
194 return NT_STATUS_NO_MEMORY
;
197 if (asprintf(&machine_krb5_principal
, "%s$@%s", global_myname(),
199 SAFE_FREE(machine_account
);
200 SAFE_FREE(machine_password
);
201 return NT_STATUS_NO_MEMORY
;
204 cm_get_ipc_userpass(&ipc_username
, &ipc_domain
, &ipc_password
);
208 got_mutex
= secrets_named_mutex(controller
,
209 WINBIND_SERVER_MUTEX_WAIT_TIME
);
212 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
214 result
= NT_STATUS_POSSIBLE_DEADLOCK
;
218 if ((*cli
= cli_initialise(NULL
)) == NULL
) {
219 DEBUG(1, ("Could not cli_initialize\n"));
220 result
= NT_STATUS_NO_MEMORY
;
224 (*cli
)->timeout
= 10000; /* 10 seconds */
226 fstrcpy((*cli
)->desthost
, controller
);
227 (*cli
)->use_kerberos
= True
;
229 peeraddr_len
= sizeof(peeraddr
);
231 if ((getpeername((*cli
)->fd
, &peeraddr
, &peeraddr_len
) != 0) ||
232 (peeraddr_len
!= sizeof(struct sockaddr_in
)) ||
233 (peeraddr_in
->sin_family
!= PF_INET
))
235 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno
)));
236 result
= NT_STATUS_UNSUCCESSFUL
;
240 if (ntohs(peeraddr_in
->sin_port
) == 139) {
241 struct nmb_name calling
;
242 struct nmb_name called
;
244 make_nmb_name(&calling
, global_myname(), 0x0);
245 make_nmb_name(&called
, "*SMBSERVER", 0x20);
247 if (!cli_session_request(*cli
, &calling
, &called
)) {
248 DEBUG(8, ("cli_session_request failed for %s\n",
250 result
= NT_STATUS_UNSUCCESSFUL
;
255 cli_setup_signing_state(*cli
, Undefined
);
257 if (!cli_negprot(*cli
)) {
258 DEBUG(1, ("cli_negprot failed\n"));
259 result
= NT_STATUS_UNSUCCESSFUL
;
263 if ((*cli
)->protocol
>= PROTOCOL_NT1
&& (*cli
)->capabilities
& CAP_EXTENDED_SECURITY
) {
264 ADS_STATUS ads_status
;
266 if (lp_security() == SEC_ADS
) {
268 /* Try a krb5 session */
270 (*cli
)->use_kerberos
= True
;
271 DEBUG(5, ("connecting to %s from %s with kerberos principal "
272 "[%s]\n", controller
, global_myname(),
273 machine_krb5_principal
));
275 ads_status
= cli_session_setup_spnego(*cli
,
276 machine_krb5_principal
,
280 if (!ADS_ERR_OK(ads_status
)) {
281 DEBUG(4,("failed kerberos session setup with %s\n",
282 ads_errstr(ads_status
)));
285 result
= ads_ntstatus(ads_status
);
286 if (NT_STATUS_IS_OK(result
)) {
287 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
288 cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
289 goto session_setup_done
;
293 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
294 (*cli
)->use_kerberos
= False
;
296 DEBUG(5, ("connecting to %s from %s with username "
297 "[%s]\\[%s]\n", controller
, global_myname(),
298 lp_workgroup(), machine_account
));
300 ads_status
= cli_session_setup_spnego(*cli
,
304 if (!ADS_ERR_OK(ads_status
)) {
305 DEBUG(4, ("authenticated session setup failed with %s\n",
306 ads_errstr(ads_status
)));
309 result
= ads_ntstatus(ads_status
);
310 if (NT_STATUS_IS_OK(result
)) {
311 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
312 cli_init_creds(*cli
, machine_account
, lp_workgroup(), machine_password
);
313 goto session_setup_done
;
317 /* Fall back to non-kerberos session setup */
319 (*cli
)->use_kerberos
= False
;
321 if ((((*cli
)->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) != 0) &&
322 (strlen(ipc_username
) > 0)) {
324 /* Only try authenticated if we have a username */
326 DEBUG(5, ("connecting to %s from %s with username "
327 "[%s]\\[%s]\n", controller
, global_myname(),
328 ipc_domain
, ipc_username
));
330 if (cli_session_setup(*cli
, ipc_username
,
331 ipc_password
, strlen(ipc_password
)+1,
332 ipc_password
, strlen(ipc_password
)+1,
334 /* Successful logon with given username. */
335 cli_init_creds(*cli
, ipc_username
, ipc_domain
, ipc_password
);
336 goto session_setup_done
;
338 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
339 ipc_domain
, ipc_username
));
343 /* Fall back to anonymous connection, this might fail later */
345 if (cli_session_setup(*cli
, "", NULL
, 0, NULL
, 0, "")) {
346 DEBUG(5, ("Connected anonymously\n"));
347 cli_init_creds(*cli
, "", "", "");
348 goto session_setup_done
;
351 result
= cli_nt_error(*cli
);
353 if (NT_STATUS_IS_OK(result
))
354 result
= NT_STATUS_UNSUCCESSFUL
;
356 /* We can't session setup */
362 /* cache the server name for later connections */
364 saf_store( domain
->name
, (*cli
)->desthost
);
366 if (!cli_send_tconX(*cli
, "IPC$", "IPC", "", 0)) {
368 result
= cli_nt_error(*cli
);
370 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result
)));
372 if (NT_STATUS_IS_OK(result
))
373 result
= NT_STATUS_UNSUCCESSFUL
;
378 secrets_named_mutex_release(controller
);
382 /* set the domain if empty; needed for schannel connections */
383 if ( !*(*cli
)->domain
) {
384 fstrcpy( (*cli
)->domain
, domain
->name
);
387 result
= NT_STATUS_OK
;
391 secrets_named_mutex_release(controller
);
394 SAFE_FREE(machine_account
);
395 SAFE_FREE(machine_password
);
396 SAFE_FREE(machine_krb5_principal
);
397 SAFE_FREE(ipc_username
);
398 SAFE_FREE(ipc_domain
);
399 SAFE_FREE(ipc_password
);
401 if (!NT_STATUS_IS_OK(result
)) {
402 add_failed_connection_entry(domain
->name
, controller
, result
);
403 if ((*cli
) != NULL
) {
417 static BOOL
add_one_dc_unique(TALLOC_CTX
*mem_ctx
, const char *domain_name
,
418 const char *dcname
, struct in_addr ip
,
419 struct dc_name_ip
**dcs
, int *num
)
421 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name
, dcname
))) {
422 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname
));
426 *dcs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *dcs
, struct dc_name_ip
, (*num
)+1);
431 fstrcpy((*dcs
)[*num
].name
, dcname
);
432 (*dcs
)[*num
].ip
= ip
;
437 static BOOL
add_sockaddr_to_array(TALLOC_CTX
*mem_ctx
,
438 struct in_addr ip
, uint16 port
,
439 struct sockaddr_in
**addrs
, int *num
)
441 *addrs
= TALLOC_REALLOC_ARRAY(mem_ctx
, *addrs
, struct sockaddr_in
, (*num
)+1);
446 (*addrs
)[*num
].sin_family
= PF_INET
;
447 putip((char *)&((*addrs
)[*num
].sin_addr
), (char *)&ip
);
448 (*addrs
)[*num
].sin_port
= htons(port
);
454 static void mailslot_name(struct in_addr dc_ip
, fstring name
)
456 fstr_sprintf(name
, "\\MAILSLOT\\NET\\GETDC%X", dc_ip
.s_addr
);
459 static BOOL
send_getdc_request(struct in_addr dc_ip
,
460 const char *domain_name
,
465 fstring my_acct_name
;
468 mailslot_name(dc_ip
, my_mailslot
);
470 memset(outbuf
, '\0', sizeof(outbuf
));
474 SCVAL(p
, 0, SAMLOGON
);
477 SCVAL(p
, 0, 0); /* Count pointer ... */
480 SIVAL(p
, 0, 0); /* The sender's token ... */
483 p
+= dos_PutUniCode(p
, global_myname(), sizeof(pstring
), True
);
484 fstr_sprintf(my_acct_name
, "%s$", global_myname());
485 p
+= dos_PutUniCode(p
, my_acct_name
, sizeof(pstring
), True
);
487 memcpy(p
, my_mailslot
, strlen(my_mailslot
)+1);
488 p
+= strlen(my_mailslot
)+1;
493 SIVAL(p
, 0, sid_size(sid
));
496 p
= ALIGN4(p
, outbuf
);
498 sid_linearize(p
, sid_size(sid
), sid
);
506 return cli_send_mailslot(False
, "\\MAILSLOT\\NET\\NTLOGON", 0,
507 outbuf
, PTR_DIFF(p
, outbuf
),
508 global_myname(), 0, domain_name
, 0x1c,
512 static BOOL
receive_getdc_response(struct in_addr dc_ip
,
513 const char *domain_name
,
516 struct packet_struct
*packet
;
519 fstring dcname
, user
, domain
;
522 mailslot_name(dc_ip
, my_mailslot
);
524 packet
= receive_unexpected(DGRAM_PACKET
, 0, my_mailslot
);
526 if (packet
== NULL
) {
527 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot
));
531 DEBUG(5, ("Received packet for %s\n", my_mailslot
));
533 buf
= packet
->packet
.dgram
.data
;
534 len
= packet
->packet
.dgram
.datasize
;
537 /* 70 is a completely arbitrary value to make sure
538 the SVAL below does not read uninitialized memory */
539 DEBUG(3, ("GetDC got short response\n"));
543 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
544 p
= buf
+SVAL(buf
, smb_vwv10
);
546 if (CVAL(p
,0) != SAMLOGON_R
) {
547 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p
, 0)));
552 pull_ucs2(buf
, dcname
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
553 STR_TERMINATE
|STR_NOALIGN
);
554 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
555 pull_ucs2(buf
, user
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
556 STR_TERMINATE
|STR_NOALIGN
);
557 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
558 pull_ucs2(buf
, domain
, p
, sizeof(dcname
), PTR_DIFF(buf
+len
, p
),
559 STR_TERMINATE
|STR_NOALIGN
);
560 p
= skip_unibuf(p
, PTR_DIFF(buf
+len
, p
));
562 if (!strequal(domain
, domain_name
)) {
563 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
564 domain_name
, domain
));
569 if (*p
== '\\') p
+= 1;
570 if (*p
== '\\') p
+= 1;
574 DEBUG(10, ("GetDC gave name %s for domain %s\n",
580 /*******************************************************************
581 convert an ip to a name
582 *******************************************************************/
584 static BOOL
dcip_to_name( const char *domainname
, const char *realm
,
585 const DOM_SID
*sid
, struct in_addr ip
, fstring name
)
587 struct ip_service ip_list
;
592 /* try GETDC requests first */
594 if (send_getdc_request(ip
, domainname
, sid
)) {
597 for (i
=0; i
<5; i
++) {
598 if (receive_getdc_response(ip
, domainname
, name
)) {
599 namecache_store(name
, 0x20, 1, &ip_list
);
606 /* try node status request */
608 if ( name_status_find(domainname
, 0x1c, 0x20, ip
, name
) ) {
609 namecache_store(name
, 0x20, 1, &ip_list
);
614 /* for active directory servers, try to get the ldap server name.
615 None of these failure should be considered critical for now */
617 if ( lp_security() == SEC_ADS
)
621 ads
= ads_init( realm
, domainname
, NULL
);
622 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
624 if ( !ads_try_connect( ads
, inet_ntoa(ip
) ) ) {
629 fstrcpy(name
, ads
->config
.ldap_server_name
);
630 namecache_store(name
, 0x20, 1, &ip_list
);
640 /*******************************************************************
641 Retreive a list of IP address for domain controllers. Fill in
642 the dcs[] with results.
643 *******************************************************************/
645 static BOOL
get_dcs(TALLOC_CTX
*mem_ctx
, const struct winbindd_domain
*domain
,
646 struct dc_name_ip
**dcs
, int *num_dcs
)
650 struct ip_service
*ip_list
= NULL
;
656 is_our_domain
= strequal(domain
->name
, lp_workgroup());
659 && get_dc_name_via_netlogon(domain
, dcname
, &ip
)
660 && add_one_dc_unique(mem_ctx
, domain
->name
, dcname
, ip
, dcs
, num_dcs
) )
662 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
663 dcname
, inet_ntoa(ip
)));
667 /* try standard netbios queries first */
669 get_sorted_dc_list(domain
->name
, &ip_list
, &iplist_size
, False
);
671 /* check for security = ads and use DNS if we can */
673 if ( iplist_size
==0 && lp_security() == SEC_ADS
)
674 get_sorted_dc_list(domain
->alt_name
, &ip_list
, &iplist_size
, True
);
676 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
678 /* now add to the dc array. We'll wait until the last minute
679 to look up the name of the DC. But we fill in the char* for
680 the ip now in to make the failed connection cache work */
682 for ( i
=0; i
<iplist_size
; i
++ ) {
683 add_one_dc_unique(mem_ctx
, domain
->name
, inet_ntoa(ip_list
[i
].ip
),
684 ip_list
[i
].ip
, dcs
, num_dcs
);
687 SAFE_FREE( ip_list
);
692 static BOOL
find_new_dc(TALLOC_CTX
*mem_ctx
,
693 const struct winbindd_domain
*domain
,
694 fstring dcname
, struct sockaddr_in
*addr
, int *fd
)
696 struct dc_name_ip
*dcs
= NULL
;
699 const char **dcnames
= NULL
;
702 struct sockaddr_in
*addrs
= NULL
;
708 if (!get_dcs(mem_ctx
, domain
, &dcs
, &num_dcs
) || (num_dcs
== 0))
711 for (i
=0; i
<num_dcs
; i
++) {
713 add_string_to_array(mem_ctx
, dcs
[i
].name
,
714 &dcnames
, &num_dcnames
);
715 add_sockaddr_to_array(mem_ctx
, dcs
[i
].ip
, 445,
718 add_string_to_array(mem_ctx
, dcs
[i
].name
,
719 &dcnames
, &num_dcnames
);
720 add_sockaddr_to_array(mem_ctx
, dcs
[i
].ip
, 139,
724 if ((num_dcnames
== 0) || (num_dcnames
!= num_addrs
))
727 if ((addrs
== NULL
) || (dcnames
== NULL
))
730 if ( !open_any_socket_out(addrs
, num_addrs
, 10000, &fd_index
, fd
) )
732 for (i
=0; i
<num_dcs
; i
++) {
733 add_failed_connection_entry(domain
->name
,
734 dcs
[i
].name
, NT_STATUS_UNSUCCESSFUL
);
739 *addr
= addrs
[fd_index
];
741 if (*dcnames
[fd_index
] != '\0' && !is_ipaddress(dcnames
[fd_index
])) {
742 /* Ok, we've got a name for the DC */
743 fstrcpy(dcname
, dcnames
[fd_index
]);
747 /* Try to figure out the name */
748 if (dcip_to_name( domain
->name
, domain
->alt_name
, &domain
->sid
,
749 addr
->sin_addr
, dcname
)) {
753 /* We can not continue without the DC's name */
754 add_failed_connection_entry(domain
->name
, dcs
[fd_index
].name
,
755 NT_STATUS_UNSUCCESSFUL
);
759 static NTSTATUS
cm_open_connection(struct winbindd_domain
*domain
,
760 struct winbindd_cm_conn
*new_conn
)
764 char *saf_servername
= saf_fetch( domain
->name
);
767 if ((mem_ctx
= talloc_init("cm_open_connection")) == NULL
)
768 return NT_STATUS_NO_MEMORY
;
770 /* we have to check the server affinity cache here since
771 later we selecte a DC based on response time and not preference */
773 if ( saf_servername
)
775 /* convert an ip address to a name */
776 if ( is_ipaddress( saf_servername
) )
781 ip
= *interpret_addr2( saf_servername
);
782 if (dcip_to_name( domain
->name
, domain
->alt_name
,
783 &domain
->sid
, ip
, saf_name
)) {
784 fstrcpy( domain
->dcname
, saf_name
);
786 add_failed_connection_entry(
787 domain
->name
, saf_servername
,
788 NT_STATUS_UNSUCCESSFUL
);
793 fstrcpy( domain
->dcname
, saf_servername
);
796 SAFE_FREE( saf_servername
);
799 for (retries
= 0; retries
< 3; retries
++) {
804 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
806 if ((strlen(domain
->dcname
) > 0)
807 && NT_STATUS_IS_OK(check_negative_conn_cache( domain
->name
, domain
->dcname
))
808 && (resolve_name(domain
->dcname
, &domain
->dcaddr
.sin_addr
, 0x20)))
810 struct sockaddr_in
*addrs
= NULL
;
814 add_sockaddr_to_array(mem_ctx
, domain
->dcaddr
.sin_addr
, 445, &addrs
, &num_addrs
);
815 add_sockaddr_to_array(mem_ctx
, domain
->dcaddr
.sin_addr
, 139, &addrs
, &num_addrs
);
817 if (!open_any_socket_out(addrs
, num_addrs
, 10000, &dummy
, &fd
)) {
818 domain
->online
= False
;
824 && !find_new_dc(mem_ctx
, domain
, domain
->dcname
, &domain
->dcaddr
, &fd
))
826 /* This is the one place where we will
827 set the global winbindd offline state
828 to true, if a "WINBINDD_OFFLINE" entry
829 is found in the winbindd cache. */
830 set_global_winbindd_state_offline();
831 domain
->online
= False
;
835 new_conn
->cli
= NULL
;
837 result
= cm_prepare_connection(domain
, fd
, domain
->dcname
,
838 &new_conn
->cli
, &retry
);
844 if (NT_STATUS_IS_OK(result
)) {
845 if (domain
->online
== False
) {
846 /* We're changing state from offline to online. */
847 set_global_winbindd_state_online();
849 domain
->online
= True
;
852 talloc_destroy(mem_ctx
);
856 /* Close down all open pipes on a connection. */
858 void invalidate_cm_connection(struct winbindd_cm_conn
*conn
)
860 if (conn
->samr_pipe
!= NULL
) {
861 cli_rpc_pipe_close(conn
->samr_pipe
);
862 conn
->samr_pipe
= NULL
;
865 if (conn
->lsa_pipe
!= NULL
) {
866 cli_rpc_pipe_close(conn
->lsa_pipe
);
867 conn
->lsa_pipe
= NULL
;
870 if (conn
->netlogon_pipe
!= NULL
) {
871 cli_rpc_pipe_close(conn
->netlogon_pipe
);
872 conn
->netlogon_pipe
= NULL
;
876 cli_shutdown(conn
->cli
);
882 void close_conns_after_fork(void)
884 struct winbindd_domain
*domain
;
886 for (domain
= domain_list(); domain
; domain
= domain
->next
) {
887 if (domain
->conn
.cli
== NULL
)
890 if (domain
->conn
.cli
->fd
== -1)
893 close(domain
->conn
.cli
->fd
);
894 domain
->conn
.cli
->fd
= -1;
898 static BOOL
connection_ok(struct winbindd_domain
*domain
)
900 if (domain
->conn
.cli
== NULL
) {
901 DEBUG(8, ("Connection to %s for domain %s has NULL "
902 "cli!\n", domain
->dcname
, domain
->name
));
906 if (!domain
->conn
.cli
->initialised
) {
907 DEBUG(3, ("Connection to %s for domain %s was never "
908 "initialised!\n", domain
->dcname
, domain
->name
));
912 if (domain
->conn
.cli
->fd
== -1) {
913 DEBUG(3, ("Connection to %s for domain %s has died or was "
914 "never started (fd == -1)\n",
915 domain
->dcname
, domain
->name
));
922 /* Initialize a new connection up to the RPC BIND. */
924 static NTSTATUS
init_dc_connection(struct winbindd_domain
*domain
)
926 if (connection_ok(domain
))
929 invalidate_cm_connection(&domain
->conn
);
931 return cm_open_connection(domain
, &domain
->conn
);
934 /******************************************************************************
935 We can 'sense' certain things about the DC by it's replies to certain
938 This tells us if this particular remote server is Active Directory, and if it
940 ******************************************************************************/
942 void set_dc_type_and_flags( struct winbindd_domain
*domain
)
946 TALLOC_CTX
*mem_ctx
= NULL
;
947 struct rpc_pipe_client
*cli
;
950 char *domain_name
= NULL
;
951 char *dns_name
= NULL
;
952 DOM_SID
*dom_sid
= NULL
;
956 domain
->native_mode
= False
;
957 domain
->active_directory
= False
;
959 if (domain
->internal
) {
960 domain
->initialized
= True
;
964 result
= init_dc_connection(domain
);
965 if (!NT_STATUS_IS_OK(result
)) {
966 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
967 "to %s: (%s)\n", domain
->name
, nt_errstr(result
)));
968 domain
->initialized
= True
;
972 cli
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
, PI_LSARPC_DS
,
976 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
977 "PI_LSARPC_DS on domain %s: (%s)\n",
978 domain
->name
, nt_errstr(result
)));
979 domain
->initialized
= True
;
983 result
= rpccli_ds_getprimarydominfo(cli
, cli
->cli
->mem_ctx
,
984 DsRolePrimaryDomainInfoBasic
,
986 cli_rpc_pipe_close(cli
);
988 if (!NT_STATUS_IS_OK(result
)) {
989 domain
->initialized
= True
;
993 if ((ctr
.basic
->flags
& DSROLE_PRIMARY_DS_RUNNING
) &&
994 !(ctr
.basic
->flags
& DSROLE_PRIMARY_DS_MIXED_MODE
) )
995 domain
->native_mode
= True
;
997 cli
= cli_rpc_pipe_open_noauth(domain
->conn
.cli
, PI_LSARPC
, &result
);
1000 domain
->initialized
= True
;
1004 mem_ctx
= talloc_init("set_dc_type_and_flags on domain %s\n",
1007 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
1008 cli_rpc_pipe_close(cli
);
1012 result
= rpccli_lsa_open_policy2(cli
, mem_ctx
, True
,
1013 SEC_RIGHTS_MAXIMUM_ALLOWED
, &pol
);
1015 if (NT_STATUS_IS_OK(result
)) {
1016 /* This particular query is exactly what Win2k clients use
1017 to determine that the DC is active directory */
1018 result
= rpccli_lsa_query_info_policy2(cli
, mem_ctx
, &pol
,
1024 if (NT_STATUS_IS_OK(result
)) {
1026 fstrcpy(domain
->name
, domain_name
);
1029 fstrcpy(domain
->alt_name
, dns_name
);
1032 sid_copy(&domain
->sid
, dom_sid
);
1034 domain
->active_directory
= True
;
1037 result
= rpccli_lsa_open_policy(cli
, mem_ctx
, True
,
1038 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1041 if (!NT_STATUS_IS_OK(result
))
1044 result
= rpccli_lsa_query_info_policy(cli
, mem_ctx
,
1045 &pol
, 5, &domain_name
,
1048 if (NT_STATUS_IS_OK(result
)) {
1050 fstrcpy(domain
->name
, domain_name
);
1053 sid_copy(&domain
->sid
, dom_sid
);
1058 cli_rpc_pipe_close(cli
);
1060 talloc_destroy(mem_ctx
);
1062 domain
->initialized
= True
;
1067 static BOOL
cm_get_schannel_dcinfo(struct winbindd_domain
*domain
,
1068 struct dcinfo
**ppdc
)
1071 struct rpc_pipe_client
*netlogon_pipe
;
1073 if (lp_client_schannel() == False
) {
1077 result
= cm_connect_netlogon(domain
, &netlogon_pipe
);
1078 if (!NT_STATUS_IS_OK(result
)) {
1082 /* Return a pointer to the struct dcinfo from the
1085 *ppdc
= domain
->conn
.netlogon_pipe
->dc
;
1089 NTSTATUS
cm_connect_sam(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
1090 struct rpc_pipe_client
**cli
, POLICY_HND
*sam_handle
)
1092 struct winbindd_cm_conn
*conn
;
1095 struct dcinfo
*p_dcinfo
;
1097 result
= init_dc_connection(domain
);
1098 if (!NT_STATUS_IS_OK(result
)) {
1102 conn
= &domain
->conn
;
1104 if (conn
->samr_pipe
!= NULL
) {
1109 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
1110 * sign and sealed pipe using the machine account password by
1111 * preference. If we can't - try schannel, if that fails, try
1115 pwd_get_cleartext(&conn
->cli
->pwd
, conn_pwd
);
1116 if ((conn
->cli
->user_name
[0] == '\0') ||
1117 (conn
->cli
->domain
[0] == '\0') ||
1118 (conn_pwd
[0] == '\0')) {
1119 DEBUG(10, ("cm_connect_sam: No no user available for "
1120 "domain %s, trying schannel\n", conn
->cli
->domain
));
1124 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1125 authenticated SAMR pipe with sign & seal. */
1127 cli_rpc_pipe_open_spnego_ntlmssp(conn
->cli
, PI_SAMR
,
1128 PIPE_AUTH_LEVEL_PRIVACY
,
1130 conn
->cli
->user_name
,
1133 if (conn
->samr_pipe
== NULL
) {
1134 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
1135 "pipe for domain %s using NTLMSSP "
1136 "authenticated pipe: user %s\\%s. Error was "
1137 "%s\n", domain
->name
, conn
->cli
->domain
,
1138 conn
->cli
->user_name
, nt_errstr(result
)));
1142 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
1143 "domain %s using NTLMSSP authenticated "
1144 "pipe: user %s\\%s\n", domain
->name
,
1145 conn
->cli
->domain
, conn
->cli
->user_name
));
1147 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1148 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1149 &conn
->sam_connect_handle
);
1150 if (NT_STATUS_IS_OK(result
)) {
1153 DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
1154 "failed for domain %s, error was %s. Trying schannel\n",
1155 domain
->name
, nt_errstr(result
) ));
1156 cli_rpc_pipe_close(conn
->samr_pipe
);
1160 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1162 if (!cm_get_schannel_dcinfo(domain
, &p_dcinfo
)) {
1163 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
1164 "for domain %s, trying anon\n", conn
->cli
->domain
));
1167 conn
->samr_pipe
= cli_rpc_pipe_open_schannel_with_key
1168 (conn
->cli
, PI_SAMR
, PIPE_AUTH_LEVEL_PRIVACY
,
1169 domain
->name
, p_dcinfo
, &result
);
1171 if (conn
->samr_pipe
== NULL
) {
1172 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
1173 "domain %s using schannel. Error was %s\n",
1174 domain
->name
, nt_errstr(result
) ));
1177 DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
1178 "schannel.\n", domain
->name
));
1180 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1181 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1182 &conn
->sam_connect_handle
);
1183 if (NT_STATUS_IS_OK(result
)) {
1186 DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
1187 "for domain %s, error was %s. Trying anonymous\n",
1188 domain
->name
, nt_errstr(result
) ));
1189 cli_rpc_pipe_close(conn
->samr_pipe
);
1193 /* Finally fall back to anonymous. */
1194 conn
->samr_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_SAMR
,
1197 if (conn
->samr_pipe
== NULL
) {
1198 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
1202 result
= rpccli_samr_connect(conn
->samr_pipe
, mem_ctx
,
1203 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1204 &conn
->sam_connect_handle
);
1205 if (!NT_STATUS_IS_OK(result
)) {
1206 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1207 "for domain %s Error was %s\n",
1208 domain
->name
, nt_errstr(result
) ));
1213 result
= rpccli_samr_open_domain(conn
->samr_pipe
,
1215 &conn
->sam_connect_handle
,
1216 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1218 &conn
->sam_domain_handle
);
1222 if (!NT_STATUS_IS_OK(result
)) {
1223 invalidate_cm_connection(conn
);
1227 *cli
= conn
->samr_pipe
;
1228 *sam_handle
= conn
->sam_domain_handle
;
1232 NTSTATUS
cm_connect_lsa(struct winbindd_domain
*domain
, TALLOC_CTX
*mem_ctx
,
1233 struct rpc_pipe_client
**cli
, POLICY_HND
*lsa_policy
)
1235 struct winbindd_cm_conn
*conn
;
1238 struct dcinfo
*p_dcinfo
;
1240 result
= init_dc_connection(domain
);
1241 if (!NT_STATUS_IS_OK(result
))
1244 conn
= &domain
->conn
;
1246 if (conn
->lsa_pipe
!= NULL
) {
1250 pwd_get_cleartext(&conn
->cli
->pwd
, conn_pwd
);
1251 if ((conn
->cli
->user_name
[0] == '\0') ||
1252 (conn
->cli
->domain
[0] == '\0') ||
1253 (conn_pwd
[0] == '\0')) {
1254 DEBUG(10, ("cm_connect_lsa: No no user available for "
1255 "domain %s, trying schannel\n", conn
->cli
->domain
));
1259 /* We have an authenticated connection. Use a NTLMSSP SPNEGO
1260 * authenticated LSA pipe with sign & seal. */
1261 conn
->lsa_pipe
= cli_rpc_pipe_open_spnego_ntlmssp
1262 (conn
->cli
, PI_LSARPC
, PIPE_AUTH_LEVEL_PRIVACY
,
1263 conn
->cli
->domain
, conn
->cli
->user_name
, conn_pwd
, &result
);
1265 if (conn
->lsa_pipe
== NULL
) {
1266 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1267 "domain %s using NTLMSSP authenticated pipe: user "
1268 "%s\\%s. Error was %s. Trying schannel.\n",
1269 domain
->name
, conn
->cli
->domain
,
1270 conn
->cli
->user_name
, nt_errstr(result
)));
1274 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1275 "NTLMSSP authenticated pipe: user %s\\%s\n",
1276 domain
->name
, conn
->cli
->domain
, conn
->cli
->user_name
));
1278 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
1279 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1281 if (NT_STATUS_IS_OK(result
)) {
1285 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1288 cli_rpc_pipe_close(conn
->lsa_pipe
);
1292 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1294 if (!cm_get_schannel_dcinfo(domain
, &p_dcinfo
)) {
1295 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
1296 "for domain %s, trying anon\n", conn
->cli
->domain
));
1299 conn
->lsa_pipe
= cli_rpc_pipe_open_schannel_with_key
1300 (conn
->cli
, PI_LSARPC
, PIPE_AUTH_LEVEL_PRIVACY
,
1301 domain
->name
, p_dcinfo
, &result
);
1303 if (conn
->lsa_pipe
== NULL
) {
1304 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
1305 "domain %s using schannel. Error was %s\n",
1306 domain
->name
, nt_errstr(result
) ));
1309 DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
1310 "schannel.\n", domain
->name
));
1312 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
1313 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1315 if (NT_STATUS_IS_OK(result
)) {
1319 DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
1322 cli_rpc_pipe_close(conn
->lsa_pipe
);
1326 conn
->lsa_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_LSARPC
,
1328 if (conn
->lsa_pipe
== NULL
) {
1329 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
1333 result
= rpccli_lsa_open_policy(conn
->lsa_pipe
, mem_ctx
, True
,
1334 SEC_RIGHTS_MAXIMUM_ALLOWED
,
1337 if (!NT_STATUS_IS_OK(result
)) {
1338 invalidate_cm_connection(conn
);
1339 return NT_STATUS_UNSUCCESSFUL
;
1342 *cli
= conn
->lsa_pipe
;
1343 *lsa_policy
= conn
->lsa_policy
;
1347 /****************************************************************************
1348 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1349 session key stored in conn->netlogon_pipe->dc->sess_key.
1350 ****************************************************************************/
1352 NTSTATUS
cm_connect_netlogon(struct winbindd_domain
*domain
,
1353 struct rpc_pipe_client
**cli
)
1355 struct winbindd_cm_conn
*conn
;
1358 uint32 neg_flags
= NETLOGON_NEG_AUTH2_FLAGS
;
1360 uint32 sec_chan_type
;
1361 const char *account_name
;
1362 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
1366 result
= init_dc_connection(domain
);
1367 if (!NT_STATUS_IS_OK(result
)) {
1371 conn
= &domain
->conn
;
1373 if (conn
->netlogon_pipe
!= NULL
) {
1374 *cli
= conn
->netlogon_pipe
;
1375 return NT_STATUS_OK
;
1378 if (!get_trust_pw(domain
->name
, mach_pwd
, &sec_chan_type
)) {
1379 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1382 netlogon_pipe
= cli_rpc_pipe_open_noauth(conn
->cli
, PI_NETLOGON
,
1384 if (netlogon_pipe
== NULL
) {
1388 if (lp_client_schannel() != False
) {
1389 neg_flags
|= NETLOGON_NEG_SCHANNEL
;
1392 /* if we are a DC and this is a trusted domain, then we need to use our
1393 domain name in the net_req_auth2() request */
1396 && !strequal(domain
->name
, lp_workgroup())
1397 && lp_allow_trusted_domains() )
1399 account_name
= lp_workgroup();
1401 account_name
= domain
->primary
?
1402 global_myname() : domain
->name
;
1405 if (account_name
== NULL
) {
1406 cli_rpc_pipe_close(netlogon_pipe
);
1407 return NT_STATUS_NO_MEMORY
;
1410 result
= rpccli_netlogon_setup_creds(
1412 domain
->dcname
, /* server name. */
1413 domain
->name
, /* domain name */
1414 global_myname(), /* client name */
1415 account_name
, /* machine account */
1416 mach_pwd
, /* machine password */
1417 sec_chan_type
, /* from get_trust_pw */
1420 if (!NT_STATUS_IS_OK(result
)) {
1421 cli_rpc_pipe_close(netlogon_pipe
);
1425 if ((lp_client_schannel() == True
) &&
1426 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
1427 DEBUG(3, ("Server did not offer schannel\n"));
1428 cli_rpc_pipe_close(netlogon_pipe
);
1429 return NT_STATUS_ACCESS_DENIED
;
1432 if ((lp_client_schannel() == False
) ||
1433 ((neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0)) {
1434 /* We're done - just keep the existing connection to NETLOGON
1436 conn
->netlogon_pipe
= netlogon_pipe
;
1437 *cli
= conn
->netlogon_pipe
;
1438 return NT_STATUS_OK
;
1441 /* Using the credentials from the first pipe, open a signed and sealed
1442 second netlogon pipe. The session key is stored in the schannel
1443 part of the new pipe auth struct.
1446 conn
->netlogon_pipe
=
1447 cli_rpc_pipe_open_schannel_with_key(conn
->cli
,
1449 PIPE_AUTH_LEVEL_PRIVACY
,
1454 /* We can now close the initial netlogon pipe. */
1455 cli_rpc_pipe_close(netlogon_pipe
);
1457 if (conn
->netlogon_pipe
== NULL
) {
1458 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
1459 "was %s\n", nt_errstr(result
)));
1461 /* make sure we return something besides OK */
1462 return !NT_STATUS_IS_OK(result
) ? result
: NT_STATUS_PIPE_NOT_AVAILABLE
;
1465 *cli
= conn
->netlogon_pipe
;
1466 return NT_STATUS_OK
;