default SID map now reads in "trusted domains" from smb.conf.
[kai/samba.git] / source / 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         if (cli->cli != NULL)
47         {
48                 if (cli->cli->initialised)
49                 {
50                         cli_ulogoff(cli->cli);
51                         cli_shutdown(cli->cli);
52                 }
53                 free(cli->cli);
54         }
55
56         free(cli);
57 }
58
59 /****************************************************************************
60 free a client array
61 ****************************************************************************/
62 static void free_cli_array(uint32 num_entries, struct cli_use **entries)
63 {
64         void(*fn)(void*) = (void(*)(void*))&cli_use_free;
65         free_void_array(num_entries, (void**)entries, *fn);
66 }
67
68 /****************************************************************************
69 add a client state to the array
70 ****************************************************************************/
71 static struct cli_use* add_cli_to_array(uint32 *len,
72                                 struct cli_use ***array,
73                                 struct cli_use *cli)
74 {
75         int i;
76         for (i = 0; i < num_clis; i++)
77         {
78                 if (clis[i] == NULL)
79                 {
80                         clis[i] = cli;
81                         return cli;
82                 }
83         }
84
85         return (struct cli_use*)add_item_to_array(len,
86                              (void***)array, (void*)cli);
87                                 
88 }
89
90 /****************************************************************************
91 initiate client array
92 ****************************************************************************/
93 void init_cli_use(void)
94 {
95         clis = NULL;
96         num_clis = 0;
97 }
98
99 /****************************************************************************
100 terminate client array
101 ****************************************************************************/
102 void free_cli_use(void)
103 {
104         free_cli_array(num_clis, clis);
105         init_cli_use();
106 }
107
108 /****************************************************************************
109 find client state.  server name, user name, domain name and password must all
110 match.
111 ****************************************************************************/
112 static struct cli_use *cli_find(const char* srv_name,
113                                 const struct user_credentials *usr_creds)
114 {
115         int i;
116         const char *sv_name = srv_name;
117         if (strnequal("\\\\", sv_name, 2))
118         {
119                 sv_name = &sv_name[2];
120         }
121
122         DEBUG(10,("cli_find: %s %s %s\n",
123                         srv_name,
124                         usr_creds->user_name,
125                         usr_creds->domain));
126
127         for (i = 0; i < num_clis; i++)
128         {
129                 char *cli_name = NULL;
130                 struct cli_use *c = clis[i];
131
132                 if (c == NULL) continue;
133
134                 cli_name = c->cli->desthost;
135
136                 DEBUG(10,("cli_find[%d]: %s %s %s\n",
137                                 i, cli_name,
138                                 c->cli->usr.user_name,
139                                 c->cli->usr.domain));
140                                 
141                 if (strnequal("\\\\", cli_name, 2))
142                 {
143                         cli_name = &cli_name[2];
144                 }
145
146                 if (!strequal(cli_name, sv_name))
147                 {
148                         continue;
149                 }
150                 if (!strequal(usr_creds->user_name, c->cli->usr.user_name))
151                 {
152                         continue;
153                 }
154                 if (!pwd_compare(&usr_creds->pwd, &c->cli->usr.pwd))
155                 {
156                         continue;
157                 }
158                 if (usr_creds->domain[0] == 0)
159                 {
160                         return c;
161                 }
162                 if (strequal(usr_creds->domain, c->cli->usr.domain))
163                 {
164                         return c;
165                 }
166         }
167
168         return NULL;
169 }
170
171 /****************************************************************************
172 create a new client state from user credentials
173 ****************************************************************************/
174 static struct cli_use *cli_use_get(const char* srv_name,
175                                 const struct user_credentials *usr_creds)
176 {
177         struct cli_use *cli = (struct cli_use*)malloc(sizeof(*cli));
178
179         if (cli == NULL)
180         {
181                 return NULL;
182         }
183
184         memset(cli, 0, sizeof(*cli));
185
186         cli->cli = cli_initialise(NULL);
187
188         if (cli->cli == NULL)
189         {
190                 return NULL;
191         }
192
193         cli_init_creds(cli->cli, usr_creds);
194
195         return cli;
196 }
197
198 /****************************************************************************
199 init client state
200 ****************************************************************************/
201 struct cli_state *cli_net_use_addlist(char* servers,
202                                 const struct user_credentials *usr_creds)
203 {
204         struct cli_use *cli = cli_find(servers, usr_creds); 
205
206         if (cli != NULL)
207         {
208                 cli->num_users++;
209                 return cli->cli;
210         }
211
212         /*
213          * allocate
214          */
215
216         cli = cli_use_get(servers, usr_creds);
217
218         if (cli == NULL)
219         {
220                 return NULL;
221         }
222
223         if (!cli_connect_serverlist(cli->cli, servers))
224         {
225                 DEBUG(0,("cli_net_use_addlist: connection failed\n"));
226                 cli_use_free(cli);
227                 return NULL;
228         }
229
230         cli->cli->ntlmssp_cli_flgs = 0x0;
231
232         add_cli_to_array(&num_clis, &clis, cli);
233         cli->num_users++;
234
235         return cli->cli;
236 }
237
238 /****************************************************************************
239 init client state
240 ****************************************************************************/
241 struct cli_state *cli_net_use_add(const char* srv_name,
242                                 const struct user_credentials *usr_creds)
243 {
244         struct nmb_name calling;
245         struct nmb_name called;
246         struct in_addr *dest_ip = NULL;
247         fstring dest_host;
248         struct in_addr ip;
249
250         struct cli_use *cli = cli_find(srv_name, usr_creds); 
251
252         if (cli != NULL)
253         {
254                 cli->num_users++;
255                 return cli->cli;
256         }
257
258         /*
259          * allocate
260          */
261
262         cli = cli_use_get(srv_name, usr_creds);
263
264         if (resolve_srv_name(srv_name, dest_host, &ip))
265         {
266                 dest_ip = &ip;
267         }
268         else
269         {
270                 cli_use_free(cli);
271                 return NULL;
272         }
273
274         make_nmb_name(&called , dns_to_netbios_name(dest_host    ), 32, scope);
275         make_nmb_name(&calling, dns_to_netbios_name(global_myname),  0, scope);
276
277         /*
278          * connect
279          */
280
281         if (!cli_establish_connection(cli->cli, 
282                                   dest_host, dest_ip,
283                                   &calling, &called,
284                                   "IPC$", "IPC",
285                                   False, True))
286         {
287                 DEBUG(0,("cli_net_use_add: connection failed\n"));
288                 cli_use_free(cli);
289                 return NULL;
290         }
291
292         cli->cli->ntlmssp_cli_flgs = 0x0;
293
294         add_cli_to_array(&num_clis, &clis, cli);
295         cli->num_users++;
296
297         return cli->cli;
298 }
299
300 /****************************************************************************
301 delete a client state
302 ****************************************************************************/
303 BOOL cli_net_use_del(const char* srv_name,
304                                 const struct user_credentials *usr_creds,
305                                 BOOL force_close,
306                                 BOOL *connection_closed)
307 {
308         int i;
309         const char *sv_name = srv_name;
310
311         DEBUG(10,("cli_net_use_del: %s. force close: %s\n",
312                    srv_name, BOOLSTR(force_close)));
313
314         if (strnequal("\\\\", sv_name, 2))
315         {
316                 sv_name = &sv_name[2];
317         }
318
319         *connection_closed = False;
320
321         for (i = 0; i < num_clis; i++)
322         {
323                 char *cli_name = NULL;
324
325                 if (clis[i] == NULL) continue;
326                 if (clis[i]->cli == NULL) continue;
327
328                 cli_name = clis[i]->cli->desthost;
329                 if (strnequal("\\\\", cli_name, 2))
330                 {
331                         cli_name = &cli_name[2];
332                 }
333
334                 if (!strequal(cli_name, sv_name)) continue;
335
336                 if (strequal(usr_creds->user_name,
337                              clis[i]->cli->usr.user_name) &&
338                     strequal(usr_creds->domain,
339                              clis[i]->cli->usr.domain))
340                 {
341                         /* decrement number of users */
342                         clis[i]->num_users--;
343
344                         DEBUG(10,("idx: %i num_users now: %d\n",
345                                    i, clis[i]->num_users));
346
347                         if (force_close || clis[i]->num_users == 0)
348                         {
349                                 cli_use_free(clis[i]);
350                                 clis[i] = NULL;
351                                 *connection_closed = True;
352                         }
353                         return True;
354                 }
355         }
356
357         return False;
358 }
359
360 /****************************************************************************
361 enumerate client states
362 ****************************************************************************/
363 void cli_net_use_enum(uint32 *num_cons, struct use_info ***use)
364 {
365         int i;
366
367         *num_cons = 0;
368         *use = NULL;
369
370         for (i = 0; i < num_clis; i++)
371         {
372                 struct use_info item;
373
374                 ZERO_STRUCT(item);
375
376                 if (clis[i] == NULL) continue;
377
378                 item.connected = clis[i]->cli != NULL ? True : False;
379         
380                 if (item.connected)
381                 {
382                         item.srv_name = clis[i]->cli->desthost;
383                         item.user_name = clis[i]->cli->usr.user_name;
384                         item.domain    = clis[i]->cli->usr.domain;
385                 }
386
387                 add_use_to_array(num_cons, use, &item);
388         }
389 }
390
391
392 /****************************************************************************
393 wait for keyboard activity, swallowing network packets on all client states.
394 ****************************************************************************/
395 void cli_use_wait_keyboard(void)
396 {
397         fd_set fds;
398         struct timeval timeout;
399   
400         while (1)
401         {
402                 int i;
403                 int maxfd = fileno(stdin);
404                 FD_ZERO(&fds);
405                 FD_SET(fileno(stdin),&fds);
406                 for (i = 0; i < num_clis; i++)
407                 {
408                         if (clis[i] != NULL && clis[i]->cli != NULL)
409                         {
410                                 int fd = clis[i]->cli->fd;
411                                 FD_SET(fd,&fds);
412                                 maxfd = MAX(fd, maxfd);
413                         }
414                 }
415
416                 timeout.tv_sec = 20;
417                 timeout.tv_usec = 0;
418                 sys_select(maxfd+1,NULL, &fds,&timeout);
419       
420                 if (FD_ISSET(fileno(stdin),&fds))
421                         return;
422
423                 /* We deliberately use receive_smb instead of
424                    client_receive_smb as we want to receive
425                    session keepalives and then drop them here.
426                 */
427                 for (i = 0; i < num_clis; i++)
428                 {
429                         int fd = clis[i]->cli->fd;
430                         if (FD_ISSET(fd,&fds))
431                                         receive_smb(fd,clis[i]->cli->inbuf,0);
432                 }
433         }  
434 }