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 smbcli_tree *tree;
34 tell the dcerpc layer that the transport is dead
36 static void pipe_dead(struct dcerpc_pipe *p, NTSTATUS status)
38 p->transport.recv_data(p, NULL, status);
43 this holds the state of an in-flight call
45 struct smb_read_state {
46 struct dcerpc_pipe *p;
47 struct smbcli_request *req;
54 called when a read request has completed
56 static void smb_read_callback(struct smbcli_request *req)
58 struct smb_private *smb;
59 struct smb_read_state *state;
64 state = req->async.private;
65 smb = state->p->transport.private;
68 if (!NT_STATUS_IS_OK(req->status)) {
69 pipe_dead(state->p, req->status);
74 status = smb_raw_read_recv(state->req, io);
75 if (!NT_STATUS_IS_OK(status)) {
76 pipe_dead(state->p, status);
81 state->received += io->readx.out.nread;
83 if (state->received < 16) {
84 DEBUG(0,("dcerpc_smb: short packet (length %d) in read callback!\n",
86 pipe_dead(state->p, NT_STATUS_INFO_LENGTH_MISMATCH);
91 frag_length = dcerpc_get_frag_length(&state->data);
92 if (frag_length <= state->received) {
93 state->data.length = state->received;
94 state->p->transport.recv_data(state->p, &state->data, NT_STATUS_OK);
99 /* initiate another read request, as we only got part of a fragment */
100 state->data.data = talloc_realloc(state->data.data, frag_length);
102 io->readx.in.mincnt = frag_length - state->received;
103 io->readx.in.maxcnt = io->readx.in.mincnt;
104 io->readx.out.data = state->data.data + state->received;
106 req = smb_raw_read_send(smb->tree, io);
108 pipe_dead(state->p, NT_STATUS_NO_MEMORY);
113 req->async.fn = smb_read_callback;
114 req->async.private = state;
118 trigger a read request from the server
120 static NTSTATUS send_read_request(struct dcerpc_pipe *p)
122 struct smb_private *smb = p->transport.private;
124 struct smb_read_state *state;
125 struct smbcli_request *req;
127 state = talloc_p(smb, struct smb_read_state);
129 return NT_STATUS_NO_MEMORY;
134 state->data = data_blob_talloc(state, NULL, 0x2000);
135 state->io = talloc_p(state, union smb_read);
138 io->generic.level = RAW_READ_READX;
139 io->readx.in.fnum = smb->fnum;
140 io->readx.in.mincnt = state->data.length;
141 io->readx.in.maxcnt = state->data.length;
142 io->readx.in.offset = 0;
143 io->readx.in.remaining = 0;
144 io->readx.out.data = state->data.data;
145 req = smb_raw_read_send(smb->tree, io);
147 return NT_STATUS_NO_MEMORY;
150 req->async.fn = smb_read_callback;
151 req->async.private = state;
160 called when a write request has completed
162 static void smb_write_callback(struct smbcli_request *req)
164 struct dcerpc_pipe *p = req->async.private;
166 if (!NT_STATUS_IS_OK(req->status)) {
167 DEBUG(0,("dcerpc_smb: write callback error\n"));
168 pipe_dead(p, req->status);
171 smbcli_request_destroy(req);
175 send a packet to the server
177 static NTSTATUS smb_send_request(struct dcerpc_pipe *p, DATA_BLOB *blob)
179 struct smb_private *smb = p->transport.private;
181 struct smbcli_request *req;
183 io.generic.level = RAW_WRITE_WRITEX;
184 io.writex.in.fnum = smb->fnum;
185 io.writex.in.offset = 0;
186 io.writex.in.wmode = PIPE_START_MESSAGE;
187 io.writex.in.remaining = blob->length;
188 io.writex.in.count = blob->length;
189 io.writex.in.data = blob->data;
191 req = smb_raw_write_send(smb->tree, &io);
193 return NT_STATUS_NO_MEMORY;
196 req->async.fn = smb_write_callback;
197 req->async.private = p;
203 return the event context for the pipe, so the caller can wait
204 for events asynchronously
206 static struct event_context *smb_event_context(struct dcerpc_pipe *p)
208 struct smb_private *smb = p->transport.private;
210 return smb->tree->session->transport->event.ctx;
215 shutdown SMB pipe connection
217 static NTSTATUS smb_shutdown_pipe(struct dcerpc_pipe *p)
219 struct smb_private *smb = p->transport.private;
222 /* maybe we're still starting up */
223 if (!smb) return NT_STATUS_OK;
225 c.close.level = RAW_CLOSE_CLOSE;
226 c.close.in.fnum = smb->fnum;
227 c.close.in.write_time = 0;
228 smb_raw_close(smb->tree, &c);
229 smbcli_tree_close(smb->tree);
235 return SMB server name
237 static const char *smb_peer_name(struct dcerpc_pipe *p)
239 struct smb_private *smb = p->transport.private;
240 return smb->tree->session->transport->called.name;
244 open a rpc connection to a named pipe
246 NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p,
247 struct smbcli_tree *tree,
248 const char *pipe_name)
250 struct smb_private *smb;
256 asprintf(&name, "\\%s", pipe_name);
258 return NT_STATUS_NO_MEMORY;
261 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
262 io.ntcreatex.in.flags = 0;
263 io.ntcreatex.in.root_fid = 0;
264 io.ntcreatex.in.access_mask =
265 STD_RIGHT_READ_CONTROL_ACCESS |
266 SA_RIGHT_FILE_WRITE_ATTRIBUTES |
267 SA_RIGHT_FILE_WRITE_EA |
268 GENERIC_RIGHTS_FILE_READ |
269 GENERIC_RIGHTS_FILE_WRITE;
270 io.ntcreatex.in.file_attr = 0;
271 io.ntcreatex.in.alloc_size = 0;
272 io.ntcreatex.in.share_access =
273 NTCREATEX_SHARE_ACCESS_READ |
274 NTCREATEX_SHARE_ACCESS_WRITE;
275 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
276 io.ntcreatex.in.create_options = 0;
277 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
278 io.ntcreatex.in.security_flags = 0;
279 io.ntcreatex.in.fname = name;
281 mem_ctx = talloc_init("torture_rpc_connection");
284 return NT_STATUS_NO_MEMORY;
286 status = smb_raw_open(tree, mem_ctx, &io);
288 talloc_destroy(mem_ctx);
290 if (!NT_STATUS_IS_OK(status)) {
294 if (!(*p = dcerpc_pipe_init())) {
295 return NT_STATUS_NO_MEMORY;
299 fill in the transport methods
301 (*p)->transport.transport = NCACN_NP;
302 (*p)->transport.private = NULL;
303 (*p)->transport.shutdown_pipe = smb_shutdown_pipe;
304 (*p)->transport.peer_name = smb_peer_name;
306 (*p)->transport.send_request = smb_send_request;
307 (*p)->transport.send_read = send_read_request;
308 (*p)->transport.event_context = smb_event_context;
309 (*p)->transport.recv_data = NULL;
311 smb = talloc((*p), sizeof(*smb));
313 dcerpc_pipe_close(*p);
314 return NT_STATUS_NO_MEMORY;
317 smb->fnum = io.ntcreatex.out.fnum;
320 (*p)->transport.private = smb;
321 tree->reference_count++;
327 return the SMB tree used for a dcerpc over SMB pipe
329 struct smbcli_tree *dcerpc_smb_tree(struct dcerpc_pipe *p)
331 struct smb_private *smb = p->transport.private;
333 if (p->transport.transport != NCACN_NP) {