The branch, master has been updated via f40ef7e... s3-dcerpc: Use common send functions for ntlmssp too via 86914b8... s3-dcerpc: properly implement gse/spnego_get_session_key via 26a3ba6... s3-dcerpc: Check data and return appropriate error via 9b8c7d4... s3-dcerpc: Remove unused function via 7b12513... s3-dcerpc: make a few local functions as static via 9a9a38c... Change debug statements to use __location__ via 72a0098... s3-dcerpc: Pull packet in the caller, before validation via 558320c... Add my (c) from 1791d05... s3-samr: Fixed some build warnings.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit f40ef7e24cda2d25dcb04cb7e83cd1f3d62a66e4 Author: Simo Sorce <i...@samba.org> Date: Tue Aug 3 05:11:28 2010 -0400 s3-dcerpc: Use common send functions for ntlmssp too Remove unused function. commit 86914b8fab764667ca5021f44b61c0222dbb2e09 Author: Simo Sorce <i...@samba.org> Date: Mon Aug 2 12:15:43 2010 -0400 s3-dcerpc: properly implement gse/spnego_get_session_key commit 26a3ba60e661bc2eaf05a2c03f8851d252515d3e Author: Simo Sorce <i...@samba.org> Date: Mon Aug 2 12:05:45 2010 -0400 s3-dcerpc: Check data and return appropriate error commit 9b8c7d47f98dffe961dc513f5452dfd72b508136 Author: Simo Sorce <i...@samba.org> Date: Mon Aug 2 12:18:58 2010 -0400 s3-dcerpc: Remove unused function commit 7b12513d125e13a4db3f32adc05030fbb302f510 Author: Simo Sorce <i...@samba.org> Date: Mon Aug 2 10:28:10 2010 -0400 s3-dcerpc: make a few local functions as static commit 9a9a38c666a8285fdfac35758aa85f5d33ba6e95 Author: Simo Sorce <i...@samba.org> Date: Mon Aug 2 10:14:02 2010 -0400 Change debug statements to use __location__ commit 72a0098415c1d676a77a032c0f5fda90e9c1b905 Author: Simo Sorce <i...@samba.org> Date: Mon Aug 2 10:03:04 2010 -0400 s3-dcerpc: Pull packet in the caller, before validation commit 558320cf582a5ebc50af28061f5e33f7e4158fba Author: Simo Sorce <i...@samba.org> Date: Mon Aug 2 09:47:01 2010 -0400 Add my (c) ----------------------------------------------------------------------- Summary of changes: source3/include/proto.h | 4 - source3/librpc/rpc/dcerpc_gssapi.c | 51 +++++++++- source3/librpc/rpc/dcerpc_gssapi.h | 3 +- source3/librpc/rpc/dcerpc_helpers.c | 1 + source3/librpc/rpc/dcerpc_spnego.c | 11 ++- source3/librpc/rpc/dcerpc_spnego.h | 3 +- source3/rpc_client/cli_pipe.c | 184 +++++++++++++++------------------- source3/rpc_server/srv_pipe.c | 27 +---- 8 files changed, 147 insertions(+), 137 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/include/proto.h b/source3/include/proto.h index 70a2102..ebb3432 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4742,10 +4742,6 @@ NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const struct ndr_syntax_id *interface, const struct api_struct *cmds, int size); bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax); -bool api_pipe_bind_req(struct pipes_struct *p, struct ncacn_packet *pkt); -bool api_pipe_alter_context(struct pipes_struct *p, struct ncacn_packet *pkt); -void free_pipe_rpc_context( PIPE_RPC_FNS *list ); -bool api_pipe_request(struct pipes_struct *p, struct ncacn_packet *pkt); /* The following definitions come from rpc_server/srv_pipe_hnd.c */ diff --git a/source3/librpc/rpc/dcerpc_gssapi.c b/source3/librpc/rpc/dcerpc_gssapi.c index 2de46b5..777f5f1 100644 --- a/source3/librpc/rpc/dcerpc_gssapi.c +++ b/source3/librpc/rpc/dcerpc_gssapi.c @@ -28,6 +28,21 @@ #include <gssapi/gssapi_krb5.h> #include <gssapi/gssapi_ext.h> +#ifndef GSS_KRB5_INQ_SSPI_SESSION_KEY_OID +#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11 +#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" +#endif + +#ifndef GSS_KRB5_SESSION_KEY_ENCTYPE_OID +#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10 +#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04" +#endif + +gss_OID_desc gse_sesskey_inq_oid = { GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH, + (void *)GSS_KRB5_INQ_SSPI_SESSION_KEY_OID }; +gss_OID_desc gse_sesskeytype_oid = { GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH, + (void *)GSS_KRB5_SESSION_KEY_ENCTYPE_OID }; + static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min); struct gse_context { @@ -44,8 +59,6 @@ struct gse_context { gss_name_t server_name; gss_cred_id_t cli_creds; - DATA_BLOB session_key; - bool more_processing; }; @@ -348,9 +361,39 @@ bool gse_require_more_processing(struct gse_context *gse_ctx) return gse_ctx->more_processing; } -DATA_BLOB gse_get_session_key(struct gse_context *gse_ctx) +DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx, + struct gse_context *gse_ctx) { - return gse_ctx->session_key; + OM_uint32 gss_min, gss_maj; + gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; + DATA_BLOB ret; + + gss_maj = gss_inquire_sec_context_by_oid( + &gss_min, gse_ctx->gss_ctx, + &gse_sesskey_inq_oid, &set); + if (gss_maj) { + DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n", + gse_errstr(talloc_tos(), gss_maj, gss_min))); + return data_blob_null; + } + + if ((set == GSS_C_NO_BUFFER_SET) || + (set->count != 2) || + (memcmp(set->elements[1].value, + gse_sesskeytype_oid.elements, + gse_sesskeytype_oid.length) != 0)) { + DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown " + "OID for data in results:\n")); + dump_data(1, set->elements[1].value, + set->elements[1].length); + return data_blob_null; + } + + ret = data_blob_talloc(mem_ctx, set->elements[0].value, + set->elements[0].length); + + gss_maj = gss_release_buffer_set(&gss_min, &set); + return ret; } size_t gse_get_signature_length(struct gse_context *gse_ctx, diff --git a/source3/librpc/rpc/dcerpc_gssapi.h b/source3/librpc/rpc/dcerpc_gssapi.h index 3152033..28bf9d1 100644 --- a/source3/librpc/rpc/dcerpc_gssapi.h +++ b/source3/librpc/rpc/dcerpc_gssapi.h @@ -43,7 +43,8 @@ NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, DATA_BLOB *token_out); bool gse_require_more_processing(struct gse_context *gse_ctx); -DATA_BLOB gse_get_session_key(struct gse_context *gse_ctx); +DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx, + struct gse_context *gse_ctx); size_t gse_get_signature_length(struct gse_context *gse_ctx, int seal, size_t payload_size); diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index f8ca8e6..b658579 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -93,6 +93,7 @@ NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx, * elements * @param blob The blob of data to decode * @param r An empty ncacn_packet, must not be NULL +* @param bigendian Whether the packet is bignedian encoded * * @return a NTSTATUS error code */ diff --git a/source3/librpc/rpc/dcerpc_spnego.c b/source3/librpc/rpc/dcerpc_spnego.c index 5627a0d..ec81a2c 100644 --- a/source3/librpc/rpc/dcerpc_spnego.c +++ b/source3/librpc/rpc/dcerpc_spnego.c @@ -338,14 +338,19 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, return NT_STATUS_OK; } -DATA_BLOB spnego_get_session_key(struct spnego_context *sp_ctx) +DATA_BLOB spnego_get_session_key(TALLOC_CTX *mem_ctx, + struct spnego_context *sp_ctx) { + DATA_BLOB sk; + switch (sp_ctx->auth_type) { case DCERPC_AUTH_TYPE_KRB5: - return gse_get_session_key(sp_ctx->mech_ctx.gssapi_state); + return gse_get_session_key(mem_ctx, + sp_ctx->mech_ctx.gssapi_state); case DCERPC_AUTH_TYPE_NTLMSSP: - return auth_ntlmssp_get_session_key( + sk = auth_ntlmssp_get_session_key( sp_ctx->mech_ctx.ntlmssp_state); + return data_blob_dup_talloc(mem_ctx, &sk); default: DEBUG(0, ("Unsupported type in request!\n")); return data_blob_null; diff --git a/source3/librpc/rpc/dcerpc_spnego.h b/source3/librpc/rpc/dcerpc_spnego.h index 58363fd..9d37fd1 100644 --- a/source3/librpc/rpc/dcerpc_spnego.h +++ b/source3/librpc/rpc/dcerpc_spnego.h @@ -49,5 +49,6 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, enum dcerpc_AuthType *auth_type, void **auth_context); -DATA_BLOB spnego_get_session_key(struct spnego_context *sp_ctx); +DATA_BLOB spnego_get_session_key(TALLOC_CTX *mem_ctx, + struct spnego_context *sp_ctx); #endif /* _DCERPC_SPENGO_H_ */ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 840148b..a8766da 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1,18 +1,19 @@ -/* +/* * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines + * RPC Pipe client routines * Largely rewritten by Jeremy Allison 2005. - * + * Heavily modified by Simo Sorce 2010. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. */ @@ -379,21 +380,10 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, DATA_BLOB *rdata, DATA_BLOB *reply_pdu) { + struct dcerpc_response *r; NTSTATUS ret = NT_STATUS_OK; size_t pad_len = 0; - ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt, false); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } - - if (pdu->length != pkt->frag_length) { - DEBUG(5, ("Incorrect pdu length %u, expected %u\n", - (unsigned int)pdu->length, - (unsigned int)pkt->frag_length)); - return NT_STATUS_INVALID_PARAMETER; - } - /* * Point the return values at the real data including the RPC * header. Just in case the caller wants it. @@ -405,38 +395,39 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, case DCERPC_PKT_ALTER_RESP: case DCERPC_PKT_BIND_ACK: - /* Alter context and bind ack share the same packet definitions. */ + /* Client code never receives this kind of packets */ break; case DCERPC_PKT_RESPONSE: + r = &pkt->u.response; + /* Here's where we deal with incoming sign/seal. */ ret = dcerpc_check_auth(cli->auth, pkt, - &pkt->u.response.stub_and_verifier, + &r->stub_and_verifier, DCERPC_RESPONSE_LENGTH, pdu, &pad_len); if (!NT_STATUS_IS_OK(ret)) { return ret; } - if (pdu->length < DCERPC_RESPONSE_LENGTH + pad_len) { + 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 = pdu->data + DCERPC_RESPONSE_LENGTH; + rdata->data = r->stub_and_verifier.data; if (pkt->auth_length) { /* We've already done integer wrap tests in * dcerpc_check_auth(). */ - rdata->length = pdu->length - - DCERPC_RESPONSE_LENGTH + rdata->length = r->stub_and_verifier.length - pad_len - DCERPC_AUTH_TRAILER_LENGTH - pkt->auth_length; } else { - rdata->length = pdu->length - DCERPC_RESPONSE_LENGTH; + rdata->length = r->stub_and_verifier.length; } DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n", @@ -451,13 +442,12 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, */ if ((reply_pdu->length == 0) && - pkt->u.response.alloc_hint && - (pkt->u.response.alloc_hint < 15*1024*1024)) { + r->alloc_hint && (r->alloc_hint < 15*1024*1024)) { if (!data_blob_realloc(mem_ctx, reply_pdu, - pkt->u.response.alloc_hint)) { + r->alloc_hint)) { DEBUG(0, ("reply alloc hint %d too " "large to allocate\n", - (int)pkt->u.response.alloc_hint)); + (int)r->alloc_hint)); return NT_STATUS_NO_MEMORY; } } @@ -465,19 +455,18 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, break; case DCERPC_PKT_BIND_NAK: - DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK " - "received from %s!\n", + 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: - DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault " - "code %s received from %s!\n", + DEBUG(1, (__location__ ": RPC fault code %s received " + "from %s!\n", dcerpc_errstr(talloc_tos(), pkt->u.fault.status), - rpccli_pipe_txt(talloc_tos(), cli))); + rpccli_pipe_txt(talloc_tos(), cli))); if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) { return NT_STATUS_UNSUCCESSFUL; @@ -486,18 +475,18 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, } default: - DEBUG(0, ("Unknown packet type %u received from %s!\n", - (unsigned int)pkt->ptype, - rpccli_pipe_txt(talloc_tos(), cli))); + DEBUG(0, (__location__ "Unknown packet type %u received " + "from %s!\n", + (unsigned int)pkt->ptype, + rpccli_pipe_txt(talloc_tos(), cli))); return NT_STATUS_INVALID_INFO_CLASS; } if (pkt->ptype != expected_pkt_type) { - DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s " - "got an unexpected RPC packet type - %u, not %u\n", - rpccli_pipe_txt(talloc_tos(), cli), - 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_INVALID_INFO_CLASS; } @@ -507,10 +496,9 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, if ((pkt->ptype == DCERPC_PKT_BIND_ACK) && !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) { - DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), " - "setting fragment first/last ON.\n")); - pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | - 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; @@ -839,6 +827,23 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) return; } + status = dcerpc_pull_ncacn_packet(state, + &state->incoming_frag, + state->pkt, + !state->endianess); + if (!NT_STATUS_IS_OK(status)) { + 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; + } + status = cli_pipe_validate_current_pdu(state, state->cli, state->pkt, &state->incoming_frag, @@ -1623,9 +1628,6 @@ struct rpc_pipe_bind_state { }; static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq); -static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, - struct rpc_pipe_bind_state *state, - DATA_BLOB *credentials); static void rpc_bind_auth3_write_done(struct tevent_req *subreq); static NTSTATUS rpc_bind_next_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, @@ -1721,7 +1723,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) 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(state->cli->auth->auth_type) { + switch(pauth->auth_type) { case DCERPC_AUTH_TYPE_NONE: case DCERPC_AUTH_TYPE_SCHANNEL: @@ -1759,7 +1761,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) * For authenticated binds we may need to do 3 or 4 leg binds. */ - switch(state->cli->auth->auth_type) { + switch(pauth->auth_type) { case DCERPC_AUTH_TYPE_NONE: case DCERPC_AUTH_TYPE_SCHANNEL: @@ -1768,9 +1770,16 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) return; case DCERPC_AUTH_TYPE_NTLMSSP: - /* Need to send AUTH3 packet - no reply. */ - status = rpc_finish_auth3_bind_send(req, state, - &auth.credentials); + status = auth_ntlmssp_update(pauth->a_u.auth_ntlmssp_state, + auth.credentials, &auth_token); + if (NT_STATUS_EQUAL(status, + NT_STATUS_MORE_PROCESSING_REQUIRED)) { + status = rpc_bind_next_send(req, state, + &auth_token); + } else if (NT_STATUS_IS_OK(status)) { + status = rpc_bind_finish_send(req, state, + &auth_token); + } break; case DCERPC_AUTH_TYPE_SPNEGO: @@ -1827,49 +1836,6 @@ err_out: tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); } -static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, - struct rpc_pipe_bind_state *state, - DATA_BLOB *credentials) -{ - struct pipe_auth_data *auth = state->cli->auth; - DATA_BLOB client_reply = data_blob_null; - struct tevent_req *subreq; - NTSTATUS status; - - /* TODO - check auth_type/auth_level match. */ - - status = auth_ntlmssp_update(auth->a_u.auth_ntlmssp_state, - *credentials, &client_reply); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server " - "blob failed: %s.\n", nt_errstr(status))); - return status; - } - - data_blob_free(&state->rpc_out); - - status = create_rpc_bind_auth3(state, state->cli, - state->rpc_call_id, - auth->auth_type, - auth->auth_level, - &client_reply, - &state->rpc_out); - data_blob_free(&client_reply); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - subreq = rpc_write_send(state, state->ev, state->cli->transport, - state->rpc_out.data, state->rpc_out.length); - if (subreq == NULL) { - return NT_STATUS_NO_MEMORY; - } - tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req); - return NT_STATUS_OK; -} - static void rpc_bind_auth3_write_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( @@ -3428,7 +3394,8 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, DATA_BLOB *session_key) { struct pipe_auth_data *a = cli->auth; - DATA_BLOB sk; + DATA_BLOB sk = data_blob_null; + bool make_dup; if (!session_key || !cli) { return NT_STATUS_INVALID_PARAMETER; @@ -3442,27 +3409,38 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, case DCERPC_AUTH_TYPE_SCHANNEL: sk = data_blob_const(a->a_u.schannel_auth->creds->session_key, 16); + make_dup = true; break; case DCERPC_AUTH_TYPE_SPNEGO: - sk = spnego_get_session_key(a->a_u.spnego_state); - if (sk.length == 0) { - return NT_STATUS_NO_USER_SESSION_KEY; - } + sk = spnego_get_session_key(mem_ctx, a->a_u.spnego_state); + make_dup = false; break; case DCERPC_AUTH_TYPE_NTLMSSP: sk = auth_ntlmssp_get_session_key(a->a_u.auth_ntlmssp_state); + make_dup = true; break; case DCERPC_AUTH_TYPE_KRB5: - sk = gse_get_session_key(a->a_u.gssapi_state); + sk = gse_get_session_key(mem_ctx, a->a_u.gssapi_state); + make_dup = false; break; case DCERPC_AUTH_TYPE_NONE: sk = data_blob_const(a->user_session_key.data, a->user_session_key.length); + make_dup = true; break; default: + break; -- Samba Shared Repository