Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header.
[metze/samba/wip.git] / source3 / rpc_client / ncacn_np_use.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB client generic functions
5    Copyright (C) Andrew Tridgell              1994-2000
6    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
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 "rpc_parse.h"
27 #include "trans2.h"
28
29 extern pstring global_myname;
30
31 struct ncacn_np_use
32 {
33         struct ncacn_np *cli;
34         uint32 num_users;
35 };
36
37 static struct ncacn_np_use **msrpcs = NULL;
38 static uint32 num_msrpcs = 0;
39
40 /****************************************************************************
41 terminate client connection
42 ****************************************************************************/
43 static void ncacn_np_shutdown(struct ncacn_np *cli)
44 {
45         struct ntuser_creds     usr;
46         BOOL                    closed;
47
48         if (cli != NULL)
49         {
50                 if (cli->smb != NULL)
51                 {
52                         if (cli->smb->initialised)
53                         {
54                                 /* cli_nt_session_close(cli->smb, cli->fnum); JERRY */
55                                 cli_nt_session_close(cli->smb);
56                         }
57                         create_ntc_from_cli_state(&usr, cli->smb);
58                         cli_net_use_del(cli->smb->desthost, &usr, False, &closed);
59                 }
60         }
61 }
62
63 static BOOL ncacn_np_establish_connection(struct ncacn_np *cli,
64                                    const char *srv_name,
65                                    const struct ntuser_creds *ntc,
66                                    const char *pipe_name,
67                                    BOOL reuse)
68 {
69         BOOL new_smb_conn;
70         cli->smb = cli_net_use_add(srv_name, ntc,
71                                    True, &new_smb_conn);
72         if (cli->smb == NULL)
73         {
74                 return False;
75         }
76         /* if (!cli_nt_session_open(cli->smb, pipe_name, &cli->fnum))  by JERRY */
77         if (!cli_nt_session_open(cli->smb, (char *)pipe_name))
78         {
79                 cli_net_use_del(srv_name, ntc, False, NULL);
80                 return False;
81         }
82         fstrcpy(cli->pipe_name, pipe_name);
83         return True;
84 }
85
86
87
88 /****************************************************************************
89 terminate client connection
90 ****************************************************************************/
91 static void ncacn_np_use_free(struct ncacn_np_use *cli)
92 {
93         if (cli->cli != NULL)
94         {
95                 if (cli->cli->initialised)
96                 {
97                         ncacn_np_shutdown(cli->cli);
98                 }
99                 ZERO_STRUCTP(cli->cli);
100                 SAFE_FREE(cli->cli);
101         }
102         ZERO_STRUCTP(cli);
103         SAFE_FREE(cli);
104 }
105
106 /****************************************************************************
107 add a client state to the array
108 ****************************************************************************/
109 static struct ncacn_np_use *add_ncacn_np_to_array(uint32 * len,
110                                                   struct ncacn_np_use
111                                                   ***array,
112                                                   struct ncacn_np_use *cli)
113 {
114         
115         int i;
116
117         /* traverse the list and try to find a previously
118            allocate spot that is not being used */
119         for (i = 0; i < num_msrpcs; i++)
120         {
121                 if (msrpcs[i] == NULL)
122                 {
123                         /* found and empty spot to 
124                            store the cli pointer */
125                         msrpcs[i] = cli;
126                         return cli;
127                 }
128         }
129
130         return (struct ncacn_np_use *)add_item_to_array(len,
131                                                         (void ***)array,
132                                                         (void *)cli);
133
134 }
135
136
137
138 /****************************************************************************
139 delete a client state
140 ****************************************************************************/
141 BOOL ncacn_np_use_del(const char *srv_name, const char *pipe_name,
142                       const vuser_key * key,
143                       BOOL force_close, BOOL *connection_closed)
144 {
145         int i;
146         DEBUG(10, ("ncacn_np_net_use_del: %s. force close: %s ",
147                    pipe_name, BOOLSTR(force_close)));
148         if (key != NULL)
149         {
150                 DEBUG(10, ("[%d,%x]", key->pid, key->vuid));
151         }
152         DEBUG(10, ("\n"));
153
154         if (connection_closed != NULL)
155         {
156                 *connection_closed = False;
157         }
158
159         if (strnequal("\\PIPE\\", pipe_name, 6))
160         {
161                 pipe_name = &pipe_name[6];
162         }
163
164         if (strnequal("\\\\", srv_name, 2))
165         {
166                 srv_name = &srv_name[2];
167         }
168
169         for (i = 0; i < num_msrpcs; i++)
170         {
171                 char *ncacn_np_name = NULL;
172                 char *ncacn_np_srv_name = NULL;
173                 struct ncacn_np_use *c = msrpcs[i];
174                 vuser_key k;
175
176                 if (c == NULL || c->cli == NULL || c->cli->smb == NULL)
177                         continue;
178
179                 ncacn_np_name = c->cli->pipe_name;
180                 ncacn_np_srv_name = c->cli->smb->desthost;
181
182                 k = c->cli->smb->key;
183
184                 DEBUG(10, ("use_del[%d]: %s %s %s %s [%d,%x]\n",
185                            i, ncacn_np_name, ncacn_np_srv_name,
186                            c->cli->smb->user_name,
187                            c->cli->smb->domain, k.pid, k.vuid));
188
189                 if (strnequal("\\PIPE\\", ncacn_np_name, 6))
190                 {
191                         ncacn_np_name = &ncacn_np_name[6];
192                 }
193                 if (!strequal(ncacn_np_name, pipe_name))
194                 {
195                         continue;
196                 }
197                 if (strnequal("\\\\", ncacn_np_srv_name, 2))
198                 {
199                         ncacn_np_srv_name = &ncacn_np_srv_name[2];
200                 }
201                 if (!strequal(ncacn_np_srv_name, srv_name))
202                 {
203                         continue;
204                 }
205                 if (key->pid != k.pid || key->vuid != k.vuid)
206                 {
207                         continue;
208                 }
209                 /* decrement number of users */
210                 c->num_users--;
211                 DEBUG(10, ("idx: %i num_users now: %d\n",
212                            i, c->num_users));
213                 if (force_close || c->num_users == 0)
214                 {
215                         ncacn_np_use_free(c);
216                         msrpcs[i] = NULL;
217                         if (connection_closed != NULL)
218                         {
219                                 *connection_closed = True;
220                         }
221                 }
222                 return True;
223         }
224
225         return False;
226 }
227
228 /****************************************************************************
229 find client state.  server name, user name, domain name and password must all
230 match.
231 ****************************************************************************/
232 static struct ncacn_np_use *ncacn_np_find(const char *srv_name,
233                                           const char *pipe_name,
234                                           const vuser_key * key,
235                                           const struct ntuser_creds
236                                           *usr_creds, BOOL reuse)
237 {
238         int i;
239         const char *sv_name = srv_name;
240
241         if (strnequal("\\PIPE\\", pipe_name, 6))
242         {
243                 pipe_name = &pipe_name[6];
244         }
245
246         if (strnequal("\\\\", sv_name, 2))
247         {
248                 sv_name = &sv_name[2];
249         }
250
251         if (usr_creds != NULL)
252         {
253                 DEBUG(10, ("ncacn_np_find: %s %s %s",
254                            srv_name, usr_creds->user_name, usr_creds->domain));
255         }
256         else
257         {
258                 DEBUG(10,("ncacn_np_find: %s (no creds)\n", srv_name));
259         }
260
261         if (key != NULL)
262         {
263                 DEBUG(10, ("[%d,%x]", key->pid, key->vuid));
264         }
265         DEBUG(10, ("\n"));
266
267         for (i = 0; i < num_msrpcs; i++)
268         {
269                 char *ncacn_np_srv_name = NULL;
270                 struct ncacn_np_use *c = msrpcs[i];
271                 vuser_key k;
272
273                 char *ncacn_np_name = NULL;
274
275                 if (c == NULL || c->cli == NULL || c->cli->smb == NULL ||
276                     c->cli->smb->fd == -1 ||
277                     !c->cli->initialised)
278                 {
279                         continue;
280                 }
281
282                 ncacn_np_name = c->cli->pipe_name;
283                 ncacn_np_srv_name = c->cli->smb->desthost;
284
285                 k = c->cli->smb->key;
286
287                 DEBUG(10, ("ncacn_np_find[%d]: %s %s %s %s [%d,%x]\n",
288                            i, ncacn_np_name, ncacn_np_srv_name,
289                            c->cli->smb->user_name,
290                            c->cli->smb->domain, k.pid, k.vuid));
291
292                 if (strnequal("\\\\", ncacn_np_srv_name, 2))
293                 {
294                         ncacn_np_srv_name = &ncacn_np_srv_name[2];
295                 }
296
297                 if (strnequal("\\PIPE\\", ncacn_np_name, 6))
298                 {
299                         ncacn_np_name = &ncacn_np_name[6];
300                 }
301
302                 if (!strequal(ncacn_np_name, pipe_name))
303                 {
304                         continue;
305                 }
306                 if (!strequal(ncacn_np_srv_name, sv_name))
307                 {
308                         continue;
309                 }
310                 if (key != NULL && (k.pid != key->pid || k.vuid != key->vuid))
311                 {
312                         continue;
313                 }
314                 if (usr_creds == NULL)
315                 {
316                         if (reuse)
317                         {
318                                 return c;
319                         }
320                         else
321                         {
322                                 continue;
323                         }
324                 }
325                 if (!strequal
326                     (usr_creds->user_name, c->cli->smb->user_name))
327                 {
328                         continue;
329                 }
330                 if (!reuse
331                     && !pwd_compare((struct pwd_info *)&usr_creds->pwd, &c->cli->smb->pwd))
332                 {
333                         DEBUG(100, ("password doesn't match\n"));
334                         continue;
335                 }
336                 if (usr_creds->domain[0] == 0)
337                 {
338                         return c;
339                 }
340                 if (strequal(usr_creds->domain, c->cli->smb->domain))
341                 {
342                         return c;
343                 }
344         }
345
346         return NULL;
347 }
348
349
350 /****************************************************************************
351 initialise a msrpcent structure
352 ****************************************************************************/
353 struct ncacn_np *ncacn_np_initialise(struct ncacn_np *msrpc,
354                                      const vuser_key * key)
355 {
356         if (!msrpc)
357         {
358                 msrpc = (struct ncacn_np *)malloc(sizeof(*msrpc));
359                 if (!msrpc)
360                         return NULL;
361                 ZERO_STRUCTP(msrpc);
362         }
363
364         if (msrpc->initialised)
365         {
366                 ncacn_np_shutdown(msrpc);
367         }
368
369         ZERO_STRUCTP(msrpc);
370
371         msrpc->fnum = -1;
372         msrpc->initialised = 1;
373
374         return msrpc;
375 }
376
377 /****************************************************************************
378 create a new client state from user credentials
379 ****************************************************************************/
380 static struct ncacn_np_use *ncacn_np_use_get(const char *pipe_name,
381                                              const vuser_key * key)
382 {
383         struct ncacn_np_use *cli =
384                 (struct ncacn_np_use *)malloc(sizeof(*cli));
385
386         if (cli == NULL)
387         {
388                 return NULL;
389         }
390
391         memset(cli, 0, sizeof(*cli));
392
393         cli->cli = ncacn_np_initialise(NULL, key);
394
395         if (cli->cli == NULL)
396         {
397                 return NULL;
398         }
399
400         return cli;
401 }
402
403 /****************************************************************************
404 init client state
405 ****************************************************************************/
406 struct ncacn_np *ncacn_np_use_add(const char *pipe_name,
407                                   const vuser_key * key,
408                                   const char *srv_name,
409                                   const struct ntuser_creds *ntc,
410                                   BOOL reuse, BOOL *is_new_connection)
411 {
412         struct ncacn_np_use *cli;
413         DEBUG(10, ("ncacn_np_use_add: %s\n", pipe_name));
414
415         (*is_new_connection) = False;
416         cli = ncacn_np_find(srv_name, pipe_name, key, ntc, reuse);
417
418         if (cli != NULL)
419         {
420                 cli->num_users++;
421                 return cli->cli;
422         }
423
424         /*
425          * allocate
426          */
427
428         (*is_new_connection) = True;
429
430         cli = ncacn_np_use_get(pipe_name, key);
431
432         if (!ncacn_np_establish_connection
433             (cli->cli, srv_name, ntc, pipe_name, True))
434         {
435                 DEBUG(0, ("ncacn_np_use_add: connection failed\n"));
436                 cli->cli = NULL;
437                 ncacn_np_use_free(cli);
438                 return NULL;
439         }
440
441         if (key != NULL)
442         {
443                 cli->cli->smb->key = *key;
444         }
445         else
446         {
447                 cli->cli->smb->key.pid = sys_getpid();
448                 cli->cli->smb->key.vuid = UID_FIELD_INVALID;
449         }
450
451         add_ncacn_np_to_array(&num_msrpcs, &msrpcs, cli);
452         cli->num_users++;
453         return cli->cli;
454 }