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