- fix a bug handling readraw packets that caused the timeout to be 30
[kai/samba.git] / source3 / smbd / pipes.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Pipe SMB reply routines
5    Copyright (C) Andrew Tridgell 1992-1995
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 /*
22    This file handles reply_ calls on named pipes that the server
23    makes to handle specific protocols
24 */
25
26
27 #include "includes.h"
28 #include "trans2.h"
29
30 #define PIPE            "\\PIPE\\"
31 #define PIPELEN         strlen(PIPE)
32
33 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
34
35 /* look in server.c for some explanation of these variables */
36 extern int Protocol;
37 extern int DEBUGLEVEL;
38 extern int maxxmit;
39 extern int chain_fnum;
40 extern char magic_char;
41 extern connection_struct Connections[];
42 extern files_struct Files[];
43 extern BOOL case_sensitive;
44 extern pstring sesssetup_user;
45 extern int Client;
46
47 /* this macro should always be used to extract an fnum (smb_fid) from
48 a packet to ensure chaining works correctly */
49 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
50
51 char * known_pipes [] =
52 {
53   "lsarpc",
54   NULL
55 };
56
57 /****************************************************************************
58   reply to an open and X on a named pipe
59
60   In fact what we do is to open a regular file with the same name in
61   /tmp. This can then be closed as normal. Reading and writing won't
62   make much sense, but will do *something*. The real reason for this
63   support is to be able to do transactions on them (well, on lsarpc
64   for domain login purposes...).
65
66   This code is basically stolen from reply_open_and_X with some
67   wrinkles to handle pipes.
68 ****************************************************************************/
69 int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
70 {
71   pstring fname;
72   int cnum = SVAL(inbuf,smb_tid);
73   int fnum = -1;
74   int smb_mode = SVAL(inbuf,smb_vwv3);
75   int smb_attr = SVAL(inbuf,smb_vwv5);
76 #if 0
77   int open_flags = SVAL(inbuf,smb_vwv2);
78   int smb_sattr = SVAL(inbuf,smb_vwv4); 
79   uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
80 #endif
81   int smb_ofun = SVAL(inbuf,smb_vwv8);
82   int unixmode;
83   int size=0,fmode=0,mtime=0,rmode=0;
84   struct stat sbuf;
85   int smb_action = 0;
86   int i;
87
88   /* XXXX we need to handle passed times, sattr and flags */
89   strcpy(fname,smb_buf(inbuf));
90
91   /* If the name doesn't start \PIPE\ then this is directed */
92   /* at a mailslot or something we really, really don't understand, */
93   /* not just something we really don't understand. */
94   if ( strncmp(fname,PIPE,PIPELEN) != 0 )
95     return(ERROR(ERRSRV,ERRaccess));
96
97   DEBUG(4,("Opening pipe %s.\n", fname));
98
99   /* Strip \PIPE\ off the name. */
100   strcpy(fname,smb_buf(inbuf) + PIPELEN);
101
102   /* See if it is one we want to handle. */
103   for( i = 0; known_pipes[i] ; i++ )
104     if( strcmp(fname,known_pipes[i]) == 0 )
105       break;
106
107   if ( known_pipes[i] == NULL )
108     return(ERROR(ERRSRV,ERRaccess));
109
110   /* Known pipes arrive with DIR attribs. Remove it so a regular file */
111   /* can be opened and add it in after the open. */
112   DEBUG(3,("Known pipe %s opening.\n",fname));
113   smb_attr &= ~aDIR;
114   Connections[cnum].read_only = 0;
115   smb_ofun |= 0x10;             /* Add Create it not exists flag */
116
117   unix_convert(fname,cnum);
118     
119   fnum = find_free_file();
120   if (fnum < 0)
121     return(ERROR(ERRSRV,ERRnofids));
122
123   if (!check_name(fname,cnum))
124     return(UNIXERROR(ERRDOS,ERRnoaccess));
125
126   unixmode = unix_mode(cnum,smb_attr);
127       
128   open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
129                    &rmode,&smb_action);
130       
131   if (!Files[fnum].open)
132     return(UNIXERROR(ERRDOS,ERRnoaccess));
133
134   if (fstat(Files[fnum].fd,&sbuf) != 0) {
135     close_file(fnum);
136     return(ERROR(ERRDOS,ERRnoaccess));
137   }
138
139   size = sbuf.st_size;
140   fmode = dos_mode(cnum,fname,&sbuf);
141   mtime = sbuf.st_mtime;
142   if (fmode & aDIR) {
143     close_file(fnum);
144     return(ERROR(ERRDOS,ERRnoaccess));
145   }
146
147   /* Prepare the reply */
148   set_message(outbuf,15,0,True);
149
150   /* Put things back the way they were. */
151   Connections[cnum].read_only = 1;
152
153   /* Mark the opened file as an existing named pipe in message mode. */
154   SSVAL(outbuf,smb_vwv9,2);
155   SSVAL(outbuf,smb_vwv10,0xc700);
156   if (rmode == 2)
157   {
158     DEBUG(4,("Resetting open result to open from create.\n"));
159     rmode = 1;
160   }
161
162   SSVAL(outbuf,smb_vwv2,fnum);
163   SSVAL(outbuf,smb_vwv3,fmode);
164   put_dos_date3(outbuf,smb_vwv4,mtime);
165   SIVAL(outbuf,smb_vwv6,size);
166   SSVAL(outbuf,smb_vwv8,rmode);
167   SSVAL(outbuf,smb_vwv11,smb_action);
168
169   chain_fnum = fnum;
170
171   DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n",
172            fname, fnum, Files[fnum].name));
173   
174   return chain_reply(inbuf,outbuf,length,bufsize);
175 }
176
177
178 /****************************************************************************
179  api_LsarpcSNPHS
180
181  SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here,
182  so just blithely return True. This is really only for NT domain stuff,
183  we we're only handling that - don't assume Samba now does complete
184  named pipe handling.
185 ****************************************************************************/
186 BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
187                      int mdrcnt,int mprcnt,
188                      char **rdata,char **rparam,
189                      int *rdata_len,int *rparam_len)
190 {
191   uint16 id;
192
193   id = param[0] + (param[1] << 8);
194   DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
195   return(True);
196 }
197
198
199 /****************************************************************************
200  api_LsarpcTNP
201
202  TransactNamedPipe on \PIPE\lsarpc.
203 ****************************************************************************/
204 static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
205 {
206   uint32 dword1, dword2;
207   char pname[] = "\\PIPE\\lsass";
208
209   /* All kinds of mysterious numbers here */
210   *rdata_len = 68;
211   *rdata = REALLOC(*rdata,*rdata_len);
212
213   dword1 = IVAL(data,0xC);
214   dword2 = IVAL(data,0x10);
215
216   SIVAL(*rdata,0,0xc0005);
217   SIVAL(*rdata,4,0x10);
218   SIVAL(*rdata,8,0x44);
219   SIVAL(*rdata,0xC,dword1);
220   
221   SIVAL(*rdata,0x10,dword2);
222   SIVAL(*rdata,0x14,0x15);
223   SSVAL(*rdata,0x18,sizeof(pname));
224   strcpy(*rdata + 0x1a,pname);
225   SIVAL(*rdata,0x28,1);
226   memcpy(*rdata + 0x30, data + 0x34, 0x14);
227 }
228
229 static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
230 {
231   uint32 dword1;
232
233   /* All kinds of mysterious numbers here */
234   *rdata_len = 48;
235   *rdata = REALLOC(*rdata,*rdata_len);
236
237   dword1 = IVAL(data,0xC);
238
239   SIVAL(*rdata,0,0x03020005);
240   SIVAL(*rdata,4,0x10);
241   SIVAL(*rdata,8,0x30);
242   SIVAL(*rdata,0xC,dword1);
243   SIVAL(*rdata,0x10,0x18);
244   SIVAL(*rdata,0x1c,0x44332211);
245   SIVAL(*rdata,0x20,0x88776655);
246   SIVAL(*rdata,0x24,0xCCBBAA99);
247   SIVAL(*rdata,0x28,0x11FFEEDD);
248 }
249
250 static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
251 {
252   uint32 dword1;
253   uint16 word1;
254   char * workgroup = lp_workgroup();
255   int wglen = strlen(workgroup);
256   int i;
257
258   /* All kinds of mysterious numbers here */
259   *rdata_len = 90 + 2 * wglen;
260   *rdata = REALLOC(*rdata,*rdata_len);
261
262   dword1 = IVAL(data,0xC);
263   word1 = SVAL(data,0x2C);
264
265   SIVAL(*rdata,0,0x03020005);
266   SIVAL(*rdata,4,0x10);
267   SIVAL(*rdata,8,0x60);
268   SIVAL(*rdata,0xC,dword1);
269   SIVAL(*rdata,0x10,0x48);
270   SSVAL(*rdata,0x18,0x5988);    /* This changes */
271   SSVAL(*rdata,0x1A,0x15);
272   SSVAL(*rdata,0x1C,word1);
273   SSVAL(*rdata,0x20,6);
274   SSVAL(*rdata,0x22,8);
275   SSVAL(*rdata,0x24,0x8E8);     /* So does this */
276   SSVAL(*rdata,0x26,0x15);
277   SSVAL(*rdata,0x28,0x4D48);    /* And this */
278   SSVAL(*rdata,0x2A,0x15);
279   SIVAL(*rdata,0x2C,4);
280   SIVAL(*rdata,0x34,wglen);
281   for ( i = 0 ; i < wglen ; i++ )
282     (*rdata)[0x38 + i * 2] = workgroup[i];
283    
284   /* Now fill in the rest */
285   i = 0x38 + wglen * 2;
286   SSVAL(*rdata,i,0x648);
287   SIVAL(*rdata,i+2,4);
288   SIVAL(*rdata,i+6,0x401);
289   SSVAL(*rdata,i+0xC,0x500);
290   SIVAL(*rdata,i+0xE,0x15);
291   SIVAL(*rdata,i+0x12,0x2372FE1);
292   SIVAL(*rdata,i+0x16,0x7E831BEF);
293   SIVAL(*rdata,i+0x1A,0x4B454B2);
294 }
295
296 static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
297 {
298   uint32 dword1;
299
300   /* All kinds of mysterious numbers here */
301   *rdata_len = 48;
302   *rdata = REALLOC(*rdata,*rdata_len);
303
304   dword1 = IVAL(data,0xC);
305
306   SIVAL(*rdata,0,0x03020005);
307   SIVAL(*rdata,4,0x10);
308   SIVAL(*rdata,8,0x30);
309   SIVAL(*rdata,0xC,dword1);
310   SIVAL(*rdata,0x10,0x18);
311 }
312
313
314 BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
315                      int mdrcnt,int mprcnt,
316                      char **rdata,char **rparam,
317                      int *rdata_len,int *rparam_len)
318 {
319   uint32 id,id2;
320
321   id = IVAL(data,0);
322
323   DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
324   switch (id)
325   {
326     case 0xb0005:
327       LsarpcTNP1(data,rdata,rdata_len);
328       break;
329
330     case 0x03000005:
331       id2 = IVAL(data,8);
332       DEBUG(4,("\t- Suboperation %lx\n",id2));
333       switch (id2 & 0xF)
334       {
335         case 8:
336           LsarpcTNP2(data,rdata,rdata_len);
337           break;
338
339         case 0xC:
340           LsarpcTNP4(data,rdata,rdata_len);
341           break;
342
343         case 0xE:
344           LsarpcTNP3(data,rdata,rdata_len);
345           break;
346       }
347       break;
348   }
349   return(True);
350 }