simple mods to add msrpc pipe redirection. default behaviour: fall back
[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  *  Copyright (C) Jeremy Allison                                    1999.
9  *  
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25
26 #include "includes.h"
27
28
29 #define PIPE            "\\PIPE\\"
30 #define PIPELEN         strlen(PIPE)
31
32 extern int DEBUGLEVEL;
33 static pipes_struct *chain_p;
34 static int pipes_open;
35
36 #ifndef MAX_OPEN_PIPES
37 #define MAX_OPEN_PIPES 64
38 #endif
39
40 static pipes_struct *Pipes;
41 static struct bitmap *bmap;
42
43 /* this must be larger than the sum of the open files and directories */
44 static int pipe_handle_offset;
45
46 /****************************************************************************
47  Set the pipe_handle_offset. Called from smbd/files.c
48 ****************************************************************************/
49
50 void set_pipe_handle_offset(int max_open_files)
51 {
52   if(max_open_files < 0x7000)
53     pipe_handle_offset = 0x7000;
54   else
55     pipe_handle_offset = max_open_files + 10; /* For safety. :-) */
56 }
57
58 /****************************************************************************
59  Reset pipe chain handle number.
60 ****************************************************************************/
61 void reset_chain_p(void)
62 {
63         chain_p = NULL;
64 }
65
66 /****************************************************************************
67  Initialise pipe handle states.
68 ****************************************************************************/
69
70 void init_rpc_pipe_hnd(void)
71 {
72         bmap = bitmap_allocate(MAX_OPEN_PIPES);
73         if (!bmap)
74                 exit_server("out of memory in init_rpc_pipe_hnd\n");
75 }
76
77 /****************************************************************************
78  Initialise an outgoing packet.
79 ****************************************************************************/
80
81 BOOL pipe_init_outgoing_data( pipes_struct *p)
82 {
83
84         memset(p->current_pdu, '\0', sizeof(p->current_pdu));
85
86         /* Free any memory in the current return data buffer. */
87         prs_mem_free(&p->rdata);
88
89         /*
90          * Initialize the outgoing RPC data buffer.
91          * we will use this as the raw data area for replying to rpc requests.
92          */     
93         if(!prs_init(&p->rdata, 1024, 4, MARSHALL)) {
94                 DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));
95                 return False;
96         }
97
98         /* Reset the offset counters. */
99         p->data_sent_length = 0;
100         p->current_pdu_len = 0;
101         p->current_pdu_sent = 0;
102
103         return True;
104 }
105
106 /****************************************************************************
107  Find first available pipe slot.
108 ****************************************************************************/
109
110 pipes_struct *open_rpc_pipe_p(char *pipe_name, 
111                               connection_struct *conn, uint16 vuid)
112 {
113         int i;
114         pipes_struct *p;
115         static int next_pipe;
116         struct msrpc_state *m = NULL;
117         user_struct *vuser = get_valid_user_struct(vuid);
118         struct user_creds usr;
119
120         ZERO_STRUCT(usr);
121
122         DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
123                  pipe_name, pipes_open));
124         
125         if (vuser == NULL)
126         {
127                 DEBUG(4,("invalid vuid %d\n", vuid));
128                 return NULL;
129         }
130
131         /* set up unix credentials from the smb side, to feed over the pipe */
132         make_creds_unix(&usr.uxc, vuser->name, vuser->requested_name,
133                                       vuser->real_name, vuser->guest);
134         usr.ptr_uxc = 1;
135         make_creds_unix_sec(&usr.uxs, vuser->uid, vuser->gid,
136                                       vuser->n_groups, vuser->groups);
137         usr.ptr_uxs = 1;
138
139         /* set up nt credentials from the smb side, to feed over the pipe */
140         /* lkclXXXX todo!
141         make_creds_nt(&usr.ntc);
142         make_creds_nt_sec(&usr.nts);
143         */
144
145         become_root(False); /* to connect to pipe */
146         m = msrpc_use_add(pipe_name, &usr, False);
147         unbecome_root(False);
148
149         if (m == NULL)
150         {
151                 DEBUG(10,("open pipes: msrpc redirect failed - go local.\n"));
152         }
153
154         /* not repeating pipe numbers makes it easier to track things in 
155            log files and prevents client bugs where pipe numbers are reused
156            over connection restarts */
157         if (next_pipe == 0)
158                 next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
159
160         i = bitmap_find(bmap, next_pipe);
161
162         if (i == -1) {
163                 DEBUG(0,("ERROR! Out of pipe structures\n"));
164                 return NULL;
165         }
166
167         next_pipe = (i+1) % MAX_OPEN_PIPES;
168
169         for (p = Pipes; p; p = p->next)
170                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
171
172         p = (pipes_struct *)malloc(sizeof(*p));
173         if (!p)
174                 return NULL;
175
176         ZERO_STRUCTP(p);
177
178         /*
179          * Initialize the RPC and PDU data buffers with no memory.
180          */     
181         prs_init(&p->rdata, 0, 4, MARSHALL);
182         
183         DLIST_ADD(Pipes, p);
184
185         bitmap_set(bmap, i);
186         i += pipe_handle_offset;
187
188         pipes_open++;
189
190         p->pnum = i;
191
192         p->open = True;
193         p->device_state = 0;
194         p->priority = 0;
195         p->conn = conn;
196         p->vuid  = vuid;
197         
198         p->m = m;
199
200         p->max_trans_reply = 0;
201         
202         p->ntlmssp_chal_flags = 0;
203         p->ntlmssp_auth_validated = False;
204         p->ntlmssp_auth_requested = False;
205
206         p->current_pdu_len = 0;
207         p->current_pdu_sent = 0;
208         p->data_sent_length = 0;
209
210         p->uid = (uid_t)-1;
211         p->gid = (gid_t)-1;
212         
213         fstrcpy(p->name, pipe_name);
214         
215         DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
216                  pipe_name, i, pipes_open));
217         
218         chain_p = p;
219         
220         /* OVERWRITE p as a temp variable, to display all open pipes */ 
221         for (p = Pipes; p; p = p->next)
222                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
223
224         return chain_p;
225 }
226
227
228 /****************************************************************************
229  Accepts incoming data on an rpc pipe.
230
231  This code is probably incorrect at the moment. The problem is
232  that the rpc request shouldn't really be executed until all the
233  data needed for it is received. This currently assumes that each
234  SMBwrite or SMBwriteX contains all the data needed for an rpc
235  request. JRA.
236  ****************************************************************************/
237
238 ssize_t write_to_pipe(pipes_struct *p, char *data, size_t n)
239 {
240         DEBUG(6,("write_to_pipe: %x", p->pnum));
241
242         DEBUG(6,("name: %s open: %s len: %d",
243                  p->name, BOOLSTR(p->open), (int)n));
244
245         dump_data(50, data, n);
246
247         return rpc_command(p, data, (int)n) ? ((ssize_t)n) : -1;
248 }
249
250
251 /****************************************************************************
252  Replyies to a request to read data from a pipe.
253
254  Headers are interspersed with the data at PDU intervals. By the time
255  this function is called, the start of the data could possibly have been
256  read by an SMBtrans (file_offset != 0).
257
258  Calling create_rpc_reply() here is a hack. The data should already
259  have been prepared into arrays of headers + data stream sections.
260
261  ****************************************************************************/
262
263 int read_from_pipe(pipes_struct *p, char *data, int n)
264 {
265         uint32 pdu_remaining = 0;
266         int data_returned = 0;
267
268         if (!p || !p->open) {
269                 DEBUG(0,("read_from_pipe: pipe not open\n"));
270                 return -1;              
271         }
272
273         DEBUG(6,("read_from_pipe: %x", p->pnum));
274
275         DEBUG(6,("name: %s len: %d\n", p->name, n));
276
277         /*
278          * We cannot return more than one PDU length per
279          * read request.
280          */
281
282         if(n > MAX_PDU_FRAG_LEN) {
283                 DEBUG(0,("read_from_pipe: loo large read (%d) requested on pipe %s. We can \
284 only service %d sized reads.\n", n, p->name, MAX_PDU_FRAG_LEN ));
285                 return -1;
286         }
287
288         /*
289          * Determine if there is still data to send in the
290          * pipe PDU buffer. Always send this first. Never
291          * send more than is left in the current PDU. The
292          * client should send a new read request for a new
293          * PDU.
294          */
295
296         if((pdu_remaining = p->current_pdu_len - p->current_pdu_sent) > 0) {
297                 data_returned = MIN(n, pdu_remaining);
298
299                 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, current_pdu_sent = %u \
300 returning %d bytes.\n", p->name, (unsigned int)p->current_pdu_len, 
301                         (unsigned int)p->current_pdu_sent, (int)data_returned));
302
303                 memcpy( data, &p->current_pdu[p->current_pdu_sent], (size_t)data_returned);
304                 p->current_pdu_sent += (uint32)data_returned;
305                 return data_returned;
306         }
307
308         /*
309          * At this point p->current_pdu_len == p->current_pdu_sent (which
310          * may of course be zero if this is the first return fragment.
311          */
312
313         DEBUG(10,("read_from_pipe: %s: data_sent_length = %u, prs_offset(&p->rdata) = %u.\n",
314                 p->name, (unsigned int)p->data_sent_length, (unsigned int)prs_offset(&p->rdata) ));
315
316         if(p->data_sent_length >= prs_offset(&p->rdata)) {
317                 /*
318                  * We have sent all possible data. Return 0.
319                  */
320                 return 0;
321         }
322
323         /*
324          * We need to create a new PDU from the data left in p->rdata.
325          * Create the header/data/footers. This also sets up the fields
326          * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
327          * and stores the outgoing PDU in p->current_pdu.
328          */
329
330         if(!create_next_pdu(p)) {
331                 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n",
332                          p->name));
333                 return -1;
334         }
335
336         data_returned = MIN(n, p->current_pdu_len);
337
338         memcpy( data, p->current_pdu, (size_t)data_returned);
339         p->current_pdu_sent += (uint32)data_returned;
340         return data_returned;
341 }
342
343 /****************************************************************************
344  Wait device state on a pipe. Exactly what this is for is unknown...
345 ****************************************************************************/
346
347 BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority)
348 {
349         if (p == NULL)
350                 return False;
351
352         if (p->open) {
353                 DEBUG(3,("wait_rpc_pipe_hnd_state: Setting pipe wait state priority=%x on pipe (name=%s)\n",
354                          priority, p->name));
355
356                 p->priority = priority;
357                 
358                 return True;
359         } 
360
361         DEBUG(3,("wait_rpc_pipe_hnd_state: Error setting pipe wait state priority=%x (name=%s)\n",
362                  priority, p->name));
363         return False;
364 }
365
366
367 /****************************************************************************
368  Set device state on a pipe. Exactly what this is for is unknown...
369 ****************************************************************************/
370
371 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
372 {
373         if (p == NULL)
374                 return False;
375
376         if (p->open) {
377                 DEBUG(3,("set_rpc_pipe_hnd_state: Setting pipe device state=%x on pipe (name=%s)\n",
378                          device_state, p->name));
379
380                 p->device_state = device_state;
381                 
382                 return True;
383         } 
384
385         DEBUG(3,("set_rpc_pipe_hnd_state: Error setting pipe device state=%x (name=%s)\n",
386                  device_state, p->name));
387         return False;
388 }
389
390
391 /****************************************************************************
392  Close an rpc pipe.
393 ****************************************************************************/
394
395 BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
396 {
397         if (!p) {
398                 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
399                 return False;
400         }
401
402         prs_mem_free(&p->rdata);
403
404         bitmap_clear(bmap, p->pnum - pipe_handle_offset);
405
406         pipes_open--;
407
408         DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n", 
409                  p->name, p->pnum, pipes_open));  
410
411         if (p->m != NULL)
412         {
413                 DEBUG(4,("closed msrpc redirect: "));
414                 if (msrpc_use_del(p->m->pipe_name, &p->m->usr, False, NULL))
415                 {
416                         DEBUG(4,("OK\n"));
417                 }
418                 else
419                 {
420                         DEBUG(4,("FAILED\n"));
421                 }
422         }
423
424         DLIST_REMOVE(Pipes, p);
425
426         ZERO_STRUCTP(p);
427
428         free(p);
429         
430         return True;
431 }
432
433 /****************************************************************************
434  Find an rpc pipe given a pipe handle in a buffer and an offset.
435 ****************************************************************************/
436
437 pipes_struct *get_rpc_pipe_p(char *buf, int where)
438 {
439         int pnum = SVAL(buf,where);
440
441         if (chain_p)
442                 return chain_p;
443
444         return get_rpc_pipe(pnum);
445 }
446
447 /****************************************************************************
448  Find an rpc pipe given a pipe handle.
449 ****************************************************************************/
450
451 pipes_struct *get_rpc_pipe(int pnum)
452 {
453         pipes_struct *p;
454
455         DEBUG(4,("search for pipe pnum=%x\n", pnum));
456
457         for (p=Pipes;p;p=p->next)
458                 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
459                           p->name, p->pnum, pipes_open));  
460
461         for (p=Pipes;p;p=p->next) {
462                 if (p->pnum == pnum) {
463                         chain_p = p;
464                         return p;
465                 }
466         }
467
468         return NULL;
469 }