merge from HEAD
[Samba.git] / source / rpc_client / cli_use.c
blob4a07bc0e1cbcb833d5670413f66e2c13b1431d61
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB client generic functions
5 Copyright (C) Andrew Tridgell 1994-1999
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #define NO_SYSLOG
25 #include "includes.h"
26 #include "trans2.h"
27 #include "rpc_client.h"
29 extern int DEBUGLEVEL;
30 extern pstring scope;
31 extern pstring global_myname;
33 struct cli_use
35 struct cli_state *cli;
36 uint32 num_users;
39 static struct cli_use **clis = NULL;
40 static uint32 num_clis = 0;
42 /****************************************************************************
43 terminate client connection
44 ****************************************************************************/
45 static void cli_use_free(struct cli_use *cli)
47 if (cli->cli != NULL)
49 if (cli->cli->initialised)
51 /* only call logoff() if we have a valid socket */
52 if (cli->cli->fd != -1)
53 cli_ulogoff(cli->cli);
54 cli_shutdown(cli->cli);
56 free(cli->cli);
59 free(cli);
62 /****************************************************************************
63 free a client array
64 ****************************************************************************/
65 static void free_cli_array(uint32 num_entries, struct cli_use **entries)
67 void (*fn) (void *) = (void (*)(void *))&cli_use_free;
68 free_void_array(num_entries, (void **)entries, *fn);
71 /****************************************************************************
72 add a client state to the array
73 ****************************************************************************/
74 static struct cli_use *add_cli_to_array(uint32 *len,
75 struct cli_use ***array,
76 struct cli_use *cli)
78 int i;
79 for (i = 0; i < num_clis; i++)
81 if (clis[i] == NULL)
83 clis[i] = cli;
84 return cli;
88 return (struct cli_use *)add_item_to_array(len,
89 (void ***)array,
90 (void *)cli);
94 /****************************************************************************
95 initiate client array
96 ****************************************************************************/
97 void init_cli_use(void)
99 clis = NULL;
100 num_clis = 0;
103 /****************************************************************************
104 terminate client array
105 ****************************************************************************/
106 void free_cli_use(void)
108 free_cli_array(num_clis, clis);
109 init_cli_use();
112 /****************************************************************************
113 find client state. server name, user name, domain name and password must all
114 match.
115 ****************************************************************************/
116 static struct cli_use *cli_find(const char *srv_name,
117 const struct ntuser_creds *usr_creds,
118 BOOL reuse)
120 int i;
121 const char *sv_name = srv_name;
122 struct ntuser_creds null_usr;
124 if (usr_creds == NULL)
126 copy_nt_creds(&null_usr, usr_creds);
127 usr_creds = &null_usr;
130 if (strnequal("\\\\", sv_name, 2))
132 sv_name = &sv_name[2];
135 DEBUG(10, ("cli_find: %s %s %s reuse: %s\n",
136 srv_name, usr_creds->user_name, usr_creds->domain,
137 BOOLSTR(reuse)));
140 for (i = 0; i < num_clis; i++)
142 char *cli_name = NULL;
143 struct cli_use *c = clis[i];
145 if (c == NULL || !c->cli->initialised || c->cli->fd == -1)
147 continue;
150 cli_name = c->cli->desthost;
152 DEBUG(10, ("cli_find[%d]: %s %s %s\n",
153 i, cli_name,
154 c->cli->usr.user_name, c->cli->usr.domain));
156 if (strnequal("\\\\", cli_name, 2))
158 cli_name = &cli_name[2];
161 if (!strequal(cli_name, sv_name))
163 continue;
165 if (strequal(usr_creds->user_name, "") &&
166 strequal(usr_creds->domain, "") &&
167 pwd_is_nullpwd(&usr_creds->pwd))
169 return c;
171 if (!strequal(usr_creds->user_name, c->cli->usr.user_name))
173 continue;
175 if (!reuse && !pwd_compare(&usr_creds->pwd, &c->cli->usr.pwd))
177 DEBUG(100, ("password doesn't match\n"));
178 continue;
180 if (usr_creds->domain[0] == 0)
182 return c;
184 if (strequal(usr_creds->domain, c->cli->usr.domain))
186 return c;
190 return NULL;
193 /****************************************************************************
194 create a new client state from user credentials
195 ****************************************************************************/
196 static struct cli_use *cli_use_get(const char *srv_name,
197 const struct ntuser_creds *usr_creds)
199 struct cli_use *cli = (struct cli_use *)malloc(sizeof(*cli));
201 if (cli == NULL)
203 return NULL;
206 memset(cli, 0, sizeof(*cli));
208 cli->cli = cli_initialise(NULL);
210 if (cli->cli == NULL)
212 return NULL;
215 cli_init_creds(cli->cli, usr_creds);
217 return cli;
220 /****************************************************************************
221 init client state
222 ****************************************************************************/
223 struct cli_state *cli_net_use_add(const char *srv_name,
224 const struct ntuser_creds *usr_creds,
225 BOOL reuse, BOOL *is_new)
227 struct nmb_name calling;
228 struct nmb_name called;
229 struct in_addr *dest_ip = NULL;
230 fstring dest_host;
231 struct in_addr ip;
232 struct cli_use *cli;
234 DEBUG(10, ("cli_net_use_add\n"));
236 cli = cli_find(srv_name, usr_creds, reuse);
238 if (cli != NULL)
240 cli->num_users++;
241 DEBUG(10,
242 ("cli_net_use_add: num_users: %d\n", cli->num_users));
243 (*is_new) = False;
244 return cli->cli;
247 /* reuse an existing connection requested, and one was not found */
248 if (usr_creds != NULL && reuse)
250 return False;
254 * allocate
257 cli = cli_use_get(srv_name, usr_creds);
259 if (resolve_srv_name(srv_name, dest_host, &ip))
261 dest_ip = &ip;
263 else
265 cli_use_free(cli);
266 return NULL;
269 make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
270 make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
273 * connect
276 if (!cli_establish_connection(cli->cli,
277 dest_host, dest_ip,
278 &calling, &called,
279 "IPC$", "IPC", False, True))
281 DEBUG(0, ("cli_net_use_add: connection failed\n"));
282 cli_use_free(cli);
283 return NULL;
286 add_cli_to_array(&num_clis, &clis, cli);
287 cli->num_users++;
289 DEBUG(10, ("cli_net_use_add: num_users: %d\n", cli->num_users));
291 (*is_new) = True;
293 return cli->cli;
296 /****************************************************************************
297 delete a client state
298 ****************************************************************************/
299 BOOL cli_net_use_del(const char *srv_name,
300 const struct ntuser_creds *usr_creds,
301 BOOL force_close, BOOL *connection_closed)
303 int i;
304 const char *sv_name = srv_name;
306 DEBUG(10, ("cli_net_use_del: %s. %s. %s. force close: %s\n",
307 srv_name,
308 usr_creds ? usr_creds->user_name : "",
309 usr_creds ? usr_creds->domain : "", BOOLSTR(force_close)));
311 if (strnequal("\\\\", sv_name, 2))
313 sv_name = &sv_name[2];
316 if (connection_closed != NULL)
318 *connection_closed = False;
321 for (i = 0; i < num_clis; i++)
323 char *cli_name = NULL;
325 if (clis[i] == NULL)
326 continue;
327 if (clis[i]->cli == NULL)
328 continue;
330 cli_name = clis[i]->cli->desthost;
332 DEBUG(10, ("connection: %s %s %s\n", cli_name,
333 clis[i]->cli->usr.user_name,
334 clis[i]->cli->usr.domain));
336 if (strnequal("\\\\", cli_name, 2))
338 cli_name = &cli_name[2];
341 if (!strequal(cli_name, sv_name))
342 continue;
344 if (strequal(usr_creds ? usr_creds->user_name : "",
345 clis[i]->cli->usr.user_name) &&
346 strequal(usr_creds ? usr_creds->domain : "",
347 clis[i]->cli->usr.domain))
349 /* decrement number of users */
350 clis[i]->num_users--;
352 DEBUG(10, ("idx: %i num_users now: %d\n",
353 i, clis[i]->num_users));
355 if (force_close || clis[i]->num_users == 0)
357 cli_use_free(clis[i]);
358 clis[i] = NULL;
359 if (connection_closed != NULL)
361 *connection_closed = True;
364 return True;
368 return False;
371 /****************************************************************************
372 enumerate client states
373 ****************************************************************************/
374 void cli_net_use_enum(uint32 *num_cons, struct use_info ***use)
376 int i;
378 *num_cons = 0;
379 *use = NULL;
381 for (i = 0; i < num_clis; i++)
383 struct use_info item;
385 ZERO_STRUCT(item);
387 if (clis[i] == NULL)
388 continue;
390 item.connected = clis[i]->cli != NULL ? True : False;
392 if (item.connected)
394 item.srv_name = clis[i]->cli->desthost;
395 item.user_name = clis[i]->cli->usr.user_name;
396 item.key = clis[i]->cli->nt.key;
397 item.domain = clis[i]->cli->usr.domain;
400 add_use_info_to_array(num_cons, use, &item);
405 /****************************************************************************
406 wait for keyboard activity, swallowing network packets on all client states.
407 ****************************************************************************/
408 void cli_use_wait_keyboard(void)
410 fd_set fds;
411 struct timeval timeout;
413 while (1)
415 int i;
416 int maxfd = fileno(stdin);
417 FD_ZERO(&fds);
418 FD_SET(fileno(stdin), &fds);
419 for (i = 0; i < num_clis; i++)
421 if (clis[i] != NULL && clis[i]->cli != NULL)
423 int fd = clis[i]->cli->fd;
424 FD_SET(fd, &fds);
425 maxfd = MAX(fd, maxfd);
429 timeout.tv_sec = 20;
430 timeout.tv_usec = 0;
431 sys_select(maxfd + 1, &fds, &timeout);
433 if (FD_ISSET(fileno(stdin), &fds))
434 return;
436 /* We deliberately use receive_smb instead of
437 client_receive_smb as we want to receive
438 session keepalives and then drop them here.
440 for (i = 0; i < num_clis; i++)
442 int fd;
443 if (clis[i] == NULL || clis[i]->cli == NULL)
444 continue;
445 fd = clis[i]->cli->fd;
446 if (FD_ISSET(fd, &fds))
447 receive_smb(fd, clis[i]->cli->inbuf, 0);