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