2 Unix SMB/Netbios implementation.
5 Winbind daemon connection manager
7 Copyright (C) Tim Potter 2001
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 We can also throw away the CLI_POLICY_HND stuff as all this information
37 will be stored within this module.
39 Why not have connection management as part of the rpc layer like tng?
40 Good question. This code may morph into libsmb/rpc_cache.c or something
41 like that but at the moment it's simply staying as part of winbind. I
42 think the TNG architecture of forcing every user of the rpc layer to use
43 the connection caching system is a bad idea. It should be an optional
44 method of using the routines.
46 The TNG design is quite good but I disagree with some aspects of the
54 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
55 moved down into another function.
57 - There needs to be a utility function in libsmb/namequery.c that does
64 /* We store lists of connections here */
66 struct winbindd_cm_conn {
67 struct winbindd_cm_conn *prev, *next;
75 /* Global list of connections. Initially a DLIST but can become a hash
76 table or whatever later. */
78 struct winbindd_cm_conn *cm_conns = NULL;
80 /* Get a domain controller name */
82 BOOL cm_get_dc_name(char *domain, fstring srv_name)
84 struct in_addr *ip_list, dc_ip;
85 extern pstring global_myname;
88 /* Lookup domain controller name */
90 if (!get_dc_list(False, domain, &ip_list, &count))
93 /* Firstly choose a PDC/BDC who has the same network address as any
96 for (i = 0; i < count; i++) {
97 if(!is_local_net(ip_list[i]))
101 i = (sys_random() % count);
107 if (!lookup_pdc_name(global_myname, domain, &dc_ip, srv_name))
113 /* Open a new smb pipe connection to a DC on a given domain */
115 static BOOL cm_open_connection(char *domain, char *pipe_name,
116 struct winbindd_cm_conn *new_conn)
118 struct nmb_name calling, called;
119 extern pstring global_myname;
121 struct in_addr dest_ip;
123 struct ntuser_creds creds;
125 ZERO_STRUCT(new_conn->cli);
127 fstrcpy(new_conn->domain, domain);
128 fstrcpy(new_conn->pipe_name, pipe_name);
130 /* Look for a domain controller for this domain */
132 if (!cm_get_dc_name(lp_workgroup(), new_conn->controller))
135 /* Initialise SMB connection */
137 if (!cli_initialise(&new_conn->cli))
140 if (!resolve_srv_name(new_conn->controller, dest_host, &dest_ip))
143 make_nmb_name(&called, dns_to_netbios_name(new_conn->controller),
145 make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
148 creds.pwd.null_pwd = 1;
150 cli_init_creds(&new_conn->cli, &creds);
152 if (!cli_establish_connection(&new_conn->cli, new_conn->controller,
153 &dest_ip, &calling, &called, "IPC$",
157 if (!cli_nt_session_open (&new_conn->cli, pipe_name))
164 cli_shutdown(&new_conn->cli);
169 /* Return a LSA policy handle on a domain */
171 CLI_POLICY_HND *cm_get_lsa_handle(char *domain)
173 struct winbindd_cm_conn *conn;
174 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
176 static CLI_POLICY_HND hnd;
178 /* Look for existing connections */
180 for (conn = cm_conns; conn; conn = conn->next) {
181 if (strequal(conn->domain, domain) &&
182 strequal(conn->pipe_name, PIPE_LSARPC))
186 /* Create a new one */
188 if (!(conn = (struct winbindd_cm_conn *)
189 malloc(sizeof(struct winbindd_cm_conn))))
192 if (!cm_open_connection(domain, PIPE_LSARPC, conn)) {
193 DEBUG(3, ("Could not connect to a dc for domain %s\n",
198 result = cli_lsa_open_policy(&conn->cli, conn->cli.mem_ctx, False,
199 des_access, &conn->pol);
201 if (!NT_STATUS_IS_OK(result))
206 DLIST_ADD(cm_conns, conn);
210 hnd.cli = &conn->cli;
215 /* Return a SAM policy handle on a domain */
217 CLI_POLICY_HND *cm_get_sam_handle(char *domain)
219 DEBUG(0, ("get_sam_handle(): not implemented\n"));
223 /* Return a SAM domain policy handle on a domain */
225 CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain)
227 DEBUG(0, ("get_sam_dom_handle(): not implemented\n"));
231 /* Return a SAM policy handle on a domain user */
233 CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, char *user)
235 DEBUG(0, ("get_sam_user_handle(): not implemented\n"));
239 /* Return a SAM policy handle on a domain group */
241 CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, char *group)
243 DEBUG(0, ("get_sam_group_handle(): not implemented\n"));