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;
117 struct rpc_pipe_client *cli;
123 /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
132 our_domain = find_our_domain();
134 if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL)
138 /* These var's can be ignored -- we're not requesting
139 anything in the credential chain here */
140 unsigned char *session_key;
142 result = cm_connect_netlogon(our_domain, mem_ctx, &cli,
143 &session_key, &creds);
146 if (!NT_STATUS_IS_OK(result))
149 result = rpccli_netlogon_getdcname(cli, mem_ctx, domain->dcname,
152 talloc_destroy(mem_ctx);
154 if (!NT_STATUS_IS_OK(result))
157 /* cli_netlogon_getdcname gives us a name with \\ */
159 if (*p == '\\') p+=1;
160 if (*p == '\\') p+=1;
164 if (!resolve_name(dcname, dc_ip, 0x20))
170 /************************************************************************
171 Given a fd with a just-connected TCP connection to a DC, open a connection
173 ************************************************************************/
175 static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
177 const char *controller,
178 struct cli_state **cli,
181 char *machine_password, *machine_krb5_principal;
182 char *ipc_username, *ipc_domain, *ipc_password;
185 BOOL add_failed_connection = True;
187 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
189 struct sockaddr peeraddr;
190 socklen_t peeraddr_len;
192 struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
194 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
197 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
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_open_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)));
238 if (ntohs(peeraddr_in->sin_port) == 139) {
239 struct nmb_name calling;
240 struct nmb_name called;
242 make_nmb_name(&calling, global_myname(), 0x0);
243 make_nmb_name(&called, "*SMBSERVER", 0x20);
245 if (!cli_session_request(*cli, &calling, &called)) {
246 DEBUG(8, ("cli_session_request failed for %s\n",
252 cli_setup_signing_state(*cli, Undefined);
254 if (!cli_negprot(*cli)) {
255 DEBUG(1, ("cli_negprot failed\n"));
262 if ((lp_security() == SEC_ADS)
263 && ((*cli)->protocol >= PROTOCOL_NT1 &&
264 (*cli)->capabilities & CAP_EXTENDED_SECURITY)) {
266 ADS_STATUS ads_status;
267 (*cli)->use_kerberos = True;
268 DEBUG(5, ("connecting to %s from %s with kerberos principal "
269 "[%s]\n", controller, global_myname(),
270 machine_krb5_principal));
272 ads_status = cli_session_setup_spnego(*cli,
273 machine_krb5_principal,
277 if (!ADS_ERR_OK(ads_status))
278 DEBUG(4,("failed kerberos session setup with %s\n",
279 ads_errstr(ads_status)));
281 result = ads_ntstatus(ads_status);
284 if (NT_STATUS_IS_OK(result))
285 goto session_setup_done;
287 /* Fall back to non-kerberos session setup */
289 (*cli)->use_kerberos = False;
291 if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
292 (strlen(ipc_username) > 0)) {
294 /* Only try authenticated if we have a username */
296 DEBUG(5, ("connecting to %s from %s with username "
297 "[%s]\\[%s]\n", controller, global_myname(),
298 ipc_domain, ipc_username));
300 if (cli_session_setup(*cli, ipc_username,
301 ipc_password, strlen(ipc_password)+1,
302 ipc_password, strlen(ipc_password)+1,
304 DEBUG(5, ("authenticated session setup failed\n"));
305 goto session_setup_done;
309 /* Fall back to anonymous connection, this might fail later */
311 if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
312 DEBUG(5, ("Connected anonymously\n"));
313 goto session_setup_done;
316 result = cli_nt_error(*cli);
318 if (NT_STATUS_IS_OK(result))
319 result = NT_STATUS_UNSUCCESSFUL;
321 /* We can't session setup */
327 if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
329 result = cli_nt_error(*cli);
331 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
333 if (NT_STATUS_IS_OK(result))
334 result = NT_STATUS_UNSUCCESSFUL;
340 secrets_named_mutex_release(controller);
344 /* set the domain if empty; needed for schannel connections */
345 if ( !*(*cli)->domain )
346 fstrcpy( (*cli)->domain, domain->name );
348 (*cli)->pipe_auth_flags = 0;
350 result = NT_STATUS_OK;
351 add_failed_connection = False;
355 secrets_named_mutex_release(controller);
357 SAFE_FREE(machine_password);
358 SAFE_FREE(machine_krb5_principal);
359 SAFE_FREE(ipc_username);
360 SAFE_FREE(ipc_domain);
361 SAFE_FREE(ipc_password);
363 if (add_failed_connection)
364 add_failed_connection_entry(domain->name, controller, result);
374 static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
375 const char *dcname, struct in_addr ip,
376 struct dc_name_ip **dcs, int *num)
378 if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname)))
381 *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
386 fstrcpy((*dcs)[*num].name, dcname);
387 (*dcs)[*num].ip = ip;
392 static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
393 struct in_addr ip, uint16 port,
394 struct sockaddr_in **addrs, int *num)
396 *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
401 (*addrs)[*num].sin_family = PF_INET;
402 putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
403 (*addrs)[*num].sin_port = htons(port);
409 static void mailslot_name(struct in_addr dc_ip, fstring name)
411 fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
414 static BOOL send_getdc_request(struct in_addr dc_ip,
415 const char *domain_name,
420 fstring my_acct_name;
423 mailslot_name(dc_ip, my_mailslot);
425 memset(outbuf, '\0', sizeof(outbuf));
429 SCVAL(p, 0, SAMLOGON);
432 SCVAL(p, 0, 0); /* Count pointer ... */
435 SIVAL(p, 0, 0); /* The sender's token ... */
438 p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True);
439 fstr_sprintf(my_acct_name, "%s$", global_myname());
440 p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True);
442 memcpy(p, my_mailslot, strlen(my_mailslot)+1);
443 p += strlen(my_mailslot)+1;
448 SIVAL(p, 0, sid_size(sid));
451 p = ALIGN4(p, outbuf);
453 sid_linearize(p, sid_size(sid), sid);
461 return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
462 outbuf, PTR_DIFF(p, outbuf),
463 global_myname(), 0, domain_name, 0x1c,
467 static BOOL receive_getdc_response(struct in_addr dc_ip,
468 const char *domain_name,
471 struct packet_struct *packet;
474 fstring dcname, user, domain;
477 mailslot_name(dc_ip, my_mailslot);
479 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
481 if (packet == NULL) {
482 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
486 DEBUG(5, ("Received packet for %s\n", my_mailslot));
488 buf = packet->packet.dgram.data;
489 len = packet->packet.dgram.datasize;
492 /* 70 is a completely arbitrary value to make sure
493 the SVAL below does not read uninitialized memory */
494 DEBUG(3, ("GetDC got short response\n"));
498 /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
499 p = buf+SVAL(buf, smb_vwv10);
501 if (CVAL(p,0) != SAMLOGON_R) {
502 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
507 pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
508 STR_TERMINATE|STR_NOALIGN);
509 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
510 pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
511 STR_TERMINATE|STR_NOALIGN);
512 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
513 pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
514 STR_TERMINATE|STR_NOALIGN);
515 p = skip_unibuf(p, PTR_DIFF(buf+len, p));
517 if (!strequal(domain, domain_name)) {
518 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
519 domain_name, domain));
524 if (*p == '\\') p += 1;
525 if (*p == '\\') p += 1;
529 DEBUG(10, ("GetDC gave name %s for domain %s\n",
535 /*******************************************************************
536 convert an ip to a name
537 *******************************************************************/
539 static void dcip_to_name( const char *domainname, const char *realm,
540 const DOM_SID *sid, struct in_addr ip, fstring name )
544 /* try GETDC requests first */
546 send_getdc_request(ip, domainname, sid);
549 for (i=0; i<5; i++) {
550 if (receive_getdc_response(ip, domainname, name))
555 /* try node status request */
557 if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
560 /* backup in case the netbios stuff fails */
562 fstrcpy( name, inet_ntoa(ip) );
565 /* for active directory servers, try to get the ldap server name.
566 None of these failure should be considered critical for now */
568 if ( lp_security() == SEC_ADS )
573 ads = ads_init( realm, domainname, NULL );
574 ads->auth.flags |= ADS_AUTH_NO_BIND;
576 if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) ) {
581 status = ads_server_info(ads);
582 if ( !ADS_ERR_OK(status) ) {
587 fstrcpy(name, ads->config.ldap_server_name);
596 /*******************************************************************
597 Retreive a list of IP address for domain controllers. Fill in
598 the dcs[] with results.
599 *******************************************************************/
601 static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
602 struct dc_name_ip **dcs, int *num_dcs)
606 struct ip_service *ip_list = NULL;
612 is_our_domain = strequal(domain->name, lp_workgroup());
615 && get_dc_name_via_netlogon(domain, dcname, &ip)
616 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
622 && must_use_pdc(domain->name)
623 && get_pdc_ip(domain->name, &ip))
625 if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs))
629 /* try standard netbios queries first */
631 get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
633 /* check for security = ads and use DNS if we can */
635 if ( iplist_size==0 && lp_security() == SEC_ADS )
636 get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
638 /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
640 /* now add to the dc array. We'll wait until the last minute
641 to look up the name of the DC. But we fill in the char* for
642 the ip now in to make the failed connection cache work */
644 for ( i=0; i<iplist_size; i++ ) {
645 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
646 ip_list[i].ip, dcs, num_dcs);
649 SAFE_FREE( ip_list );
654 static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
655 const struct winbindd_domain *domain,
656 fstring dcname, struct sockaddr_in *addr, int *fd)
658 struct dc_name_ip *dcs = NULL;
661 const char **dcnames = NULL;
664 struct sockaddr_in *addrs = NULL;
669 if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
672 for (i=0; i<num_dcs; i++) {
674 add_string_to_array(mem_ctx, dcs[i].name,
675 &dcnames, &num_dcnames);
676 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
679 add_string_to_array(mem_ctx, dcs[i].name,
680 &dcnames, &num_dcnames);
681 add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
685 if ((num_dcnames == 0) || (num_dcnames != num_addrs))
688 if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) )
690 for (i=0; i<num_dcs; i++) {
691 add_failed_connection_entry(domain->name,
692 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
697 *addr = addrs[fd_index];
699 /* if we have no name on the server or just an IP address for
700 the name, now try to get the name */
702 if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
703 dcip_to_name( domain->name, domain->alt_name, &domain->sid, addr->sin_addr, dcname );
705 fstrcpy(dcname, dcnames[fd_index]);
710 static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
711 struct winbindd_cm_conn *new_conn)
718 if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
719 return NT_STATUS_NO_MEMORY;
721 for (retries = 0; retries < 3; retries++) {
726 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
728 if ((strlen(domain->dcname) > 0) &&
729 NT_STATUS_IS_OK(check_negative_conn_cache(domain->name,
732 if (!open_any_socket_out(&domain->dcaddr, 1, 10000,
739 !find_new_dc(mem_ctx, domain, domain->dcname,
740 &domain->dcaddr, &fd))
743 new_conn->cli = NULL;
745 result = cm_prepare_connection(domain, fd, domain->dcname,
746 &new_conn->cli, &retry);
752 talloc_destroy(mem_ctx);
756 /* Return true if a connection is still alive */
758 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
760 if (conn->samr_pipe != NULL) {
761 cli_rpc_close(conn->samr_pipe);
762 conn->samr_pipe = NULL;
765 if (conn->lsa_pipe != NULL) {
766 cli_rpc_close(conn->lsa_pipe);
767 conn->lsa_pipe = NULL;
770 if (conn->netlogon_auth2_pipe != NULL) {
771 cli_rpc_close(conn->netlogon_auth2_pipe);
772 conn->netlogon_auth2_pipe = NULL;
775 if (conn->netlogon_pipe != NULL) {
776 cli_rpc_close(conn->netlogon_pipe);
777 conn->netlogon_pipe = NULL;
781 cli_shutdown(conn->cli);
786 void close_conns_after_fork(void)
788 struct winbindd_domain *domain;
790 for (domain = domain_list(); domain; domain = domain->next) {
791 if (domain->conn.cli == NULL)
794 if (domain->conn.cli->fd == -1)
797 close(domain->conn.cli->fd);
798 domain->conn.cli->fd = -1;
802 static BOOL connection_ok(struct winbindd_domain *domain)
804 if (domain->conn.cli == NULL) {
805 DEBUG(8, ("Connection to %s for domain %s has NULL "
806 "cli!\n", domain->dcname, domain->name));
810 if (!domain->conn.cli->initialised) {
811 DEBUG(3, ("Connection to %s for domain %s was never "
812 "initialised!\n", domain->dcname, domain->name));
816 if (domain->conn.cli->fd == -1) {
817 DEBUG(3, ("Connection to %s for domain %s has died or was "
818 "never started (fd == -1)\n",
819 domain->dcname, domain->name));
826 /* Initialize a new connection up to the RPC BIND. */
828 static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
830 if (connection_ok(domain))
833 invalidate_cm_connection(&domain->conn);
835 return cm_open_connection(domain, &domain->conn);
838 /**********************************************************************************
839 We can 'sense' certain things about the DC by it's replies to certain questions.
841 This tells us if this particular remote server is Active Directory, and if it is
843 **********************************************************************************/
845 void set_dc_type_and_flags( struct winbindd_domain *domain )
849 TALLOC_CTX *mem_ctx = NULL;
850 struct rpc_pipe_client *cli;
853 char *domain_name = NULL;
854 char *dns_name = NULL;
855 DOM_SID *dom_sid = NULL;
859 domain->native_mode = False;
860 domain->active_directory = False;
862 if (domain->internal) {
863 domain->initialized = True;
867 result = init_dc_connection(domain);
868 if (!NT_STATUS_IS_OK(result)) {
869 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
870 "to %s: (%s)\n", domain->name, nt_errstr(result)));
871 domain->initialized = True;
875 cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC_DS);
878 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
879 "PI_LSARPC_DS on domain %s: (%s)\n",
880 domain->name, nt_errstr(result)));
881 domain->initialized = True;
885 result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
886 DsRolePrimaryDomainInfoBasic,
890 if (!NT_STATUS_IS_OK(result)) {
891 domain->initialized = True;
895 if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
896 !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
897 domain->native_mode = True;
899 cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC);
902 domain->initialized = True;
906 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
909 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
913 result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
914 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
916 if (NT_STATUS_IS_OK(result)) {
917 /* This particular query is exactly what Win2k clients use
918 to determine that the DC is active directory */
919 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
925 if (NT_STATUS_IS_OK(result)) {
927 fstrcpy(domain->name, domain_name);
930 fstrcpy(domain->alt_name, dns_name);
933 sid_copy(&domain->sid, dom_sid);
935 domain->active_directory = True;
938 result = rpccli_lsa_open_policy(cli, mem_ctx, True,
939 SEC_RIGHTS_MAXIMUM_ALLOWED,
942 if (!NT_STATUS_IS_OK(result))
945 result = rpccli_lsa_query_info_policy(cli, mem_ctx,
946 &pol, 5, &domain_name,
949 if (NT_STATUS_IS_OK(result)) {
951 fstrcpy(domain->name, domain_name);
954 sid_copy(&domain->sid, dom_sid);
961 talloc_destroy(mem_ctx);
963 domain->initialized = True;
968 static BOOL cm_get_schannel_key(struct winbindd_domain *domain,
970 unsigned char **session_key)
972 struct rpc_pipe_client *cli;
973 DOM_CRED *credentials;
975 if (lp_client_schannel() == False)
978 return NT_STATUS_IS_OK(cm_connect_netlogon(domain, mem_ctx,
983 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
984 struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
986 struct winbindd_cm_conn *conn;
989 result = init_dc_connection(domain);
990 if (!NT_STATUS_IS_OK(result))
993 conn = &domain->conn;
995 if (conn->samr_pipe == NULL) {
996 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
997 unsigned char *session_key;
999 if (cm_get_schannel_key(domain, mem_ctx, &session_key))
1000 conn->samr_pipe = cli_rpc_open_schannel(conn->cli,
1005 #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */
1006 conn->samr_pipe = cli_rpc_open_noauth(conn->cli,
1009 if (conn->samr_pipe == NULL) {
1010 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1014 result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
1015 SEC_RIGHTS_MAXIMUM_ALLOWED,
1016 &conn->sam_connect_handle);
1017 if (!NT_STATUS_IS_OK(result))
1020 result = rpccli_samr_open_domain(conn->samr_pipe,
1022 &conn->sam_connect_handle,
1023 SEC_RIGHTS_MAXIMUM_ALLOWED,
1025 &conn->sam_domain_handle);
1029 if (!NT_STATUS_IS_OK(result)) {
1030 invalidate_cm_connection(conn);
1031 return NT_STATUS_UNSUCCESSFUL;
1034 *cli = conn->samr_pipe;
1035 *sam_handle = conn->sam_domain_handle;
1039 NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
1040 struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
1042 struct winbindd_cm_conn *conn;
1045 result = init_dc_connection(domain);
1046 if (!NT_STATUS_IS_OK(result))
1049 conn = &domain->conn;
1051 if (conn->lsa_pipe == NULL) {
1052 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
1053 unsigned char *session_key;
1055 if (cm_get_schannel_key(domain, mem_ctx, &session_key))
1056 conn->lsa_pipe = cli_rpc_open_schannel(conn->cli,
1061 #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */
1062 conn->lsa_pipe = cli_rpc_open_noauth(conn->cli,
1065 if (conn->lsa_pipe == NULL) {
1066 result = NT_STATUS_PIPE_NOT_AVAILABLE;
1070 result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
1071 SEC_RIGHTS_MAXIMUM_ALLOWED,
1076 if (!NT_STATUS_IS_OK(result)) {
1077 invalidate_cm_connection(conn);
1078 return NT_STATUS_UNSUCCESSFUL;
1081 *cli = conn->lsa_pipe;
1082 *lsa_policy = conn->lsa_policy;
1086 /*******************************************************************
1087 wrapper around retrieving the trust account password
1088 *******************************************************************/
1090 static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16],
1095 time_t last_set_time;
1097 /* if we are a DC and this is not our domain, then lookup an account
1098 for the domain trust */
1100 if ( IS_DC && !strequal(domain, lp_workgroup()) &&
1101 lp_allow_trusted_domains() ) {
1103 if (!secrets_fetch_trusted_domain_password(domain, &pwd, &sid,
1105 DEBUG(0, ("get_trust_pw: could not fetch trust "
1106 "account password for trusted domain %s\n",
1111 *channel = SEC_CHAN_DOMAIN;
1112 E_md4hash(pwd, ret_pwd);
1118 /* Just get the account for the requested domain. In the future this
1119 * might also cover to be member of more than one domain. */
1121 if (secrets_fetch_trust_account_password(domain, ret_pwd,
1122 &last_set_time, channel))
1125 DEBUG(5, ("get_trust_pw: could not fetch trust account "
1126 "password for domain %s\n", domain));
1130 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
1131 TALLOC_CTX *mem_ctx,
1132 struct rpc_pipe_client **cli,
1133 unsigned char **session_key,
1134 DOM_CRED **credentials)
1136 struct winbindd_cm_conn *conn;
1139 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
1141 uint32 sec_chan_type;
1142 DOM_CHAL clnt_chal, srv_chal, rcv_chal;
1143 const char *server_name;
1144 const char *account_name;
1147 result = init_dc_connection(domain);
1148 if (!NT_STATUS_IS_OK(result))
1151 conn = &domain->conn;
1153 if (conn->netlogon_pipe != NULL) {
1154 *cli = conn->netlogon_pipe;
1155 *session_key = (unsigned char *)&conn->sess_key;
1156 *credentials = &conn->clnt_cred;
1157 return NT_STATUS_OK;
1160 if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type))
1161 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1163 conn->netlogon_auth2_pipe = cli_rpc_open_noauth(conn->cli,
1165 if (conn->netlogon_auth2_pipe == NULL)
1166 return NT_STATUS_UNSUCCESSFUL;
1168 if (lp_client_schannel() != False)
1169 neg_flags |= NETLOGON_NEG_SCHANNEL;
1171 generate_random_buffer(clnt_chal.data, 8);
1173 server_name = talloc_asprintf(mem_ctx, "\\\\%s", domain->dcname);
1175 /* if we are a DC and this is a trusted domain, then we need to use our
1176 domain name in the net_req_auth2() request */
1179 && !strequal(domain->name, lp_workgroup())
1180 && lp_allow_trusted_domains() )
1182 account_name = talloc_asprintf( mem_ctx, "%s$", lp_workgroup() );
1185 account_name = talloc_asprintf(mem_ctx, "%s$",
1186 domain->primary ? global_myname() : domain->name);
1189 if ((server_name == NULL) || (account_name == NULL))
1190 return NT_STATUS_NO_MEMORY;
1192 result = rpccli_net_req_chal(conn->netlogon_auth2_pipe, server_name,
1193 global_myname(), &clnt_chal, &srv_chal);
1194 if (!NT_STATUS_IS_OK(result))
1197 /**************** Long-term Session key **************/
1199 /* calculate the session key */
1200 cred_session_key(&clnt_chal, &srv_chal, mach_pwd, conn->sess_key);
1201 memset((char *)conn->sess_key+8, '\0', 8);
1203 /* calculate auth2 credentials */
1205 cred_create(conn->sess_key, &clnt_chal, zerotime,
1206 &conn->clnt_cred.challenge);
1208 result = rpccli_net_auth2(conn->netlogon_auth2_pipe, server_name,
1209 account_name, sec_chan_type, global_myname(),
1210 &conn->clnt_cred.challenge, &neg_flags,
1213 if (!NT_STATUS_IS_OK(result))
1217 if (!cred_assert(&rcv_chal, conn->sess_key, &srv_chal, zerotime)) {
1218 DEBUG(0, ("Server replied with bad credential\n"));
1219 return NT_STATUS_ACCESS_DENIED;
1222 if ((lp_client_schannel() == True) &&
1223 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1224 DEBUG(3, ("Server did not offer schannel\n"));
1225 cli_rpc_close(conn->netlogon_auth2_pipe);
1226 conn->netlogon_auth2_pipe = NULL;
1227 return NT_STATUS_ACCESS_DENIED;
1230 if ((lp_client_schannel() == False) ||
1231 ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
1232 /* keep the existing connection to NETLOGON open */
1233 conn->netlogon_pipe = conn->netlogon_auth2_pipe;
1234 conn->netlogon_auth2_pipe = NULL;
1235 *cli = conn->netlogon_pipe;
1236 *session_key = (unsigned char *)&conn->sess_key;
1237 *credentials = &conn->clnt_cred;
1238 return NT_STATUS_OK;
1241 conn->netlogon_pipe = cli_rpc_open_schannel(conn->cli, PI_NETLOGON,
1245 if (conn->netlogon_pipe == NULL) {
1246 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe\n"));
1247 cli_rpc_close(conn->netlogon_auth2_pipe);
1248 conn->netlogon_auth2_pipe = NULL;
1249 return NT_STATUS_ACCESS_DENIED;
1252 *cli = conn->netlogon_pipe;
1253 *session_key = (unsigned char *)&conn->sess_key;
1254 *credentials = &conn->clnt_cred;
1256 return NT_STATUS_OK;