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