#include "libcli/named_pipe_auth/npa_tstream.h"
#include "librpc/gen_ndr/ndr_winreg.h"
#include "local_np.h"
+#include "libcli/smb/tstream_smbXcli_np.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_CLI
+static const uint16_t default_bt_features =
+ DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN |
+ DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
+
struct rpc_client_association {
struct dcerpc_binding *binding;
+ struct {
+ uint16_t client;
+ uint16_t negotiated;
+ bool negotiation_done;
+ } features;
+
struct samba_sockaddr addr;
+
+ uint32_t next_call_id;
};
static NTSTATUS rpc_client_association_create(TALLOC_CTX *mem_ctx,
+ uint16_t client_features,
+ uint32_t flags,
const char *target_hostname,
enum dcerpc_transport_t transport,
const struct samba_sockaddr *addr,
if (assoc == NULL) {
return NT_STATUS_NO_MEMORY;
}
+ assoc->features.client = client_features;
+ if (client_features == 0) {
+ /*
+ * Without requested features there
+ * is no point in trying to negotiate
+ * something, so we are done...
+ */
+ assoc->features.negotiation_done = true;
+ }
status = dcerpc_parse_binding(assoc, "", &bd);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(assoc);
return status;
}
+ status = dcerpc_binding_set_flags(bd, flags, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(assoc);
+ return status;
+ }
assoc->binding = bd;
assoc->addr = *addr;
struct rpc_client_connection {
DATA_BLOB transport_session_key;
struct rpc_cli_transport *transport;
+
+ struct {
+ uint16_t max_xmit_frag;
+ uint16_t max_recv_frag;
+ bool client_hdr_signing;
+ bool hdr_signing;
+ bool bind_done;
+ } features;
+
+ uint32_t next_auth_context_id;
+ uint16_t next_pres_context_id;
};
static NTSTATUS rpc_client_connection_create(TALLOC_CTX *mem_ctx,
+ const struct rpc_client_association *assoc,
+ uint16_t max_frag,
struct rpc_client_connection **pconn)
{
struct rpc_client_connection *conn = NULL;
+ uint32_t flags = dcerpc_binding_get_flags(assoc->binding);
+ bool client_hdr_signing = (flags & DCERPC_PROPOSE_HEADER_SIGNING);
conn = talloc_zero(mem_ctx, struct rpc_client_connection);
if (conn == NULL) {
return NT_STATUS_NO_MEMORY;
}
+ conn->features.max_xmit_frag = max_frag;
+ conn->features.max_recv_frag = max_frag;
+ conn->features.client_hdr_signing = client_hdr_signing;
*pconn = conn;
return NT_STATUS_OK;
result->assoc = talloc_move(result, passoc);
result->conn = talloc_move(result, pconn);
- result->transport_session_key = result->conn->transport_session_key;
- result->transport = result->conn->transport;
-
- result->abstract_syntax = table->syntax_id;
+ /* rpc_pipe_bind_send should allocate an id... */
+ result->pres_context_id = UINT16_MAX;
+ result->table = table;
result->transfer_syntax = ndr_transfer_syntax_ndr;
hostname = dcerpc_binding_get_string_option(result->assoc->binding,
return NT_STATUS_NO_MEMORY;
}
- result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
-
- result->binding_handle = rpccli_bh_create(result, NULL, table);
- if (result->binding_handle == NULL) {
- TALLOC_FREE(result);
- return NT_STATUS_NO_MEMORY;
- }
-
if (np_cli != NULL) {
result->np_cli = np_cli;
DLIST_ADD_END(np_cli->pipe_list, result);
return result;
}
-/********************************************************************
- Rpc pipe call id.
- ********************************************************************/
-
-static uint32_t get_rpc_call_id(void)
-{
- static uint32_t call_id = 0;
- return ++call_id;
-}
-
/*******************************************************************
Use SMBreadX to get rest of one fragment's worth of rpc data.
Reads the whole size or give an error message
return tevent_req_post(req, ev);
}
subreq = rpc_read_send(state, state->ev,
- state->cli->transport,
+ state->cli->conn->transport,
pdu->data + received,
RPC_HEADER_LEN - received);
if (tevent_req_nomem(subreq, req)) {
subreq = rpc_read_send(
state,
state->ev,
- state->cli->transport,
+ state->cli->conn->transport,
pdu->data + received,
state->frag_len - received);
if (tevent_req_nomem(subreq, req)) {
* RPC_HEADER_LEN bytes into state->pdu.
*/
- subreq = rpc_read_send(state, state->ev, state->cli->transport,
+ subreq = rpc_read_send(state, state->ev,
+ state->cli->conn->transport,
state->pdu->data + RPC_HEADER_LEN,
state->frag_len - RPC_HEADER_LEN);
if (tevent_req_nomem(subreq, req)) {
/*
* Ensure we're not sending too much.
*/
- if (data->length > cli->max_xmit_frag) {
+ if (data->length > cli->conn->features.max_xmit_frag) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
- subreq = rpc_write_send(state, ev, cli->transport,
+ subreq = rpc_write_send(state, ev, cli->conn->transport,
data->data, data->length);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
* the frag_length available */
max_recv_frag = RPC_HEADER_LEN;
- subreq = cli_api_pipe_send(state, ev, cli->transport,
+ subreq = cli_api_pipe_send(state, ev, cli->conn->transport,
data->data, data->length, max_recv_frag);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
*
* For now do it sync...
*/
- TALLOC_FREE(state->cli->transport);
+ TALLOC_FREE(state->cli->conn);
tevent_req_oom(req);
return;
}
*
* For now do it sync...
*/
- TALLOC_FREE(state->cli->transport);
+ TALLOC_FREE(state->cli->conn);
return;
}
*
* For now do it sync...
*/
- TALLOC_FREE(state->cli->transport);
+ TALLOC_FREE(state->cli->conn);
} else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
/*
* TODO: do a real async disconnect ...
*
* For now do it sync...
*/
- TALLOC_FREE(state->cli->transport);
+ TALLOC_FREE(state->cli->conn);
} else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
/*
* TODO: do a real async disconnect ...
*
* For now do it sync...
*/
- TALLOC_FREE(state->cli->transport);
+ TALLOC_FREE(state->cli->conn);
}
if (tevent_req_nterror(req, status)) {
return;
*
* For now do it sync...
*/
- TALLOC_FREE(state->cli->transport);
+ TALLOC_FREE(state->cli->conn);
tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
return;
}
*
* For now do it sync...
*/
- TALLOC_FREE(state->cli->transport);
+ TALLOC_FREE(state->cli->conn);
tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
return;
}
*
* For now do it sync...
*/
- TALLOC_FREE(state->cli->transport);
+ TALLOC_FREE(state->cli->conn);
tevent_req_oom(req);
return;
}
*
* For now do it sync...
*/
- TALLOC_FREE(state->cli->transport);
+ TALLOC_FREE(state->cli->conn);
}
if (tevent_req_nomem(subreq, req)) {
return;
static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
enum dcerpc_pkt_type ptype,
uint32_t rpc_call_id,
+ struct rpc_client_association *assoc,
+ struct rpc_client_connection *conn,
+ uint16_t pres_context_id,
const struct ndr_syntax_id *abstract,
const struct ndr_syntax_id *transfer,
const DATA_BLOB *auth_info,
uint16_t auth_len = auth_info->length;
NTSTATUS status;
struct ndr_syntax_id bind_time_features = dcerpc_construct_bind_time_features(
- DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING |
- DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN);
+ assoc->features.client);
struct dcerpc_ctx_list ctx_list[2] = {
[0] = {
- .context_id = 0,
+ .context_id = pres_context_id,
.num_transfer_syntaxes = 1,
.abstract_syntax = *abstract,
.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer),
},
[1] = {
- .context_id = 1,
+ /*
+ * For now we assume pres_context_id is 0
+ * because bind time feature negotiation
+ * only happens once per association,
+ * with the first DCERPC Bind.
+ *
+ * With that we use pres_context_id + 1,
+ * but only consume it from conn->next_pres_context_id
+ * in check_bind_response().
+ */
+ .context_id = pres_context_id + 1,
.num_transfer_syntaxes = 1,
.abstract_syntax = *abstract,
.transfer_syntaxes = &bind_time_features,
},
};
+ uint32_t assoc_group_id =
+ dcerpc_binding_get_assoc_group_id(assoc->binding);
union dcerpc_payload u = {
- .bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN,
- .bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN,
- .bind.num_contexts = ptype == DCERPC_PKT_BIND ? 2 : 1,
+ .bind.max_xmit_frag = conn->features.max_xmit_frag,
+ .bind.max_recv_frag = conn->features.max_recv_frag,
+ .bind.assoc_group_id = assoc_group_id,
+ .bind.num_contexts = assoc->features.negotiation_done ? 1 : 2,
.bind.ctx_list = ctx_list,
.bind.auth_info = *auth_info,
};
uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
- if (auth_len) {
- auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
+ if (conn->features.client_hdr_signing &&
+ auth_len != 0 &&
+ !conn->features.hdr_signing)
+ {
+ /*
+ * The first authenticated bind or alter_context
+ * negotiates header signing
+ */
+ pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
}
- if (ptype == DCERPC_PKT_BIND) {
- pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
+ if (auth_len) {
+ auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
}
status = dcerpc_push_ncacn_packet(mem_ctx,
const struct ndr_syntax_id *transfer,
DATA_BLOB *rpc_out)
{
+ enum dcerpc_pkt_type ptype = DCERPC_PKT_BIND;
DATA_BLOB auth_token = { .data = NULL };
DATA_BLOB auth_info = { .data = NULL };
NTSTATUS ret;
+ if (cli->conn->features.bind_done) {
+ ptype = DCERPC_PKT_ALTER;
+ }
+
if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
ret = create_generic_auth_rpc_bind_req(
cli, mem_ctx, &auth_token);
}
ret = create_bind_or_alt_ctx_internal(mem_ctx,
- DCERPC_PKT_BIND,
+ ptype,
rpc_call_id,
+ cli->assoc,
+ cli->conn,
+ cli->pres_context_id,
abstract,
transfer,
&auth_info,
state->op_num = op_num;
state->object_uuid = object_uuid;
state->req_data = req_data;
- state->call_id = get_rpc_call_id();
+ state->call_id = ++cli->assoc->next_call_id;
- if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
+ if (cli->conn->features.max_xmit_frag < DCERPC_REQUEST_LENGTH
+ RPC_MAX_SIGN_SIZE) {
/* Server is screwed up ! */
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
}
tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
} else {
- subreq = rpc_write_send(state, ev, cli->transport,
+ subreq = rpc_write_send(state, ev, cli->conn->transport,
state->rpc_out.data,
state->rpc_out.length);
if (tevent_req_nomem(subreq, req)) {
}
t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
.command = DCERPC_SEC_VT_COMMAND_BITMASK1,
- .u.bitmask1 = (state->cli->client_hdr_signing) ?
+ .u.bitmask1 = (state->cli->conn->features.client_hdr_signing) ?
DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING :
0,
};
t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
.command = DCERPC_SEC_VT_COMMAND_PCONTEXT,
.u.pcontext.abstract_syntax =
- state->cli->abstract_syntax,
+ state->cli->table->syntax_id,
.u.pcontext.transfer_syntax =
state->cli->transfer_syntax,
};
.u.header2.ptype = DCERPC_PKT_REQUEST,
.u.header2.drep[0] = DCERPC_DREP_LE,
.u.header2.call_id = state->call_id,
- .u.header2.context_id = 0,
+ .u.header2.context_id = state->cli->pres_context_id,
.u.header2.opnum = state->op_num,
};
}
status = dcerpc_guess_sizes(state->cli->auth,
DCERPC_REQUEST_LENGTH, total_left,
- state->cli->max_xmit_frag,
+ state->cli->conn->features.max_xmit_frag,
&total_thistime,
&frag_len, &auth_len, &pad_len);
if (!NT_STATUS_IS_OK(status)) {
u = (union dcerpc_payload) {
.request.alloc_hint = total_left,
- .request.context_id = 0,
+ .request.context_id = state->cli->pres_context_id,
.request.opnum = state->op_num,
};
tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
} else {
subreq = rpc_write_send(state, state->ev,
- state->cli->transport,
+ state->cli->conn->transport,
state->rpc_out.data,
state->rpc_out.length);
if (tevent_req_nomem(subreq, req)) {
struct rpc_pipe_client *cli)
{
const struct ndr_syntax_id *transfer = &cli->transfer_syntax;
+ uint32_t assoc_group_id =
+ dcerpc_binding_get_assoc_group_id(cli->assoc->binding);
struct dcerpc_ack_ctx ctx;
bool equal;
DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)\n"));
}
+ if (assoc_group_id == 0) {
+ NTSTATUS status;
+
+ /*
+ * We only capture the first assoc_group_id we're
+ * getting.
+ *
+ * Current samba releases may ignore the client value
+ * and return a different assoc_group_id if the
+ * client given one is not found in the preforked
+ * process. This applies to the source4 netlogon,
+ * which uses DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED.
+ */
+
+ status = dcerpc_binding_set_assoc_group_id(cli->assoc->binding,
+ r->assoc_group_id);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+ }
+
+ if (!cli->conn->features.bind_done) {
+ /*
+ * DCE-RPC 1.1 (c706) specifies
+ * CONST_MUST_RCV_FRAG_SIZE as 1432
+ */
+
+ if (r->max_xmit_frag < 1432) {
+ return false;
+ }
+ if (r->max_recv_frag < 1432) {
+ return false;
+ }
+
+ cli->conn->features.max_xmit_frag =
+ MIN(cli->conn->features.max_xmit_frag, r->max_xmit_frag);
+ cli->conn->features.max_recv_frag =
+ MIN(cli->conn->features.max_recv_frag, r->max_recv_frag);
+
+ cli->conn->features.bind_done = true;
+ }
+
if (r->num_results < 1 || !r->ctx_list) {
return false;
}
const struct dcerpc_ack_ctx *neg = &r->ctx_list[1];
if (neg->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
- cli->bind_time_features = neg->reason.negotiate;
+ cli->assoc->features.negotiated = neg->reason.negotiate;
+ cli->assoc->features.negotiation_done = true;
+ /*
+ * consume presentation context used for bind time
+ * feature negotiation
+ */
+ cli->conn->next_pres_context_id++;
} else {
DBG_DEBUG("bind_time_feature failed - "
"result: %d reason %x\n",
static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
struct pipe_auth_data *auth,
uint32_t rpc_call_id,
+ struct rpc_client_association *assoc,
+ struct rpc_client_connection *conn,
+ uint16_t pres_context_id,
const struct ndr_syntax_id *abstract,
const struct ndr_syntax_id *transfer,
const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
status = create_bind_or_alt_ctx_internal(mem_ctx,
DCERPC_PKT_ALTER,
rpc_call_id,
+ assoc,
+ conn,
+ pres_context_id,
abstract,
transfer,
&auth_info,
struct rpc_pipe_bind_state *state;
struct cli_credentials *creds = NULL;
const char *username = NULL;
+ enum dcerpc_pkt_type rep_ptype = DCERPC_PKT_BIND_ACK;
NTSTATUS status;
+ if (cli->conn->features.bind_done) {
+ rep_ptype = DCERPC_PKT_ALTER_RESP;
+ }
+
req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
if (req == NULL) {
return NULL;
state->ev = ev;
state->cli = cli;
- state->rpc_call_id = get_rpc_call_id();
-
- cli->client_hdr_signing = true;
+ state->rpc_call_id = ++cli->assoc->next_call_id;
cli->auth = talloc_move(cli, &auth);
+ if (cli->auth->auth_context_id == UINT32_MAX) {
+ if (cli->conn->next_auth_context_id == UINT32_MAX) {
+ tevent_req_nterror(req, NT_STATUS_RPC_NO_MORE_BINDINGS);
+ return tevent_req_post(req, ev);
+ }
+ cli->auth->auth_context_id = cli->conn->next_auth_context_id++;
+ }
+ if (cli->pres_context_id == UINT16_MAX) {
+ if (cli->conn->next_pres_context_id == UINT16_MAX) {
+ tevent_req_nterror(req, NT_STATUS_RPC_NO_MORE_BINDINGS);
+ return tevent_req_post(req, ev);
+ }
+ cli->pres_context_id = cli->conn->next_pres_context_id++;
+ }
+
+ cli->binding_handle = rpccli_bh_create(cli, NULL, cli->table);
+ if (tevent_req_nomem(cli->binding_handle, req)) {
+ return tevent_req_post(req, ev);
+ }
creds = gensec_get_credentials(cli->auth->auth_ctx);
username = cli_credentials_get_username(creds);
status = create_rpc_bind_req(state, cli,
cli->auth,
state->rpc_call_id,
- &cli->abstract_syntax,
+ &cli->table->syntax_id,
&cli->transfer_syntax,
&state->rpc_out);
}
subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
- DCERPC_PKT_BIND_ACK, state->rpc_call_id);
+ rep_ptype, state->rpc_call_id);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
return;
}
- if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
- if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
- state->cli->hdr_signing = true;
- }
+ if (state->cli->conn->features.client_hdr_signing &&
+ pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)
+ {
+ state->cli->conn->features.hdr_signing = true;
}
- state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
-
if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
/* Bind complete. */
tevent_req_done(req);
return;
}
- pauth->hdr_signing = state->cli->hdr_signing;
+ pauth->hdr_signing = state->cli->conn->features.hdr_signing;
/* get auth credentials */
status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
status = create_rpc_alter_context(state, auth,
state->rpc_call_id,
- &state->cli->abstract_syntax,
+ state->cli->assoc,
+ state->cli->conn,
+ state->cli->pres_context_id,
+ &state->cli->table->syntax_id,
&state->cli->transfer_syntax,
auth_token,
&state->rpc_out);
{
struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
struct rpccli_bh_state);
- struct rpc_cli_transport *transport = hs->rpc_cli->transport;
+ struct rpc_cli_transport *transport = NULL;
+
+ if (hs->rpc_cli == NULL) {
+ return false;
+ }
+ if (hs->rpc_cli->conn == NULL) {
+ return false;
+ }
+
+ transport = hs->rpc_cli->conn->transport;
if (transport == NULL) {
return false;
}
{
struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
struct rpccli_bh_state);
- struct rpc_cli_transport *transport = hs->rpc_cli->transport;
+ struct rpc_cli_transport *transport = NULL;
unsigned int old;
+ if (hs->rpc_cli->conn == NULL) {
+ return RPCCLI_DEFAULT_TIMEOUT;
+ }
+
+ transport = hs->rpc_cli->conn->transport;
if (transport == NULL) {
return RPCCLI_DEFAULT_TIMEOUT;
}
return NT_STATUS_NO_USER_SESSION_KEY;
}
- if (hs->rpc_cli->transport_session_key.length == 0) {
+ if (hs->rpc_cli->conn == NULL) {
return NT_STATUS_NO_USER_SESSION_KEY;
}
- sk = hs->rpc_cli->transport_session_key;
+ if (hs->rpc_cli->conn->transport_session_key.length == 0) {
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
+ sk = hs->rpc_cli->conn->transport_session_key;
sk.length = MIN(sk.length, 16);
*session_key = data_blob_dup_talloc(mem_ctx, sk);
*
* For now we do it sync...
*/
- TALLOC_FREE(hs->rpc_cli->transport);
+ TALLOC_FREE(hs->rpc_cli->conn);
hs->rpc_cli = NULL;
tevent_req_done(req);
struct dcerpc_binding_handle *h = NULL;
struct rpccli_bh_state *hs = NULL;
struct dcerpc_binding *b = NULL;
+ uint32_t a_flags = 0;
+ uint32_t c_flags = 0;
NTSTATUS status;
+ if (c->conn->features.hdr_signing) {
+ a_flags |= DCERPC_HEADER_SIGNING;
+ } else {
+ c_flags |= DCERPC_HEADER_SIGNING;
+ }
+
+ switch (c->auth->auth_type) {
+ case DCERPC_AUTH_TYPE_KRB5:
+ a_flags |= DCERPC_AUTH_KRB5;
+ c_flags |= DCERPC_AUTH_NTLM;
+ c_flags |= DCERPC_AUTH_SPNEGO;
+ c_flags |= DCERPC_SCHANNEL;
+ break;
+ case DCERPC_AUTH_TYPE_NTLMSSP:
+ c_flags |= DCERPC_AUTH_KRB5;
+ a_flags |= DCERPC_AUTH_NTLM;
+ c_flags |= DCERPC_AUTH_SPNEGO;
+ c_flags |= DCERPC_SCHANNEL;
+ break;
+ case DCERPC_AUTH_TYPE_SPNEGO:
+ c_flags |= DCERPC_AUTH_KRB5;
+ c_flags |= DCERPC_AUTH_NTLM;
+ a_flags |= DCERPC_AUTH_SPNEGO;
+ c_flags |= DCERPC_SCHANNEL;
+ break;
+ case DCERPC_AUTH_TYPE_SCHANNEL:
+ c_flags |= DCERPC_AUTH_KRB5;
+ c_flags |= DCERPC_AUTH_NTLM;
+ c_flags |= DCERPC_AUTH_SPNEGO;
+ a_flags |= DCERPC_SCHANNEL;
+ break;
+ default:
+ c_flags |= DCERPC_AUTH_KRB5;
+ c_flags |= DCERPC_AUTH_NTLM;
+ c_flags |= DCERPC_AUTH_SPNEGO;
+ c_flags |= DCERPC_SCHANNEL;
+ break;
+ }
+
+ if (c->auth->auth_level >= DCERPC_AUTH_LEVEL_PRIVACY) {
+ a_flags |= DCERPC_SEAL;
+ c_flags |= DCERPC_SIGN;
+ c_flags |= DCERPC_CONNECT;
+ } else if (c->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
+ c_flags |= DCERPC_SEAL;
+ a_flags |= DCERPC_SIGN;
+ c_flags |= DCERPC_CONNECT;
+ } else if (c->auth->auth_level >= DCERPC_AUTH_LEVEL_CONNECT) {
+ c_flags |= DCERPC_SEAL;
+ c_flags |= DCERPC_SIGN;
+ a_flags |= DCERPC_CONNECT;
+ } else {
+ c_flags |= DCERPC_SEAL;
+ c_flags |= DCERPC_SIGN;
+ c_flags |= DCERPC_CONNECT;
+ }
+
h = dcerpc_binding_handle_create(c,
&rpccli_bh_ops,
object,
}
hs->rpc_cli = c;
- status = dcerpc_parse_binding(hs, "", &b);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(h);
- return NULL;
- }
- status = dcerpc_binding_set_transport(b, c->transport->transport);
- if (!NT_STATUS_IS_OK(status)) {
+ b = dcerpc_binding_dup(h, c->assoc->binding);
+ if (b == NULL) {
TALLOC_FREE(h);
return NULL;
}
- status = dcerpc_binding_set_string_option(b, "host", c->desthost);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(h);
- return NULL;
- }
- status = dcerpc_binding_set_string_option(b, "target_hostname", c->desthost);
+ status = dcerpc_binding_set_abstract_syntax(b, &table->syntax_id);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(h);
return NULL;
}
- status = dcerpc_binding_set_abstract_syntax(b, &table->syntax_id);
+ status = dcerpc_binding_set_flags(b, a_flags, c_flags);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(h);
return NULL;
result->auth_type = DCERPC_AUTH_TYPE_NONE;
result->auth_level = DCERPC_AUTH_LEVEL_NONE;
- result->auth_context_id = 0;
+ /* rpc_pipe_bind_send should allocate an id... */
+ result->auth_context_id = UINT32_MAX;
status = auth_generic_client_prepare(result,
&auth_generic_ctx);
result->auth_type = auth_type;
result->auth_level = auth_level;
- result->auth_context_id = 1;
+ /* rpc_pipe_bind_send should allocate an id... */
+ result->auth_context_id = UINT32_MAX;
status = auth_generic_client_prepare(result,
&auth_generic_ctx);
result->auth_type = auth_type;
result->auth_level = auth_level;
- result->auth_context_id = 1;
+ /* rpc_pipe_bind_send should allocate an id... */
+ result->auth_context_id = UINT32_MAX;
status = auth_generic_client_prepare(result,
&auth_generic_ctx);
return NT_STATUS_RPC_INVALID_ENDPOINT_FORMAT;
}
- status = rpc_client_connection_create(mem_ctx, &conn);
+ status = rpc_client_connection_create(mem_ctx,
+ assoc,
+ DCERPC_FRAG_MAX_SIZE,
+ &conn);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
}
status = rpc_client_association_create(frame,
+ default_bt_features,
+ DCERPC_PROPOSE_HEADER_SIGNING,
host,
NCACN_IP_TCP,
saddr,
TALLOC_FREE(socket_name);
status = rpc_client_association_create(mem_ctx,
+ 0, /* no client_features */
+ 0, /* flags */
myname,
NCALRPC,
&saddr,
}
talloc_steal(frame, assoc);
- status = rpc_client_connection_create(mem_ctx, &conn);
+ status = rpc_client_connection_create(mem_ctx,
+ assoc,
+ DCERPC_FRAG_MAX_SIZE,
+ &conn);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(frame);
return status;
}
status = rpc_client_association_create(mem_ctx,
+ 0, /* no client_features */
+ 0, /* flags */
local_server_name,
NCACN_NP,
&saddr,
}
talloc_steal(frame, assoc);
- status = rpc_client_connection_create(mem_ctx, &conn);
+ status = rpc_client_connection_create(mem_ctx,
+ assoc,
+ DCERPC_FRAG_MAX_SIZE,
+ &conn);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(frame);
return status;
return tevent_req_post(req, ev);
}
- status = rpc_client_connection_create(state, &state->conn);
+ status = rpc_client_connection_create(state,
+ assoc,
+ TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE,
+ &state->conn);
if (tevent_req_nterror(req, status)) {
return tevent_req_post(req, ev);
}
}
status = rpc_client_association_create(state,
+ default_bt_features,
+ DCERPC_PROPOSE_HEADER_SIGNING,
remote_name,
NCACN_NP,
&saddr,
}
status = rpc_client_association_create(NULL,
+ default_bt_features,
+ DCERPC_PROPOSE_HEADER_SIGNING,
remote_name,
transport,
&saddr,