dce/rpc
[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-1997,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
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, 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_request() 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->frag_len_left = p->hdr.frag_len;
272                         p->next_frag_start += p->hdr.frag_len;
273                         p->hdr_offsets += 0x18;
274                 }                       
275         }
276         
277         if (num < hdr_num)
278         {
279                 DEBUG(5,("read_pipe: warning - data read only part of a header\n"));
280         }
281
282         DEBUG(6,("read_pipe: adjusted data_pos: %d num-hdr_num: %d\n",
283                  data_pos, num - hdr_num));
284         mem_buf_copy(data, p->rhdr.data, data_pos, num - hdr_num);
285         
286         data_pos += num;
287         data_hdr_pos += num;
288         
289         if (hdr_num == 0x18 && num == 0x18)
290         {
291                 DEBUG(6,("read_pipe: just header read\n"));
292
293                 /* advance to the next fragment */
294                 p->frag_len_left -= 0x18; 
295         }
296         else if (data_hdr_pos == p->next_frag_start)
297         {
298                 DEBUG(6,("read_pipe: next fragment expected\n"));
299         }
300
301         p->file_offset  += num;
302         
303         return num;
304 }
305
306
307 /****************************************************************************
308   wait device state on a pipe.  exactly what this is for is unknown...
309 ****************************************************************************/
310 BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority)
311 {
312         if (p == NULL) return False;
313
314         if (p->open)
315         {
316                 DEBUG(3,("%s Setting pipe wait state priority=%x on pipe (name=%s)\n",
317                          timestring(), priority, p->name));
318
319                 p->priority = priority;
320                 
321                 return True;
322         } 
323
324         DEBUG(3,("%s Error setting pipe wait state priority=%x (name=%s)\n",
325                  timestring(), priority, p->name));
326         return False;
327 }
328
329
330 /****************************************************************************
331   set device state on a pipe.  exactly what this is for is unknown...
332 ****************************************************************************/
333 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
334 {
335         if (p == NULL) return False;
336
337         if (p->open) {
338                 DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s)\n",
339                          timestring(), device_state, p->name));
340
341                 p->device_state = device_state;
342                 
343                 return True;
344         } 
345
346         DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n",
347                  timestring(), device_state, p->name));
348         return False;
349 }
350
351
352 /****************************************************************************
353   close an rpc pipe
354 ****************************************************************************/
355 BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
356 {
357         if (!p) {
358                 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
359                 return False;
360         }
361
362         mem_buf_free(&(p->rdata.data));
363         mem_buf_free(&(p->rhdr .data));
364
365         bitmap_clear(bmap, p->pnum - pipe_handle_offset);
366
367         pipes_open--;
368
369         DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n", 
370                  p->name, p->pnum, pipes_open));  
371
372         DLIST_REMOVE(Pipes, p);
373
374         ZERO_STRUCTP(p);
375
376         free(p);
377         
378         return True;
379 }
380
381 /****************************************************************************
382   close an rpc pipe
383 ****************************************************************************/
384 pipes_struct *get_rpc_pipe_p(char *buf, int where)
385 {
386         int pnum = SVAL(buf,where);
387
388         if (chain_p) return chain_p;
389
390         return get_rpc_pipe(pnum);
391 }
392
393 /****************************************************************************
394   close an rpc pipe
395 ****************************************************************************/
396 pipes_struct *get_rpc_pipe(int pnum)
397 {
398         pipes_struct *p;
399
400         DEBUG(4,("search for pipe pnum=%x\n", pnum));
401
402         for (p=Pipes;p;p=p->next)
403         {
404                 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
405                           p->name, p->pnum, pipes_open));  
406         }
407
408         for (p=Pipes;p;p=p->next)
409         {
410                 if (p->pnum == pnum)
411                 {
412                         chain_p = p;
413                         return p;
414                 }
415         }
416
417         return NULL;
418 }
419