a953d332e1ecd1db4ad6895ae75d2be98a6556df
[kai/samba.git] / source3 / rpc_client / cli_use.c
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
7    
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.
12    
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.
17    
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.
21 */
22
23 #define NO_SYSLOG
24
25 #include "includes.h"
26 #include "trans2.h"
27
28 extern int DEBUGLEVEL;
29 extern pstring scope;
30 extern pstring global_myname;
31
32 struct cli_use
33 {
34         struct cli_state *cli;
35         uint32 num_users;
36 };
37
38 static struct cli_use **clis = NULL;
39 uint32 num_clis = 0;
40
41 /****************************************************************************
42 terminate client connection
43 ****************************************************************************/
44 static void cli_use_free(struct cli_use *cli)
45 {
46         cli_ulogoff(cli->cli);
47         cli_shutdown(cli->cli);
48         free(cli->cli);
49
50         free(cli);
51 }
52
53 /****************************************************************************
54 free a client array
55 ****************************************************************************/
56 static void free_cli_array(uint32 num_entries, struct cli_use **entries)
57 {
58         void(*fn)(void*) = (void(*)(void*))&cli_use_free;
59         free_void_array(num_entries, (void**)entries, *fn);
60 }
61
62 /****************************************************************************
63 add a client state to the array
64 ****************************************************************************/
65 static struct cli_use* add_cli_to_array(uint32 *len,
66                                 struct cli_use ***array,
67                                 struct cli_use *cli)
68 {
69         int i;
70         for (i = 0; i < num_clis; i++)
71         {
72                 if (clis[i] == NULL)
73                 {
74                         clis[i] = cli;
75                         return cli;
76                 }
77         }
78
79         return (struct cli_use*)add_item_to_array(len,
80                              (void***)array, (void*)cli);
81                                 
82 }
83
84 /****************************************************************************
85 initiate client array
86 ****************************************************************************/
87 void init_cli_use(void)
88 {
89         clis = NULL;
90         num_clis = 0;
91 }
92
93 /****************************************************************************
94 terminate client array
95 ****************************************************************************/
96 void free_cli_use(void)
97 {
98         free_cli_array(num_clis, clis);
99         init_cli_use();
100 }
101
102 /****************************************************************************
103 find client state.  server name, user name, domain name and password must all
104 match.
105 ****************************************************************************/
106 static struct cli_use *cli_find(const char* srv_name,
107                                 const struct user_credentials *usr_creds)
108 {
109         int i;
110         const char *sv_name = srv_name;
111         if (strnequal("\\\\", sv_name, 2))
112         {
113                 sv_name = &sv_name[2];
114         }
115
116         DEBUG(10,("cli_find: %s %s %s\n",
117                         srv_name,
118                         usr_creds->user_name,
119                         usr_creds->domain));
120
121         for (i = 0; i < num_clis; i++)
122         {
123                 char *cli_name = NULL;
124                 struct cli_use *c = clis[i];
125
126                 if (c == NULL) continue;
127
128                 cli_name = c->cli->desthost;
129
130                 DEBUG(10,("cli_find[%d]: %s %s %s\n",
131                                 i, cli_name,
132                                 c->cli->usr.user_name,
133                                 c->cli->usr.domain));
134                                 
135                 if (strnequal("\\\\", cli_name, 2))
136                 {
137                         cli_name = &cli_name[2];
138                 }
139
140                 if (!strequal(cli_name, sv_name))
141                 {
142                         continue;
143                 }
144                 if (!strequal(usr_creds->user_name, c->cli->usr.user_name))
145                 {
146                         continue;
147                 }
148                 if (!pwd_compare(&usr_creds->pwd, &c->cli->usr.pwd))
149                 {
150                         continue;
151                 }
152                 if (usr_creds->domain[0] == 0)
153                 {
154                         return c;
155                 }
156                 if (strequal(usr_creds->domain, c->cli->usr.domain))
157                 {
158                         return c;
159                 }
160         }
161
162         return NULL;
163 }
164
165 /****************************************************************************
166 create a new client state from user credentials
167 ****************************************************************************/
168 static struct cli_use *cli_use_get(const char* srv_name,
169                                 const struct user_credentials *usr_creds)
170 {
171         struct cli_use *cli = (struct cli_use*)malloc(sizeof(*cli));
172
173         if (cli == NULL)
174         {
175                 return NULL;
176         }
177
178         memset(cli, 0, sizeof(*cli));
179
180         cli->cli = cli_initialise(NULL);
181
182         if (cli->cli == NULL)
183         {
184                 return NULL;
185         }
186
187         cli_init_creds(cli->cli, usr_creds);
188
189         return cli;
190 }
191
192 /****************************************************************************
193 init client state
194 ****************************************************************************/
195 struct cli_state *cli_net_use_addlist(char* servers,
196                                 const struct user_credentials *usr_creds)
197 {
198         struct cli_use *cli = cli_find(servers, usr_creds); 
199
200         if (cli != NULL)
201         {
202                 cli->num_users++;
203                 return cli->cli;
204         }
205
206         /*
207          * allocate
208          */
209
210         cli = cli_use_get(servers, usr_creds);
211
212         if (cli == NULL)
213         {
214                 return NULL;
215         }
216
217         if (!cli_connect_serverlist(cli->cli, servers))
218         {
219                 DEBUG(0,("cli_net_use_addlist: connection failed\n"));
220                 cli_use_free(cli);
221                 return NULL;
222         }
223
224         cli->cli->ntlmssp_cli_flgs = 0x0;
225
226         add_cli_to_array(&num_clis, &clis, cli);
227         cli->num_users++;
228
229         return cli->cli;
230 }
231
232 /****************************************************************************
233 init client state
234 ****************************************************************************/
235 struct cli_state *cli_net_use_add(const char* srv_name,
236                                 const struct user_credentials *usr_creds)
237 {
238         struct nmb_name calling;
239         struct nmb_name called;
240         struct in_addr *dest_ip = NULL;
241         fstring dest_host;
242         struct in_addr ip;
243
244         struct cli_use *cli = cli_find(srv_name, usr_creds); 
245
246         if (cli != NULL)
247         {
248                 cli->num_users++;
249                 return cli->cli;
250         }
251
252         /*
253          * allocate
254          */
255
256         cli = cli_use_get(srv_name, usr_creds);
257
258         if (resolve_srv_name(srv_name, dest_host, &ip))
259         {
260                 dest_ip = &ip;
261         }
262         else
263         {
264                 cli_use_free(cli);
265                 return NULL;
266         }
267
268         make_nmb_name(&called , dns_to_netbios_name(dest_host    ), 32, scope);
269         make_nmb_name(&calling, dns_to_netbios_name(global_myname),  0, scope);
270
271         /*
272          * connect
273          */
274
275         if (!cli_establish_connection(cli->cli, 
276                                   dest_host, dest_ip,
277                                   &calling, &called,
278                                   "IPC$", "IPC",
279                                   False, True))
280         {
281                 DEBUG(0,("cli_net_use_add: connection failed\n"));
282                 cli_use_free(cli);
283                 return NULL;
284         }
285
286         cli->cli->ntlmssp_cli_flgs = 0x0;
287
288         add_cli_to_array(&num_clis, &clis, cli);
289         cli->num_users++;
290
291         return cli->cli;
292 }
293
294 /****************************************************************************
295 delete a client state
296 ****************************************************************************/
297 BOOL cli_net_use_del(const char* srv_name,
298                                 const struct user_credentials *usr_creds,
299                                 BOOL force_close,
300                                 BOOL *connection_closed)
301 {
302         int i;
303         const char *sv_name = srv_name;
304
305         DEBUG(10,("cli_net_use_del: %s. force close: %s\n",
306                    srv_name, BOOLSTR(force_close)));
307
308         if (strnequal("\\\\", sv_name, 2))
309         {
310                 sv_name = &sv_name[2];
311         }
312
313         *connection_closed = False;
314
315         for (i = 0; i < num_clis; i++)
316         {
317                 char *cli_name = NULL;
318
319                 if (clis[i] == NULL) continue;
320                 if (clis[i]->cli == NULL) continue;
321
322                 cli_name = clis[i]->cli->desthost;
323                 if (strnequal("\\\\", cli_name, 2))
324                 {
325                         cli_name = &cli_name[2];
326                 }
327
328                 if (!strequal(cli_name, sv_name)) continue;
329
330                 if (strequal(usr_creds->user_name,
331                              clis[i]->cli->usr.user_name) &&
332                     strequal(usr_creds->domain,
333                              clis[i]->cli->usr.domain))
334                 {
335                         /* decrement number of users */
336                         clis[i]->num_users--;
337
338                         DEBUG(10,("idx: %i num_users now: %d\n",
339                                    i, clis[i]->num_users));
340
341                         if (force_close || clis[i]->num_users == 0)
342                         {
343                                 cli_use_free(clis[i]);
344                                 clis[i] = NULL;
345                                 *connection_closed = True;
346                         }
347                         return True;
348                 }
349         }
350
351         return False;
352 }
353
354 /****************************************************************************
355 enumerate client states
356 ****************************************************************************/
357 void cli_net_use_enum(uint32 *num_cons, struct use_info ***use)
358 {
359         int i;
360
361         *num_cons = 0;
362         *use = NULL;
363
364         for (i = 0; i < num_clis; i++)
365         {
366                 struct use_info item;
367
368                 ZERO_STRUCT(item);
369
370                 if (clis[i] == NULL) continue;
371
372                 item.connected = clis[i]->cli != NULL ? True : False;
373         
374                 if (item.connected)
375                 {
376                         item.srv_name = clis[i]->cli->desthost;
377                         item.user_name = clis[i]->cli->usr.user_name;
378                         item.domain    = clis[i]->cli->usr.domain;
379                 }
380
381                 add_use_to_array(num_cons, use, &item);
382         }
383 }
384