*/
#include "includes.h"
+#include "libsmb/namequery.h"
#include "../lib/util/tevent_ntstatus.h"
#include "librpc/gen_ndr/ndr_epmapper_c.h"
#include "../librpc/gen_ndr/ndr_dssetup.h"
Rpc pipe call id.
********************************************************************/
-static uint32 get_rpc_call_id(void)
+static uint32_t get_rpc_call_id(void)
{
- static uint32 call_id = 0;
+ static uint32_t call_id = 0;
return ++call_id;
}
DATA_BLOB *rdata,
DATA_BLOB *reply_pdu)
{
- struct dcerpc_response *r;
- NTSTATUS ret = NT_STATUS_OK;
- size_t pad_len = 0;
+ const struct dcerpc_response *r = NULL;
+ DATA_BLOB tmp_stub = data_blob_null;
+ NTSTATUS ret;
/*
* Point the return values at the real data including the RPC
*/
*rdata = *pdu;
+ if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
+ !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
+ /*
+ * TODO: do we still need this hack which was introduced
+ * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
+ *
+ * I don't even know what AS/U might be...
+ */
+ DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
+ "fragment first/last ON.\n"));
+ pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
+ }
+
/* Ensure we have the correct type. */
switch (pkt->ptype) {
- case DCERPC_PKT_ALTER_RESP:
+ case DCERPC_PKT_BIND_NAK:
+ DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
+ rpccli_pipe_txt(talloc_tos(), cli)));
+
+ ret = dcerpc_verify_ncacn_packet_header(pkt,
+ DCERPC_PKT_BIND_NAK,
+ 0, /* max_auth_info */
+ DCERPC_PFC_FLAG_FIRST |
+ DCERPC_PFC_FLAG_LAST,
+ 0); /* optional flags */
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+ "RPC packet type - %u, expected %u: %s\n",
+ rpccli_pipe_txt(talloc_tos(), cli),
+ pkt->ptype, expected_pkt_type,
+ nt_errstr(ret)));
+ NDR_PRINT_DEBUG(ncacn_packet, pkt);
+ return ret;
+ }
+
+ /* Use this for now... */
+ return NT_STATUS_NETWORK_ACCESS_DENIED;
+
case DCERPC_PKT_BIND_ACK:
+ ret = dcerpc_verify_ncacn_packet_header(pkt,
+ expected_pkt_type,
+ pkt->u.bind_ack.auth_info.length,
+ DCERPC_PFC_FLAG_FIRST |
+ DCERPC_PFC_FLAG_LAST,
+ DCERPC_PFC_FLAG_CONC_MPX |
+ DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+ "RPC packet type - %u, expected %u: %s\n",
+ rpccli_pipe_txt(talloc_tos(), cli),
+ pkt->ptype, expected_pkt_type,
+ nt_errstr(ret)));
+ NDR_PRINT_DEBUG(ncacn_packet, pkt);
+ return ret;
+ }
- /* Client code never receives this kind of packets */
break;
+ case DCERPC_PKT_ALTER_RESP:
+ ret = dcerpc_verify_ncacn_packet_header(pkt,
+ expected_pkt_type,
+ pkt->u.alter_resp.auth_info.length,
+ DCERPC_PFC_FLAG_FIRST |
+ DCERPC_PFC_FLAG_LAST,
+ DCERPC_PFC_FLAG_CONC_MPX |
+ DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+ "RPC packet type - %u, expected %u: %s\n",
+ rpccli_pipe_txt(talloc_tos(), cli),
+ pkt->ptype, expected_pkt_type,
+ nt_errstr(ret)));
+ NDR_PRINT_DEBUG(ncacn_packet, pkt);
+ return ret;
+ }
+
+ break;
case DCERPC_PKT_RESPONSE:
r = &pkt->u.response;
+ ret = dcerpc_verify_ncacn_packet_header(pkt,
+ expected_pkt_type,
+ r->stub_and_verifier.length,
+ 0, /* required_flags */
+ DCERPC_PFC_FLAG_FIRST |
+ DCERPC_PFC_FLAG_LAST);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+ "RPC packet type - %u, expected %u: %s\n",
+ rpccli_pipe_txt(talloc_tos(), cli),
+ pkt->ptype, expected_pkt_type,
+ nt_errstr(ret)));
+ NDR_PRINT_DEBUG(ncacn_packet, pkt);
+ return ret;
+ }
+
+ tmp_stub.data = r->stub_and_verifier.data;
+ tmp_stub.length = r->stub_and_verifier.length;
+
/* Here's where we deal with incoming sign/seal. */
ret = dcerpc_check_auth(cli->auth, pkt,
- &r->stub_and_verifier,
+ &tmp_stub,
DCERPC_RESPONSE_LENGTH,
- pdu, &pad_len);
+ pdu);
if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+ "RPC packet type - %u, expected %u: %s\n",
+ rpccli_pipe_txt(talloc_tos(), cli),
+ pkt->ptype, expected_pkt_type,
+ nt_errstr(ret)));
+ NDR_PRINT_DEBUG(ncacn_packet, pkt);
return ret;
}
- if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
- return NT_STATUS_BUFFER_TOO_SMALL;
- }
-
/* Point the return values at the NDR data. */
- rdata->data = r->stub_and_verifier.data;
-
- if (pkt->auth_length) {
- /* We've already done integer wrap tests in
- * dcerpc_check_auth(). */
- rdata->length = r->stub_and_verifier.length
- - pad_len
- - DCERPC_AUTH_TRAILER_LENGTH
- - pkt->auth_length;
- } else {
- rdata->length = r->stub_and_verifier.length;
- }
+ *rdata = tmp_stub;
- DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
+ DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
(long unsigned int)pdu->length,
- (long unsigned int)rdata->length,
- (unsigned int)pad_len));
+ (long unsigned int)rdata->length));
/*
* If this is the first reply, and the allocation hint is
break;
- case DCERPC_PKT_BIND_NAK:
- DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
- rpccli_pipe_txt(talloc_tos(), cli)));
- /* Use this for now... */
- return NT_STATUS_NETWORK_ACCESS_DENIED;
-
case DCERPC_PKT_FAULT:
+ ret = dcerpc_verify_ncacn_packet_header(pkt,
+ DCERPC_PKT_FAULT,
+ 0, /* max_auth_info */
+ DCERPC_PFC_FLAG_FIRST |
+ DCERPC_PFC_FLAG_LAST,
+ DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+ "RPC packet type - %u, expected %u: %s\n",
+ rpccli_pipe_txt(talloc_tos(), cli),
+ pkt->ptype, expected_pkt_type,
+ nt_errstr(ret)));
+ NDR_PRINT_DEBUG(ncacn_packet, pkt);
+ return ret;
+ }
+
DEBUG(1, (__location__ ": RPC fault code %s received "
"from %s!\n",
dcerpc_errstr(talloc_tos(),
return NT_STATUS_RPC_PROTOCOL_ERROR;
}
- if (pkt->ptype != expected_pkt_type) {
- DEBUG(3, (__location__ ": Connection to %s got an unexpected "
- "RPC packet type - %u, not %u\n",
- rpccli_pipe_txt(talloc_tos(), cli),
- pkt->ptype, expected_pkt_type));
- return NT_STATUS_RPC_PROTOCOL_ERROR;
- }
if (pkt->call_id != call_id) {
DEBUG(3, (__location__ ": Connection to %s got an unexpected "
return NT_STATUS_RPC_PROTOCOL_ERROR;
}
- /* Do this just before return - we don't want to modify any rpc header
- data before now as we may have needed to do cryptographic actions on
- it before. */
-
- if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
- !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
- DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
- "fragment first/last ON.\n"));
- pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
- }
-
return NT_STATUS_OK;
}
state->pkt = talloc(state, struct ncacn_packet);
if (!state->pkt) {
+ /*
+ * TODO: do a real async disconnect ...
+ *
+ * For now do it sync...
+ */
+ TALLOC_FREE(state->cli->transport);
tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
status = dcerpc_pull_ncacn_packet(state->pkt,
&state->incoming_frag,
- state->pkt,
- !state->endianess);
+ state->pkt);
if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * TODO: do a real async disconnect ...
+ *
+ * For now do it sync...
+ */
+ TALLOC_FREE(state->cli->transport);
tevent_req_nterror(req, status);
return;
}
- if (state->incoming_frag.length != state->pkt->frag_length) {
- DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
- (unsigned int)state->incoming_frag.length,
- (unsigned int)state->pkt->frag_length));
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
}
status = cli_pipe_validate_current_pdu(state,
(unsigned)state->reply_pdu_offset,
nt_errstr(status)));
+ if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
+ /*
+ * TODO: do a real async disconnect ...
+ *
+ * For now do it sync...
+ */
+ TALLOC_FREE(state->cli->transport);
+ } 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);
+ } 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);
+ }
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
return;
"%s\n",
state->endianess?"little":"big",
state->pkt->drep[0]?"little":"big"));
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ /*
+ * TODO: do a real async disconnect ...
+ *
+ * For now do it sync...
+ */
+ TALLOC_FREE(state->cli->transport);
+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+ return;
+ }
+
+ if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
+ /*
+ * TODO: do a real async disconnect ...
+ *
+ * For now do it sync...
+ */
+ TALLOC_FREE(state->cli->transport);
+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
return;
}
if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
if (!data_blob_realloc(NULL, &state->reply_pdu,
state->reply_pdu_offset + rdata.length)) {
+ /*
+ * TODO: do a real async disconnect ...
+ *
+ * For now do it sync...
+ */
+ TALLOC_FREE(state->cli->transport);
tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
subreq = get_complete_frag_send(state, state->ev, state->cli,
&state->incoming_frag);
+ if (subreq == NULL) {
+ /*
+ * TODO: do a real async disconnect ...
+ *
+ * For now do it sync...
+ */
+ TALLOC_FREE(state->cli->transport);
+ }
if (tevent_req_nomem(subreq, req)) {
return;
}
DATA_BLOB null_blob = data_blob_null;
NTSTATUS status;
- gensec_security = talloc_get_type_abort(cli->auth->auth_ctx,
- struct gensec_security);
+ gensec_security = cli->auth->auth_ctx;
DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
return status;
}
- if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
+ if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
*client_hdr_signing = false;
return status;
}
static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
enum dcerpc_pkt_type ptype,
- uint32 rpc_call_id,
+ uint32_t rpc_call_id,
const struct ndr_syntax_id *abstract,
const struct ndr_syntax_id *transfer,
const DATA_BLOB *auth_info,
bool client_hdr_signing,
DATA_BLOB *blob)
{
- uint16 auth_len = auth_info->length;
+ uint16_t auth_len = auth_info->length;
NTSTATUS status;
union dcerpc_payload u;
struct dcerpc_ctx_list ctx_list;
static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
struct rpc_pipe_client *cli,
struct pipe_auth_data *auth,
- uint32 rpc_call_id,
+ uint32_t rpc_call_id,
const struct ndr_syntax_id *abstract,
const struct ndr_syntax_id *transfer,
DATA_BLOB *rpc_out)
{
DATA_BLOB auth_token = data_blob_null;
DATA_BLOB auth_info = data_blob_null;
- NTSTATUS ret = NT_STATUS_OK;
+ NTSTATUS ret;
switch (auth->auth_type) {
case DCERPC_AUTH_TYPE_NONE:
auth->auth_type,
auth->auth_level,
0, /* auth_pad_length */
- 1, /* auth_context_id */
+ auth->auth_context_id,
&auth_token,
&auth_info);
if (!NT_STATUS_IS_OK(ret)) {
uint8_t op_num;
uint32_t call_id;
const DATA_BLOB *req_data;
+ const struct GUID *object_uuid;
uint32_t req_data_sent;
DATA_BLOB req_trailer;
uint32_t req_trailer_sent;
struct tevent_context *ev,
struct rpc_pipe_client *cli,
uint8_t op_num,
+ const struct GUID *object_uuid,
const DATA_BLOB *req_data)
{
struct tevent_req *req, *subreq;
state->ev = ev;
state->cli = cli;
state->op_num = op_num;
+ state->object_uuid = object_uuid;
state->req_data = req_data;
state->req_data_sent = 0;
state->call_id = get_rpc_call_id();
return NT_STATUS_OK;
}
- if (a->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
+ if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
return NT_STATUS_OK;
}
status = dcerpc_guess_sizes(state->cli->auth,
DCERPC_REQUEST_LENGTH, total_left,
state->cli->max_xmit_frag,
- CLIENT_NDR_PADDING_SIZE,
&total_thistime,
&frag_len, &auth_len, &pad_len);
if (!NT_STATUS_IS_OK(status)) {
u.request.context_id = 0;
u.request.opnum = state->op_num;
+ if (state->object_uuid) {
+ flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
+ u.request.object.object = *state->object_uuid;
+ frag_len += ndr_size_GUID(state->object_uuid, 0);
+ }
+
status = dcerpc_push_ncacn_packet(state,
DCERPC_PKT_REQUEST,
flags,
switch (state->cli->auth->auth_level) {
case DCERPC_AUTH_LEVEL_NONE:
case DCERPC_AUTH_LEVEL_CONNECT:
- case DCERPC_AUTH_LEVEL_PACKET:
break;
+ case DCERPC_AUTH_LEVEL_PACKET:
case DCERPC_AUTH_LEVEL_INTEGRITY:
case DCERPC_AUTH_LEVEL_PRIVACY:
status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
struct rpc_pipe_client *cli,
- uint32 rpc_call_id,
- enum dcerpc_AuthType auth_type,
- enum dcerpc_AuthLevel auth_level,
+ struct pipe_auth_data *auth,
+ uint32_t rpc_call_id,
DATA_BLOB *pauth_blob,
DATA_BLOB *rpc_out)
{
u.auth3._pad = 0;
status = dcerpc_push_dcerpc_auth(mem_ctx,
- auth_type,
- auth_level,
+ auth->auth_type,
+ auth->auth_level,
0, /* auth_pad_length */
- 1, /* auth_context_id */
+ auth->auth_context_id,
pauth_blob,
&u.auth3.auth_info);
if (!NT_STATUS_IS_OK(status)) {
********************************************************************/
static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
- enum dcerpc_AuthType auth_type,
- enum dcerpc_AuthLevel auth_level,
- uint32 rpc_call_id,
+ struct pipe_auth_data *auth,
+ uint32_t rpc_call_id,
const struct ndr_syntax_id *abstract,
const struct ndr_syntax_id *transfer,
const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
NTSTATUS status;
status = dcerpc_push_dcerpc_auth(mem_ctx,
- auth_type,
- auth_level,
+ auth->auth_type,
+ auth->auth_level,
0, /* auth_pad_length */
- 1, /* auth_context_id */
+ auth->auth_context_id,
pauth_blob,
&auth_info);
if (!NT_STATUS_IS_OK(status)) {
return;
}
+ if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
+ if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
+ if (pauth->client_hdr_signing) {
+ pauth->hdr_signing = true;
+ }
+ }
+ }
+
state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
- state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
switch(pauth->auth_type) {
return;
default:
- /* Paranoid lenght checks */
- if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
- + pkt->auth_length) {
- tevent_req_nterror(req,
- NT_STATUS_INFO_LENGTH_MISMATCH);
+ if (pkt->auth_length == 0) {
+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
return;
}
+
/* get auth credentials */
- status = dcerpc_pull_dcerpc_auth(talloc_tos(),
- &pkt->u.bind_ack.auth_info,
- &auth, false);
+ status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
+ &pkt->u.bind_ack.auth_info,
+ &auth, NULL, true);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
nt_errstr(status)));
tevent_req_nterror(req, status);
return;
}
+
+ if (auth.auth_type != pauth->auth_type) {
+ DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
+ auth.auth_type, pauth->auth_type));
+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+ return;
+ }
+
+ if (auth.auth_level != pauth->auth_level) {
+ DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
+ auth.auth_level, pauth->auth_level));
+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+ return;
+ }
+
+ if (auth.auth_context_id != pauth->auth_context_id) {
+ DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
+ (unsigned)auth.auth_context_id,
+ (unsigned)pauth->auth_context_id));
+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+ return;
+ }
+
break;
}
return;
default:
- gensec_security = talloc_get_type_abort(pauth->auth_ctx,
- struct gensec_security);
+ gensec_security = pauth->auth_ctx;
- if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
- if (pauth->client_hdr_signing) {
- pauth->hdr_signing = true;
- gensec_want_feature(gensec_security,
- GENSEC_FEATURE_SIGN_PKT_HEADER);
- }
- }
status = gensec_update(gensec_security, state,
auth.credentials, &auth_token);
status = rpc_bind_next_send(req, state,
&auth_token);
} else if (NT_STATUS_IS_OK(status)) {
+ if (pauth->hdr_signing) {
+ gensec_want_feature(gensec_security,
+ GENSEC_FEATURE_SIGN_PKT_HEADER);
+ }
+
if (auth_token.length == 0) {
/* Bind complete. */
tevent_req_done(req);
/* Now prepare the alter context pdu. */
data_blob_free(&state->rpc_out);
- status = create_rpc_alter_context(state,
- auth->auth_type,
- auth->auth_level,
+ status = create_rpc_alter_context(state, auth,
state->rpc_call_id,
&state->cli->abstract_syntax,
&state->cli->transfer_syntax,
/* Now prepare the auth3 context pdu. */
data_blob_free(&state->rpc_out);
- status = create_rpc_bind_auth3(state, state->cli,
+ status = create_rpc_bind_auth3(state, state->cli, auth,
state->rpc_call_id,
- auth->auth_type,
- auth->auth_level,
auth_token,
&state->rpc_out);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- if (!tevent_req_poll(req, ev)) {
- status = map_nt_error_from_unix(errno);
+ if (!tevent_req_poll_ntstatus(req, ev, &status)) {
goto fail;
}
}
subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
- opnum, &state->in_data);
+ opnum, object, &state->in_data);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
/*
* TODO: do a real async disconnect ...
*
- * For now the caller needs to free rpc_cli
+ * For now we do it sync...
*/
+ TALLOC_FREE(hs->rpc_cli->transport);
hs->rpc_cli = NULL;
tevent_req_done(req);
struct pipe_auth_data **presult)
{
struct pipe_auth_data *result;
+ struct auth_generic_state *auth_generic_ctx;
+ NTSTATUS status;
result = talloc_zero(mem_ctx, struct pipe_auth_data);
if (result == NULL) {
result->auth_type = DCERPC_AUTH_TYPE_NONE;
result->auth_level = DCERPC_AUTH_LEVEL_NONE;
+ result->auth_context_id = 0;
- result->user_name = talloc_strdup(result, "");
- result->domain = talloc_strdup(result, "");
- if ((result->user_name == NULL) || (result->domain == NULL)) {
- TALLOC_FREE(result);
- return NT_STATUS_NO_MEMORY;
+ status = auth_generic_client_prepare(result,
+ &auth_generic_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to create auth_generic context: %s\n",
+ nt_errstr(status)));
+ }
+
+ status = auth_generic_set_username(auth_generic_ctx, "");
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to set username: %s\n",
+ nt_errstr(status)));
+ }
+
+ status = auth_generic_set_domain(auth_generic_ctx, "");
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to set domain: %s\n",
+ nt_errstr(status)));
+ return status;
}
+ status = gensec_set_credentials(auth_generic_ctx->gensec_security,
+ auth_generic_ctx->credentials);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+ talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
+ auth_generic_ctx->credentials = NULL;
+
+ result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
+ talloc_free(auth_generic_ctx);
*presult = result;
return NT_STATUS_OK;
}
result->auth_type = auth_type;
result->auth_level = auth_level;
-
- result->user_name = talloc_strdup(result, username);
- result->domain = talloc_strdup(result, domain);
- if ((result->user_name == NULL) || (result->domain == NULL)) {
- status = NT_STATUS_NO_MEMORY;
- goto fail;
- }
+ result->auth_context_id = 1;
status = auth_generic_client_prepare(result,
&auth_generic_ctx);
return status;
}
+/* This routine steals the creds pointer that is passed in */
+static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
+ enum dcerpc_AuthType auth_type,
+ enum dcerpc_AuthLevel auth_level,
+ const char *server,
+ const char *target_service,
+ struct cli_credentials *creds,
+ struct pipe_auth_data **presult)
+{
+ struct auth_generic_state *auth_generic_ctx;
+ struct pipe_auth_data *result;
+ NTSTATUS status;
+
+ result = talloc_zero(mem_ctx, struct pipe_auth_data);
+ if (result == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ result->auth_type = auth_type;
+ result->auth_level = auth_level;
+ result->auth_context_id = 1;
+
+ status = auth_generic_client_prepare(result,
+ &auth_generic_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ status = auth_generic_set_creds(auth_generic_ctx, creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
+ talloc_free(auth_generic_ctx);
+ *presult = result;
+ return NT_STATUS_OK;
+
+ fail:
+ TALLOC_FREE(result);
+ return status;
+}
+
NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
struct pipe_auth_data **presult)
{
"host", /* target_service */
NAME_NT_AUTHORITY, /* domain */
"SYSTEM",
- "", /* password */
+ NULL, /* password */
CRED_DONT_USE_KERBEROS,
NULL, /* netlogon_creds_CredentialState */
presult);
result->transfer_syntax = ndr_transfer_syntax_ndr;
result->desthost = talloc_strdup(result, host);
+ if (result->desthost == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
result->srv_name_slash = talloc_asprintf_strupper_m(
result, "\\\\%s", result->desthost);
- if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
+ if (result->srv_name_slash == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
- result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
if (ss_addr == NULL) {
if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
result->transfer_syntax = ndr_transfer_syntax_ndr;
result->desthost = get_myname(result);
+ if (result->desthost == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
result->srv_name_slash = talloc_asprintf_strupper_m(
result, "\\\\%s", result->desthost);
- if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
+ if (result->srv_name_slash == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
- result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
result->abstract_syntax = table->syntax_id;
result->transfer_syntax = ndr_transfer_syntax_ndr;
- result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
- result->srv_name_slash = talloc_asprintf_strupper_m(
- result, "\\\\%s", result->desthost);
- result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
- result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
+ result->desthost = talloc_strdup(
+ result, smbXcli_conn_remote_name(cli->conn));
+ if (result->desthost == NULL) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
- if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
+ result->srv_name_slash = talloc_asprintf_strupper_m(
+ result, "\\\\%s", result->desthost);
+ if (result->srv_name_slash == NULL) {
TALLOC_FREE(result);
return NT_STATUS_NO_MEMORY;
}
+ result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
+
status = rpc_transport_np_init(result, cli, table,
&result->transport);
if (!NT_STATUS_IS_OK(status)) {
* from the enclosing SMB creds
*/
- TALLOC_FREE(auth->user_name);
- TALLOC_FREE(auth->domain);
-
- auth->user_name = talloc_strdup(auth, cli->user_name);
- auth->domain = talloc_strdup(auth, cli->domain);
-
- if ((cli->user_name != NULL && auth->user_name == NULL)
- || (cli->domain != NULL && auth->domain == NULL)) {
- TALLOC_FREE(result);
- return NT_STATUS_NO_MEMORY;
- }
-
if (transport == NCACN_NP) {
struct smbXcli_session *session;
/****************************************************************************
Open a named pipe to an SMB server and bind using the mech specified
+
+ This routine references the creds pointer that is passed in
****************************************************************************/
-NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
- const struct ndr_interface_table *table,
- enum dcerpc_transport_t transport,
- enum dcerpc_AuthType auth_type,
- enum dcerpc_AuthLevel auth_level,
- const char *server,
- const char *domain,
- const char *username,
- const char *password,
- struct rpc_pipe_client **presult)
+NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
+ const struct ndr_interface_table *table,
+ enum dcerpc_transport_t transport,
+ enum dcerpc_AuthType auth_type,
+ enum dcerpc_AuthLevel auth_level,
+ const char *server,
+ struct cli_credentials *creds,
+ struct rpc_pipe_client **presult)
{
struct rpc_pipe_client *result;
struct pipe_auth_data *auth = NULL;
const char *target_service = table->authservices->names[0];
-
NTSTATUS status;
status = cli_rpc_pipe_open(cli, transport, table, &result);
return status;
}
- status = rpccli_generic_bind_data(result,
- auth_type, auth_level,
- server, target_service,
- domain, username, password,
- CRED_AUTO_USE_KERBEROS,
- NULL,
- &auth);
+ status = rpccli_generic_bind_data_from_creds(result,
+ auth_type, auth_level,
+ server, target_service,
+ creds,
+ &auth);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
- nt_errstr(status)));
+ DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
+ nt_errstr(status));
goto err;
}
status = rpc_pipe_bind(result, auth);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
- nt_errstr(status) ));
+ DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
+ nt_errstr(status));
goto err;
}
- DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
- "machine %s and bound as user %s\\%s.\n", table->name,
- result->desthost, domain, username));
+ DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
+ table->name,
+ result->desthost,
+ cli_credentials_get_unparsed_name(creds, talloc_tos()));
*presult = result;
return NT_STATUS_OK;
return status;
}
-/****************************************************************************
- External interface.
- Open a named pipe to an SMB server and bind using schannel (bind type 68)
- using session_key. sign and seal.
-
- The *pdc will be stolen onto this new pipe
- ****************************************************************************/
-
-NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
- const struct ndr_interface_table *table,
- enum dcerpc_transport_t transport,
- const char *domain,
- struct netlogon_creds_cli_context *netlogon_creds,
- struct rpc_pipe_client **_rpccli)
+NTSTATUS cli_rpc_pipe_open_bind_schannel(
+ struct cli_state *cli,
+ const struct ndr_interface_table *table,
+ enum dcerpc_transport_t transport,
+ struct netlogon_creds_cli_context *netlogon_creds,
+ struct rpc_pipe_client **_rpccli)
{
struct rpc_pipe_client *rpccli;
struct pipe_auth_data *rpcauth;
- struct netlogon_creds_CredentialState *creds = NULL;
+ const char *target_service = table->authservices->names[0];
+ struct cli_credentials *cli_creds;
enum dcerpc_AuthLevel auth_level;
NTSTATUS status;
- const char *target_service = table->authservices->names[0];
- int rpc_pipe_bind_dbglvl = 0;
status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &creds);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("netlogon_creds_cli_get returned %s\n",
- nt_errstr(status)));
- TALLOC_FREE(rpccli);
- return status;
- }
-
auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
- status = rpccli_generic_bind_data(rpccli,
- DCERPC_AUTH_TYPE_SCHANNEL,
- auth_level,
- NULL,
- target_service,
- domain,
- creds->computer_name,
- NULL,
- CRED_AUTO_USE_KERBEROS,
- creds,
- &rpcauth);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
- nt_errstr(status)));
+ status = netlogon_creds_bind_cli_credentials(
+ netlogon_creds, rpccli, &cli_creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
+ nt_errstr(status));
TALLOC_FREE(rpccli);
return status;
}
- status = rpc_pipe_bind(rpccli, rpcauth);
- if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
- rpc_pipe_bind_dbglvl = 1;
- netlogon_creds_cli_delete(netlogon_creds, &creds);
- }
+ status = rpccli_generic_bind_data_from_creds(rpccli,
+ DCERPC_AUTH_TYPE_SCHANNEL,
+ auth_level,
+ rpccli->desthost,
+ target_service,
+ cli_creds,
+ &rpcauth);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(rpc_pipe_bind_dbglvl,
- ("cli_rpc_pipe_open_schannel_with_key: "
- "rpc_pipe_bind failed with error %s\n",
- nt_errstr(status)));
+ DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
+ nt_errstr(status)));
TALLOC_FREE(rpccli);
return status;
}
- TALLOC_FREE(creds);
+ status = rpc_pipe_bind(rpccli, rpcauth);
- if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
- goto done;
- }
+ /* No TALLOC_FREE, gensec takes references */
+ talloc_unlink(rpccli, cli_creds);
+ cli_creds = NULL;
- status = netlogon_creds_cli_check(netlogon_creds,
- rpccli->binding_handle);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
- nt_errstr(status)));
+ DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
+ nt_errstr(status));
TALLOC_FREE(rpccli);
return status;
}
-
-done:
- DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
- "for domain %s and bound using schannel.\n",
- table->name,
- rpccli->desthost, domain));
-
*_rpccli = rpccli;
+
return NT_STATUS_OK;
}
-NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli,
- const struct ndr_interface_table *table,
- enum dcerpc_transport_t transport,
- const char *oid,
- enum dcerpc_AuthLevel auth_level,
- const char *server,
- const char *domain,
- const char *username,
- const char *password,
- struct rpc_pipe_client **presult)
+NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
+ const struct ndr_interface_table *table,
+ enum dcerpc_transport_t transport,
+ struct netlogon_creds_cli_context *netlogon_creds,
+ struct rpc_pipe_client **_rpccli)
{
- struct rpc_pipe_client *result;
- struct pipe_auth_data *auth = NULL;
- const char *target_service = table->authservices->names[0];
-
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct rpc_pipe_client *rpccli;
+ struct netlogon_creds_cli_lck *lck;
NTSTATUS status;
- enum credentials_use_kerberos use_kerberos;
-
- if (strcmp(oid, GENSEC_OID_KERBEROS5) == 0) {
- use_kerberos = CRED_MUST_USE_KERBEROS;
- } else if (strcmp(oid, GENSEC_OID_NTLMSSP) == 0) {
- use_kerberos = CRED_DONT_USE_KERBEROS;
- } else {
- return NT_STATUS_INVALID_PARAMETER;
- }
- status = cli_rpc_pipe_open(cli, transport, table, &result);
+ status = netlogon_creds_cli_lck(
+ netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
+ frame, &lck);
if (!NT_STATUS_IS_OK(status)) {
+ DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
+ nt_errstr(status));
+ TALLOC_FREE(frame);
return status;
}
- status = rpccli_generic_bind_data(result,
- DCERPC_AUTH_TYPE_SPNEGO, auth_level,
- server, target_service,
- domain, username, password,
- use_kerberos, NULL,
- &auth);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
- nt_errstr(status)));
- goto err;
+ status = cli_rpc_pipe_open_bind_schannel(
+ cli, table, transport, netlogon_creds, &rpccli);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
+ netlogon_creds_cli_delete_lck(netlogon_creds);
}
-
- status = rpc_pipe_bind(result, auth);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("cli_rpc_pipe_open_spnego: cli_rpc_pipe_bind failed with error %s\n",
- nt_errstr(status) ));
- goto err;
+ DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
+ nt_errstr(status));
+ TALLOC_FREE(frame);
+ return status;
}
- DEBUG(10,("cli_rpc_pipe_open_spnego: opened pipe %s to "
- "machine %s.\n", table->name,
- result->desthost));
+ if (ndr_syntax_id_equal(&table->syntax_id,
+ &ndr_table_netlogon.syntax_id)) {
+ status = netlogon_creds_cli_check(netlogon_creds,
+ rpccli->binding_handle,
+ NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(frame);
+ return status;
+ }
+ }
- *presult = result;
- return NT_STATUS_OK;
+ DBG_DEBUG("opened pipe %s to machine %s with key %s "
+ "and bound using schannel.\n",
+ table->name, rpccli->desthost,
+ netlogon_creds_cli_debug_string(netlogon_creds, lck));
- err:
+ TALLOC_FREE(frame);
- TALLOC_FREE(result);
- return status;
+ *_rpccli = rpccli;
+ return NT_STATUS_OK;
}
NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
make_dup = true;
break;
default:
- gensec_security = talloc_get_type(a->auth_ctx,
- struct gensec_security);
+ gensec_security = a->auth_ctx;
status = gensec_session_key(gensec_security, mem_ctx, &sk);
if (!NT_STATUS_IS_OK(status)) {
return status;