delineation between smb and msrpc more marked. smbd now constructs
[tprouty/samba.git] / source / rpc_server / srv_pipe_hnd.c
1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-1998,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
8  *  
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *  
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *  
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24
25 #include "includes.h"
26
27
28 #define PIPE            "\\PIPE\\"
29 #define PIPELEN         strlen(PIPE)
30
31 extern int DEBUGLEVEL;
32 static pipes_struct *chain_p;
33 static int pipes_open;
34
35 #ifndef MAX_OPEN_PIPES
36 #define MAX_OPEN_PIPES 64
37 #endif
38
39 static pipes_struct *Pipes;
40 static struct bitmap *bmap;
41
42 /* this must be larger than the sum of the open files and directories */
43 static int pipe_handle_offset;
44
45 /****************************************************************************
46  Set the pipe_handle_offset. Called from smbd/files.c
47 ****************************************************************************/
48
49 void set_pipe_handle_offset(int max_open_files)
50 {
51   if(max_open_files < 0x7000)
52     pipe_handle_offset = 0x7000;
53   else
54     pipe_handle_offset = max_open_files + 10; /* For safety. :-) */
55 }
56
57 /****************************************************************************
58   reset pipe chain handle number
59 ****************************************************************************/
60 void reset_chain_p(void)
61 {
62         chain_p = NULL;
63 }
64
65 /****************************************************************************
66   initialise pipe handle states...
67 ****************************************************************************/
68 void init_rpc_pipe_hnd(void)
69 {
70         bmap = bitmap_allocate(MAX_OPEN_PIPES);
71         if (!bmap) {
72                 exit_server("out of memory in init_rpc_pipe_hnd\n");
73         }
74 }
75
76
77 /****************************************************************************
78   find first available file slot
79 ****************************************************************************/
80 pipes_struct *open_rpc_pipe_p(char *pipe_name, 
81                               connection_struct *conn, uint16 vuid)
82 {
83         int i;
84         pipes_struct *p;
85         static int next_pipe;
86         struct msrpc_state *m = NULL;
87         struct rpcsrv_struct *l = NULL;
88         user_struct *vuser = get_valid_user_struct(vuid);
89         struct user_creds usr;
90
91         ZERO_STRUCT(usr);
92
93         DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
94                  pipe_name, pipes_open));
95         
96         if (vuser == NULL)
97         {
98                 DEBUG(4,("invalid vuid %d\n", vuid));
99                 return NULL;
100         }
101
102         /* set up unix credentials from the smb side, to feed over the pipe */
103         make_creds_unix(&usr.uxc, vuser->name, vuser->requested_name,
104                                       vuser->real_name, vuser->guest);
105         usr.ptr_uxc = 1;
106         make_creds_unix_sec(&usr.uxs, vuser->uid, vuser->gid,
107                                       vuser->n_groups, vuser->groups);
108         usr.ptr_uxs = 1;
109
110         /* set up nt credentials from the smb side, to feed over the pipe */
111         /* lkclXXXX todo!
112         make_creds_nt(&usr.ntc);
113         make_creds_nt_sec(&usr.nts);
114         */
115
116         /* not repeating pipe numbers makes it easier to track things in 
117            log files and prevents client bugs where pipe numbers are reused
118            over connection restarts */
119         if (next_pipe == 0)
120         {
121                 next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
122         }
123
124         i = bitmap_find(bmap, next_pipe);
125
126         if (i == -1) {
127                 DEBUG(0,("ERROR! Out of pipe structures\n"));
128                 return NULL;
129         }
130
131         next_pipe = (i+1) % MAX_OPEN_PIPES;
132
133         for (p = Pipes; p; p = p->next)
134         {
135                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
136         }
137
138         if (strequal(pipe_name, "lsarpc"))
139         {
140                 m = msrpc_use_add(pipe_name, &usr, False);
141                 if (m == NULL)
142                 {
143                         DEBUG(5,("open pipes: msrpc redirect failed\n"));
144                         return NULL;
145                 }
146         }
147         else
148         {
149                 l = malloc(sizeof(*l));
150                 if (l == NULL)
151                 {
152                         DEBUG(5,("open pipes: local msrpc malloc failed\n"));
153                         return NULL;
154                 }
155                 ZERO_STRUCTP(l);
156                 l->rhdr.data  = NULL;
157                 l->rdata.data = NULL;
158                 l->rhdr.offset  = 0;
159                 l->rdata.offset = 0;
160                 
161                 l->ntlmssp_validated = False;
162                 l->ntlmssp_auth      = False;
163
164                 memcpy(l->user_sess_key, vuser->user_sess_key,
165                        sizeof(l->user_sess_key));
166         }
167
168         p = (pipes_struct *)malloc(sizeof(*p));
169         if (!p) return NULL;
170
171         ZERO_STRUCTP(p);
172         DLIST_ADD(Pipes, p);
173
174         bitmap_set(bmap, i);
175         i += pipe_handle_offset;
176
177         pipes_open++;
178
179         p->pnum = i;
180         p->m = m;
181         p->l = l;
182
183         p->open = True;
184         p->device_state = 0;
185         p->priority = 0;
186         p->conn = conn;
187         p->vuid  = vuid;
188         
189         p->file_offset     = 0;
190         p->prev_pdu_file_offset = 0;
191         p->hdr_offsets     = 0;
192         
193         fstrcpy(p->name, pipe_name);
194
195         prs_init(&p->smb_pdu, 0, 4, 0, True);
196         prs_init(&p->rsmb_pdu, 0, 4, 0, False);
197
198         DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
199                  pipe_name, i, pipes_open));
200         
201         chain_p = p;
202         
203         /* OVERWRITE p as a temp variable, to display all open pipes */ 
204         for (p = Pipes; p; p = p->next)
205         {
206                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
207         }
208
209         return chain_p;
210 }
211
212
213 /****************************************************************************
214  writes data to a pipe.
215
216  SERIOUSLY ALPHA CODE!
217  ****************************************************************************/
218 ssize_t write_pipe(pipes_struct *p, char *data, size_t n)
219 {
220         DEBUG(6,("write_pipe: %x", p->pnum));
221         DEBUG(6,("name: %s open: %s len: %d",
222                  p->name, BOOLSTR(p->open), n));
223
224         dump_data(50, data, n);
225
226         return rpc_to_smb(p, data, n) ? ((ssize_t)n) : -1;
227 }
228
229
230 /****************************************************************************
231  reads data from a pipe.
232
233  headers are interspersed with the data at regular intervals.  by the time
234  this function is called, the start of the data could possibly have been
235  read by an SMBtrans (file_offset != 0).
236
237  calling create_rpc_reply() here is a fudge.  the data should already
238  have been prepared into arrays of headers + data stream sections.
239
240  ****************************************************************************/
241 int read_pipe(pipes_struct *p, char *data, uint32 pos, int n)
242 {
243         int num = 0;
244         int pdu_len = 0;
245         uint32 hdr_num = 0;
246         int pdu_data_sent; /* amount of current pdu already sent */
247         int data_pos; /* entire rpc data sent - no headers, no auth verifiers */
248         int this_pdu_data_pos;
249
250         DEBUG(6,("read_pipe: %x name: %s open: %s pos: %d len: %d",
251                  p->pnum, p->name, BOOLSTR(p->open),
252                  pos, n));
253
254         if (!p || !p->open)
255         {
256                 DEBUG(6,("pipe not open\n"));
257                 return -1;              
258         }
259
260
261         if (p->rsmb_pdu.data == NULL || p->rsmb_pdu.data->data == NULL ||
262             p->rsmb_pdu.data->data_used == 0)
263         {
264                 return 0;
265         }
266
267         DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n",
268                  p, p->file_offset, n));
269
270         /* the read request starts from where the SMBtrans2 left off. */
271         data_pos = p->file_offset - p->hdr_offsets;
272         pdu_data_sent = p->file_offset - p->prev_pdu_file_offset;
273         this_pdu_data_pos = (pdu_data_sent == 0) ? 0 : (pdu_data_sent - 0x18);
274
275         if (!IS_BITS_SET_ALL(p->l->hdr.flags, RPC_FLG_LAST))
276         {
277                 /* intermediate fragment - possibility of another header */
278                 
279                 DEBUG(5,("read_pipe: frag_len: %d data_pos: %d pdu_data_sent: %d\n",
280                          p->l->hdr.frag_len, data_pos, pdu_data_sent));
281                 
282                 if (pdu_data_sent == 0)
283                 {
284                         DEBUG(6,("read_pipe: next fragment header\n"));
285
286                         /* this is subtracted from the total data bytes, later */
287                         hdr_num = 0x18;
288                         p->hdr_offsets += 0x18;
289                         data_pos -= 0x18;
290
291                         /* create and copy in a new header. */
292                         create_rpc_reply(p->l, data_pos);
293                 }                       
294         }
295         
296         pdu_len = mem_buf_len(p->rsmb_pdu.data);
297         num = pdu_len - this_pdu_data_pos;
298         
299         DEBUG(6,("read_pipe: pdu_len: %d num: %d n: %d\n", pdu_len, num, n));
300         
301         if (num > n) num = n;
302         if (num <= 0)
303         {
304                 DEBUG(5,("read_pipe: 0 or -ve data length\n"));
305                 return 0;
306         }
307
308         if (num < hdr_num)
309         {
310                 DEBUG(5,("read_pipe: warning - data read only part of a header\n"));
311         }
312
313         mem_buf_copy(data, p->rsmb_pdu.data, pdu_data_sent, num);
314         
315         p->file_offset  += num;
316         pdu_data_sent  += num;
317         
318         if (hdr_num == 0x18 && num == 0x18)
319         {
320                 DEBUG(6,("read_pipe: just header read\n"));
321         }
322
323         if (pdu_data_sent == p->l->hdr.frag_len)
324         {
325                 DEBUG(6,("read_pipe: next fragment expected\n"));
326                 p->prev_pdu_file_offset = p->file_offset;
327         }
328
329         return num;
330 }
331
332
333 /****************************************************************************
334   wait device state on a pipe.  exactly what this is for is unknown...
335 ****************************************************************************/
336 BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority)
337 {
338         if (p == NULL) return False;
339
340         if (p->open)
341         {
342                 DEBUG(3,("%s Setting pipe wait state priority=%x on pipe (name=%s)\n",
343                          timestring(), priority, p->name));
344
345                 p->priority = priority;
346                 
347                 return True;
348         } 
349
350         DEBUG(3,("%s Error setting pipe wait state priority=%x (name=%s)\n",
351                  timestring(), priority, p->name));
352         return False;
353 }
354
355
356 /****************************************************************************
357   set device state on a pipe.  exactly what this is for is unknown...
358 ****************************************************************************/
359 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
360 {
361         if (p == NULL) return False;
362
363         if (p->open) {
364                 DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s)\n",
365                          timestring(), device_state, p->name));
366
367                 p->device_state = device_state;
368                 
369                 return True;
370         } 
371
372         DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n",
373                  timestring(), device_state, p->name));
374         return False;
375 }
376
377
378 /****************************************************************************
379   close an rpc pipe
380 ****************************************************************************/
381 BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
382 {
383         if (!p) {
384                 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
385                 return False;
386         }
387
388         mem_buf_free(&(p->smb_pdu .data));
389         mem_buf_free(&(p->rsmb_pdu.data));
390
391         bitmap_clear(bmap, p->pnum - pipe_handle_offset);
392
393         pipes_open--;
394
395         DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n", 
396                  p->name, p->pnum, pipes_open));  
397
398         DLIST_REMOVE(Pipes, p);
399
400         if (p->m != NULL)
401         {
402                 DEBUG(4,("closed msrpc redirect: "));
403                 if (msrpc_use_del(p->m->pipe_name, &p->m->usr, False, NULL))
404                 {
405                         DEBUG(4,("OK\n"));
406                 }
407                 else
408                 {
409                         DEBUG(4,("FAILED\n"));
410                 }
411         }
412
413         if (p->l != NULL)
414         {
415                 DEBUG(4,("closed msrpc local: OK\n"));
416
417                 mem_free_data(p->l->rdata  .data);
418                 rpcsrv_free_temp(p->l);
419
420                 free(p->l);
421         }
422
423         ZERO_STRUCTP(p);
424         free(p);
425         
426         return True;
427 }
428
429 /****************************************************************************
430   close an rpc pipe
431 ****************************************************************************/
432 pipes_struct *get_rpc_pipe_p(char *buf, int where)
433 {
434         int pnum = SVAL(buf,where);
435
436         if (chain_p) return chain_p;
437
438         return get_rpc_pipe(pnum);
439 }
440
441 /****************************************************************************
442   close an rpc pipe
443 ****************************************************************************/
444 pipes_struct *get_rpc_pipe(int pnum)
445 {
446         pipes_struct *p;
447
448         DEBUG(4,("search for pipe pnum=%x\n", pnum));
449
450         for (p=Pipes;p;p=p->next)
451         {
452                 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
453                           p->name, p->pnum, pipes_open));  
454         }
455
456         for (p=Pipes;p;p=p->next)
457         {
458                 if (p->pnum == pnum)
459                 {
460                         chain_p = p;
461                         return p;
462                 }
463         }
464
465         return NULL;
466 }
467