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