e2f704e6af988158c54db9c4ebe54e83c8d365f3
[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-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 extern BOOL case_sensitive;
42 extern pstring sesssetup_user;
43 extern int Client;
44 extern fstring myworkgroup;
45
46 #define VALID_PNUM(pnum)   (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES))
47 #define OPEN_PNUM(pnum)    (VALID_PNUM(pnum) && Pipes[pnum].open)
48 #define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum)
49
50 /* this macro should always be used to extract an pnum (smb_fid) from
51    a packet to ensure chaining works correctly */
52 #define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where))
53
54 char * known_pipes [] =
55 {
56   "lsarpc",
57 #if NTDOMAIN
58   "NETLOGON",
59   "srvsvc",
60   "wkssvc",
61   "samr",
62 #endif
63   NULL
64 };
65
66 /****************************************************************************
67   reply to an open and X on a named pipe
68
69   This code is basically stolen from reply_open_and_X with some
70   wrinkles to handle pipes.
71 ****************************************************************************/
72 int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
73 {
74   pstring fname;
75   int cnum = SVAL(inbuf,smb_tid);
76   int pnum = -1;
77   int smb_ofun = SVAL(inbuf,smb_vwv8);
78   int size=0,fmode=0,mtime=0,rmode=0;
79   int i;
80
81   /* XXXX we need to handle passed times, sattr and flags */
82   pstrcpy(fname,smb_buf(inbuf));
83
84   /* If the name doesn't start \PIPE\ then this is directed */
85   /* at a mailslot or something we really, really don't understand, */
86   /* not just something we really don't understand. */
87   if ( strncmp(fname,PIPE,PIPELEN) != 0 )
88     return(ERROR(ERRSRV,ERRaccess));
89
90   DEBUG(4,("Opening pipe %s.\n", fname));
91
92   /* Strip \PIPE\ off the name. */
93   pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
94
95   /* See if it is one we want to handle. */
96   for( i = 0; known_pipes[i] ; i++ )
97     if( strcmp(fname,known_pipes[i]) == 0 )
98       break;
99
100   if ( known_pipes[i] == NULL )
101     return(ERROR(ERRSRV,ERRaccess));
102
103   /* Known pipes arrive with DIR attribs. Remove it so a regular file */
104   /* can be opened and add it in after the open. */
105   DEBUG(3,("Known pipe %s opening.\n",fname));
106   smb_ofun |= 0x10;             /* Add Create it not exists flag */
107
108   pnum = open_rpc_pipe_hnd(fname, cnum);
109   if (pnum < 0) return(ERROR(ERRSRV,ERRnofids));
110
111   /* Prepare the reply */
112   set_message(outbuf,15,0,True);
113
114   /* Mark the opened file as an existing named pipe in message mode. */
115   SSVAL(outbuf,smb_vwv9,2);
116   SSVAL(outbuf,smb_vwv10,0xc700);
117
118   if (rmode == 2)
119   {
120     DEBUG(4,("Resetting open result to open from create.\n"));
121     rmode = 1;
122   }
123
124   SSVAL(outbuf,smb_vwv2, pnum + 0x800); /* mark file handle up into high range */
125   SSVAL(outbuf,smb_vwv3,fmode);
126   put_dos_date3(outbuf,smb_vwv4,mtime);
127   SIVAL(outbuf,smb_vwv6,size);
128   SSVAL(outbuf,smb_vwv8,rmode);
129   SSVAL(outbuf,smb_vwv11,0);
130
131   return chain_reply(inbuf,outbuf,length,bufsize);
132 }
133
134
135 /****************************************************************************
136   reply to a close
137 ****************************************************************************/
138 int reply_pipe_close(char *inbuf,char *outbuf)
139 {
140   int pnum = get_rpc_pipe_num(inbuf,smb_vwv0);
141   int cnum = SVAL(inbuf,smb_tid);
142   int outsize = set_message(outbuf,0,0,True);
143
144   DEBUG(5,("reply_pipe_close: pnum:%x cnum:%x\n", pnum, cnum));
145
146   if (!close_rpc_pipe_hnd(pnum, cnum)) return(ERROR(ERRDOS,ERRbadfid));
147
148   return(outsize);
149 }
150
151
152 /****************************************************************************
153  api_LsarpcSNPHS
154
155  SetNamedPipeHandleState on \PIPE\lsarpc. 
156 ****************************************************************************/
157 BOOL api_LsarpcSNPHS(int pnum, int cnum, char *param)
158 {
159   uint16 id;
160
161   if (!param) return False;
162
163   id = param[0] + (param[1] << 8);
164   DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
165
166   return set_rpc_pipe_hnd_state(pnum, cnum, id);
167 }
168
169
170 /****************************************************************************
171  api_LsarpcTNP
172
173  TransactNamedPipe on \PIPE\lsarpc.
174 ****************************************************************************/
175 static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
176 {
177   uint32 dword1, dword2;
178   char pname[] = "\\PIPE\\lsass";
179
180   /* All kinds of mysterious numbers here */
181   *rdata_len = 68;
182   *rdata = REALLOC(*rdata,*rdata_len);
183
184   dword1 = IVAL(data,0xC);
185   dword2 = IVAL(data,0x10);
186
187   SIVAL(*rdata,0,0xc0005);
188   SIVAL(*rdata,4,0x10);
189   SIVAL(*rdata,8,0x44);
190   SIVAL(*rdata,0xC,dword1);
191   
192   SIVAL(*rdata,0x10,dword2);
193   SIVAL(*rdata,0x14,0x15);
194   SSVAL(*rdata,0x18,sizeof(pname));
195   strcpy(*rdata + 0x1a,pname);
196   SIVAL(*rdata,0x28,1);
197   memcpy(*rdata + 0x30, data + 0x34, 0x14);
198 }
199
200 static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
201 {
202   uint32 dword1;
203
204   /* All kinds of mysterious numbers here */
205   *rdata_len = 48;
206   *rdata = REALLOC(*rdata,*rdata_len);
207
208   dword1 = IVAL(data,0xC);
209
210   SIVAL(*rdata,0,0x03020005);
211   SIVAL(*rdata,4,0x10);
212   SIVAL(*rdata,8,0x30);
213   SIVAL(*rdata,0xC,dword1);
214   SIVAL(*rdata,0x10,0x18);
215   SIVAL(*rdata,0x1c,0x44332211);
216   SIVAL(*rdata,0x20,0x88776655);
217   SIVAL(*rdata,0x24,0xCCBBAA99);
218   SIVAL(*rdata,0x28,0x11FFEEDD);
219 }
220
221 static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
222 {
223   uint32 dword1;
224   uint16 word1;
225   char * workgroup = myworkgroup;
226   int wglen = strlen(workgroup);
227   int i;
228
229   /* All kinds of mysterious numbers here */
230   *rdata_len = 90 + 2 * wglen;
231   *rdata = REALLOC(*rdata,*rdata_len);
232
233   dword1 = IVAL(data,0xC);
234   word1 = SVAL(data,0x2C);
235
236   SIVAL(*rdata,0,0x03020005);
237   SIVAL(*rdata,4,0x10);
238   SIVAL(*rdata,8,0x60);
239   SIVAL(*rdata,0xC,dword1);
240   SIVAL(*rdata,0x10,0x48);
241   SSVAL(*rdata,0x18,0x5988);    /* This changes */
242   SSVAL(*rdata,0x1A,0x15);
243   SSVAL(*rdata,0x1C,word1);
244   SSVAL(*rdata,0x20,6);
245   SSVAL(*rdata,0x22,8);
246   SSVAL(*rdata,0x24,0x8E8);     /* So does this */
247   SSVAL(*rdata,0x26,0x15);
248   SSVAL(*rdata,0x28,0x4D48);    /* And this */
249   SSVAL(*rdata,0x2A,0x15);
250   SIVAL(*rdata,0x2C,4);
251   SIVAL(*rdata,0x34,wglen);
252   for ( i = 0 ; i < wglen ; i++ )
253     (*rdata)[0x38 + i * 2] = workgroup[i];
254    
255   /* Now fill in the rest */
256   i = 0x38 + wglen * 2;
257   SSVAL(*rdata,i,0x648);
258   SIVAL(*rdata,i+2,4);
259   SIVAL(*rdata,i+6,0x401);
260   SSVAL(*rdata,i+0xC,0x500);
261   SIVAL(*rdata,i+0xE,0x15);
262   SIVAL(*rdata,i+0x12,0x2372FE1);
263   SIVAL(*rdata,i+0x16,0x7E831BEF);
264   SIVAL(*rdata,i+0x1A,0x4B454B2);
265 }
266
267 static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
268 {
269   uint32 dword1;
270
271   /* All kinds of mysterious numbers here */
272   *rdata_len = 48;
273   *rdata = REALLOC(*rdata,*rdata_len);
274
275   dword1 = IVAL(data,0xC);
276
277   SIVAL(*rdata,0,0x03020005);
278   SIVAL(*rdata,4,0x10);
279   SIVAL(*rdata,8,0x30);
280   SIVAL(*rdata,0xC,dword1);
281   SIVAL(*rdata,0x10,0x18);
282 }
283
284
285 BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
286                      int mdrcnt,int mprcnt,
287                      char **rdata,char **rparam,
288                      int *rdata_len,int *rparam_len)
289 {
290   uint32 id,id2;
291
292   id = IVAL(data,0);
293
294   DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
295   switch (id)
296   {
297     case 0xb0005:
298       LsarpcTNP1(data,rdata,rdata_len);
299       break;
300
301     case 0x03000005:
302       id2 = IVAL(data,8);
303       DEBUG(4,("\t- Suboperation %lx\n",id2));
304       switch (id2 & 0xF)
305       {
306         case 8:
307           LsarpcTNP2(data,rdata,rdata_len);
308           break;
309
310         case 0xC:
311           LsarpcTNP4(data,rdata,rdata_len);
312           break;
313
314         case 0xE:
315           LsarpcTNP3(data,rdata,rdata_len);
316           break;
317       }
318       break;
319   }
320   return(True);
321 }
322