2 Unix SMB/CIFS implementation.
4 dcerpc over SMB transport
6 Copyright (C) Tim Potter 2003
7 Copyright (C) Andrew Tridgell 2003
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.
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.
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.
26 /* transport private information used by SMB pipe transport */
29 struct cli_tree *tree;
32 static struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
34 struct smb_private *smb = p->transport.private;
35 struct smb_trans2 trans;
37 struct cli_request *req;
40 mem_ctx = talloc_init("dcerpc_raw_send");
41 if (!mem_ctx) return NULL;
43 trans.in.data = *blob;
44 trans.in.params = data_blob(NULL, 0);
46 setup[0] = TRANSACT_DCERPCCMD;
49 trans.in.max_param = 0;
50 trans.in.max_data = 0x8000;
51 trans.in.max_setup = 0;
52 trans.in.setup_count = 2;
55 trans.in.setup = setup;
56 trans.in.trans_name = "\\PIPE\\";
58 req = smb_raw_trans_send(smb->tree, &trans);
60 talloc_destroy(mem_ctx);
66 static NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p,
67 struct cli_request *req,
71 struct smb_private *smb = p->transport.private;
72 struct smb_trans2 trans;
77 status = smb_raw_trans_recv(req, mem_ctx, &trans);
78 /* STATUS_BUFFER_OVERFLOW means that there is more data
79 available via SMBreadX */
80 if (!NT_STATUS_IS_OK(status) &&
81 !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
85 payload = trans.out.data;
87 if (trans.out.data.length < 16 ||
88 !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
92 /* we might have recieved a partial fragment, in which case we
93 need to pull the rest of it */
94 frag_length = dcerpc_get_frag_length(&payload);
95 if (frag_length <= payload.length) {
99 /* make sure the payload can hold the whole fragment */
100 payload.data = talloc_realloc(mem_ctx, payload.data, frag_length);
102 return NT_STATUS_NO_MEMORY;
105 /* the rest of the data is available via SMBreadX */
106 while (frag_length > payload.length) {
110 n = frag_length - payload.length;
115 io.generic.level = RAW_READ_READX;
116 io.readx.in.fnum = smb->fnum;
117 io.readx.in.mincnt = n;
118 io.readx.in.maxcnt = n;
119 io.readx.in.offset = 0;
120 io.readx.in.remaining = 0;
121 io.readx.out.data = payload.data + payload.length;
122 status = smb_raw_read(smb->tree, &io);
123 if (!NT_STATUS_IS_OK(status) &&
124 !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
128 n = io.readx.out.nread;
130 status = NT_STATUS_UNSUCCESSFUL;
136 /* if the SMBreadX returns NT_STATUS_OK then there
137 isn't any more data to be read */
138 if (NT_STATUS_IS_OK(status)) {
151 static NTSTATUS smb_full_request(struct dcerpc_pipe *p,
153 DATA_BLOB *request_blob,
154 DATA_BLOB *reply_blob)
156 struct cli_request *req;
157 req = dcerpc_raw_send(p, request_blob);
158 return dcerpc_raw_recv(p, req, mem_ctx, reply_blob);
163 retrieve a secondary pdu from a pipe
165 static NTSTATUS smb_secondary_request(struct dcerpc_pipe *p,
169 struct smb_private *smb = p->transport.private;
175 *blob = data_blob_talloc(mem_ctx, NULL, n);
177 return NT_STATUS_NO_MEMORY;
180 io.generic.level = RAW_READ_READX;
181 io.readx.in.fnum = smb->fnum;
182 io.readx.in.mincnt = n;
183 io.readx.in.maxcnt = n;
184 io.readx.in.offset = 0;
185 io.readx.in.remaining = 0;
186 io.readx.out.data = blob->data;
188 status = smb_raw_read(smb->tree, &io);
189 if (!NT_STATUS_IS_OK(status) &&
190 !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
194 blob->length = io.readx.out.nread;
196 if (blob->length < 16) {
200 frag_length = dcerpc_get_frag_length(blob);
201 if (frag_length <= blob->length) {
205 blob->data = talloc_realloc(mem_ctx, blob->data, frag_length);
207 return NT_STATUS_NO_MEMORY;
210 while (frag_length > blob->length &&
211 NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
213 n = frag_length - blob->length;
218 io.readx.in.mincnt = n;
219 io.readx.in.maxcnt = n;
220 io.readx.out.data = blob->data + blob->length;
221 status = smb_raw_read(smb->tree, &io);
223 if (!NT_STATUS_IS_OK(status) &&
224 !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
228 n = io.readx.out.nread;
237 send an initial pdu in a multi-pdu sequence
239 static NTSTATUS smb_initial_request(struct dcerpc_pipe *p,
243 struct smb_private *smb = p->transport.private;
247 io.generic.level = RAW_WRITE_WRITEX;
248 io.writex.in.fnum = smb->fnum;
249 io.writex.in.offset = 0;
250 io.writex.in.wmode = PIPE_START_MESSAGE;
251 io.writex.in.remaining = blob->length;
252 io.writex.in.count = blob->length;
253 io.writex.in.data = blob->data;
255 status = smb_raw_write(smb->tree, &io);
256 if (NT_STATUS_IS_OK(status)) {
260 /* make sure it accepted it all */
261 if (io.writex.out.nwritten != blob->length) {
262 return NT_STATUS_UNSUCCESSFUL;
270 shutdown SMB pipe connection
272 static NTSTATUS smb_shutdown_pipe(struct dcerpc_pipe *p)
274 struct smb_private *smb = p->transport.private;
277 /* maybe we're still starting up */
278 if (!smb) return NT_STATUS_OK;
280 c.close.level = RAW_CLOSE_CLOSE;
281 c.close.in.fnum = smb->fnum;
282 c.close.in.write_time = 0;
283 smb_raw_close(smb->tree, &c);
284 cli_tree_close(smb->tree);
290 return SMB server name
292 static const char *smb_peer_name(struct dcerpc_pipe *p)
294 struct smb_private *smb = p->transport.private;
295 return smb->tree->session->transport->called.name;
300 open a rpc connection to a named pipe
302 NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p,
303 struct cli_tree *tree,
304 const char *pipe_name)
306 struct smb_private *smb;
312 asprintf(&name, "\\%s", pipe_name);
314 return NT_STATUS_NO_MEMORY;
317 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
318 io.ntcreatex.in.flags = 0;
319 io.ntcreatex.in.root_fid = 0;
320 io.ntcreatex.in.access_mask =
321 STD_RIGHT_READ_CONTROL_ACCESS |
322 SA_RIGHT_FILE_WRITE_ATTRIBUTES |
323 SA_RIGHT_FILE_WRITE_EA |
324 GENERIC_RIGHTS_FILE_READ |
325 GENERIC_RIGHTS_FILE_WRITE;
326 io.ntcreatex.in.file_attr = 0;
327 io.ntcreatex.in.alloc_size = 0;
328 io.ntcreatex.in.share_access =
329 NTCREATEX_SHARE_ACCESS_READ |
330 NTCREATEX_SHARE_ACCESS_WRITE;
331 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
332 io.ntcreatex.in.create_options = 0;
333 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
334 io.ntcreatex.in.security_flags = 0;
335 io.ntcreatex.in.fname = name;
337 mem_ctx = talloc_init("torture_rpc_connection");
340 return NT_STATUS_NO_MEMORY;
342 status = smb_raw_open(tree, mem_ctx, &io);
344 talloc_destroy(mem_ctx);
346 if (!NT_STATUS_IS_OK(status)) {
350 if (!(*p = dcerpc_pipe_init())) {
351 return NT_STATUS_NO_MEMORY;
355 fill in the transport methods
357 (*p)->transport.transport = NCACN_NP;
358 (*p)->transport.private = NULL;
359 (*p)->transport.full_request = smb_full_request;
360 (*p)->transport.secondary_request = smb_secondary_request;
361 (*p)->transport.initial_request = smb_initial_request;
362 (*p)->transport.shutdown_pipe = smb_shutdown_pipe;
363 (*p)->transport.peer_name = smb_peer_name;
365 smb = talloc((*p)->mem_ctx, sizeof(*smb));
367 dcerpc_pipe_close(*p);
368 return NT_STATUS_NO_MEMORY;
371 smb->fnum = io.ntcreatex.out.fnum;
374 (*p)->transport.private = smb;
375 tree->reference_count++;
381 return the SMB tree used for a dcerpc over SMB pipe
383 struct cli_tree *dcerpc_smb_tree(struct dcerpc_pipe *p)
385 struct smb_private *smb = p->transport.private;
387 if (p->transport.transport != NCACN_NP) {