8f6f6f39c4d8e34d36d69c8459c46f2f37c23e1e
[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-1998
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1998
7    Copyright (C) Paul Ashton  1997-1998.
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
31 #define PIPE            "\\PIPE\\"
32 #define PIPELEN         strlen(PIPE)
33
34 extern struct pipe_id_info pipe_names[];
35
36 /****************************************************************************
37   reply to an open and X on a named pipe
38
39   This code is basically stolen from reply_open_and_X with some
40   wrinkles to handle pipes.
41 ****************************************************************************/
42 int reply_open_pipe_and_X(connection_struct *conn,
43                           char *inbuf,char *outbuf,int length,int bufsize)
44 {
45         pstring fname;
46         pstring pipe_name;
47         uint16 vuid = SVAL(inbuf, smb_uid);
48         smb_np_struct *p;
49         int smb_ofun = SVAL(inbuf,smb_vwv8);
50         int size=0,fmode=0,mtime=0,rmode=0;
51         int i;
52
53         /* XXXX we need to handle passed times, sattr and flags */
54         srvstr_pull(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), -1, STR_TERMINATE);
55
56         /* If the name doesn't start \PIPE\ then this is directed */
57         /* at a mailslot or something we really, really don't understand, */
58         /* not just something we really don't understand. */
59         if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 )
60                 return(ERROR_DOS(ERRSRV,ERRaccess));
61
62         DEBUG(4,("Opening pipe %s.\n", pipe_name));
63
64         /* See if it is one we want to handle. */
65         for( i = 0; pipe_names[i].client_pipe ; i++ )
66                 if( strequal(pipe_name,pipe_names[i].client_pipe) )
67                         break;
68
69         if (pipe_names[i].client_pipe == NULL)
70                 return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe));
71
72         /* Strip \PIPE\ off the name. */
73         pstrcpy(fname, pipe_name + PIPELEN);
74
75
76 #if 0
77         /*
78          * Hack for NT printers... JRA.
79          */
80     if(should_fail_next_srvsvc_open(fname))
81       return(ERROR(ERRSRV,ERRaccess));
82 #endif
83
84         /* Known pipes arrive with DIR attribs. Remove it so a regular file */
85         /* can be opened and add it in after the open. */
86         DEBUG(3,("Known pipe %s opening.\n",fname));
87         smb_ofun |= FILE_CREATE_IF_NOT_EXIST;
88
89         p = open_rpc_pipe_p(fname, conn, vuid);
90         if (!p) return(ERROR_DOS(ERRSRV,ERRnofids));
91
92         /* Prepare the reply */
93         set_message(outbuf,15,0,True);
94
95         /* Mark the opened file as an existing named pipe in message mode. */
96         SSVAL(outbuf,smb_vwv9,2);
97         SSVAL(outbuf,smb_vwv10,0xc700);
98
99         if (rmode == 2) {
100                 DEBUG(4,("Resetting open result to open from create.\n"));
101                 rmode = 1;
102         }
103
104         SSVAL(outbuf,smb_vwv2, p->pnum);
105         SSVAL(outbuf,smb_vwv3,fmode);
106         put_dos_date3(outbuf,smb_vwv4,mtime);
107         SIVAL(outbuf,smb_vwv6,size);
108         SSVAL(outbuf,smb_vwv8,rmode);
109         SSVAL(outbuf,smb_vwv11,0x0001);
110
111         return chain_reply(inbuf,outbuf,length,bufsize);
112 }
113
114 /****************************************************************************
115   reply to a write on a pipe
116 ****************************************************************************/
117 int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize)
118 {
119         smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0);
120         size_t numtowrite = SVAL(inbuf,smb_vwv1);
121         int nwritten;
122         int outsize;
123         char *data;
124
125         if (!p)
126                 return(ERROR_DOS(ERRDOS,ERRbadfid));
127
128         data = smb_buf(inbuf) + 3;
129
130         if (numtowrite == 0)
131                 nwritten = 0;
132         else
133                 nwritten = write_to_pipe(p, data, numtowrite);
134
135         if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0))
136                 return (UNIXERROR(ERRDOS,ERRnoaccess));
137   
138         outsize = set_message(outbuf,1,0,True);
139
140         SSVAL(outbuf,smb_vwv0,nwritten);
141   
142         DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n",
143                  p->pnum, nwritten));
144
145         return(outsize);
146 }
147
148 /****************************************************************************
149  Reply to a write and X.
150
151  This code is basically stolen from reply_write_and_X with some
152  wrinkles to handle pipes.
153 ****************************************************************************/
154
155 int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
156 {
157         smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2);
158         size_t numtowrite = SVAL(inbuf,smb_vwv10);
159         int nwritten = -1;
160         int smb_doff = SVAL(inbuf, smb_vwv11);
161         BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) ==
162                                                                         (PIPE_START_MESSAGE|PIPE_RAW_MODE));
163         char *data;
164
165         if (!p)
166                 return(ERROR_DOS(ERRDOS,ERRbadfid));
167
168         data = smb_base(inbuf) + smb_doff;
169
170         if (numtowrite == 0)
171                 nwritten = 0;
172         else {
173                 if(pipe_start_message_raw) {
174                         /*
175                          * For the start of a message in named pipe byte mode,
176                          * the first two bytes are a length-of-pdu field. Ignore
177                          * them (we don't trust the client. JRA.
178                          */
179                 if(numtowrite < 2) {
180                                 DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n",
181                                         (unsigned int)numtowrite ));
182                                 return (UNIXERROR(ERRDOS,ERRnoaccess));
183                         }
184
185                         data += 2;
186                         numtowrite -= 2;
187         }                        
188                 nwritten = write_to_pipe(p, data, numtowrite);
189         }
190
191         if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0))
192                 return (UNIXERROR(ERRDOS,ERRnoaccess));
193   
194         set_message(outbuf,6,0,True);
195
196         nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
197         SSVAL(outbuf,smb_vwv2,nwritten);
198   
199         DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n",
200                  p->pnum, nwritten));
201
202         return chain_reply(inbuf,outbuf,length,bufsize);
203 }
204
205 /****************************************************************************
206   reply to a read and X
207
208   This code is basically stolen from reply_read_and_X with some
209   wrinkles to handle pipes.
210 ****************************************************************************/
211 int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
212 {
213         smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2);
214         int smb_maxcnt = SVAL(inbuf,smb_vwv5);
215         int smb_mincnt = SVAL(inbuf,smb_vwv6);
216         int nread = -1;
217         char *data;
218         BOOL unused;
219
220         /* we don't use the offset given to use for pipe reads. This
221            is deliberate, instead we always return the next lump of
222            data on the pipe */
223 #if 0
224         uint32 smb_offs = IVAL(inbuf,smb_vwv3);
225 #endif
226
227         if (!p)
228                 return(ERROR_DOS(ERRDOS,ERRbadfid));
229
230         set_message(outbuf,12,0,True);
231         data = smb_buf(outbuf);
232
233         nread = read_from_pipe(p, data, smb_maxcnt, &unused);
234
235         if (nread < 0)
236                 return(UNIXERROR(ERRDOS,ERRnoaccess));
237   
238         SSVAL(outbuf,smb_vwv5,nread);
239         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
240         SSVAL(smb_buf(outbuf),-2,nread);
241   
242         DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n",
243                  p->pnum, smb_mincnt, smb_maxcnt, nread));
244
245         return chain_reply(inbuf,outbuf,length,bufsize);
246 }
247
248 /****************************************************************************
249   reply to a close
250 ****************************************************************************/
251 int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf)
252 {
253         smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0);
254         int outsize = set_message(outbuf,0,0,True);
255
256         if (!p)
257                 return(ERROR_DOS(ERRDOS,ERRbadfid));
258
259         DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum));
260
261         if (!close_rpc_pipe_hnd(p))
262                 return ERROR_DOS(ERRDOS,ERRbadfid);
263
264         return(outsize);
265 }