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