#include "librpc/rpc/dcerpc.h"
#include "librpc/rpc/dcerpc_proto.h"
#include "librpc/rpc/rpc_common.h"
+#include "../libcli/smb/smbXcli_base.h"
/* transport private information used by SMB pipe transport */
struct smb_private {
uint16_t fnum;
struct smbcli_tree *tree;
+ DATA_BLOB session_key;
const char *server_name;
bool dead;
};
/*
tell the dcerpc layer that the transport is dead
*/
-static void pipe_dead(struct dcerpc_connection *c, NTSTATUS status)
+static void pipe_dead(struct dcecli_connection *c, NTSTATUS status)
{
struct smb_private *smb = (struct smb_private *)c->transport.private_data;
this holds the state of an in-flight call
*/
struct smb_read_state {
- struct dcerpc_connection *c;
+ struct dcecli_connection *c;
struct smbcli_request *req;
size_t received;
DATA_BLOB data;
*/
static void smb_read_callback(struct smbcli_request *req)
{
+ struct dcecli_connection *c;
struct smb_private *smb;
struct smb_read_state *state;
union smb_read *io;
state = talloc_get_type(req->async.private_data, struct smb_read_state);
smb = talloc_get_type(state->c->transport.private_data, struct smb_private);
io = state->io;
+ c = state->c;
status = smb_raw_read_recv(state->req, io);
if (NT_STATUS_IS_ERR(status)) {
- pipe_dead(state->c, status);
talloc_free(state);
+ pipe_dead(c, status);
return;
}
if (state->received < 16) {
DEBUG(0,("dcerpc_smb: short packet (length %d) in read callback!\n",
(int)state->received));
- pipe_dead(state->c, NT_STATUS_INFO_LENGTH_MISMATCH);
talloc_free(state);
+ pipe_dead(c, NT_STATUS_INFO_LENGTH_MISMATCH);
return;
}
if (frag_length <= state->received) {
DATA_BLOB data = state->data;
- struct dcerpc_connection *c = state->c;
data.length = state->received;
talloc_steal(state->c, data.data);
talloc_free(state);
state->req = smb_raw_read_send(smb->tree, io);
if (state->req == NULL) {
- pipe_dead(state->c, NT_STATUS_NO_MEMORY);
talloc_free(state);
+ pipe_dead(c, NT_STATUS_NO_MEMORY);
return;
}
trigger a read request from the server, possibly with some initial
data in the read buffer
*/
-static NTSTATUS send_read_request_continue(struct dcerpc_connection *c, DATA_BLOB *blob)
+static NTSTATUS send_read_request_continue(struct dcecli_connection *c, DATA_BLOB *blob)
{
struct smb_private *smb = (struct smb_private *)c->transport.private_data;
union smb_read *io;
/*
trigger a read request from the server
*/
-static NTSTATUS send_read_request(struct dcerpc_connection *c)
+static NTSTATUS send_read_request(struct dcecli_connection *c)
{
struct smb_private *smb = (struct smb_private *)c->transport.private_data;
this holds the state of an in-flight trans call
*/
struct smb_trans_state {
- struct dcerpc_connection *c;
+ struct dcecli_connection *c;
struct smbcli_request *req;
struct smb_trans2 *trans;
};
static void smb_trans_callback(struct smbcli_request *req)
{
struct smb_trans_state *state = (struct smb_trans_state *)req->async.private_data;
- struct dcerpc_connection *c = state->c;
+ struct dcecli_connection *c = state->c;
NTSTATUS status;
status = smb_raw_trans_recv(req, state, state->trans);
/*
send a SMBtrans style request
*/
-static NTSTATUS smb_send_trans_request(struct dcerpc_connection *c, DATA_BLOB *blob)
+static NTSTATUS smb_send_trans_request(struct dcecli_connection *c, DATA_BLOB *blob)
{
struct smb_private *smb = (struct smb_private *)c->transport.private_data;
struct smb_trans2 *trans;
struct smb_trans_state *state;
uint16_t max_data;
- state = talloc(smb, struct smb_trans_state);
+ state = talloc(c, struct smb_trans_state);
if (state == NULL) {
return NT_STATUS_NO_MEMORY;
}
*/
static void smb_write_callback(struct smbcli_request *req)
{
- struct dcerpc_connection *c = (struct dcerpc_connection *)req->async.private_data;
+ struct dcecli_connection *c = (struct dcecli_connection *)req->async.private_data;
+ union smb_write io;
+ NTSTATUS status;
- if (!NT_STATUS_IS_OK(req->status)) {
- DEBUG(0,("dcerpc_smb: write callback error\n"));
- pipe_dead(c, req->status);
- }
+ ZERO_STRUCT(io);
+ io.generic.level = RAW_WRITE_WRITEX;
- smbcli_request_destroy(req);
+ status = smb_raw_write_recv(req, &io);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("dcerpc_smb: write callback error: %s\n",
+ nt_errstr(status)));
+ pipe_dead(c, status);
+ }
}
/*
send a packet to the server
*/
-static NTSTATUS smb_send_request(struct dcerpc_connection *c, DATA_BLOB *blob,
+static NTSTATUS smb_send_request(struct dcecli_connection *c, DATA_BLOB *blob,
bool trigger_read)
{
struct smb_private *smb = (struct smb_private *)c->transport.private_data;
req->async.fn = smb_write_callback;
req->async.private_data = c;
- if (trigger_read) {
- send_read_request(c);
- }
-
return NT_STATUS_OK;
}
/*
shutdown SMB pipe connection
*/
-static NTSTATUS smb_shutdown_pipe(struct dcerpc_connection *c, NTSTATUS status)
+static NTSTATUS smb_shutdown_pipe(struct dcecli_connection *c, NTSTATUS status)
{
struct smb_private *smb = (struct smb_private *)c->transport.private_data;
union smb_close io;
/*
return SMB server name (called name)
*/
-static const char *smb_peer_name(struct dcerpc_connection *c)
+static const char *smb_peer_name(struct dcecli_connection *c)
{
struct smb_private *smb = (struct smb_private *)c->transport.private_data;
if (smb == NULL) return "";
/*
return remote name we make the actual connection (good for kerberos)
*/
-static const char *smb_target_hostname(struct dcerpc_connection *c)
+static const char *smb_target_hostname(struct dcecli_connection *c)
{
struct smb_private *smb = talloc_get_type(c->transport.private_data, struct smb_private);
if (smb == NULL) return "";
- return smb->tree->session->transport->socket->hostname;
+ return smbXcli_conn_remote_name(smb->tree->session->transport->conn);
}
/*
fetch the user session key
*/
-static NTSTATUS smb_session_key(struct dcerpc_connection *c, DATA_BLOB *session_key)
+static NTSTATUS smb_session_key(struct dcecli_connection *c, DATA_BLOB *session_key)
{
struct smb_private *smb = (struct smb_private *)c->transport.private_data;
if (smb == NULL) return NT_STATUS_CONNECTION_DISCONNECTED;
- if (smb->tree->session->user_session_key.data) {
- *session_key = smb->tree->session->user_session_key;
- return NT_STATUS_OK;
+
+ if (smb->session_key.length == 0) {
+ return NT_STATUS_NO_USER_SESSION_KEY;
}
- return NT_STATUS_NO_USER_SESSION_KEY;
+
+ *session_key = smb->session_key;
+ return NT_STATUS_OK;
}
struct pipe_open_smb_state {
union smb_open *open;
- struct dcerpc_connection *c;
+ struct dcecli_connection *c;
struct smbcli_tree *tree;
struct composite_context *ctx;
};
struct composite_context *ctx;
struct pipe_open_smb_state *state;
struct smbcli_request *req;
- struct dcerpc_connection *c = p->conn;
+ struct dcecli_connection *c = p->conn;
/* if we don't have a binding on this pipe yet, then create one */
if (p->binding == NULL) {
NTSTATUS status;
+ const char *r = smbXcli_conn_remote_name(tree->session->transport->conn);
char *s;
- SMB_ASSERT(tree->session->transport->socket->hostname != NULL);
- s = talloc_asprintf(p, "ncacn_np:%s", tree->session->transport->socket->hostname);
+ SMB_ASSERT(r != NULL);
+ s = talloc_asprintf(p, "ncacn_np:%s", r);
if (s == NULL) return NULL;
status = dcerpc_parse_binding(p, s, &p->binding);
talloc_free(s);
struct pipe_open_smb_state *state = talloc_get_type(req->async.private_data,
struct pipe_open_smb_state);
struct composite_context *ctx = state->ctx;
- struct dcerpc_connection *c = state->c;
+ struct dcecli_connection *c = state->c;
struct smb_private *smb;
ctx->status = smb_raw_open_recv(req, state, state->open);
smb->fnum = state->open->ntcreatex.out.file.fnum;
smb->tree = talloc_reference(smb, state->tree);
smb->server_name= strupper_talloc(smb,
- state->tree->session->transport->called.name);
+ smbXcli_conn_remote_name(state->tree->session->transport->conn));
if (composite_nomem(smb->server_name, ctx)) return;
smb->dead = false;
+ ctx->status = smbXcli_session_application_key(state->tree->session->smbXcli,
+ smb, &smb->session_key);
+ if (NT_STATUS_EQUAL(ctx->status, NT_STATUS_NO_USER_SESSION_KEY)) {
+ smb->session_key = data_blob_null;
+ ctx->status = NT_STATUS_OK;
+ }
+ if (!composite_is_ok(ctx)) return;
+
c->transport.private_data = smb;
composite_done(ctx);
/*
return the SMB tree used for a dcerpc over SMB pipe
*/
-_PUBLIC_ struct smbcli_tree *dcerpc_smb_tree(struct dcerpc_connection *c)
+_PUBLIC_ struct smbcli_tree *dcerpc_smb_tree(struct dcecli_connection *c)
{
struct smb_private *smb;
return smb->tree;
}
-
-/*
- return the SMB fnum used for a dcerpc over SMB pipe (hack for torture operations)
-*/
-_PUBLIC_ uint16_t dcerpc_smb_fnum(struct dcerpc_connection *c)
-{
- struct smb_private *smb;
-
- if (c->transport.transport != NCACN_NP) return 0;
-
- smb = talloc_get_type(c->transport.private_data, struct smb_private);
- if (!smb) return 0;
-
- return smb->fnum;
-}