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