2f79d4c2cf188e3ce74142f90d4377785dd1a556
[kai/samba-autobuild/.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         for (i = 0; i < num_clis; i++)
117         {
118                 uchar ntpw[16], clintpw[16];
119                 char *cli_name = NULL;
120
121                 if (clis[i] == NULL) continue;
122
123                 cli_name = clis[i]->cli->desthost;
124                 if (strnequal("\\\\", cli_name, 2))
125                 {
126                         cli_name = &cli_name[2];
127                 }
128
129                 if (!strequal(cli_name, sv_name)) continue;
130
131                 pwd_get_lm_nt_16(&usr_creds->pwd, NULL, ntpw);
132                 pwd_get_lm_nt_16(&clis[i]->cli->usr.pwd, NULL, clintpw);
133
134                 if (strequal(usr_creds->user_name, clis[i]->cli->usr.user_name) &&
135                     strequal(usr_creds->domain, clis[i]->cli->usr.domain) &&
136                     memcmp(ntpw, clintpw, 16) == 0)
137                 {
138                         return clis[i];
139                 }
140         }
141
142         return NULL;
143 }
144
145 /****************************************************************************
146 create a new client state from user credentials
147 ****************************************************************************/
148 static struct cli_use *cli_use_get(const char* srv_name,
149                                 const struct user_credentials *usr_creds)
150 {
151         struct cli_use *cli = (struct cli_use*)malloc(sizeof(*cli));
152
153         if (cli == NULL)
154         {
155                 return NULL;
156         }
157
158         memset(cli, 0, sizeof(*cli));
159
160         cli->cli = cli_initialise(NULL);
161
162         if (cli->cli == NULL)
163         {
164                 return NULL;
165         }
166
167         cli->cli->capabilities |= CAP_NT_SMBS | CAP_STATUS32;
168         cli_init_creds(cli->cli, usr_creds);
169
170         cli->cli->use_ntlmv2 = lp_client_ntlmv2();
171
172         return cli;
173 }
174
175 /****************************************************************************
176 init client state
177 ****************************************************************************/
178 struct cli_state *cli_net_use_addlist(char* servers,
179                                 const struct user_credentials *usr_creds)
180 {
181         struct cli_use *cli = cli_find(servers, usr_creds); 
182
183         if (cli != NULL)
184         {
185                 cli->num_users++;
186                 return cli->cli;
187         }
188
189         /*
190          * allocate
191          */
192
193         cli = cli_use_get(servers, usr_creds);
194
195         if (cli == NULL)
196         {
197                 return NULL;
198         }
199
200         if (!cli_connect_serverlist(cli->cli, servers))
201         {
202                 DEBUG(0,("cli_net_use_addlist: connection failed\n"));
203                 cli_use_free(cli);
204                 return NULL;
205         }
206
207         cli->cli->ntlmssp_cli_flgs = 0x0;
208
209         add_cli_to_array(&num_clis, &clis, cli);
210         cli->num_users++;
211
212         return cli->cli;
213 }
214
215 /****************************************************************************
216 init client state
217 ****************************************************************************/
218 struct cli_state *cli_net_use_add(const char* srv_name,
219                                 const struct user_credentials *usr_creds)
220 {
221         struct nmb_name calling;
222         struct nmb_name called;
223         struct in_addr *dest_ip = NULL;
224         fstring dest_host;
225         struct in_addr ip;
226
227         struct cli_use *cli = cli_find(srv_name, usr_creds); 
228
229         if (cli != NULL)
230         {
231                 cli->num_users++;
232                 return cli->cli;
233         }
234
235         /*
236          * allocate
237          */
238
239         cli = cli_use_get(srv_name, usr_creds);
240
241         if (resolve_srv_name(srv_name, dest_host, &ip))
242         {
243                 dest_ip = &ip;
244         }
245         else
246         {
247                 cli_use_free(cli);
248                 return NULL;
249         }
250
251         make_nmb_name(&called , dns_to_netbios_name(dest_host    ), 32, scope);
252         make_nmb_name(&calling, dns_to_netbios_name(global_myname),  0, scope);
253
254         /*
255          * connect
256          */
257
258         if (!cli_establish_connection(cli->cli, 
259                                   dest_host, dest_ip,
260                                   &calling, &called,
261                                   "IPC$", "IPC",
262                                   False, True))
263         {
264                 DEBUG(0,("cli_net_use_add: connection failed\n"));
265                 cli_use_free(cli);
266                 return NULL;
267         }
268
269         cli->cli->ntlmssp_cli_flgs = 0x0;
270
271         add_cli_to_array(&num_clis, &clis, cli);
272         cli->num_users++;
273
274         return cli->cli;
275 }
276
277 /****************************************************************************
278 delete a client state
279 ****************************************************************************/
280 BOOL cli_net_use_del(const char* srv_name,
281                                 const struct user_credentials *usr_creds,
282                                 BOOL force_close,
283                                 BOOL *connection_closed)
284 {
285         int i;
286         const char *sv_name = srv_name;
287
288         DEBUG(10,("cli_net_use_del: %s. force close: %s\n",
289                    srv_name, BOOLSTR(force_close)));
290         dbgflush();
291
292         if (strnequal("\\\\", sv_name, 2))
293         {
294                 sv_name = &sv_name[2];
295         }
296
297         *connection_closed = False;
298
299         for (i = 0; i < num_clis; i++)
300         {
301                 char *cli_name = NULL;
302
303                 if (clis[i] == NULL) continue;
304                 if (clis[i]->cli == NULL) continue;
305
306                 cli_name = clis[i]->cli->desthost;
307                 if (strnequal("\\\\", cli_name, 2))
308                 {
309                         cli_name = &cli_name[2];
310                 }
311
312                 if (!strequal(cli_name, sv_name)) continue;
313
314                 if (strequal(usr_creds->user_name,
315                              clis[i]->cli->usr.user_name) &&
316                     strequal(usr_creds->domain,
317                              clis[i]->cli->usr.domain))
318                 {
319                         /* decrement number of users */
320                         clis[i]->num_users--;
321
322                         DEBUG(10,("idx: %i num_users now: %d\n",
323                                    i, clis[i]->num_users));
324                         dbgflush();
325
326                         if (force_close || clis[i]->num_users == 0)
327                         {
328                                 cli_use_free(clis[i]);
329                                 clis[i] = NULL;
330                                 *connection_closed = True;
331                         }
332                         return True;
333                 }
334         }
335
336         return False;
337 }
338