The branch, v4-0-test has been updated via bde2496e6b7034c99243b22434a97aebeb8f75b9 (commit) via 54f1fca582b1474693b5ee11b7b847086d27f75f (commit) via 60b3523da485d845b1d930d990688d8434d39ef3 (commit) via c62e5d23a69789d23516a6d150fd3b756e270998 (commit) via d7dfdbaf34843cb6783d8e686e659c53c5ac27ef (commit) from 8e201ecf3e86c3c8865c7276fad8dad07106efaf (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test - Log ----------------------------------------------------------------- commit bde2496e6b7034c99243b22434a97aebeb8f75b9 Author: Stefan Metzmacher <[EMAIL PROTECTED]> Date: Wed Aug 6 22:28:04 2008 +0200 rpc_server: add support for DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN you need "dcesrv:header signing=yes" to enable it. metze commit 54f1fca582b1474693b5ee11b7b847086d27f75f Author: Stefan Metzmacher <[EMAIL PROTECTED]> Date: Wed Aug 6 21:35:07 2008 +0200 librpc/rpc: add support DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN You can trigger it like this: ncacn_ip_tcp:172.31.9.234[sign,hdrsign] or ncacn_ip_tcp:172.31.9.234[seal,hdrsign] metze commit 60b3523da485d845b1d930d990688d8434d39ef3 Author: Stefan Metzmacher <[EMAIL PROTECTED]> Date: Wed Aug 6 21:34:00 2008 +0200 librpc/rpc: pass struct dcerpc_pipe to dcerpc_auth3() metze commit c62e5d23a69789d23516a6d150fd3b756e270998 Author: Stefan Metzmacher <[EMAIL PROTECTED]> Date: Wed Aug 6 21:30:17 2008 +0200 gensec_gssapi: add support for GENSEC_FEATURE_SIGN_PKT_HEADER This only works for sign/verify_packet() yet, seal/unseal_packet() doesn't work yet... metze commit d7dfdbaf34843cb6783d8e686e659c53c5ac27ef Author: Stefan Metzmacher <[EMAIL PROTECTED]> Date: Wed Aug 6 21:26:20 2008 +0200 gensec: add GENSEC_FEATURE_SIGN_PKT_HEADER flag metze ----------------------------------------------------------------------- Summary of changes: source/auth/gensec/gensec.h | 1 + source/auth/gensec/gensec_gssapi.c | 86 ++++++++++++++++++++++++++++++++++-- source/librpc/rpc/binding.c | 3 +- source/librpc/rpc/dcerpc.c | 39 ++++++++++++++-- source/librpc/rpc/dcerpc.h | 3 + source/librpc/rpc/dcerpc_auth.c | 6 ++- source/rpc_server/dcerpc_server.c | 9 +++- source/rpc_server/dcerpc_server.h | 1 + source/rpc_server/dcesrv_auth.c | 5 ++ 9 files changed, 141 insertions(+), 12 deletions(-) Changeset truncated at 500 lines: diff --git a/source/auth/gensec/gensec.h b/source/auth/gensec/gensec.h index 7a1abfb..2a89e67 100644 --- a/source/auth/gensec/gensec.h +++ b/source/auth/gensec/gensec.h @@ -52,6 +52,7 @@ struct gensec_target { #define GENSEC_FEATURE_DCE_STYLE 0x00000008 #define GENSEC_FEATURE_ASYNC_REPLIES 0x00000010 #define GENSEC_FEATURE_DATAGRAM_MODE 0x00000020 +#define GENSEC_FEATURE_SIGN_PKT_HEADER 0x00000040 /* GENSEC mode */ enum gensec_role diff --git a/source/auth/gensec/gensec_gssapi.c b/source/auth/gensec/gensec_gssapi.c index bb44c75..1541c88 100644 --- a/source/auth/gensec/gensec_gssapi.c +++ b/source/auth/gensec/gensec_gssapi.c @@ -37,6 +37,7 @@ #include "param/param.h" #include "auth/session_proto.h" #include <gssapi/gssapi.h> +#include <gssapi/gssapi_krb5.h> enum gensec_gssapi_sasl_state { @@ -77,6 +78,7 @@ struct gensec_gssapi_state { size_t max_wrap_buf_size; int gss_exchange_count; + size_t sig_size; }; static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security); @@ -191,6 +193,7 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security) gensec_gssapi_state->pac = data_blob(NULL, 0); gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL; + gensec_gssapi_state->sig_size = 0; talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor); @@ -1035,8 +1038,13 @@ static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_securit OM_uint32 maj_stat, min_stat; gss_buffer_desc input_token, output_token; - input_token.length = length; - input_token.value = discard_const_p(uint8_t *, data); + if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { + input_token.length = pdu_length; + input_token.value = discard_const_p(uint8_t *, whole_pdu); + } else { + input_token.length = length; + input_token.value = discard_const_p(uint8_t *, data); + } maj_stat = gss_get_mic(&min_stat, gensec_gssapi_state->gssapi_context, @@ -1073,8 +1081,13 @@ static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_securi dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length); - input_message.length = length; - input_message.value = data; + if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { + input_message.length = pdu_length; + input_message.value = whole_pdu; + } else { + input_message.length = length; + input_message.value = data; + } input_token.length = sig->length; input_token.value = sig->data; @@ -1369,6 +1382,70 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi return NT_STATUS_OK; } +size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size) +{ + struct gensec_gssapi_state *gensec_gssapi_state + = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state); + OM_uint32 maj_stat, min_stat; + gss_krb5_lucid_context_v1_t *lucid = NULL; + + if (gensec_gssapi_state->sig_size) { + return gensec_gssapi_state->sig_size; + } + + if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) { + gensec_gssapi_state->sig_size = 45; + } else { + gensec_gssapi_state->sig_size = 37; + } + + maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, + &gensec_gssapi_state->gssapi_context, + 1, (void **)&lucid); + if (maj_stat != GSS_S_COMPLETE) { + return gensec_gssapi_state->sig_size; + } + + if (lucid->version != 1) { + return gensec_gssapi_state->sig_size; + } + + if (lucid->protocol == 1) { + if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) { + /* + * TODO: windows uses 76 here, but we don't know + * gss_wrap works with aes keys yet + */ + gensec_gssapi_state->sig_size = 60; + } else { + gensec_gssapi_state->sig_size = 28; + } + } else if (lucid->protocol == 0) { + switch (lucid->rfc1964_kd.ctx_key.type) { + case KEYTYPE_DES: + case KEYTYPE_ARCFOUR: + case KEYTYPE_ARCFOUR_56: + if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) { + gensec_gssapi_state->sig_size = 45; + } else { + gensec_gssapi_state->sig_size = 37; + } + break; + case KEYTYPE_DES3: + if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) { + gensec_gssapi_state->sig_size = 57; + } else { + gensec_gssapi_state->sig_size = 49; + } + break; + } + } + + gss_krb5_free_lucid_sec_context(&min_stat, lucid); + + return gensec_gssapi_state->sig_size; +} + static const char *gensec_gssapi_krb5_oids[] = { GENSEC_OID_KERBEROS5_OLD, GENSEC_OID_KERBEROS5, @@ -1415,6 +1492,7 @@ static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = { .update = gensec_gssapi_update, .session_key = gensec_gssapi_session_key, .session_info = gensec_gssapi_session_info, + .sig_size = gensec_gssapi_sig_size, .sign_packet = gensec_gssapi_sign_packet, .check_packet = gensec_gssapi_check_packet, .seal_packet = gensec_gssapi_seal_packet, diff --git a/source/librpc/rpc/binding.c b/source/librpc/rpc/binding.c index ae88dce..bfe62c4 100644 --- a/source/librpc/rpc/binding.c +++ b/source/librpc/rpc/binding.c @@ -83,7 +83,8 @@ static const struct { {"print", DCERPC_DEBUG_PRINT_BOTH}, {"padcheck", DCERPC_DEBUG_PAD_CHECK}, {"bigendian", DCERPC_PUSH_BIGENDIAN}, - {"smb2", DCERPC_SMB2} + {"smb2", DCERPC_SMB2}, + {"hdrsign", DCERPC_HEADER_SIGNING} }; const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor) diff --git a/source/librpc/rpc/dcerpc.c b/source/librpc/rpc/dcerpc.c index 4758189..a6c7e00 100644 --- a/source/librpc/rpc/dcerpc.c +++ b/source/librpc/rpc/dcerpc.c @@ -658,6 +658,16 @@ static void dcerpc_bind_recv_handler(struct rpc_request *req, conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag; conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag; + if ((req->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) && + (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) { + conn->flags |= DCERPC_CONCURRENT_MULTIPLEX; + } + + if ((req->p->binding->flags & DCERPC_HEADER_SIGNING) && + (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) { + conn->flags |= DCERPC_HEADER_SIGNING; + } + /* the bind_ack might contain a reply set of credentials */ if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) { @@ -731,6 +741,10 @@ struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p, pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; } + if (p->binding->flags & DCERPC_HEADER_SIGNING) { + pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + pkt.u.bind.max_xmit_frag = 5840; pkt.u.bind.max_recv_frag = 5840; pkt.u.bind.assoc_group_id = p->binding->assoc_group_id; @@ -790,30 +804,41 @@ NTSTATUS dcerpc_bind_recv(struct composite_context *ctx) /* perform a continued bind (and auth3) */ -NTSTATUS dcerpc_auth3(struct dcerpc_connection *c, +NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { struct ncacn_packet pkt; NTSTATUS status; DATA_BLOB blob; - init_ncacn_hdr(c, &pkt); + init_ncacn_hdr(p->conn, &pkt); pkt.ptype = DCERPC_PKT_AUTH3; pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; - pkt.call_id = next_call_id(c); + pkt.call_id = next_call_id(p->conn); pkt.auth_length = 0; pkt.u.auth3._pad = 0; pkt.u.auth3.auth_info = data_blob(NULL, 0); + if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) { + pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; + } + + if (p->binding->flags & DCERPC_HEADER_SIGNING) { + pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + /* construct the NDR form of the packet */ - status = ncacn_push_auth(&blob, mem_ctx, c->iconv_convenience, &pkt, c->security_state.auth_info); + status = ncacn_push_auth(&blob, mem_ctx, + p->conn->iconv_convenience, + &pkt, + p->conn->security_state.auth_info); if (!NT_STATUS_IS_OK(status)) { return status; } /* send it on its way */ - status = c->transport.send_request(c, &blob, false); + status = p->conn->transport.send_request(p->conn, &blob, false); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1627,6 +1652,10 @@ struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p, pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; } + if (p->binding->flags & DCERPC_HEADER_SIGNING) { + pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + pkt.u.alter.max_xmit_frag = 5840; pkt.u.alter.max_recv_frag = 5840; pkt.u.alter.assoc_group_id = p->binding->assoc_group_id; diff --git a/source/librpc/rpc/dcerpc.h b/source/librpc/rpc/dcerpc.h index 487f9f2..1fd56cb 100644 --- a/source/librpc/rpc/dcerpc.h +++ b/source/librpc/rpc/dcerpc.h @@ -163,6 +163,9 @@ struct dcerpc_pipe { /* this triggers the DCERPC_PFC_FLAG_CONC_MPX flag in the bind request */ #define DCERPC_CONCURRENT_MULTIPLEX (1<<19) +/* this triggers the DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN flag in the bind request */ +#define DCERPC_HEADER_SIGNING (1<<20) + /* this describes a binding to a particular transport/pipe */ struct dcerpc_binding { enum dcerpc_transport_t transport; diff --git a/source/librpc/rpc/dcerpc_auth.c b/source/librpc/rpc/dcerpc_auth.c index f990029..49fc3d9 100644 --- a/source/librpc/rpc/dcerpc_auth.c +++ b/source/librpc/rpc/dcerpc_auth.c @@ -137,6 +137,10 @@ static void bind_auth_next_step(struct composite_context *c) if (!composite_is_ok(c)) return; + if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) { + gensec_want_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER); + } + if (state->credentials.length == 0) { composite_done(c); return; @@ -146,7 +150,7 @@ static void bind_auth_next_step(struct composite_context *c) if (!more_processing) { /* NO reply expected, so just send it */ - c->status = dcerpc_auth3(state->pipe->conn, state); + c->status = dcerpc_auth3(state->pipe, state); if (!composite_is_ok(c)) return; composite_done(c); diff --git a/source/rpc_server/dcerpc_server.c b/source/rpc_server/dcerpc_server.c index 9558949..a336ddb 100644 --- a/source/rpc_server/dcerpc_server.c +++ b/source/rpc_server/dcerpc_server.c @@ -544,6 +544,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) uint32_t result=0, reason=0; uint32_t context_id; const struct dcesrv_interface *iface; + uint32_t extra_flags = 0; /* * Association groups allow policy handles to be shared across @@ -617,6 +618,12 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) call->conn->cli_max_recv_frag = call->pkt.u.bind.max_recv_frag; } + if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) && + lp_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","header signing", false)) { + call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING; + extra_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + /* handle any authentication that is being requested */ if (!dcesrv_auth_bind(call)) { return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE); @@ -627,7 +634,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) pkt.auth_length = 0; pkt.call_id = call->pkt.call_id; pkt.ptype = DCERPC_PKT_BIND_ACK; - pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; + pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags; pkt.u.bind_ack.max_xmit_frag = 0x2000; pkt.u.bind_ack.max_recv_frag = 0x2000; /* we need to send a non zero assoc_group_id here to make longhorn happy, it also matches samba3 */ diff --git a/source/rpc_server/dcerpc_server.h b/source/rpc_server/dcerpc_server.h index 058dfe3..b5672b4 100644 --- a/source/rpc_server/dcerpc_server.h +++ b/source/rpc_server/dcerpc_server.h @@ -101,6 +101,7 @@ struct dcesrv_call_state { */ #define DCESRV_CALL_STATE_FLAG_ASYNC (1<<0) #define DCESRV_CALL_STATE_FLAG_MAY_ASYNC (1<<1) +#define DCESRV_CALL_STATE_FLAG_HEADER_SIGNING (1<<2) uint32_t state_flags; /* the time the request arrived in the server */ diff --git a/source/rpc_server/dcesrv_auth.c b/source/rpc_server/dcesrv_auth.c index 1d89441..64f42ee 100644 --- a/source/rpc_server/dcesrv_auth.c +++ b/source/rpc_server/dcesrv_auth.c @@ -124,6 +124,11 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe return status; } + if (dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_HEADER_SIGNING) { + gensec_want_feature(dce_conn->auth_state.gensec_security, + GENSEC_FEATURE_SIGN_PKT_HEADER); + } + /* Now that we are authenticated, go back to the generic session key... */ dce_conn->auth_state.session_key = dcesrv_generic_session_key; return NT_STATUS_OK; -- Samba Shared Repository