removed mechanism that created actual files NETLOGON, lsarpc and the like,
[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    Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
7    Copyright (C) Paul Ashton  1997.
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    This file handles reply_ calls on named pipes that the server
25    makes to handle specific protocols
26 */
27
28
29 #include "includes.h"
30 #include "trans2.h"
31
32 #define PIPE            "\\PIPE\\"
33 #define PIPELEN         strlen(PIPE)
34
35 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
36
37 /* look in server.c for some explanation of these variables */
38 extern int Protocol;
39 extern int DEBUGLEVEL;
40 extern char magic_char;
41 static int chain_pnum = -1;
42 extern BOOL case_sensitive;
43 extern pstring sesssetup_user;
44 extern int Client;
45 extern fstring myworkgroup;
46
47 #ifndef MAX_OPEN_PIPES
48 #define MAX_OPEN_PIPES 50
49 #endif
50
51 static struct
52 {
53   int cnum;
54   BOOL open;
55   fstring name;
56
57 } Pipes[MAX_OPEN_PIPES];
58
59 #define VALID_PNUM(pnum)   (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES))
60 #define OPEN_PNUM(pnum)    (VALID_PNUM(pnum) && Pipes[pnum].open)
61 #define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum)
62
63 #define CHECK_PNUM(pnum,c) if (!PNUM_OK(pnum,c)) \
64                                return(ERROR(ERRDOS,ERRbadfid))
65 /* this macro should always be used to extract an pnum (smb_fid) from
66    a packet to ensure chaining works correctly */
67 #define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where))
68
69 char * known_pipes [] =
70 {
71   "lsarpc",
72 #if NTDOMAIN
73   "NETLOGON",
74   "srvsvc",
75 #endif
76   NULL
77 };
78
79 /****************************************************************************
80   find first available file slot
81 ****************************************************************************/
82 static int find_free_pipe(void )
83 {
84   int i;
85   /* we start at 1 here for an obscure reason I can't now remember,
86      but I think is important :-) */
87   for (i = 1; i < MAX_OPEN_PIPES; i++)
88     if (!Pipes[i].open)
89       return(i);
90
91   DEBUG(1,("ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES?\n"));
92
93   return(-1);
94 }
95
96 /****************************************************************************
97   gets the name of a pipe
98 ****************************************************************************/
99 char *get_pipe_name(int pnum)
100 {
101         DEBUG(6,("get_pipe_name: "));
102
103         if (VALID_PNUM(pnum - 0x800))
104         {
105                 DEBUG(6,("name: %s cnum: %d open: %s ",
106                           Pipes[pnum - 0x800].name,
107                           Pipes[pnum - 0x800].cnum,
108                           BOOLSTR(Pipes[pnum - 0x800].open)));
109         }
110         if (OPEN_PNUM(pnum - 0x800))
111         {
112                 DEBUG(6,("OK\n"));
113                 return Pipes[pnum - 0x800].name;
114         }
115         else
116         {
117                 DEBUG(6,("NOT\n"));
118                 return NULL;
119         }
120 }
121
122 /****************************************************************************
123   reply to an open and X on a named pipe
124
125   This code is basically stolen from reply_open_and_X with some
126   wrinkles to handle pipes.
127 ****************************************************************************/
128 int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
129 {
130   pstring fname;
131   int cnum = SVAL(inbuf,smb_tid);
132   int pnum = -1;
133   int smb_ofun = SVAL(inbuf,smb_vwv8);
134   int size=0,fmode=0,mtime=0,rmode=0;
135   int i;
136
137   /* XXXX we need to handle passed times, sattr and flags */
138   pstrcpy(fname,smb_buf(inbuf));
139
140   /* If the name doesn't start \PIPE\ then this is directed */
141   /* at a mailslot or something we really, really don't understand, */
142   /* not just something we really don't understand. */
143   if ( strncmp(fname,PIPE,PIPELEN) != 0 )
144     return(ERROR(ERRSRV,ERRaccess));
145
146   DEBUG(4,("Opening pipe %s.\n", fname));
147
148   /* Strip \PIPE\ off the name. */
149   pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
150
151   /* See if it is one we want to handle. */
152   for( i = 0; known_pipes[i] ; i++ )
153     if( strcmp(fname,known_pipes[i]) == 0 )
154       break;
155
156   if ( known_pipes[i] == NULL )
157     return(ERROR(ERRSRV,ERRaccess));
158
159   /* Known pipes arrive with DIR attribs. Remove it so a regular file */
160   /* can be opened and add it in after the open. */
161   DEBUG(3,("Known pipe %s opening.\n",fname));
162   smb_ofun |= 0x10;             /* Add Create it not exists flag */
163
164   pnum = find_free_pipe();
165   if (pnum < 0) return(ERROR(ERRSRV,ERRnofids));
166
167   Pipes[pnum].open = True;
168   Pipes[pnum].cnum = cnum;
169   fstrcpy(Pipes[pnum].name, fname);
170
171   /* Prepare the reply */
172   set_message(outbuf,15,0,True);
173
174   /* Mark the opened file as an existing named pipe in message mode. */
175   SSVAL(outbuf,smb_vwv9,2);
176   SSVAL(outbuf,smb_vwv10,0xc700);
177
178   if (rmode == 2)
179   {
180     DEBUG(4,("Resetting open result to open from create.\n"));
181     rmode = 1;
182   }
183
184   SSVAL(outbuf,smb_vwv2, pnum + 0x800); /* mark file handle up into high range */
185   SSVAL(outbuf,smb_vwv3,fmode);
186   put_dos_date3(outbuf,smb_vwv4,mtime);
187   SIVAL(outbuf,smb_vwv6,size);
188   SSVAL(outbuf,smb_vwv8,rmode);
189   SSVAL(outbuf,smb_vwv11,0);
190
191   DEBUG(4,("Opened pipe %s with handle %x name %s.\n",
192            fname, pnum + 0x800, Pipes[pnum].name));
193   
194   chain_pnum = pnum;
195
196   return chain_reply(inbuf,outbuf,length,bufsize);
197 }
198
199
200 /****************************************************************************
201   reply to a close
202 ****************************************************************************/
203 int reply_pipe_close(char *inbuf,char *outbuf)
204 {
205   int pnum = GETPNUM(inbuf,smb_vwv0);
206   int cnum = SVAL(inbuf,smb_tid);
207   int outsize = set_message(outbuf,0,0,True);
208
209   /* mapping is 0x800 up... */
210
211   CHECK_PNUM(pnum-0x800,cnum);
212
213   DEBUG(3,("%s Closed pipe name %s pnum=%d cnum=%d\n",
214            timestring(),Pipes[pnum-0x800].name, pnum,cnum));
215   
216   Pipes[pnum-0x800].open = False;
217
218   return(outsize);
219 }
220
221
222 /****************************************************************************
223  api_LsarpcSNPHS
224
225  SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here,
226  so just blithely return True. This is really only for NT domain stuff,
227  we we're only handling that - don't assume Samba now does complete
228  named pipe handling.
229 ****************************************************************************/
230 BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
231                      int mdrcnt,int mprcnt,
232                      char **rdata,char **rparam,
233                      int *rdata_len,int *rparam_len)
234 {
235   uint16 id;
236
237   id = param[0] + (param[1] << 8);
238   DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
239   return(True);
240 }
241
242
243 /****************************************************************************
244  api_LsarpcTNP
245
246  TransactNamedPipe on \PIPE\lsarpc.
247 ****************************************************************************/
248 static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
249 {
250   uint32 dword1, dword2;
251   char pname[] = "\\PIPE\\lsass";
252
253   /* All kinds of mysterious numbers here */
254   *rdata_len = 68;
255   *rdata = REALLOC(*rdata,*rdata_len);
256
257   dword1 = IVAL(data,0xC);
258   dword2 = IVAL(data,0x10);
259
260   SIVAL(*rdata,0,0xc0005);
261   SIVAL(*rdata,4,0x10);
262   SIVAL(*rdata,8,0x44);
263   SIVAL(*rdata,0xC,dword1);
264   
265   SIVAL(*rdata,0x10,dword2);
266   SIVAL(*rdata,0x14,0x15);
267   SSVAL(*rdata,0x18,sizeof(pname));
268   strcpy(*rdata + 0x1a,pname);
269   SIVAL(*rdata,0x28,1);
270   memcpy(*rdata + 0x30, data + 0x34, 0x14);
271 }
272
273 static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
274 {
275   uint32 dword1;
276
277   /* All kinds of mysterious numbers here */
278   *rdata_len = 48;
279   *rdata = REALLOC(*rdata,*rdata_len);
280
281   dword1 = IVAL(data,0xC);
282
283   SIVAL(*rdata,0,0x03020005);
284   SIVAL(*rdata,4,0x10);
285   SIVAL(*rdata,8,0x30);
286   SIVAL(*rdata,0xC,dword1);
287   SIVAL(*rdata,0x10,0x18);
288   SIVAL(*rdata,0x1c,0x44332211);
289   SIVAL(*rdata,0x20,0x88776655);
290   SIVAL(*rdata,0x24,0xCCBBAA99);
291   SIVAL(*rdata,0x28,0x11FFEEDD);
292 }
293
294 static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
295 {
296   uint32 dword1;
297   uint16 word1;
298   char * workgroup = myworkgroup;
299   int wglen = strlen(workgroup);
300   int i;
301
302   /* All kinds of mysterious numbers here */
303   *rdata_len = 90 + 2 * wglen;
304   *rdata = REALLOC(*rdata,*rdata_len);
305
306   dword1 = IVAL(data,0xC);
307   word1 = SVAL(data,0x2C);
308
309   SIVAL(*rdata,0,0x03020005);
310   SIVAL(*rdata,4,0x10);
311   SIVAL(*rdata,8,0x60);
312   SIVAL(*rdata,0xC,dword1);
313   SIVAL(*rdata,0x10,0x48);
314   SSVAL(*rdata,0x18,0x5988);    /* This changes */
315   SSVAL(*rdata,0x1A,0x15);
316   SSVAL(*rdata,0x1C,word1);
317   SSVAL(*rdata,0x20,6);
318   SSVAL(*rdata,0x22,8);
319   SSVAL(*rdata,0x24,0x8E8);     /* So does this */
320   SSVAL(*rdata,0x26,0x15);
321   SSVAL(*rdata,0x28,0x4D48);    /* And this */
322   SSVAL(*rdata,0x2A,0x15);
323   SIVAL(*rdata,0x2C,4);
324   SIVAL(*rdata,0x34,wglen);
325   for ( i = 0 ; i < wglen ; i++ )
326     (*rdata)[0x38 + i * 2] = workgroup[i];
327    
328   /* Now fill in the rest */
329   i = 0x38 + wglen * 2;
330   SSVAL(*rdata,i,0x648);
331   SIVAL(*rdata,i+2,4);
332   SIVAL(*rdata,i+6,0x401);
333   SSVAL(*rdata,i+0xC,0x500);
334   SIVAL(*rdata,i+0xE,0x15);
335   SIVAL(*rdata,i+0x12,0x2372FE1);
336   SIVAL(*rdata,i+0x16,0x7E831BEF);
337   SIVAL(*rdata,i+0x1A,0x4B454B2);
338 }
339
340 static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
341 {
342   uint32 dword1;
343
344   /* All kinds of mysterious numbers here */
345   *rdata_len = 48;
346   *rdata = REALLOC(*rdata,*rdata_len);
347
348   dword1 = IVAL(data,0xC);
349
350   SIVAL(*rdata,0,0x03020005);
351   SIVAL(*rdata,4,0x10);
352   SIVAL(*rdata,8,0x30);
353   SIVAL(*rdata,0xC,dword1);
354   SIVAL(*rdata,0x10,0x18);
355 }
356
357
358 BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
359                      int mdrcnt,int mprcnt,
360                      char **rdata,char **rparam,
361                      int *rdata_len,int *rparam_len)
362 {
363   uint32 id,id2;
364
365   id = IVAL(data,0);
366
367   DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
368   switch (id)
369   {
370     case 0xb0005:
371       LsarpcTNP1(data,rdata,rdata_len);
372       break;
373
374     case 0x03000005:
375       id2 = IVAL(data,8);
376       DEBUG(4,("\t- Suboperation %lx\n",id2));
377       switch (id2 & 0xF)
378       {
379         case 8:
380           LsarpcTNP2(data,rdata,rdata_len);
381           break;
382
383         case 0xC:
384           LsarpcTNP4(data,rdata,rdata_len);
385           break;
386
387         case 0xE:
388           LsarpcTNP3(data,rdata,rdata_len);
389           break;
390       }
391       break;
392   }
393   return(True);
394 }
395