*/
#include "includes.h"
-
-extern int max_send;
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "smbprofile.h"
+#include "rpc_server/srv_pipe_hnd.h"
#define NERR_notsupported 50
int ldata = rdata ? rdata_len : 0;
int lparam = rparam ? rparam_len : 0;
+ struct smbd_server_connection *sconn = req->sconn;
+ int max_send = sconn->smb1.sessions.max_send;
if (buffer_too_large)
DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
}
show_msg((char *)req->outbuf);
- if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
- IS_CONN_ENCRYPTED(conn))) {
+ if (!srv_send_smb(sconn, (char *)req->outbuf,
+ true, req->seqnum+1,
+ IS_CONN_ENCRYPTED(conn), &req->pcd)) {
exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
}
rparam, tot_param_sent, this_lparam,
rdata, tot_data_sent, this_ldata);
+ SSVAL(req->outbuf,smb_vwv0,lparam);
+ SSVAL(req->outbuf,smb_vwv1,ldata);
+
SSVAL(req->outbuf,smb_vwv3,this_lparam);
SSVAL(req->outbuf,smb_vwv4,
smb_offset(smb_buf(req->outbuf)+1,req->outbuf));
}
show_msg((char *)req->outbuf);
- if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
- IS_CONN_ENCRYPTED(conn)))
+ if (!srv_send_smb(sconn, (char *)req->outbuf,
+ true, req->seqnum+1,
+ IS_CONN_ENCRYPTED(conn), &req->pcd))
exit_server_cleanly("send_trans_reply: srv_send_smb "
"failed.");
Start the first part of an RPC reply which began with an SMBtrans request.
****************************************************************************/
-static void api_rpc_trans_reply(connection_struct *conn,
- struct smb_request *req,
- files_struct *fsp,
- int max_trans_reply)
+struct dcerpc_cmd_state {
+ struct fake_file_handle *handle;
+ uint8_t *data;
+ size_t num_data;
+ size_t max_read;
+};
+
+static void api_dcerpc_cmd_write_done(struct tevent_req *subreq);
+static void api_dcerpc_cmd_read_done(struct tevent_req *subreq);
+
+static void api_dcerpc_cmd(connection_struct *conn, struct smb_request *req,
+ files_struct *fsp, uint8_t *data, size_t length,
+ size_t max_read)
{
- bool is_data_outstanding;
- uint8_t *rdata = SMB_MALLOC_ARRAY(uint8_t, max_trans_reply);
- ssize_t data_len;
- NTSTATUS status;
+ struct tevent_req *subreq;
+ struct dcerpc_cmd_state *state;
+ bool busy;
+
+ if (!fsp_is_np(fsp)) {
+ api_no_reply(conn, req);
+ return;
+ }
- if(rdata == NULL) {
- DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
+ /*
+ * Trans requests are only allowed
+ * if no other Trans or Read is active
+ */
+ busy = np_read_in_progress(fsp->fake_file_handle);
+ if (busy) {
+ reply_nterror(req, NT_STATUS_PIPE_BUSY);
+ return;
+ }
+
+ state = talloc(req, struct dcerpc_cmd_state);
+ if (state == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
+ req->async_priv = state;
+
+ state->handle = fsp->fake_file_handle;
+
+ /*
+ * This memdup severely sucks. But doing it properly essentially means
+ * to rewrite lanman.c, something which I don't really want to do now.
+ */
+ state->data = (uint8_t *)talloc_memdup(state, data, length);
+ if (state->data == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ state->num_data = length;
+ state->max_read = max_read;
+
+ subreq = np_write_send(state, server_event_context(), state->handle,
+ state->data, length);
+ if (subreq == NULL) {
+ TALLOC_FREE(state);
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ tevent_req_set_callback(subreq, api_dcerpc_cmd_write_done,
+ talloc_move(conn, &req));
+}
+
+static void api_dcerpc_cmd_write_done(struct tevent_req *subreq)
+{
+ struct smb_request *req = tevent_req_callback_data(
+ subreq, struct smb_request);
+ struct dcerpc_cmd_state *state = talloc_get_type_abort(
+ req->async_priv, struct dcerpc_cmd_state);
+ NTSTATUS status;
+ ssize_t nwritten = -1;
+
+ status = np_write_recv(subreq, &nwritten);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status) || (nwritten != state->num_data)) {
+ DEBUG(10, ("Could not write to pipe: %s (%d/%d)\n",
+ nt_errstr(status), (int)state->num_data,
+ (int)nwritten));
+ reply_nterror(req, NT_STATUS_PIPE_NOT_AVAILABLE);
+ goto send;
+ }
+
+ state->data = talloc_realloc(state, state->data, uint8_t,
+ state->max_read);
+ if (state->data == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ goto send;
+ }
+
+ subreq = np_read_send(req->conn, server_event_context(),
+ state->handle, state->data, state->max_read);
+ if (subreq == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ goto send;
+ }
+ tevent_req_set_callback(subreq, api_dcerpc_cmd_read_done, req);
+ return;
+
+ send:
+ if (!srv_send_smb(
+ req->sconn, (char *)req->outbuf,
+ true, req->seqnum+1,
+ IS_CONN_ENCRYPTED(req->conn) || req->encrypted,
+ &req->pcd)) {
+ exit_server_cleanly("api_dcerpc_cmd_write_done: "
+ "srv_send_smb failed.");
+ }
+ TALLOC_FREE(req);
+}
+
+static void api_dcerpc_cmd_read_done(struct tevent_req *subreq)
+{
+ struct smb_request *req = tevent_req_callback_data(
+ subreq, struct smb_request);
+ struct dcerpc_cmd_state *state = talloc_get_type_abort(
+ req->async_priv, struct dcerpc_cmd_state);
+ NTSTATUS status;
+ ssize_t nread;
+ bool is_data_outstanding;
+
+ status = np_read_recv(subreq, &nread, &is_data_outstanding);
+ TALLOC_FREE(subreq);
- status = np_read(fsp, rdata, max_trans_reply, &data_len,
- &is_data_outstanding);
if (!NT_STATUS_IS_OK(status)) {
- SAFE_FREE(rdata);
- api_no_reply(conn,req);
+ DEBUG(10, ("Could not read from to pipe: %s\n",
+ nt_errstr(status)));
+ reply_nterror(req, status);
+
+ if (!srv_send_smb(req->sconn, (char *)req->outbuf,
+ true, req->seqnum+1,
+ IS_CONN_ENCRYPTED(req->conn)
+ ||req->encrypted, &req->pcd)) {
+ exit_server_cleanly("api_dcerpc_cmd_read_done: "
+ "srv_send_smb failed.");
+ }
+ TALLOC_FREE(req);
return;
}
- send_trans_reply(conn, req, NULL, 0, (char *)rdata, data_len,
+ send_trans_reply(req->conn, req, NULL, 0, (char *)state->data, nread,
is_data_outstanding);
- SAFE_FREE(rdata);
- return;
+ TALLOC_FREE(req);
}
/****************************************************************************
struct files_struct *fsp;
int pnum;
int subcommand;
- NTSTATUS status;
DEBUG(5,("api_fd_reply\n"));
}
DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n",
- subcommand, fsp->fsp_name, pnum));
+ subcommand, fsp_str_dbg(fsp), pnum));
DEBUG(10, ("api_fd_reply: p:%p max_trans_reply: %d\n", fsp, mdrcnt));
switch (subcommand) {
case TRANSACT_DCERPCCMD: {
/* dce/rpc command */
- ssize_t nwritten;
- status = np_write(fsp, data, tdscnt, &nwritten);
- if (!NT_STATUS_IS_OK(status)) {
- api_no_reply(conn, req);
- return;
- }
- api_rpc_trans_reply(conn, req, fsp, mdrcnt);
+ api_dcerpc_cmd(conn, req, fsp, (uint8_t *)data, tdscnt,
+ mdrcnt);
break;
}
case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
goto bad_param;
}
- if((state->setup = TALLOC_ARRAY(
+ if((state->setup = talloc_array(
state, uint16, state->setup_count)) == NULL) {
DEBUG(0,("reply_trans: setup malloc fail for %u "
"bytes !\n", (unsigned int)
return;
}
+ talloc_steal(talloc_tos(), state);
+
handle_trans(conn, req, state);
SAFE_FREE(state->data);
START_PROFILE(SMBtranss);
- show_msg((char *)req->inbuf);
+ show_msg((const char *)req->inbuf);
if (req->wct < 8) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
}
+ talloc_steal(talloc_tos(), state);
+
handle_trans(conn, req, state);
DLIST_REMOVE(conn->pending_trans, state);