me stupid.
[Samba.git] / source / rpc_client / cli_use.c
blob5cd50ca5b00519e443604476bc5504e7bc4cfbfb
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"
28 extern int DEBUGLEVEL;
29 extern pstring scope;
30 extern pstring global_myname;
32 struct cli_use
34 struct cli_state *cli;
35 uint32 num_users;
38 static struct cli_use **clis = NULL;
39 static uint32 num_clis = 0;
41 /****************************************************************************
42 terminate client connection
43 ****************************************************************************/
44 static void cli_use_free(struct cli_use *cli)
46 if (cli->cli != NULL)
48 if (cli->cli->initialised)
50 /* only logoff if we have a valid socket */
51 if (cli->cli->fd != -1)
52 cli_ulogoff(cli->cli);
53 cli_shutdown(cli->cli);
55 free(cli->cli);
58 free(cli);
61 /****************************************************************************
62 free a client array
63 ****************************************************************************/
64 static void free_cli_array(uint32 num_entries, struct cli_use **entries)
66 void (*fn) (void *) = (void (*)(void *))&cli_use_free;
67 free_void_array(num_entries, (void **)entries, *fn);
70 /****************************************************************************
71 add a client state to the array
72 ****************************************************************************/
73 static struct cli_use *add_cli_to_array(uint32 *len,
74 struct cli_use ***array,
75 struct cli_use *cli)
77 int i;
78 for (i = 0; i < num_clis; i++)
80 if (clis[i] == NULL)
82 clis[i] = cli;
83 return cli;
87 return (struct cli_use *)add_item_to_array(len,
88 (void ***)array,
89 (void *)cli);
93 /****************************************************************************
94 initiate client array
95 ****************************************************************************/
96 void init_cli_use(void)
98 clis = NULL;
99 num_clis = 0;
102 /****************************************************************************
103 terminate client array
104 ****************************************************************************/
105 void free_cli_use(void)
107 free_cli_array(num_clis, clis);
108 init_cli_use();
111 /****************************************************************************
112 find client state. server name, user name, domain name and password must all
113 match.
114 ****************************************************************************/
115 static struct cli_use *cli_find(const char *srv_name,
116 const struct ntuser_creds *usr_creds,
117 BOOL reuse)
119 int i;
120 const char *sv_name = srv_name;
121 struct ntuser_creds null_usr;
123 if (usr_creds == NULL)
125 copy_nt_creds(&null_usr, usr_creds);
126 usr_creds = &null_usr;
129 if (strnequal("\\\\", sv_name, 2))
131 sv_name = &sv_name[2];
134 DEBUG(10, ("cli_find: %s %s %s reuse: %s\n",
135 srv_name, usr_creds->user_name, usr_creds->domain,
136 BOOLSTR(reuse)));
139 for (i = 0; i < num_clis; i++)
141 char *cli_name = NULL;
142 struct cli_use *c = clis[i];
144 if (c == NULL || !c->cli->initialised || c->cli->fd == -1)
146 continue;
149 cli_name = c->cli->desthost;
151 DEBUG(10, ("cli_find[%d]: %s %s %s\n",
152 i, cli_name,
153 c->cli->user_name, c->cli->domain));
155 if (strnequal("\\\\", cli_name, 2))
157 cli_name = &cli_name[2];
160 if (!strequal(cli_name, sv_name))
162 continue;
164 if (strequal(usr_creds->user_name, "") &&
165 strequal(usr_creds->domain, "") &&
166 pwd_is_nullpwd(&usr_creds->pwd))
168 return c;
170 if (!strequal(usr_creds->user_name, c->cli->user_name))
172 continue;
174 if (!reuse && !pwd_compare((struct pwd_info *)&usr_creds->pwd, &c->cli->pwd))
176 DEBUG(100, ("password doesn't match\n"));
177 continue;
179 if (usr_creds->domain[0] == 0)
181 return c;
183 if (strequal(usr_creds->domain, c->cli->domain))
185 return c;
189 return NULL;
192 /****************************************************************************
193 create a new client state from user credentials
194 ****************************************************************************/
195 static struct cli_use *cli_use_get(const char *srv_name,
196 const struct ntuser_creds *usr_creds)
198 struct cli_use *cli = (struct cli_use *)malloc(sizeof(*cli));
200 if (cli == NULL)
202 return NULL;
205 memset(cli, 0, sizeof(*cli));
207 cli->cli = cli_initialise(NULL);
209 if (cli->cli == NULL)
211 return NULL;
214 cli_init_creds(cli->cli, usr_creds);
216 return cli;
219 /****************************************************************************
220 init client state
221 ****************************************************************************/
222 struct cli_state *cli_net_use_add(const char *srv_name,
223 const struct ntuser_creds *usr_creds,
224 BOOL reuse, BOOL *is_new)
226 struct nmb_name calling;
227 struct nmb_name called;
228 struct in_addr *dest_ip = NULL;
229 fstring dest_host;
230 struct in_addr ip;
231 struct cli_use *cli;
233 DEBUG(10, ("cli_net_use_add\n"));
235 cli = cli_find(srv_name, usr_creds, reuse);
237 if (cli != NULL)
239 cli->num_users++;
240 DEBUG(10,
241 ("cli_net_use_add: num_users: %d\n", cli->num_users));
242 (*is_new) = False;
243 return cli->cli;
246 /* reuse an existing connection requested, and one was not found */
247 if (usr_creds != NULL && reuse)
249 return False;
253 * allocate
256 cli = cli_use_get(srv_name, usr_creds);
258 if (resolve_srv_name(srv_name, dest_host, &ip))
260 dest_ip = &ip;
262 else
264 cli_use_free(cli);
265 return NULL;
268 make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
269 make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
272 * connect
275 if (!cli_establish_connection(cli->cli,
276 dest_host, dest_ip,
277 &calling, &called,
278 "IPC$", "IPC", False, True))
280 DEBUG(0, ("cli_net_use_add: connection failed\n"));
281 cli_use_free(cli);
282 return NULL;
285 add_cli_to_array(&num_clis, &clis, cli);
286 cli->num_users++;
288 DEBUG(10, ("cli_net_use_add: num_users: %d\n", cli->num_users));
290 (*is_new) = True;
292 return cli->cli;
295 /****************************************************************************
296 delete a client state
297 ****************************************************************************/
298 BOOL cli_net_use_del(const char *srv_name,
299 const struct ntuser_creds *usr_creds,
300 BOOL force_close, BOOL *connection_closed)
302 int i;
303 const char *sv_name = srv_name;
305 DEBUG(10, ("cli_net_use_del: %s. %s. %s. force close: %s\n",
306 srv_name,
307 usr_creds ? usr_creds->user_name : "",
308 usr_creds ? usr_creds->domain : "", BOOLSTR(force_close)));
310 if (strnequal("\\\\", sv_name, 2))
312 sv_name = &sv_name[2];
315 if (connection_closed != NULL)
317 *connection_closed = False;
320 for (i = 0; i < num_clis; i++)
322 char *cli_name = NULL;
324 if (clis[i] == NULL)
325 continue;
326 if (clis[i]->cli == NULL)
327 continue;
329 cli_name = clis[i]->cli->desthost;
331 DEBUG(10, ("connection: %s %s %s\n", cli_name,
332 clis[i]->cli->user_name,
333 clis[i]->cli->domain));
335 if (strnequal("\\\\", cli_name, 2))
337 cli_name = &cli_name[2];
340 if (!strequal(cli_name, sv_name))
341 continue;
343 if (strequal(usr_creds ? usr_creds->user_name : "",
344 clis[i]->cli->user_name) &&
345 strequal(usr_creds ? usr_creds->domain : "",
346 clis[i]->cli->domain))
348 /* decrement number of users */
349 clis[i]->num_users--;
351 DEBUG(10, ("idx: %i num_users now: %d\n",
352 i, clis[i]->num_users));
354 if (force_close || clis[i]->num_users == 0)
356 cli_use_free(clis[i]);
357 clis[i] = NULL;
358 if (connection_closed != NULL)
360 *connection_closed = True;
363 return True;
367 return False;
370 /****************************************************************************
371 enumerate client states
372 ****************************************************************************/
373 void cli_net_use_enum(uint32 *num_cons, struct use_info ***use)
375 int i;
377 *num_cons = 0;
378 *use = NULL;
380 for (i = 0; i < num_clis; i++)
382 struct use_info item;
384 ZERO_STRUCT(item);
386 if (clis[i] == NULL)
387 continue;
389 item.connected = clis[i]->cli != NULL ? True : False;
391 if (item.connected)
393 item.srv_name = clis[i]->cli->desthost;
394 item.user_name = clis[i]->cli->user_name;
395 item.key = clis[i]->cli->key;
396 item.domain = clis[i]->cli->domain;
399 add_use_info_to_array(num_cons, use, &item);
404 /****************************************************************************
405 wait for keyboard activity, swallowing network packets on all client states.
406 ****************************************************************************/
407 void cli_use_wait_keyboard(void)
409 fd_set fds;
410 struct timeval timeout;
412 while (1)
414 int i;
415 int maxfd = fileno(stdin);
416 FD_ZERO(&fds);
417 FD_SET(fileno(stdin), &fds);
418 for (i = 0; i < num_clis; i++)
420 if (clis[i] != NULL && clis[i]->cli != NULL)
422 int fd = clis[i]->cli->fd;
423 FD_SET(fd, &fds);
424 maxfd = MAX(fd, maxfd);
428 timeout.tv_sec = 20;
429 timeout.tv_usec = 0;
430 sys_select(maxfd + 1, &fds, &timeout);
432 if (FD_ISSET(fileno(stdin), &fds))
433 return;
435 /* We deliberately use receive_smb instead of
436 client_receive_smb as we want to receive
437 session keepalives and then drop them here.
439 for (i = 0; i < num_clis; i++)
441 int fd;
442 if (clis[i] == NULL || clis[i]->cli == NULL)
443 continue;
444 fd = clis[i]->cli->fd;
445 if (FD_ISSET(fd, &fds))
446 receive_smb(fd, clis[i]->cli->inbuf, 0);