Merge branch 'master' of ssh://git.samba.org/data/git/samba
[metze/samba/wip.git] / source3 / smbd / pipes.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Pipe SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Luke Kenneth Casson Leighton 1996-1998
6    Copyright (C) Paul Ashton  1997-1998.
7    Copyright (C) Jeremy Allison 2005.
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 3 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, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles reply_ calls on named pipes that the server
24    makes to handle specific protocols
25 */
26
27
28 #include "includes.h"
29
30 #define PIPE            "\\PIPE\\"
31 #define PIPELEN         strlen(PIPE)
32
33 #define MAX_PIPE_NAME_LEN       24
34
35 /****************************************************************************
36  Reply to an open and X on a named pipe.
37  This code is basically stolen from reply_open_and_X with some
38  wrinkles to handle pipes.
39 ****************************************************************************/
40
41 void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
42 {
43         const char *fname = NULL;
44         char *pipe_name = NULL;
45         files_struct *fsp;
46         int size=0,fmode=0,mtime=0,rmode=0;
47         TALLOC_CTX *ctx = talloc_tos();
48         NTSTATUS status;
49
50         /* XXXX we need to handle passed times, sattr and flags */
51         srvstr_pull_req_talloc(ctx, req, &pipe_name, req->buf, STR_TERMINATE);
52         if (!pipe_name) {
53                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
54                                 ERRDOS, ERRbadpipe);
55                 return;
56         }
57
58         /* If the name doesn't start \PIPE\ then this is directed */
59         /* at a mailslot or something we really, really don't understand, */
60         /* not just something we really don't understand. */
61         if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) {
62                 reply_doserror(req, ERRSRV, ERRaccess);
63                 return;
64         }
65
66         DEBUG(4,("Opening pipe %s.\n", pipe_name));
67
68         /* Strip \PIPE\ off the name. */
69         fname = pipe_name + PIPELEN;
70
71 #if 0
72         /*
73          * Hack for NT printers... JRA.
74          */
75         if(should_fail_next_srvsvc_open(fname)) {
76                 reply_doserror(req, ERRSRV, ERRaccess);
77                 return;
78         }
79 #endif
80
81         status = np_open(req, fname, &fsp);
82         if (!NT_STATUS_IS_OK(status)) {
83                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
84                         reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
85                                         ERRDOS, ERRbadpipe);
86                         return;
87                 }
88                 reply_nterror(req, status);
89                 return;
90         }
91
92         /* Prepare the reply */
93         reply_outbuf(req, 15, 0);
94
95         /* Mark the opened file as an existing named pipe in message mode. */
96         SSVAL(req->outbuf,smb_vwv9,2);
97         SSVAL(req->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(req->outbuf,smb_vwv2, fsp->fnum);
105         SSVAL(req->outbuf,smb_vwv3,fmode);
106         srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
107         SIVAL(req->outbuf,smb_vwv6,size);
108         SSVAL(req->outbuf,smb_vwv8,rmode);
109         SSVAL(req->outbuf,smb_vwv11,0x0001);
110
111         chain_reply(req);
112         return;
113 }
114
115 /****************************************************************************
116  Reply to a write on a pipe.
117 ****************************************************************************/
118
119 void reply_pipe_write(struct smb_request *req)
120 {
121         files_struct *fsp = file_fsp(req, SVAL(req->vwv+0, 0));
122         size_t numtowrite = SVAL(req->vwv+1, 0);
123         ssize_t nwritten;
124         const uint8_t *data;
125
126         if (!fsp_is_np(fsp)) {
127                 reply_doserror(req, ERRDOS, ERRbadfid);
128                 return;
129         }
130
131         if (fsp->vuid != req->vuid) {
132                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
133                 return;
134         }
135
136         data = req->buf + 3;
137
138         if (numtowrite == 0) {
139                 nwritten = 0;
140         } else {
141                 NTSTATUS status;
142                 status = np_write(fsp, data, numtowrite, &nwritten);
143                 if (!NT_STATUS_IS_OK(status)) {
144                         reply_nterror(req, status);
145                         return;
146                 }
147         }
148
149         if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
150                 reply_unixerror(req, ERRDOS, ERRnoaccess);
151                 return;
152         }
153
154         reply_outbuf(req, 1, 0);
155
156         SSVAL(req->outbuf,smb_vwv0,nwritten);
157   
158         DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", fsp->fnum,
159                  (int)nwritten));
160
161         return;
162 }
163
164 /****************************************************************************
165  Reply to a write and X.
166
167  This code is basically stolen from reply_write_and_X with some
168  wrinkles to handle pipes.
169 ****************************************************************************/
170
171 void reply_pipe_write_and_X(struct smb_request *req)
172 {
173         files_struct *fsp = file_fsp(req, SVAL(req->vwv+2, 0));
174         size_t numtowrite = SVAL(req->vwv+10, 0);
175         ssize_t nwritten;
176         int smb_doff = SVAL(req->vwv+11, 0);
177         bool pipe_start_message_raw =
178                 ((SVAL(req->vwv+7, 0) & (PIPE_START_MESSAGE|PIPE_RAW_MODE))
179                  == (PIPE_START_MESSAGE|PIPE_RAW_MODE));
180         uint8_t *data;
181
182         if (!fsp_is_np(fsp)) {
183                 reply_doserror(req, ERRDOS, ERRbadfid);
184                 return;
185         }
186
187         if (fsp->vuid != req->vuid) {
188                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
189                 return;
190         }
191
192         data = (uint8_t *)smb_base(req->inbuf) + smb_doff;
193
194         if (numtowrite == 0) {
195                 nwritten = 0;
196         } else {
197                 NTSTATUS status;
198
199                 if(pipe_start_message_raw) {
200                         /*
201                          * For the start of a message in named pipe byte mode,
202                          * the first two bytes are a length-of-pdu field. Ignore
203                          * them (we don't trust the client). JRA.
204                          */
205                        if(numtowrite < 2) {
206                                 DEBUG(0,("reply_pipe_write_and_X: start of "
207                                          "message set and not enough data "
208                                          "sent.(%u)\n",
209                                          (unsigned int)numtowrite ));
210                                 reply_unixerror(req, ERRDOS, ERRnoaccess);
211                                 return;
212                         }
213
214                         data += 2;
215                         numtowrite -= 2;
216                 }                        
217                 status = np_write(fsp, data, numtowrite, &nwritten);
218                 if (!NT_STATUS_IS_OK(status)) {
219                         reply_nterror(req, status);
220                         return;
221                 }
222         }
223
224         if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
225                 reply_unixerror(req, ERRDOS,ERRnoaccess);
226                 return;
227         }
228
229         reply_outbuf(req, 6, 0);
230
231         nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
232         SSVAL(req->outbuf,smb_vwv2,nwritten);
233   
234         DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", fsp->fnum,
235                  (int)nwritten));
236
237         chain_reply(req);
238 }
239
240 /****************************************************************************
241  Reply to a read and X.
242  This code is basically stolen from reply_read_and_X with some
243  wrinkles to handle pipes.
244 ****************************************************************************/
245
246 void reply_pipe_read_and_X(struct smb_request *req)
247 {
248         files_struct *fsp = file_fsp(req, SVAL(req->vwv+0, 0));
249         int smb_maxcnt = SVAL(req->vwv+5, 0);
250         int smb_mincnt = SVAL(req->vwv+6, 0);
251         ssize_t nread;
252         uint8_t *data;
253         bool unused;
254         NTSTATUS status;
255
256         /* we don't use the offset given to use for pipe reads. This
257            is deliberate, instead we always return the next lump of
258            data on the pipe */
259 #if 0
260         uint32 smb_offs = IVAL(req->vwv+3, 0);
261 #endif
262
263         if (!fsp_is_np(fsp)) {
264                 reply_doserror(req, ERRDOS, ERRbadfid);
265                 return;
266         }
267
268         if (fsp->vuid != req->vuid) {
269                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
270                 return;
271         }
272
273         reply_outbuf(req, 12, smb_maxcnt);
274
275         data = (uint8_t *)smb_buf(req->outbuf);
276
277         status = np_read(fsp, data, smb_maxcnt, &nread, &unused);
278
279         if (!NT_STATUS_IS_OK(status)) {
280                 reply_doserror(req, ERRDOS, ERRnoaccess);
281                 return;
282         }
283
284         srv_set_message((char *)req->outbuf, 12, nread, False);
285   
286         SSVAL(req->outbuf,smb_vwv5,nread);
287         SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf));
288         SSVAL(smb_buf(req->outbuf),-2,nread);
289   
290         DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n",
291                  fsp->fnum, smb_mincnt, smb_maxcnt, (int)nread));
292
293         chain_reply(req);
294 }