~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/smbd/pipes.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
        /* TODO: REMOVE PIPE FROM DB */
304
 
 
305
 
        return(outsize);
306
 
}