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