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 /******************************************************************
69 Disabling schannl on the LSA pipe for now since
70 both Win2K-SP4 SR1 & Win2K3-SP1 fail the open_policy()
71 call (return codes 0xc0020042 and 0xc0020041 respectively).
72 We really need to fix this soon. Had to disable on the
73 SAMR pipe as well for now. --jerry
74 ******************************************************************/
76 /* #define DISABLE_SCHANNEL_WIN2K3_SP1 1 */
79 /* Choose between anonymous or authenticated connections. We need to use
80 an authenticated connection if DCs have the RestrictAnonymous registry
81 entry set > 0, or the "Additional restrictions for anonymous
82 connections" set in the win2k Local Security Policy.
84 Caller to free() result in domain, username, password
87 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
89 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
90 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
91 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
93 if (*username && **username) {
95 if (!*domain || !**domain)
96 *domain = smb_xstrdup(lp_workgroup());
98 if (!*password || !**password)
99 *password = smb_xstrdup("");
101 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n",
102 *domain, *username));
105 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
106 *username = smb_xstrdup("");
107 *domain = smb_xstrdup("");
108 *password = smb_xstrdup("");
112 static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
113 fstring dcname, struct in_addr *dc_ip)
115 struct winbindd_domain *our_domain;
116 struct rpc_pipe_client *netlogon_pipe;
123 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
130 if (domain->primary) {
134 our_domain = find_our_domain();
136 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
140 result = cm_connect_netlogon(our_domain, &netlogon_pipe);
141 if (!NT_STATUS_IS_OK(result)) {
145 result = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, domain->dcname,
148 talloc_destroy(mem_ctx);
150 if (!NT_STATUS_IS_OK(result))
153 /* cli_netlogon_getdcname gives us a name with \\ */
164 if (!resolve_name(dcname, dc_ip, 0x20)) {
171 /************************************************************************
172 Given a fd with a just-connected TCP connection to a DC, open a connection
174 ************************************************************************/
176 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
178 const char *controller,
179 struct cli_state **cli,
182 char *machine_password, *machine_krb5_principal, *machine_account;
183 char *ipc_username, *ipc_domain, *ipc_password;
186 BOOL add_failed_connection = True;
188 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
190 struct sockaddr peeraddr;
191 socklen_t peeraddr_len;
193 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
195 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
198 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
199 SAFE_FREE(machine_password);
200 return NT_STATUS_NO_MEMORY;
203 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
205 SAFE_FREE(machine_account);
206 SAFE_FREE(machine_password);
207 return NT_STATUS_NO_MEMORY;
210 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
214 got_mutex = secrets_named_mutex(controller,
215 WINBIND_SERVER_MUTEX_WAIT_TIME);
218 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n",
220 result = NT_STATUS_POSSIBLE_DEADLOCK;
224 if ((*cli = cli_initialise(NULL)) == NULL) {
225 DEBUG(1, ("Could not cli_initialize\n"));
226 result = NT_STATUS_NO_MEMORY;
230 (*cli)->timeout = 10000; /* 10 seconds */
232 fstrcpy((*cli)->desthost, controller);
233 (*cli)->use_kerberos = True;
235 peeraddr_len = sizeof(peeraddr);
237 if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
238 (peeraddr_len != sizeof(struct sockaddr_in)) ||
239 (peeraddr_in->sin_family != PF_INET))
241 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
245 if (ntohs(peeraddr_in->sin_port) == 139) {
246 struct nmb_name calling;
247 struct nmb_name called;
249 make_nmb_name(&calling, global_myname(), 0x0);
250 make_nmb_name(&called, "*SMBSERVER", 0x20);
252 if (!cli_session_request(*cli, &calling, &called)) {
253 DEBUG(8, ("cli_session_request failed for %s\n",
259 cli_setup_signing_state(*cli, Undefined);
261 if (!cli_negprot(*cli)) {
262 DEBUG(1, ("cli_negprot failed\n"));
268 if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
269 ADS_STATUS ads_status;
271 if (lp_security() == SEC_ADS) {
273 /* Try a krb5 session */
275 (*cli)->use_kerberos = True;
276 DEBUG(5, ("connecting to %s from %s with kerberos principal "
277 "[%s]\n", controller, global_myname(),
278 machine_krb5_principal));
280 ads_status = cli_session_setup_spnego(*cli,
281 machine_krb5_principal,
285 if (!ADS_ERR_OK(ads_status)) {
286 DEBUG(4,("failed kerberos session setup with %s\n",
287 ads_errstr(ads_status)));
290 result = ads_ntstatus(ads_status);
291 if (NT_STATUS_IS_OK(result)) {
292 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
293 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
294 goto session_setup_done;
298 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
299 (*cli)->use_kerberos = False;
301 DEBUG(5, ("connecting to %s from %s with username "
302 "[%s]\\[%s]\n", controller, global_myname(),
303 machine_account, machine_password));
305 ads_status = cli_session_setup_spnego(*cli,
309 if (!ADS_ERR_OK(ads_status)) {
310 DEBUG(4, ("authenticated session setup failed with %s\n",
311 ads_errstr(ads_status)));
314 result = ads_ntstatus(ads_status);
315 if (NT_STATUS_IS_OK(result)) {
316 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
317 cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
318 goto session_setup_done;
322 /* Fall back to non-kerberos session setup */
324 (*cli)->use_kerberos = False;
326 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
327 (strlen(ipc_username) > 0)) {
329 /* Only try authenticated if we have a username */
331 DEBUG(5, ("connecting to %s from %s with username "
332 "[%s]\\[%s]\n", controller, global_myname(),
333 ipc_domain, ipc_username));
335 if (cli_session_setup(*cli, ipc_username,
336 ipc_password, strlen(ipc_password)+1,
337 ipc_password, strlen(ipc_password)+1,
339 /* Successful logon with given username. */
340 cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
341 goto session_setup_done;
343 DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
344 ipc_domain, ipc_username ));
348 /* Fall back to anonymous connection, this might fail later */
350 if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
351 DEBUG(5, ("Connected anonymously\n"));
352 cli_init_creds(*cli, "", "", "");
353 goto session_setup_done;
356 result = cli_nt_error(*cli);
358 if (NT_STATUS_IS_OK(result))
359 result = NT_STATUS_UNSUCCESSFUL;
361 /* We can't session setup */
367 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
369 result = cli_nt_error(*cli);
371 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
373 if (NT_STATUS_IS_OK(result))
374 result = NT_STATUS_UNSUCCESSFUL;
380 secrets_named_mutex_release(controller);
384 /* set the domain if empty; needed for schannel connections */
385 if ( !*(*cli)->domain ) {
386 fstrcpy( (*cli)->domain, domain->name );
389 result = NT_STATUS_OK;
390 add_failed_connection = False;
394 secrets_named_mutex_release(controller);
397 SAFE_FREE(machine_account);
398 SAFE_FREE(machine_password);
399 SAFE_FREE(machine_krb5_principal);
400 SAFE_FREE(ipc_username);
401 SAFE_FREE(ipc_domain);
402 SAFE_FREE(ipc_password);
404 if (add_failed_connection) {
405 add_failed_connection_entry(domain->name, controller, result);
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)))
423 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
428 fstrcpy((*dcs)[*num].name, dcname);
429 (*dcs)[*num].ip = ip;
434 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
435 struct in_addr ip, uint16 port,
436 struct sockaddr_in **addrs, int *num)
438 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
443 (*addrs)[*num].sin_family = PF_INET;
444 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
445 (*addrs)[*num].sin_port = htons(port);
451 static void mailslot_name(struct in_addr dc_ip, fstring name)
453 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
456 static BOOL send_getdc_request(struct in_addr dc_ip,
457 const char *domain_name,
462 fstring my_acct_name;
465 mailslot_name(dc_ip, my_mailslot);
467 memset(outbuf, '\0', sizeof(outbuf));
471 SCVAL(p, 0, SAMLOGON);
474 SCVAL(p, 0, 0); /* Count pointer ... */
477 SIVAL(p, 0, 0); /* The sender's token ... */
480 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
481 fstr_sprintf(my_acct_name, "%s$", global_myname());
482 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
484 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
485 p += strlen(my_mailslot)+1;
490 SIVAL(p, 0, sid_size(sid));
493 p = ALIGN4(p, outbuf);
495 sid_linearize(p, sid_size(sid), sid);
503 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
504 outbuf, PTR_DIFF(p, outbuf),
505 global_myname(), 0, domain_name, 0x1c,
509 static BOOL receive_getdc_response(struct in_addr dc_ip,
510 const char *domain_name,
513 struct packet_struct *packet;
516 fstring dcname, user, domain;
519 mailslot_name(dc_ip, my_mailslot);
521 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
523 if (packet == NULL) {
524 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
528 DEBUG(5, ("Received packet for %s\n", my_mailslot));
530 buf = packet->packet.dgram.data;
531 len = packet->packet.dgram.datasize;
534 /* 70 is a completely arbitrary value to make sure
535 the SVAL below does not read uninitialized memory */
536 DEBUG(3, ("GetDC got short response\n"));
540 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
541 p = buf+SVAL(buf, smb_vwv10);
543 if (CVAL(p,0) != SAMLOGON_R) {
544 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
549 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
550 STR_TERMINATE|STR_NOALIGN);
551 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
552 pull_ucs2(buf, user, 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, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
556 STR_TERMINATE|STR_NOALIGN);
557 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
559 if (!strequal(domain, domain_name)) {
560 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
561 domain_name, domain));
566 if (*p == '\\') p += 1;
567 if (*p == '\\') p += 1;
571 DEBUG(10, ("GetDC gave name %s for domain %s\n",
577 /*******************************************************************
578 convert an ip to a name
579 *******************************************************************/
581 static void dcip_to_name( const char *domainname, const char *realm,
582 const DOM_SID *sid, struct in_addr ip, fstring name )
585 /* try GETDC requests first */
587 if (send_getdc_request(ip, domainname, sid)) {
590 for (i=0; i<5; i++) {
591 if (receive_getdc_response(ip, domainname, name))
597 /* try node status request */
599 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
602 /* backup in case the netbios stuff fails */
604 fstrcpy( name, inet_ntoa(ip) );
607 /* for active directory servers, try to get the ldap server name.
608 None of these failure should be considered critical for now */
610 if ( lp_security() == SEC_ADS )
615 ads = ads_init( realm, domainname, NULL );
616 ads->auth.flags |= ADS_AUTH_NO_BIND;
618 if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) ) {
623 status = ads_server_info(ads);
624 if ( !ADS_ERR_OK(status) ) {
629 fstrcpy(name, ads->config.ldap_server_name);
638 /*******************************************************************
639 Retreive a list of IP address for domain controllers. Fill in
640 the dcs[] with results.
641 *******************************************************************/
643 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
644 struct dc_name_ip **dcs, int *num_dcs)
648 struct ip_service *ip_list = NULL;
654 is_our_domain = strequal(domain->name, lp_workgroup());
657 && get_dc_name_via_netlogon(domain, dcname, &ip)
658 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
664 && must_use_pdc(domain->name)
665 && get_pdc_ip(domain->name, &ip))
667 if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs))
671 /* try standard netbios queries first */
673 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
675 /* check for security = ads and use DNS if we can */
677 if ( iplist_size==0 && lp_security() == SEC_ADS )
678 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
680 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
682 /* now add to the dc array. We'll wait until the last minute
683 to look up the name of the DC. But we fill in the char* for
684 the ip now in to make the failed connection cache work */
686 for ( i=0; i<iplist_size; i++ ) {
687 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
688 ip_list[i].ip, dcs, num_dcs);
691 SAFE_FREE( ip_list );
696 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
697 const struct winbindd_domain *domain,
698 fstring dcname, struct sockaddr_in *addr, int *fd)
700 struct dc_name_ip *dcs = NULL;
703 const char **dcnames = NULL;
706 struct sockaddr_in *addrs = NULL;
711 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
714 for (i=0; i<num_dcs; i++) {
716 add_string_to_array(mem_ctx, dcs[i].name,
717 &dcnames, &num_dcnames);
718 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
721 add_string_to_array(mem_ctx, dcs[i].name,
722 &dcnames, &num_dcnames);
723 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
727 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
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 we have no name on the server or just an IP address for
742 the name, now try to get the name */
744 if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
745 dcip_to_name( domain->name, domain->alt_name, &domain->sid, addr->sin_addr, dcname );
747 fstrcpy(dcname, dcnames[fd_index]);
752 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
753 struct winbindd_cm_conn *new_conn)
760 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
761 return NT_STATUS_NO_MEMORY;
763 for (retries = 0; retries < 3; retries++) {
768 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
770 if ((strlen(domain->dcname) > 0) &&
771 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
774 if (!open_any_socket_out(&domain->dcaddr, 1, 10000,
781 !find_new_dc(mem_ctx, domain, domain->dcname,
782 &domain->dcaddr, &fd))
785 new_conn->cli = NULL;
787 result = cm_prepare_connection(domain, fd, domain->dcname,
788 &new_conn->cli, &retry);
794 talloc_destroy(mem_ctx);
798 /* Return true if a connection is still alive */
800 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
802 if (conn->samr_pipe != NULL) {
803 cli_rpc_pipe_close(conn->samr_pipe);
804 conn->samr_pipe = NULL;
807 if (conn->lsa_pipe != NULL) {
808 cli_rpc_pipe_close(conn->lsa_pipe);
809 conn->lsa_pipe = NULL;
812 if (conn->netlogon_pipe != NULL) {
813 cli_rpc_pipe_close(conn->netlogon_pipe);
814 conn->netlogon_pipe = NULL;
818 cli_shutdown(conn->cli);
824 void close_conns_after_fork(void)
826 struct winbindd_domain *domain;
828 for (domain = domain_list(); domain; domain = domain->next) {
829 if (domain->conn.cli == NULL)
832 if (domain->conn.cli->fd == -1)
835 close(domain->conn.cli->fd);
836 domain->conn.cli->fd = -1;
840 static BOOL connection_ok(struct winbindd_domain *domain)
842 if (domain->conn.cli == NULL) {
843 DEBUG(8, ("Connection to %s for domain %s has NULL "
844 "cli!\n", domain->dcname, domain->name));
848 if (!domain->conn.cli->initialised) {
849 DEBUG(3, ("Connection to %s for domain %s was never "
850 "initialised!\n", domain->dcname, domain->name));
854 if (domain->conn.cli->fd == -1) {
855 DEBUG(3, ("Connection to %s for domain %s has died or was "
856 "never started (fd == -1)\n",
857 domain->dcname, domain->name));
864 /* Initialize a new connection up to the RPC BIND. */
866 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
868 if (connection_ok(domain))
871 invalidate_cm_connection(&domain->conn);
873 return cm_open_connection(domain, &domain->conn);
876 /**********************************************************************************
877 We can 'sense' certain things about the DC by it's replies to certain questions.
879 This tells us if this particular remote server is Active Directory, and if it is
881 **********************************************************************************/
883 void set_dc_type_and_flags( struct winbindd_domain *domain )
887 TALLOC_CTX *mem_ctx = NULL;
888 struct rpc_pipe_client *cli;
891 char *domain_name = NULL;
892 char *dns_name = NULL;
893 DOM_SID *dom_sid = NULL;
897 domain->native_mode = False;
898 domain->active_directory = False;
900 if (domain->internal) {
901 domain->initialized = True;
905 result = init_dc_connection(domain);
906 if (!NT_STATUS_IS_OK(result)) {
907 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
908 "to %s: (%s)\n", domain->name, nt_errstr(result)));
909 domain->initialized = True;
913 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS, &result);
916 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
917 "PI_LSARPC_DS on domain %s: (%s)\n",
918 domain->name, nt_errstr(result)));
919 domain->initialized = True;
923 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
924 DsRolePrimaryDomainInfoBasic,
926 cli_rpc_pipe_close(cli);
928 if (!NT_STATUS_IS_OK(result)) {
929 domain->initialized = True;
933 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
934 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
935 domain->native_mode = True;
937 cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
940 domain->initialized = True;
944 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
947 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
948 cli_rpc_pipe_close(cli);
952 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
953 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
955 if (NT_STATUS_IS_OK(result)) {
956 /* This particular query is exactly what Win2k clients use
957 to determine that the DC is active directory */
958 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
964 if (NT_STATUS_IS_OK(result)) {
966 fstrcpy(domain->name, domain_name);
969 fstrcpy(domain->alt_name, dns_name);
972 sid_copy(&domain->sid, dom_sid);
974 domain->active_directory = True;
977 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
978 SEC_RIGHTS_MAXIMUM_ALLOWED,
981 if (!NT_STATUS_IS_OK(result))
984 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
985 &pol, 5, &domain_name,
988 if (NT_STATUS_IS_OK(result)) {
990 fstrcpy(domain->name, domain_name);
993 sid_copy(&domain->sid, dom_sid);
998 cli_rpc_pipe_close(cli);
1000 talloc_destroy(mem_ctx);
1002 domain->initialized = True;
1007 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
1008 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain, struct dcinfo **ppdc)
1011 struct rpc_pipe_client *netlogon_pipe;
1013 if (lp_client_schannel() == False) {
1017 result = cm_connect_netlogon(domain, &netlogon_pipe);
1018 if (!NT_STATUS_IS_OK(result)) {
1022 /* Return a pointer to the struct dcinfo from the
1025 *ppdc = domain->conn.netlogon_pipe->dc;
1030 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1031 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
1033 struct winbindd_cm_conn *conn;
1036 result = init_dc_connection(domain);
1037 if (!NT_STATUS_IS_OK(result)) {
1041 conn = &domain->conn;
1043 if (conn->samr_pipe == NULL) {
1045 * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO
1046 * authenticated sign and sealed pipe using the machine
1047 * account password by preference. If we can't - try schannel,
1048 * if that fails, try anonymous.
1052 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1053 if (conn->cli->user_name[0] && conn->cli->domain[0] &&
1055 /* We have an authenticated connection. Use
1056 a NTLMSSP SPNEGO authenticated SAMR pipe with
1059 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
1061 PIPE_AUTH_LEVEL_PRIVACY,
1063 conn->cli->user_name,
1066 if (conn->samr_pipe == NULL) {
1067 DEBUG(10,("cm_connect_sam: failed to connect "
1068 "to SAMR pipe for domain %s using "
1069 "NTLMSSP authenticated pipe: user "
1070 "%s\\%s. Error was %s\n",
1071 domain->name, conn->cli->domain,
1072 conn->cli->user_name,
1073 nt_errstr(result)));
1075 DEBUG(10,("cm_connect_sam: connected to SAMR "
1076 "pipe for domain %s using NTLMSSP "
1077 "authenticated pipe: user %s\\%s\n",
1078 domain->name, conn->cli->domain,
1079 conn->cli->user_name ));
1083 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
1084 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1085 if (conn->samr_pipe == NULL) {
1086 struct dcinfo *p_dcinfo;
1088 if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1090 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1092 PIPE_AUTH_LEVEL_PRIVACY,
1097 if (conn->samr_pipe == NULL) {
1098 DEBUG(10,("cm_connect_sam: failed to connect "
1099 "to SAMR pipe for domain %s using "
1100 "schannel authenticated. Error "
1101 "was %s\n", domain->name,
1102 nt_errstr(result) ));
1104 DEBUG(10,("cm_connect_sam: connected to SAMR "
1105 "pipe for domain %s using schannel.\n",
1109 #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */
1111 /* Finally fall back to anonymous. */
1112 if (conn->samr_pipe == NULL) {
1114 cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR, &result);
1117 if (conn->samr_pipe == NULL) {
1118 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1122 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1123 SEC_RIGHTS_MAXIMUM_ALLOWED,
1124 &conn->sam_connect_handle);
1125 if (!NT_STATUS_IS_OK(result)) {
1126 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
1127 "for domain %s Error was %s\n",
1128 domain->name, nt_errstr(result) ));
1132 result = rpccli_samr_open_domain(conn->samr_pipe,
1134 &conn->sam_connect_handle,
1135 SEC_RIGHTS_MAXIMUM_ALLOWED,
1137 &conn->sam_domain_handle);
1142 if (!NT_STATUS_IS_OK(result)) {
1143 invalidate_cm_connection(conn);
1147 *cli = conn->samr_pipe;
1148 *sam_handle = conn->sam_domain_handle;
1152 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1153 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1155 struct winbindd_cm_conn *conn;
1158 result = init_dc_connection(domain);
1159 if (!NT_STATUS_IS_OK(result))
1162 conn = &domain->conn;
1164 if (conn->lsa_pipe == NULL) {
1166 pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
1167 if (conn->cli->user_name[0] && conn->cli->domain[0] &&
1169 /* We have an authenticated connection. Use
1170 a NTLMSSP SPNEGO authenticated LSA pipe with
1173 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
1175 PIPE_AUTH_LEVEL_PRIVACY,
1177 conn->cli->user_name,
1180 if (conn->lsa_pipe == NULL) {
1181 DEBUG(10,("cm_connect_lsa: failed to connect "
1182 "to LSA pipe for domain %s using "
1183 "NTLMSSP authenticated pipe: user "
1184 "%s\\%s. Error was %s\n",
1185 domain->name, conn->cli->domain,
1186 conn->cli->user_name,
1187 nt_errstr(result)));
1189 DEBUG(10,("cm_connect_lsa: connected to LSA "
1190 "pipe for domain %s using NTLMSSP "
1191 "authenticated pipe: user %s\\%s\n",
1192 domain->name, conn->cli->domain,
1193 conn->cli->user_name ));
1197 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
1198 /* Fall back to schannel if it's a W2K pre-SP1 box. */
1199 if (conn->lsa_pipe == NULL) {
1200 struct dcinfo *p_dcinfo;
1202 if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
1204 cli_rpc_pipe_open_schannel_with_key(conn->cli,
1206 PIPE_AUTH_LEVEL_PRIVACY,
1211 if (conn->lsa_pipe == NULL) {
1212 DEBUG(10,("cm_connect_lsa: failed to connect "
1213 "to LSA pipe for domain %s using "
1214 "schannel authenticated. Error "
1215 "was %s\n", domain->name,
1216 nt_errstr(result) ));
1218 DEBUG(10,("cm_connect_lsa: connected to LSA "
1219 "pipe for domain %s using schannel.\n",
1223 #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */
1225 /* Finally fall back to anonymous. */
1226 if (conn->lsa_pipe == NULL) {
1227 conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli,
1232 if (conn->lsa_pipe == NULL) {
1233 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1237 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1238 SEC_RIGHTS_MAXIMUM_ALLOWED,
1243 if (!NT_STATUS_IS_OK(result)) {
1244 invalidate_cm_connection(conn);
1245 return NT_STATUS_UNSUCCESSFUL;
1248 *cli = conn->lsa_pipe;
1249 *lsa_policy = conn->lsa_policy;
1253 /****************************************************************************
1254 Open the netlogon pipe to this DC. Use schannel if specified in client conf.
1255 session key stored in conn->netlogon_pipe->dc->sess_key.
1256 ****************************************************************************/
1258 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct rpc_pipe_client **cli)
1260 struct winbindd_cm_conn *conn;
1263 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1265 uint32 sec_chan_type;
1266 const char *account_name;
1267 struct rpc_pipe_client *netlogon_pipe;
1269 result = init_dc_connection(domain);
1270 if (!NT_STATUS_IS_OK(result)) {
1274 conn = &domain->conn;
1276 if (conn->netlogon_pipe != NULL) {
1277 *cli = conn->netlogon_pipe;
1278 return NT_STATUS_OK;
1281 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
1282 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1285 netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, &result);
1286 if (netlogon_pipe == NULL) {
1290 if (lp_client_schannel() != False) {
1291 neg_flags |= NETLOGON_NEG_SCHANNEL;
1294 /* if we are a DC and this is a trusted domain, then we need to use our
1295 domain name in the net_req_auth2() request */
1298 && !strequal(domain->name, lp_workgroup())
1299 && lp_allow_trusted_domains() )
1301 account_name = lp_workgroup();
1303 account_name = domain->primary ? global_myname() : domain->name;
1306 if (account_name == NULL) {
1307 cli_rpc_pipe_close(netlogon_pipe);
1308 return NT_STATUS_NO_MEMORY;
1311 result = rpccli_netlogon_setup_creds(netlogon_pipe,
1312 domain->dcname, /* server name. */
1313 domain->name, /* domain name */
1314 account_name, /* machine account */
1315 mach_pwd, /* machine password */
1316 sec_chan_type, /* from get_trust_pw */
1319 if (!NT_STATUS_IS_OK(result)) {
1320 cli_rpc_pipe_close(netlogon_pipe);
1324 if ((lp_client_schannel() == True) &&
1325 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1326 DEBUG(3, ("Server did not offer schannel\n"));
1327 cli_rpc_pipe_close(netlogon_pipe);
1328 return NT_STATUS_ACCESS_DENIED;
1331 if ((lp_client_schannel() == False) ||
1332 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1333 /* We're done - just keep the existing connection to NETLOGON open */
1334 conn->netlogon_pipe = netlogon_pipe;
1335 *cli = conn->netlogon_pipe;
1336 return NT_STATUS_OK;
1339 /* Using the credentials from the first pipe, open a signed and sealed
1340 second netlogon pipe. The session key is stored in the schannel
1341 part of the new pipe auth struct.
1344 conn->netlogon_pipe = cli_rpc_pipe_open_schannel_with_key(conn->cli,
1346 PIPE_AUTH_LEVEL_PRIVACY,
1351 /* We can now close the initial netlogon pipe. */
1352 cli_rpc_pipe_close(netlogon_pipe);
1354 if (conn->netlogon_pipe == NULL) {
1355 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error was %s\n",
1356 nt_errstr(result)));
1360 *cli = conn->netlogon_pipe;
1361 return NT_STATUS_OK;