54ecbf707e2f60a13b9162ef6a3341c70a20692f
[samba.git] / source3 / 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
87         DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
88                  pipe_name, pipes_open));
89         
90         /* not repeating pipe numbers makes it easier to track things in 
91            log files and prevents client bugs where pipe numbers are reused
92            over connection restarts */
93         if (next_pipe == 0) {
94                 next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
95         }
96
97         i = bitmap_find(bmap, next_pipe);
98
99         if (i == -1) {
100                 DEBUG(0,("ERROR! Out of pipe structures\n"));
101                 return NULL;
102         }
103
104         next_pipe = (i+1) % MAX_OPEN_PIPES;
105
106         for (p = Pipes; p; p = p->next)
107         {
108                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
109         }
110
111         p = (pipes_struct *)malloc(sizeof(*p));
112         if (!p) return NULL;
113
114         ZERO_STRUCTP(p);
115         DLIST_ADD(Pipes, p);
116
117         bitmap_set(bmap, i);
118         i += pipe_handle_offset;
119
120         pipes_open++;
121
122         p->pnum = i;
123
124         p->open = True;
125         p->device_state = 0;
126         p->priority = 0;
127         p->conn = conn;
128         p->vuid  = vuid;
129         
130         p->rhdr.data  = NULL;
131         p->rdata.data = NULL;
132         p->rhdr.offset  = 0;
133         p->rdata.offset = 0;
134         
135         p->file_offset     = 0;
136         p->hdr_offsets     = 0;
137         p->frag_len_left   = 0;
138         p->next_frag_start = 0;
139         
140         p->ntlmssp_validated = False;
141         p->ntlmssp_auth      = False;
142         
143         fstrcpy(p->name, pipe_name);
144         
145         DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
146                  pipe_name, i, pipes_open));
147         
148         chain_p = p;
149         
150         /* OVERWRITE p as a temp variable, to display all open pipes */ 
151         for (p = Pipes; p; p = p->next)
152         {
153                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
154         }
155
156         return chain_p;
157 }
158
159
160 /****************************************************************************
161  writes data to a pipe.
162
163  SERIOUSLY ALPHA CODE!
164  ****************************************************************************/
165 ssize_t write_pipe(pipes_struct *p, char *data, size_t n)
166 {
167         prs_struct pd;
168         struct mem_buf data_buf;
169
170         DEBUG(6,("write_pipe: %x", p->pnum));
171
172         DEBUG(6,("name: %s open: %s len: %d",
173                  p->name, BOOLSTR(p->open), n));
174
175         dump_data(50, data, n);
176
177         /* fake up a data buffer from the write_pipe data parameters */
178         mem_create(&data_buf, data, 0, n, 0, False);
179         data_buf.offset.start = 0;
180         data_buf.offset.end   = n;
181
182         /* fake up a parsing structure */
183         pd.data = &data_buf;
184         pd.align = 4;
185         pd.io = True;
186         pd.offset = 0;
187
188         return rpc_command(p, &pd) ? ((ssize_t)n) : -1;
189 }
190
191
192 /****************************************************************************
193  reads data from a pipe.
194
195  headers are interspersed with the data at regular intervals.  by the time
196  this function is called, the start of the data could possibly have been
197  read by an SMBtrans (file_offset != 0).
198
199  calling create_rpc_reply() here is a fudge.  the data should already
200  have been prepared into arrays of headers + data stream sections.
201
202  ****************************************************************************/
203 int read_pipe(pipes_struct *p, char *data, uint32 pos, int n)
204 {
205         int num = 0;
206         int len = 0;
207         uint32 hdr_num = 0;
208         int data_hdr_pos;
209         int data_pos;
210
211         DEBUG(6,("read_pipe: %x", p->pnum));
212
213         DEBUG(6,("name: %s open: %s pos: %d len: %d",
214                  p->name,
215                  BOOLSTR(p->open),
216                  pos, n));
217
218         if (!p || !p->open)
219         {
220                 DEBUG(6,("pipe not open\n"));
221                 return -1;              
222         }
223
224
225         if (p->rhdr.data == NULL || p->rhdr.data->data == NULL ||
226             p->rhdr.data->data_used == 0)
227         {
228                 return 0;
229         }
230
231         DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n",
232                  p, p->file_offset, n));
233         DEBUG(6,("read_pipe: frag_len_left: %d next_frag_start: %d\n",
234                  p->frag_len_left, p->next_frag_start));
235
236         /* the read request starts from where the SMBtrans2 left off. */
237         data_pos     = p->file_offset - p->hdr_offsets;
238         data_hdr_pos = p->file_offset;
239
240         len = mem_buf_len(p->rhdr.data);
241         num = len - (int)data_pos;
242         
243         DEBUG(6,("read_pipe: len: %d num: %d n: %d\n", len, num, n));
244         
245         if (num > n) num = n;
246         if (num <= 0)
247         {
248                 DEBUG(5,("read_pipe: 0 or -ve data length\n"));
249                 return 0;
250         }
251
252         if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST))
253         {
254                 /* intermediate fragment - possibility of another header */
255                 
256                 DEBUG(5,("read_pipe: frag_len: %d data_pos: %d data_hdr_pos: %d\n",
257                          p->hdr.frag_len, data_pos, data_hdr_pos));
258                 
259                 if (data_hdr_pos == p->next_frag_start)
260                 {
261                         DEBUG(6,("read_pipe: next fragment header\n"));
262
263                         /* this is subtracted from the total data bytes, later */
264                         hdr_num = 0x18;
265
266                         /* create and copy in a new header. */
267                         create_rpc_reply(p, data_pos, p->rdata.offset);
268                         mem_buf_copy(data, p->rhdr.data, 0, 0x18);
269                         
270                         data += 0x18;
271                         p->hdr_offsets += 0x18;
272                 }                       
273         }
274         
275         if (num < hdr_num)
276         {
277                 DEBUG(5,("read_pipe: warning - data read only part of a header\n"));
278         }
279
280         DEBUG(6,("read_pipe: adjusted data_pos: %d num-hdr_num: %d\n",
281                  data_pos, num - hdr_num));
282         mem_buf_copy(data, p->rhdr.data, data_pos, num - hdr_num);
283         
284         data_pos += num;
285         data_hdr_pos += num;
286         
287         if (hdr_num == 0x18 && num == 0x18)
288         {
289                 DEBUG(6,("read_pipe: just header read\n"));
290
291                 /* advance to the next fragment */
292                 p->frag_len_left -= 0x18; 
293         }
294         else if (data_hdr_pos == p->next_frag_start)
295         {
296                 DEBUG(6,("read_pipe: next fragment expected\n"));
297         }
298
299         p->file_offset  += num;
300         
301         return num;
302 }
303
304
305 /****************************************************************************
306   wait device state on a pipe.  exactly what this is for is unknown...
307 ****************************************************************************/
308 BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority)
309 {
310         if (p == NULL) return False;
311
312         if (p->open)
313         {
314                 DEBUG(3,("%s Setting pipe wait state priority=%x on pipe (name=%s)\n",
315                          timestring(), priority, p->name));
316
317                 p->priority = priority;
318                 
319                 return True;
320         } 
321
322         DEBUG(3,("%s Error setting pipe wait state priority=%x (name=%s)\n",
323                  timestring(), priority, p->name));
324         return False;
325 }
326
327
328 /****************************************************************************
329   set device state on a pipe.  exactly what this is for is unknown...
330 ****************************************************************************/
331 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
332 {
333         if (p == NULL) return False;
334
335         if (p->open) {
336                 DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s)\n",
337                          timestring(), device_state, p->name));
338
339                 p->device_state = device_state;
340                 
341                 return True;
342         } 
343
344         DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n",
345                  timestring(), device_state, p->name));
346         return False;
347 }
348
349
350 /****************************************************************************
351   close an rpc pipe
352 ****************************************************************************/
353 BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
354 {
355         if (!p) {
356                 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
357                 return False;
358         }
359
360         mem_buf_free(&(p->rdata.data));
361         mem_buf_free(&(p->rhdr .data));
362
363         bitmap_clear(bmap, p->pnum - pipe_handle_offset);
364
365         pipes_open--;
366
367         DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n", 
368                  p->name, p->pnum, pipes_open));  
369
370         DLIST_REMOVE(Pipes, p);
371
372         ZERO_STRUCTP(p);
373
374         free(p);
375         
376         return True;
377 }
378
379 /****************************************************************************
380   close an rpc pipe
381 ****************************************************************************/
382 pipes_struct *get_rpc_pipe_p(char *buf, int where)
383 {
384         int pnum = SVAL(buf,where);
385
386         if (chain_p) return chain_p;
387
388         return get_rpc_pipe(pnum);
389 }
390
391 /****************************************************************************
392   close an rpc pipe
393 ****************************************************************************/
394 pipes_struct *get_rpc_pipe(int pnum)
395 {
396         pipes_struct *p;
397
398         DEBUG(4,("search for pipe pnum=%x\n", pnum));
399
400         for (p=Pipes;p;p=p->next)
401         {
402                 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
403                           p->name, p->pnum, pipes_open));  
404         }
405
406         for (p=Pipes;p;p=p->next)
407         {
408                 if (p->pnum == pnum)
409                 {
410                         chain_p = p;
411                         return p;
412                 }
413         }
414
415         return NULL;
416 }
417