a7e451e6da21b80ee74327ad2580d3d02804a9ee
[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
88         DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
89                  pipe_name, pipes_open));
90         
91         /* not repeating pipe numbers makes it easier to track things in 
92            log files and prevents client bugs where pipe numbers are reused
93            over connection restarts */
94         if (next_pipe == 0) {
95                 next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
96         }
97
98         i = bitmap_find(bmap, next_pipe);
99
100         if (i == -1) {
101                 DEBUG(0,("ERROR! Out of pipe structures\n"));
102                 return NULL;
103         }
104
105         next_pipe = (i+1) % MAX_OPEN_PIPES;
106
107         for (p = Pipes; p; p = p->next)
108         {
109                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
110         }
111
112         if (strequal(pipe_name, "lsarpc"))
113         {
114                 m = msrpc_use_add(pipe_name, NULL, False);
115                 if (m == NULL)
116                 {
117                         DEBUG(5,("open pipes: msrpc redirect failed\n"));
118                         return NULL;
119                 }
120         }
121
122         p = (pipes_struct *)malloc(sizeof(*p));
123         if (!p) return NULL;
124
125         ZERO_STRUCTP(p);
126         DLIST_ADD(Pipes, p);
127
128         bitmap_set(bmap, i);
129         i += pipe_handle_offset;
130
131         pipes_open++;
132
133         p->pnum = i;
134         p->m = m;
135
136         p->open = True;
137         p->device_state = 0;
138         p->priority = 0;
139         p->conn = conn;
140         p->vuid  = vuid;
141         
142         p->rhdr.data  = NULL;
143         p->rdata.data = NULL;
144         p->rhdr.offset  = 0;
145         p->rdata.offset = 0;
146         
147         p->file_offset     = 0;
148         p->prev_pdu_file_offset = 0;
149         p->hdr_offsets     = 0;
150         
151         p->ntlmssp_validated = False;
152         p->ntlmssp_auth      = False;
153         
154         fstrcpy(p->name, pipe_name);
155
156         DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
157                  pipe_name, i, pipes_open));
158         
159         chain_p = p;
160         
161         /* OVERWRITE p as a temp variable, to display all open pipes */ 
162         for (p = Pipes; p; p = p->next)
163         {
164                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
165         }
166
167         return chain_p;
168 }
169
170
171 /****************************************************************************
172  writes data to a pipe.
173
174  SERIOUSLY ALPHA CODE!
175  ****************************************************************************/
176 ssize_t write_pipe(pipes_struct *p, char *data, size_t n)
177 {
178         prs_struct pd;
179         struct mem_buf data_buf;
180
181         DEBUG(6,("write_pipe: %x", p->pnum));
182
183         DEBUG(6,("name: %s open: %s len: %d",
184                  p->name, BOOLSTR(p->open), n));
185
186         dump_data(50, data, n);
187
188         /* fake up a data buffer from the write_pipe data parameters */
189         mem_create(&data_buf, data, 0, n, 0, False);
190         data_buf.offset.start = 0;
191         data_buf.offset.end   = n;
192
193         /* fake up a parsing structure */
194         pd.data = &data_buf;
195         pd.align = 4;
196         pd.io = True;
197         pd.error = False;
198         pd.offset = 0;
199
200         return rpc_command(p, &pd) ? ((ssize_t)n) : -1;
201 }
202
203
204 /****************************************************************************
205  reads data from a pipe.
206
207  headers are interspersed with the data at regular intervals.  by the time
208  this function is called, the start of the data could possibly have been
209  read by an SMBtrans (file_offset != 0).
210
211  calling create_rpc_reply() here is a fudge.  the data should already
212  have been prepared into arrays of headers + data stream sections.
213
214  ****************************************************************************/
215 int read_pipe(pipes_struct *p, char *data, uint32 pos, int n)
216 {
217         int num = 0;
218         int pdu_len = 0;
219         uint32 hdr_num = 0;
220         int pdu_data_sent; /* amount of current pdu already sent */
221         int data_pos; /* entire rpc data sent - no headers, no auth verifiers */
222         int this_pdu_data_pos;
223
224         DEBUG(6,("read_pipe: %x name: %s open: %s pos: %d len: %d",
225                  p->pnum, p->name, BOOLSTR(p->open),
226                  pos, n));
227
228         if (!p || !p->open)
229         {
230                 DEBUG(6,("pipe not open\n"));
231                 return -1;              
232         }
233
234
235         if (p->rhdr.data == NULL || p->rhdr.data->data == NULL ||
236             p->rhdr.data->data_used == 0)
237         {
238                 return 0;
239         }
240
241         DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n",
242                  p, p->file_offset, n));
243
244         /* the read request starts from where the SMBtrans2 left off. */
245         data_pos = p->file_offset - p->hdr_offsets;
246         pdu_data_sent = p->file_offset - p->prev_pdu_file_offset;
247         this_pdu_data_pos = (pdu_data_sent == 0) ? 0 : (pdu_data_sent - 0x18);
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 pdu_data_sent: %d\n",
254                          p->hdr.frag_len, data_pos, pdu_data_sent));
255                 
256                 if (pdu_data_sent == 0)
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                         p->hdr_offsets += 0x18;
263                         data_pos -= 0x18;
264
265                         /* create and copy in a new header. */
266                         create_rpc_reply(p, data_pos, p->rdata.offset);
267                 }                       
268         }
269         
270         pdu_len = mem_buf_len(p->rhdr.data);
271         num = pdu_len - this_pdu_data_pos;
272         
273         DEBUG(6,("read_pipe: pdu_len: %d num: %d n: %d\n", pdu_len, num, n));
274         
275         if (num > n) num = n;
276         if (num <= 0)
277         {
278                 DEBUG(5,("read_pipe: 0 or -ve data length\n"));
279                 return 0;
280         }
281
282         if (num < hdr_num)
283         {
284                 DEBUG(5,("read_pipe: warning - data read only part of a header\n"));
285         }
286
287         mem_buf_copy(data, p->rhdr.data, pdu_data_sent, num);
288         
289         p->file_offset  += num;
290         pdu_data_sent  += num;
291         
292         if (hdr_num == 0x18 && num == 0x18)
293         {
294                 DEBUG(6,("read_pipe: just header read\n"));
295         }
296
297         if (pdu_data_sent == p->hdr.frag_len)
298         {
299                 DEBUG(6,("read_pipe: next fragment expected\n"));
300                 p->prev_pdu_file_offset = p->file_offset;
301         }
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         if (p->m != NULL)
375         {
376                 DEBUG(4,("closed msrpc redirect: "));
377                 if (msrpc_use_del(p->m->pipe_name, &p->m->usr, False, NULL))
378                 {
379                         DEBUG(4,("OK\n"));
380                 }
381                 else
382                 {
383                         DEBUG(4,("FAILED\n"));
384                 }
385         }
386
387         ZERO_STRUCTP(p);
388
389         free(p);
390         
391         return True;
392 }
393
394 /****************************************************************************
395   close an rpc pipe
396 ****************************************************************************/
397 pipes_struct *get_rpc_pipe_p(char *buf, int where)
398 {
399         int pnum = SVAL(buf,where);
400
401         if (chain_p) return chain_p;
402
403         return get_rpc_pipe(pnum);
404 }
405
406 /****************************************************************************
407   close an rpc pipe
408 ****************************************************************************/
409 pipes_struct *get_rpc_pipe(int pnum)
410 {
411         pipes_struct *p;
412
413         DEBUG(4,("search for pipe pnum=%x\n", pnum));
414
415         for (p=Pipes;p;p=p->next)
416         {
417                 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
418                           p->name, p->pnum, pipes_open));  
419         }
420
421         for (p=Pipes;p;p=p->next)
422         {
423                 if (p->pnum == pnum)
424                 {
425                         chain_p = p;
426                         return p;
427                 }
428         }
429
430         return NULL;
431 }
432