multiple dce/rpc PDUs failed to work after ntlmssp update was added.
[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->prev_pdu_file_offset = 0;
137         p->hdr_offsets     = 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: next_frag_start: %d\n",
234                  p->next_frag_start));
235
236         /* the read request starts from where the SMBtrans2 left off. */
237         data_hdr_pos = p->file_offset - p->prev_pdu_file_offset;
238         data_pos     = data_hdr_pos - p->hdr_offsets;
239
240         if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST))
241         {
242                 /* intermediate fragment - possibility of another header */
243                 
244                 DEBUG(5,("read_pipe: frag_len: %d data_pos: %d data_hdr_pos: %d\n",
245                          p->hdr.frag_len, data_pos, data_hdr_pos));
246                 
247                 if (data_hdr_pos == 0)
248                 {
249                         DEBUG(6,("read_pipe: next fragment header\n"));
250
251                         /* this is subtracted from the total data bytes, later */
252                         hdr_num = 0x18;
253                         p->hdr_offsets += 0x18;
254
255                         /* create and copy in a new header. */
256                         create_rpc_reply(p, p->file_offset - p->hdr_offsets, p->rdata.offset);
257                 }                       
258         }
259         
260         len = mem_buf_len(p->rhdr.data);
261         num = len - (int)data_pos;
262         
263         DEBUG(6,("read_pipe: len: %d num: %d n: %d\n", len, num, n));
264         
265         if (num > n) num = n;
266         if (num <= 0)
267         {
268                 DEBUG(5,("read_pipe: 0 or -ve data length\n"));
269                 return 0;
270         }
271
272         if (num < hdr_num)
273         {
274                 DEBUG(5,("read_pipe: warning - data read only part of a header\n"));
275         }
276
277         mem_buf_copy(data, p->rhdr.data, data_pos, num);
278         
279         data_pos += num;
280         data_hdr_pos += num;
281         p->file_offset  += num;
282         
283         if (hdr_num == 0x18 && num == 0x18)
284         {
285                 DEBUG(6,("read_pipe: just header read\n"));
286         }
287         else if (data_hdr_pos == p->next_frag_start)
288         {
289                 DEBUG(6,("read_pipe: next fragment expected\n"));
290                 p->prev_pdu_file_offset = p->file_offset;
291         }
292
293         return num;
294 }
295
296
297 /****************************************************************************
298   wait device state on a pipe.  exactly what this is for is unknown...
299 ****************************************************************************/
300 BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority)
301 {
302         if (p == NULL) return False;
303
304         if (p->open)
305         {
306                 DEBUG(3,("%s Setting pipe wait state priority=%x on pipe (name=%s)\n",
307                          timestring(), priority, p->name));
308
309                 p->priority = priority;
310                 
311                 return True;
312         } 
313
314         DEBUG(3,("%s Error setting pipe wait state priority=%x (name=%s)\n",
315                  timestring(), priority, p->name));
316         return False;
317 }
318
319
320 /****************************************************************************
321   set device state on a pipe.  exactly what this is for is unknown...
322 ****************************************************************************/
323 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
324 {
325         if (p == NULL) return False;
326
327         if (p->open) {
328                 DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s)\n",
329                          timestring(), device_state, p->name));
330
331                 p->device_state = device_state;
332                 
333                 return True;
334         } 
335
336         DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n",
337                  timestring(), device_state, p->name));
338         return False;
339 }
340
341
342 /****************************************************************************
343   close an rpc pipe
344 ****************************************************************************/
345 BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
346 {
347         if (!p) {
348                 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
349                 return False;
350         }
351
352         mem_buf_free(&(p->rdata.data));
353         mem_buf_free(&(p->rhdr .data));
354
355         bitmap_clear(bmap, p->pnum - pipe_handle_offset);
356
357         pipes_open--;
358
359         DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n", 
360                  p->name, p->pnum, pipes_open));  
361
362         DLIST_REMOVE(Pipes, p);
363
364         ZERO_STRUCTP(p);
365
366         free(p);
367         
368         return True;
369 }
370
371 /****************************************************************************
372   close an rpc pipe
373 ****************************************************************************/
374 pipes_struct *get_rpc_pipe_p(char *buf, int where)
375 {
376         int pnum = SVAL(buf,where);
377
378         if (chain_p) return chain_p;
379
380         return get_rpc_pipe(pnum);
381 }
382
383 /****************************************************************************
384   close an rpc pipe
385 ****************************************************************************/
386 pipes_struct *get_rpc_pipe(int pnum)
387 {
388         pipes_struct *p;
389
390         DEBUG(4,("search for pipe pnum=%x\n", pnum));
391
392         for (p=Pipes;p;p=p->next)
393         {
394                 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
395                           p->name, p->pnum, pipes_open));  
396         }
397
398         for (p=Pipes;p;p=p->next)
399         {
400                 if (p->pnum == pnum)
401                 {
402                         chain_p = p;
403                         return p;
404                 }
405         }
406
407         return NULL;
408 }
409