Adding Andrews buffer overflow fixes into the main branch.
[samba.git] / source / smbd / pipes.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Pipe SMB reply routines
5    Copyright (C) Andrew Tridgell 1992-1997
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 chain_fnum;
39 extern char magic_char;
40 extern connection_struct Connections[];
41 extern files_struct Files[];
42 extern BOOL case_sensitive;
43 extern pstring sesssetup_user;
44 extern int Client;
45 extern fstring myworkgroup;
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   BOOL bad_path = False;
88
89   /* XXXX we need to handle passed times, sattr and flags */
90   pstrcpy(fname,smb_buf(inbuf));
91
92   /* If the name doesn't start \PIPE\ then this is directed */
93   /* at a mailslot or something we really, really don't understand, */
94   /* not just something we really don't understand. */
95   if ( strncmp(fname,PIPE,PIPELEN) != 0 )
96     return(ERROR(ERRSRV,ERRaccess));
97
98   DEBUG(4,("Opening pipe %s.\n", fname));
99
100   /* Strip \PIPE\ off the name. */
101   pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
102
103   /* See if it is one we want to handle. */
104   for( i = 0; known_pipes[i] ; i++ )
105     if( strcmp(fname,known_pipes[i]) == 0 )
106       break;
107
108   if ( known_pipes[i] == NULL )
109     return(ERROR(ERRSRV,ERRaccess));
110
111   /* Known pipes arrive with DIR attribs. Remove it so a regular file */
112   /* can be opened and add it in after the open. */
113   DEBUG(3,("Known pipe %s opening.\n",fname));
114   smb_attr &= ~aDIR;
115   Connections[cnum].read_only = 0;
116   smb_ofun |= 0x10;             /* Add Create it not exists flag */
117
118   unix_convert(fname,cnum,0,&bad_path);
119     
120   fnum = find_free_file();
121   if (fnum < 0)
122     return(ERROR(ERRSRV,ERRnofids));
123
124   if (!check_name(fname,cnum))
125     return(UNIXERROR(ERRDOS,ERRnoaccess));
126
127   unixmode = unix_mode(cnum,smb_attr);
128       
129   open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
130                    &rmode,&smb_action);
131       
132   if (!Files[fnum].open)
133   {
134     /* Change the error code if bad_path was set. */
135     if((errno == ENOENT) && bad_path)
136     {
137       unix_ERR_class = ERRDOS;
138       unix_ERR_code = ERRbadpath;
139     }
140     return(UNIXERROR(ERRDOS,ERRnoaccess));
141   }
142
143   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
144     close_file(fnum);
145     return(ERROR(ERRDOS,ERRnoaccess));
146   }
147
148   size = sbuf.st_size;
149   fmode = dos_mode(cnum,fname,&sbuf);
150   mtime = sbuf.st_mtime;
151   if (fmode & aDIR) {
152     close_file(fnum);
153     return(ERROR(ERRDOS,ERRnoaccess));
154   }
155
156   /* Prepare the reply */
157   set_message(outbuf,15,0,True);
158
159   /* Put things back the way they were. */
160   Connections[cnum].read_only = 1;
161
162   /* Mark the opened file as an existing named pipe in message mode. */
163   SSVAL(outbuf,smb_vwv9,2);
164   SSVAL(outbuf,smb_vwv10,0xc700);
165   if (rmode == 2)
166   {
167     DEBUG(4,("Resetting open result to open from create.\n"));
168     rmode = 1;
169   }
170
171   SSVAL(outbuf,smb_vwv2,fnum);
172   SSVAL(outbuf,smb_vwv3,fmode);
173   put_dos_date3(outbuf,smb_vwv4,mtime);
174   SIVAL(outbuf,smb_vwv6,size);
175   SSVAL(outbuf,smb_vwv8,rmode);
176   SSVAL(outbuf,smb_vwv11,smb_action);
177
178   chain_fnum = fnum;
179
180   DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n",
181            fname, fnum, Files[fnum].name));
182   
183   return chain_reply(inbuf,outbuf,length,bufsize);
184 }
185
186
187 /****************************************************************************
188  api_LsarpcSNPHS
189
190  SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here,
191  so just blithely return True. This is really only for NT domain stuff,
192  we we're only handling that - don't assume Samba now does complete
193  named pipe handling.
194 ****************************************************************************/
195 BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
196                      int mdrcnt,int mprcnt,
197                      char **rdata,char **rparam,
198                      int *rdata_len,int *rparam_len)
199 {
200   uint16 id;
201
202   id = param[0] + (param[1] << 8);
203   DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
204   return(True);
205 }
206
207
208 /****************************************************************************
209  api_LsarpcTNP
210
211  TransactNamedPipe on \PIPE\lsarpc.
212 ****************************************************************************/
213 static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
214 {
215   uint32 dword1, dword2;
216   char pname[] = "\\PIPE\\lsass";
217
218   /* All kinds of mysterious numbers here */
219   *rdata_len = 68;
220   *rdata = REALLOC(*rdata,*rdata_len);
221
222   dword1 = IVAL(data,0xC);
223   dword2 = IVAL(data,0x10);
224
225   SIVAL(*rdata,0,0xc0005);
226   SIVAL(*rdata,4,0x10);
227   SIVAL(*rdata,8,0x44);
228   SIVAL(*rdata,0xC,dword1);
229   
230   SIVAL(*rdata,0x10,dword2);
231   SIVAL(*rdata,0x14,0x15);
232   SSVAL(*rdata,0x18,sizeof(pname));
233   strcpy(*rdata + 0x1a,pname);
234   SIVAL(*rdata,0x28,1);
235   memcpy(*rdata + 0x30, data + 0x34, 0x14);
236 }
237
238 static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
239 {
240   uint32 dword1;
241
242   /* All kinds of mysterious numbers here */
243   *rdata_len = 48;
244   *rdata = REALLOC(*rdata,*rdata_len);
245
246   dword1 = IVAL(data,0xC);
247
248   SIVAL(*rdata,0,0x03020005);
249   SIVAL(*rdata,4,0x10);
250   SIVAL(*rdata,8,0x30);
251   SIVAL(*rdata,0xC,dword1);
252   SIVAL(*rdata,0x10,0x18);
253   SIVAL(*rdata,0x1c,0x44332211);
254   SIVAL(*rdata,0x20,0x88776655);
255   SIVAL(*rdata,0x24,0xCCBBAA99);
256   SIVAL(*rdata,0x28,0x11FFEEDD);
257 }
258
259 static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
260 {
261   uint32 dword1;
262   uint16 word1;
263   char * workgroup = myworkgroup;
264   int wglen = strlen(workgroup);
265   int i;
266
267   /* All kinds of mysterious numbers here */
268   *rdata_len = 90 + 2 * wglen;
269   *rdata = REALLOC(*rdata,*rdata_len);
270
271   dword1 = IVAL(data,0xC);
272   word1 = SVAL(data,0x2C);
273
274   SIVAL(*rdata,0,0x03020005);
275   SIVAL(*rdata,4,0x10);
276   SIVAL(*rdata,8,0x60);
277   SIVAL(*rdata,0xC,dword1);
278   SIVAL(*rdata,0x10,0x48);
279   SSVAL(*rdata,0x18,0x5988);    /* This changes */
280   SSVAL(*rdata,0x1A,0x15);
281   SSVAL(*rdata,0x1C,word1);
282   SSVAL(*rdata,0x20,6);
283   SSVAL(*rdata,0x22,8);
284   SSVAL(*rdata,0x24,0x8E8);     /* So does this */
285   SSVAL(*rdata,0x26,0x15);
286   SSVAL(*rdata,0x28,0x4D48);    /* And this */
287   SSVAL(*rdata,0x2A,0x15);
288   SIVAL(*rdata,0x2C,4);
289   SIVAL(*rdata,0x34,wglen);
290   for ( i = 0 ; i < wglen ; i++ )
291     (*rdata)[0x38 + i * 2] = workgroup[i];
292    
293   /* Now fill in the rest */
294   i = 0x38 + wglen * 2;
295   SSVAL(*rdata,i,0x648);
296   SIVAL(*rdata,i+2,4);
297   SIVAL(*rdata,i+6,0x401);
298   SSVAL(*rdata,i+0xC,0x500);
299   SIVAL(*rdata,i+0xE,0x15);
300   SIVAL(*rdata,i+0x12,0x2372FE1);
301   SIVAL(*rdata,i+0x16,0x7E831BEF);
302   SIVAL(*rdata,i+0x1A,0x4B454B2);
303 }
304
305 static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
306 {
307   uint32 dword1;
308
309   /* All kinds of mysterious numbers here */
310   *rdata_len = 48;
311   *rdata = REALLOC(*rdata,*rdata_len);
312
313   dword1 = IVAL(data,0xC);
314
315   SIVAL(*rdata,0,0x03020005);
316   SIVAL(*rdata,4,0x10);
317   SIVAL(*rdata,8,0x30);
318   SIVAL(*rdata,0xC,dword1);
319   SIVAL(*rdata,0x10,0x18);
320 }
321
322
323 BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
324                      int mdrcnt,int mprcnt,
325                      char **rdata,char **rparam,
326                      int *rdata_len,int *rparam_len)
327 {
328   uint32 id,id2;
329
330   id = IVAL(data,0);
331
332   DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
333   switch (id)
334   {
335     case 0xb0005:
336       LsarpcTNP1(data,rdata,rdata_len);
337       break;
338
339     case 0x03000005:
340       id2 = IVAL(data,8);
341       DEBUG(4,("\t- Suboperation %lx\n",id2));
342       switch (id2 & 0xF)
343       {
344         case 8:
345           LsarpcTNP2(data,rdata,rdata_len);
346           break;
347
348         case 0xC:
349           LsarpcTNP4(data,rdata,rdata_len);
350           break;
351
352         case 0xE:
353           LsarpcTNP3(data,rdata,rdata_len);
354           break;
355       }
356       break;
357   }
358   return(True);
359 }