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