2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 We need to manage connections to domain controllers without having to
26 mess up the main winbindd code with other issues. The aim of the
27 connection manager is to:
29 - make connections to domain controllers and cache them
30 - re-establish connections when networks or servers go down
31 - centralise the policy on connection timeouts, domain controller
33 - manage re-entrancy for when winbindd becomes able to handle
34 multiple outstanding rpc requests
36 Why not have connection management as part of the rpc layer like tng?
37 Good question. This code may morph into libsmb/rpc_cache.c or something
38 like that but at the moment it's simply staying as part of winbind. I
39 think the TNG architecture of forcing every user of the rpc layer to use
40 the connection caching system is a bad idea. It should be an optional
41 method of using the routines.
43 The TNG design is quite good but I disagree with some aspects of the
51 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
52 moved down into another function.
54 - Take care when destroying cli_structs as they can be shared between
63 #define DBGC_CLASS DBGC_WINBIND
65 /* Global list of connections. Initially a DLIST but can become a hash
66 table or whatever later. */
68 struct winbindd_cm_conn {
69 struct winbindd_cm_conn *prev, *next;
73 size_t mutex_ref_count;
74 struct cli_state *cli;
78 static struct winbindd_cm_conn *cm_conns = NULL;
81 /* Choose between anonymous or authenticated connections. We need to use
82 an authenticated connection if DCs have the RestrictAnonymous registry
83 entry set > 0, or the "Additional restrictions for anonymous
84 connections" set in the win2k Local Security Policy.
86 Caller to free() result in domain, username, password
89 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
91 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
92 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
93 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
95 if (*username && **username) {
97 if (!*domain || !**domain)
98 *domain = smb_xstrdup(lp_workgroup());
100 if (!*password || !**password)
101 *password = smb_xstrdup("");
103 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
104 *domain, *username));
107 DEBUG(3, ("IPC$ connections done anonymously\n"));
108 *username = smb_xstrdup("");
109 *domain = smb_xstrdup("");
110 *password = smb_xstrdup("");
115 setup for schannel on any pipes opened on this connection
117 static NTSTATUS setup_schannel(struct cli_state *cli)
120 uchar trust_password[16];
121 uint32 sec_channel_type;
123 if (!secrets_fetch_trust_account_password(lp_workgroup(),
125 NULL, &sec_channel_type)) {
126 return NT_STATUS_UNSUCCESSFUL;
129 ret = cli_nt_setup_netsec(cli, sec_channel_type,
130 AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN,
136 /* Open a connction to the remote server, cache failures for 30 seconds */
138 static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const int pipe_index,
139 struct winbindd_cm_conn *new_conn)
142 char *machine_password;
143 char *machine_krb5_principal, *ipc_username, *ipc_domain, *ipc_password;
144 struct in_addr dc_ip;
150 fstrcpy(new_conn->domain, domain->name);
152 /* connection failure cache has been moved inside of get_dc_name
153 so we can deal with half dead DC's --jerry */
155 if (!get_dc_name(domain->name, domain->alt_name[0] ? domain->alt_name : NULL,
156 new_conn->controller, &dc_ip)) {
157 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
158 add_failed_connection_entry(domain->name, "", result);
162 /* Initialise SMB connection */
163 fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
165 /* grab stored passwords */
166 machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
168 if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), lp_realm()) == -1) {
169 SAFE_FREE(machine_password);
170 return NT_STATUS_NO_MEMORY;
173 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
175 for (i = 0; retry && (i < 3); i++) {
177 if (!(got_mutex = secrets_named_mutex(new_conn->controller, WINBIND_SERVER_MUTEX_WAIT_TIME))) {
178 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller));
179 result = NT_STATUS_POSSIBLE_DEADLOCK;
183 new_conn->cli = NULL;
184 result = cli_start_connection(&new_conn->cli, global_myname(),
185 new_conn->controller,
186 &dc_ip, 0, Undefined,
187 CLI_FULL_CONNECTION_USE_KERBEROS,
190 if (NT_STATUS_IS_OK(result)) {
192 /* reset the error code */
193 result = NT_STATUS_UNSUCCESSFUL;
197 if ((lp_security() == SEC_ADS)
198 && (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) {
199 ADS_STATUS ads_status;
200 new_conn->cli->use_kerberos = True;
201 DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n",
202 new_conn->controller, global_myname(), machine_krb5_principal));
204 ads_status = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal,
207 if (!ADS_ERR_OK(ads_status)) {
208 DEBUG(4,("failed kerberos session setup with %s\n", ads_errstr(ads_status)));
209 result = ads_ntstatus(ads_status);
211 result = NT_STATUS_OK;
214 new_conn->cli->use_kerberos = False;
216 /* only do this is we have a username/password for thr IPC$ connection */
218 if ( !NT_STATUS_IS_OK(result)
219 && new_conn->cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
220 && strlen(ipc_username) )
222 DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
223 new_conn->controller, global_myname(), ipc_domain, ipc_username));
225 result = NT_STATUS_OK;
227 if (!cli_session_setup(new_conn->cli, ipc_username,
228 ipc_password, strlen(ipc_password)+1,
229 ipc_password, strlen(ipc_password)+1,
231 result = cli_nt_error(new_conn->cli);
232 DEBUG(4,("failed authenticated session setup with %s\n", nt_errstr(result)));
233 if (NT_STATUS_IS_OK(result))
234 result = NT_STATUS_UNSUCCESSFUL;
238 /* anonymous is all that is left if we get to here */
240 if (!NT_STATUS_IS_OK(result)) {
242 DEBUG(5, ("anonymous connection attempt to %s from %s\n",
243 new_conn->controller, global_myname()));
245 result = NT_STATUS_OK;
247 if (!cli_session_setup(new_conn->cli, "", NULL, 0, NULL, 0, ""))
249 result = cli_nt_error(new_conn->cli);
250 DEBUG(4,("failed anonymous session setup with %s\n", nt_errstr(result)));
251 if (NT_STATUS_IS_OK(result))
252 result = NT_STATUS_UNSUCCESSFUL;
257 if (NT_STATUS_IS_OK(result) && !cli_send_tconX(new_conn->cli, "IPC$", "IPC",
259 result = cli_nt_error(new_conn->cli);
260 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
261 cli_shutdown(new_conn->cli);
262 if (NT_STATUS_IS_OK(result)) {
263 result = NT_STATUS_UNSUCCESSFUL;
268 if (NT_STATUS_IS_OK(result)) {
269 struct ntuser_creds creds;
270 init_creds(&creds, ipc_username, ipc_domain, ipc_password);
271 cli_init_creds(new_conn->cli, &creds);
275 secrets_named_mutex_release(new_conn->controller);
277 if (NT_STATUS_IS_OK(result))
281 /* try and use schannel if possible, but continue anyway if it
282 failed. This allows existing setups to continue working,
283 while solving the win2003 '100 user' limit for systems that
284 are joined properly */
285 if (NT_STATUS_IS_OK(result)) {
286 NTSTATUS status = setup_schannel(new_conn->cli);
287 if (!NT_STATUS_IS_OK(status)) {
288 DEBUG(3,("schannel refused - continuing without schannel (%s)\n",
293 SAFE_FREE(ipc_username);
294 SAFE_FREE(ipc_domain);
295 SAFE_FREE(ipc_password);
296 SAFE_FREE(machine_password);
297 SAFE_FREE(machine_krb5_principal);
299 if (!NT_STATUS_IS_OK(result)) {
300 add_failed_connection_entry(domain->name, new_conn->controller, result);
304 /* set the domain if empty; needed for schannel connections */
305 if ( !*new_conn->cli->domain )
306 fstrcpy( new_conn->cli->domain, domain->name );
309 if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
310 result = NT_STATUS_PIPE_NOT_AVAILABLE;
312 * only cache a failure if we are not trying to open the
313 * **win2k** specific lsarpc UUID. This could be an NT PDC
314 * and therefore a failure is normal. This should probably
315 * be abstracted to a check for 2k specific pipes and wondering
316 * if the PDC is an NT4 box. but since there is only one 2k
317 * specific UUID right now, i'm not going to bother. --jerry
319 if ( !is_win2k_pipe(pipe_index) )
320 add_failed_connection_entry(domain->name, new_conn->controller, result);
321 cli_shutdown(new_conn->cli);
328 /************************************************************************
329 Wrapper around statuc cm_open_connection to retreive a freshly
330 setup cli_state struct
331 ************************************************************************/
333 NTSTATUS cm_fresh_connection(struct winbindd_domain *domain, const int pipe_index,
334 struct cli_state **cli)
337 struct winbindd_cm_conn conn;
339 result = cm_open_connection( domain, pipe_index, &conn );
341 if ( NT_STATUS_IS_OK(result) )
347 /* Return true if a connection is still alive */
349 static BOOL connection_ok(struct winbindd_cm_conn *conn)
352 smb_panic("Invalid parameter passed to connection_ok(): conn was NULL!\n");
357 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n",
358 conn->controller, conn->domain, conn->pipe_name));
362 if (!conn->cli->initialised) {
363 DEBUG(3, ("Connection to %s for domain %s (pipe %s) was never initialised!\n",
364 conn->controller, conn->domain, conn->pipe_name));
368 if (conn->cli->fd == -1) {
369 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n",
370 conn->controller, conn->domain, conn->pipe_name));
377 /* Search the cache for a connection. If there is a broken one,
378 shut it down properly and return NULL. */
380 static void find_cm_connection(struct winbindd_domain *domain, const char *pipe_name,
381 struct winbindd_cm_conn **conn_out)
383 struct winbindd_cm_conn *conn;
385 for (conn = cm_conns; conn; ) {
386 if (strequal(conn->domain, domain->name) &&
387 strequal(conn->pipe_name, pipe_name)) {
388 if (!connection_ok(conn)) {
389 /* Dead connection - remove it. */
390 struct winbindd_cm_conn *conn_temp = conn->next;
392 cli_shutdown(conn->cli);
393 DLIST_REMOVE(cm_conns, conn);
395 conn = conn_temp; /* Keep the loop moving */
407 /* Initialize a new connection up to the RPC BIND. */
409 static NTSTATUS new_cm_connection(struct winbindd_domain *domain, const char *pipe_name,
410 struct winbindd_cm_conn **conn_out)
412 struct winbindd_cm_conn *conn;
415 if (!(conn = malloc(sizeof(*conn))))
416 return NT_STATUS_NO_MEMORY;
420 if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
421 DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
422 domain->name, pipe_name, nt_errstr(result)));
426 DLIST_ADD(cm_conns, conn);
432 /* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */
434 static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const char *pipe_name,
435 struct winbindd_cm_conn **conn_out)
437 find_cm_connection(domain, pipe_name, conn_out);
439 if (*conn_out != NULL)
442 return new_cm_connection(domain, pipe_name, conn_out);
445 /**********************************************************************************
446 We can 'sense' certain things about the DC by it's replies to certain questions.
448 This tells us if this particular remote server is Active Directory, and if it is
450 **********************************************************************************/
452 void set_dc_type_and_flags( struct winbindd_domain *domain )
455 struct winbindd_cm_conn conn;
457 TALLOC_CTX *mem_ctx = NULL;
462 domain->native_mode = False;
463 domain->active_directory = False;
465 if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
466 DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
467 domain->name, nt_errstr(result)));
472 if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli,
473 conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) {
478 if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING)
479 && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
480 domain->native_mode = True;
482 /* Cheat - shut down the DS pipe, and open LSA */
484 cli_nt_session_close(conn.cli);
486 if ( cli_nt_session_open (conn.cli, PI_LSARPC) ) {
487 char *domain_name = NULL;
488 char *dns_name = NULL;
489 DOM_SID *dom_sid = NULL;
491 mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", domain->name);
493 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
497 result = cli_lsa_open_policy2(conn.cli, mem_ctx, True,
498 SEC_RIGHTS_MAXIMUM_ALLOWED,
501 if (NT_STATUS_IS_OK(result)) {
502 /* This particular query is exactly what Win2k clients use
503 to determine that the DC is active directory */
504 result = cli_lsa_query_info_policy2(conn.cli, mem_ctx,
511 if (NT_STATUS_IS_OK(result)) {
513 fstrcpy(domain->name, domain_name);
516 fstrcpy(domain->alt_name, dns_name);
519 sid_copy(&domain->sid, dom_sid);
521 domain->active_directory = True;
524 result = cli_lsa_open_policy(conn.cli, mem_ctx, True,
525 SEC_RIGHTS_MAXIMUM_ALLOWED,
528 if (!NT_STATUS_IS_OK(result))
531 result = cli_lsa_query_info_policy(conn.cli, mem_ctx,
532 &conn.pol, 5, &domain_name,
535 if (NT_STATUS_IS_OK(result)) {
537 fstrcpy(domain->name, domain_name);
540 sid_copy(&domain->sid, dom_sid);
547 /* close the connection; no other calls use this pipe and it is called only
548 on reestablishing the domain list --jerry */
551 cli_shutdown( conn.cli );
553 talloc_destroy(mem_ctx);
560 /* Return a LSA policy handle on a domain */
562 NTSTATUS cm_get_lsa_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd)
564 struct winbindd_cm_conn *conn;
565 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
567 static CLI_POLICY_HND hnd;
569 /* Look for existing connections */
571 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
574 /* This *shitty* code needs scrapping ! JRA */
576 if (policy_handle_is_valid(&conn->pol)) {
584 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
585 des_access, &conn->pol);
587 if (!NT_STATUS_IS_OK(result)) {
588 /* Hit the cache code again. This cleans out the old connection and gets a new one */
589 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
590 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
593 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
594 des_access, &conn->pol);
597 if (!NT_STATUS_IS_OK(result)) {
598 cli_shutdown(conn->cli);
599 DLIST_REMOVE(cm_conns, conn);
613 /* Return a SAM policy handle on a domain */
615 NTSTATUS cm_get_sam_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd)
617 struct winbindd_cm_conn *conn;
618 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
620 static CLI_POLICY_HND hnd;
622 /* Look for existing connections */
624 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
627 /* This *shitty* code needs scrapping ! JRA */
629 if (policy_handle_is_valid(&conn->pol)) {
638 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
639 des_access, &conn->pol);
641 if (!NT_STATUS_IS_OK(result)) {
642 /* Hit the cache code again. This cleans out the old connection and gets a new one */
643 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
645 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
648 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
649 des_access, &conn->pol);
652 if (!NT_STATUS_IS_OK(result)) {
654 cli_shutdown(conn->cli);
655 DLIST_REMOVE(cm_conns, conn);
670 /* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
671 netlogon pipe as no handle is returned. */
673 NTSTATUS cm_get_netlogon_cli(struct winbindd_domain *domain,
674 const unsigned char *trust_passwd,
675 uint32 sec_channel_type,
677 struct cli_state **cli)
679 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
680 struct winbindd_cm_conn *conn;
685 return NT_STATUS_INVALID_PARAMETER;
687 /* Open an initial conection - keep the mutex. */
689 find_cm_connection(domain, PIPE_NETLOGON, &conn);
691 if ( fresh && (conn != NULL) ) {
692 cli_shutdown(conn->cli);
697 /* purge connection from cache */
698 find_cm_connection(domain, PIPE_NETLOGON, &conn);
700 DEBUG(0,("Could not purge connection\n"));
701 return NT_STATUS_UNSUCCESSFUL;
710 result = new_cm_connection(domain, PIPE_NETLOGON, &conn);
712 if (!NT_STATUS_IS_OK(result))
715 fstr_sprintf(lock_name, "NETLOGON\\%s", conn->controller);
717 if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) {
718 DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller));
721 if ( sec_channel_type == SEC_CHAN_DOMAIN )
722 fstr_sprintf(conn->cli->mach_acct, "%s$", lp_workgroup());
724 /* This must be the remote domain (not ours) for schannel */
726 fstrcpy( conn->cli->domain, domain->name);
728 result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd);
731 secrets_named_mutex_release(lock_name);
733 if (!NT_STATUS_IS_OK(result)) {
734 cli_shutdown(conn->cli);
735 DLIST_REMOVE(cm_conns, conn);
745 /* Dump the current connection status */
747 static void dump_conn_list(void)
749 struct winbindd_cm_conn *con;
751 DEBUG(0, ("\tDomain Controller Pipe\n"));
753 for(con = cm_conns; con; con = con->next) {
756 /* Display pipe info */
758 if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) {
759 DEBUG(0, ("Error: not enough memory!\n"));
761 DEBUG(0, ("%s\n", msg));
767 void winbindd_cm_status(void)
769 /* List open connections */
771 DEBUG(0, ("winbindd connection manager status:\n"));
776 DEBUG(0, ("\tNo active connections\n"));
779 /* Close all cached connections */
781 void winbindd_cm_flush(void)
783 struct winbindd_cm_conn *conn, tmp;
785 /* Flush connection cache */
787 for (conn = cm_conns; conn; conn = conn->next) {
789 if (!connection_ok(conn))
792 DEBUG(10, ("Closing connection to %s on %s\n",
793 conn->pipe_name, conn->controller));
796 cli_shutdown(conn->cli);
798 tmp.next = conn->next;
800 DLIST_REMOVE(cm_conns, conn);
805 /* Flush failed connection cache */
807 flush_negative_conn_cache();