diff options
author | Günther Deschner <gd@samba.org> | 2009-09-16 00:26:17 +0200 |
---|---|---|
committer | Günther Deschner <gd@samba.org> | 2009-09-16 01:55:06 +0200 |
commit | 799f8d7e13cc712f32cdd779770e4868ad17486b (patch) | |
tree | 61da8c7ed7a16b5139708fad679367b15811861b | |
parent | f3979b50a9b2aacb0497df770f09950b78878fcc (diff) | |
download | samba-799f8d7e13cc712f32cdd779770e4868ad17486b.tar.gz samba-799f8d7e13cc712f32cdd779770e4868ad17486b.tar.bz2 samba-799f8d7e13cc712f32cdd779770e4868ad17486b.zip |
schannel: fully share schannel sign/seal between s3 and 4.
Guenther
-rw-r--r-- | libcli/auth/schannel_state_ldb.c | 1 | ||||
-rw-r--r-- | source3/Makefile.in | 1 | ||||
-rw-r--r-- | source3/auth/auth_netlogond.c | 26 | ||||
-rw-r--r-- | source3/include/client.h | 2 | ||||
-rw-r--r-- | source3/include/ntdomain.h | 2 | ||||
-rw-r--r-- | source3/include/proto.h | 2 | ||||
-rw-r--r-- | source3/rpc_client/cli_pipe.c | 105 | ||||
-rw-r--r-- | source3/rpc_server/srv_netlog_nt.c | 3 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe.c | 85 |
9 files changed, 144 insertions, 83 deletions
diff --git a/libcli/auth/schannel_state_ldb.c b/libcli/auth/schannel_state_ldb.c index 37458c7cc5..69d6bad22c 100644 --- a/libcli/auth/schannel_state_ldb.c +++ b/libcli/auth/schannel_state_ldb.c @@ -29,6 +29,7 @@ #include "auth/auth.h" #include "param/param.h" #include "auth/gensec/schannel_state.h" +#include "../libcli/auth/schannel_state_proto.h" static struct ldb_val *schannel_dom_sid_ldb_val(TALLOC_CTX *mem_ctx, struct dom_sid *sid) diff --git a/source3/Makefile.in b/source3/Makefile.in index 903ae94049..65feb8446b 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -496,6 +496,7 @@ CLDAP_OBJ = libads/cldap.o \ TLDAP_OBJ = lib/tldap.o lib/tldap_util.o lib/util_tsock.o SCHANNEL_OBJ = ../libcli/auth/credentials.o \ + ../libcli/auth/schannel_sign.o \ ../libcli/auth/schannel_state_tdb.o \ ../librpc/gen_ndr/ndr_schannel.o \ ../librpc/ndr/ndr_schannel.o \ diff --git a/source3/auth/auth_netlogond.c b/source3/auth/auth_netlogond.c index 5f4d2f16e3..8c930a552a 100644 --- a/source3/auth/auth_netlogond.c +++ b/source3/auth/auth_netlogond.c @@ -46,9 +46,21 @@ static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx, return status; } + /* + * We have to fake a struct dcinfo, so that + * rpccli_netlogon_sam_network_logon_ex can decrypt the session keys. + */ + + p->dc = netlogon_creds_client_init_session_key(p, schannel_key); + if (p->dc == NULL) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(p); + return NT_STATUS_NO_MEMORY; + } + status = rpccli_schannel_bind_data(p, lp_workgroup(), DCERPC_AUTH_LEVEL_PRIVACY, - schannel_key, &auth); + p->dc, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("rpccli_schannel_bind_data failed: %s\n", nt_errstr(status))); @@ -64,18 +76,6 @@ static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx, return status; } - /* - * We have to fake a struct dcinfo, so that - * rpccli_netlogon_sam_network_logon_ex can decrypt the session keys. - */ - - p->dc = netlogon_creds_client_init_session_key(p, schannel_key); - if (p->dc == NULL) { - DEBUG(0, ("talloc failed\n")); - TALLOC_FREE(p); - return NT_STATUS_NO_MEMORY; - } - status = rpccli_netlogon_sam_network_logon_ex( p, p, user_info->logon_parameters,/* flags such as 'allow diff --git a/source3/include/client.h b/source3/include/client.h index e83927cfe5..82d94b055f 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -55,7 +55,7 @@ struct cli_pipe_auth_data { DATA_BLOB user_session_key; union { - struct schannel_auth_struct *schannel_auth; + struct schannel_state *schannel_auth; NTLMSSP_STATE *ntlmssp_state; struct kerberos_auth_struct *kerberos_auth; } a_u; diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index 1d303ca64a..f90478296c 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -150,7 +150,7 @@ struct pipe_auth_data { enum pipe_auth_type auth_type; /* switch for union below. */ enum dcerpc_AuthLevel auth_level; union { - struct schannel_auth_struct *schannel_auth; + struct schannel_state *schannel_auth; AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* struct kerberos_auth_struct *kerberos_auth; TO BE ADDED... */ } a_u; diff --git a/source3/include/proto.h b/source3/include/proto.h index 35d1a9929d..2c7c7b1b09 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5298,7 +5298,7 @@ NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx, struct cli_pipe_auth_data **presult); NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain, enum dcerpc_AuthLevel auth_level, - const uint8_t sess_key[16], + struct netlogon_creds_CredentialState *creds, struct cli_pipe_auth_data **presult); NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx, enum dcerpc_AuthLevel auth_level, diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index d71c561625..febf787815 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -21,6 +21,8 @@ #include "../libcli/auth/libcli_auth.h" #include "librpc/gen_ndr/cli_epmapper.h" #include "../librpc/gen_ndr/ndr_schannel.h" +#include "../libcli/auth/schannel.h" +#include "../libcli/auth/schannel_proto.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_CLI @@ -673,11 +675,12 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p struct NL_AUTH_SIGNATURE schannel_chk; uint32 auth_len = prhdr->auth_len; uint32 save_offset = prs_offset(current_pdu); - struct schannel_auth_struct *schannel_auth = + struct schannel_state *schannel_auth = cli->auth->a_u.schannel_auth; uint32 data_len; enum ndr_err_code ndr_err; DATA_BLOB blob; + NTSTATUS status; if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) { @@ -733,21 +736,34 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &schannel_chk); } - if (!schannel_decode(schannel_auth, - cli->auth->auth_level, - SENDER_IS_ACCEPTOR, - &schannel_chk, - prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN, - data_len)) { + switch (cli->auth->auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = schannel_unseal_packet(schannel_auth, + talloc_tos(), + (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN, + data_len, + &blob); + break; + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = schannel_check_packet(schannel_auth, + talloc_tos(), + (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN, + data_len, + &blob); + break; + default: + status = NT_STATUS_INTERNAL_ERROR; + break; + } + + if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU " - "Connection to %s.\n", - rpccli_pipe_txt(debug_ctx(), cli))); + "Connection to %s (%s).\n", + rpccli_pipe_txt(debug_ctx(), cli), + nt_errstr(status))); return NT_STATUS_INVALID_PARAMETER; } - /* The sequence number gets incremented on both send and receive. */ - schannel_auth->seq_num++; - /* * Return the current pointer to the data offset. */ @@ -1915,11 +1931,12 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, { RPC_HDR_AUTH auth_info; struct NL_AUTH_SIGNATURE verf; - struct schannel_auth_struct *sas = cli->auth->a_u.schannel_auth; + struct schannel_state *sas = cli->auth->a_u.schannel_auth; char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN; size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; enum ndr_err_code ndr_err; DATA_BLOB blob; + NTSTATUS status; if (!sas) { return NT_STATUS_INVALID_PARAMETER; @@ -1937,29 +1954,35 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, return NT_STATUS_NO_MEMORY; } - switch (cli->auth->auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - case DCERPC_AUTH_LEVEL_INTEGRITY: - DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n", - sas->seq_num)); + DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n", + sas->seq_num)); - schannel_encode(sas, - cli->auth->auth_level, - SENDER_IS_INITIATOR, - &verf, - data_p, - data_and_pad_len); - - sas->seq_num++; - break; - - default: - /* Can't happen. */ - smb_panic("bad auth level"); - /* Notreached. */ - return NT_STATUS_INVALID_PARAMETER; + switch (cli->auth->auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = schannel_seal_packet(sas, + talloc_tos(), + (uint8_t *)data_p, + data_and_pad_len, + &blob); + break; + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = schannel_sign_packet(sas, + talloc_tos(), + (uint8_t *)data_p, + data_and_pad_len, + &blob); + break; + default: + status = NT_STATUS_INTERNAL_ERROR; + break; } + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n", + nt_errstr(status))); + return status; + } +#if 0 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), NULL, &verf, (ndr_push_flags_fn_t)ndr_push_NL_AUTH_SIGNATURE); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { @@ -1969,7 +1992,7 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &verf); } - +#endif /* Finally marshall the blob. */ if (!prs_copy_data_in(outgoing_pdu, (const char *)blob.data, blob.length)) { return NT_STATUS_NO_MEMORY; @@ -3070,7 +3093,7 @@ NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx, NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain, enum dcerpc_AuthLevel auth_level, - const uint8_t sess_key[16], + struct netlogon_creds_CredentialState *creds, struct cli_pipe_auth_data **presult) { struct cli_pipe_auth_data *result; @@ -3089,15 +3112,15 @@ NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain, goto fail; } - result->a_u.schannel_auth = talloc(result, - struct schannel_auth_struct); + result->a_u.schannel_auth = talloc(result, struct schannel_state); if (result->a_u.schannel_auth == NULL) { goto fail; } - memcpy(result->a_u.schannel_auth->sess_key, sess_key, - sizeof(result->a_u.schannel_auth->sess_key)); + result->a_u.schannel_auth->state = SCHANNEL_STATE_START; result->a_u.schannel_auth->seq_num = 0; + result->a_u.schannel_auth->initiator = true; + result->a_u.schannel_auth->creds = creds; *presult = result; return NT_STATUS_OK; @@ -3904,7 +3927,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, } status = rpccli_schannel_bind_data(result, domain, auth_level, - (*pdc)->session_key, &auth); + *pdc, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("rpccli_schannel_bind_data returned %s\n", nt_errstr(status))); @@ -4122,7 +4145,7 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, switch (cli->auth->auth_type) { case PIPE_AUTH_TYPE_SCHANNEL: *session_key = data_blob_talloc(mem_ctx, - cli->auth->a_u.schannel_auth->sess_key, 16); + cli->auth->a_u.schannel_auth->creds->session_key, 16); break; case PIPE_AUTH_TYPE_NTLMSSP: case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 06d4937261..33a81fa651 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -27,6 +27,7 @@ #include "includes.h" #include "../libcli/auth/libcli_auth.h" #include "../libcli/auth/schannel_state.h" +#include "../libcli/auth/schannel.h" extern userdom_struct current_user_info; @@ -1053,7 +1054,7 @@ static NTSTATUS _netr_LogonSamLogon_base(pipes_struct *p, || (p->auth.a_u.schannel_auth == NULL)) { return NT_STATUS_INVALID_HANDLE; } - memcpy(pipe_session_key, p->auth.a_u.schannel_auth->sess_key, 16); + memcpy(pipe_session_key, p->auth.a_u.schannel_auth->creds->session_key, 16); } switch (r->in.validation_level) { diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 3bd68c4e72..576bd85745 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -30,6 +30,8 @@ #include "includes.h" #include "../libcli/auth/libcli_auth.h" #include "../librpc/gen_ndr/ndr_schannel.h" +#include "../libcli/auth/schannel.h" +#include "../libcli/auth/schannel_proto.h" extern struct current_user current_user; @@ -285,6 +287,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) uint32 data_space_available; uint32 data_len_left; uint32 data_pos; + NTSTATUS status; /* * If we're in the fault state, keep returning fault PDU's until @@ -426,13 +429,36 @@ static bool create_next_pdu_schannel(pipes_struct *p) return False; } - schannel_encode(p->auth.a_u.schannel_auth, - p->auth.auth_level, SENDER_IS_ACCEPTOR, &verf, - prs_data_p(&p->out_data.frag) + data_pos, - data_len + ss_padding_len); + switch (p->auth.auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = schannel_seal_packet(p->auth.a_u.schannel_auth, + talloc_tos(), + (uint8_t *)prs_data_p(&p->out_data.frag) + data_pos, + data_len + ss_padding_len, + &blob); + break; + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = schannel_sign_packet(p->auth.a_u.schannel_auth, + talloc_tos(), + (uint8_t *)prs_data_p(&p->out_data.frag) + data_pos, + data_len + ss_padding_len, + &blob); + break; + default: + status = NT_STATUS_INTERNAL_ERROR; + break; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("create_next_pdu_schannel: failed to process packet: %s\n", + nt_errstr(status))); + prs_mem_free(&p->out_data.frag); + return false; + } /* Finally marshall the blob. */ +#if 0 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), NULL, &verf, (ndr_push_flags_fn_t)ndr_push_NL_AUTH_SIGNATURE); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { @@ -443,13 +469,11 @@ static bool create_next_pdu_schannel(pipes_struct *p) if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &verf); } - +#endif if (!prs_copy_data_in(&p->out_data.frag, (const char *)blob.data, blob.length)) { prs_mem_free(&p->out_data.frag); return false; } - - p->auth.a_u.schannel_auth->seq_num++; } /* @@ -1376,7 +1400,7 @@ static bool pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, */ become_root(); - status = schannel_fetch_session_key(p->mem_ctx, + status = schannel_fetch_session_key(p, neg.oem_netbios_computer.a, &creds); unbecome_root(); @@ -1386,19 +1410,16 @@ static bool pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, return False; } - p->auth.a_u.schannel_auth = talloc(p, struct schannel_auth_struct); + p->auth.a_u.schannel_auth = talloc(p, struct schannel_state); if (!p->auth.a_u.schannel_auth) { TALLOC_FREE(creds); return False; } - memset(p->auth.a_u.schannel_auth->sess_key, 0, sizeof(p->auth.a_u.schannel_auth->sess_key)); - memcpy(p->auth.a_u.schannel_auth->sess_key, creds->session_key, - sizeof(creds->session_key)); - - TALLOC_FREE(creds); - + p->auth.a_u.schannel_auth->state = SCHANNEL_STATE_START; p->auth.a_u.schannel_auth->seq_num = 0; + p->auth.a_u.schannel_auth->initiator = false; + p->auth.a_u.schannel_auth->creds = creds; /* * JRA. Should we also copy the schannel session key into the pipe session key p->session_key @@ -2152,6 +2173,7 @@ bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss struct NL_AUTH_SIGNATURE schannel_chk; enum ndr_err_code ndr_err; DATA_BLOB blob; + NTSTATUS status; auth_len = p->hdr.auth_len; @@ -2213,13 +2235,29 @@ bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &schannel_chk); } - if (!schannel_decode(p->auth.a_u.schannel_auth, - p->auth.auth_level, - SENDER_IS_INITIATOR, - &schannel_chk, - prs_data_p(rpc_in)+RPC_HDR_REQ_LEN, data_len)) { - DEBUG(3,("failed to decode PDU\n")); - return False; + switch (auth_info.auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = schannel_unseal_packet(p->auth.a_u.schannel_auth, + talloc_tos(), + (uint8_t *)prs_data_p(rpc_in)+RPC_HDR_REQ_LEN, + data_len, + &blob); + break; + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = schannel_check_packet(p->auth.a_u.schannel_auth, + talloc_tos(), + (uint8_t *)prs_data_p(rpc_in)+RPC_HDR_REQ_LEN, + data_len, + &blob); + break; + default: + status = NT_STATUS_INTERNAL_ERROR; + break; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("failed to unseal packet: %s\n", nt_errstr(status))); + return false; } /* @@ -2232,9 +2270,6 @@ bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss return False; } - /* The sequence number gets incremented on both send and receive. */ - p->auth.a_u.schannel_auth->seq_num++; - /* * Remember the padding length. We must remove it from the real data * stream once the sign/seal is done. |