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