mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
libcli/auth: rewrite schannel sign/seal code to be more generic
This prepares support for HMAC-SHA256/AES. metze
This commit is contained in:
parent
8f482ae663
commit
033ced60ac
@ -23,20 +23,15 @@
|
||||
#ifndef _LIBCLI_AUTH_SCHANNEL_PROTO_H__
|
||||
#define _LIBCLI_AUTH_SCHANNEL_PROTO_H__
|
||||
|
||||
NTSTATUS schannel_unseal_packet(struct schannel_state *state,
|
||||
NTSTATUS netsec_incoming_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
bool do_unseal,
|
||||
uint8_t *data, size_t length,
|
||||
const DATA_BLOB *sig);
|
||||
NTSTATUS schannel_check_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const uint8_t *data, size_t length,
|
||||
const DATA_BLOB *sig);
|
||||
NTSTATUS schannel_seal_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint8_t *data, size_t length,
|
||||
DATA_BLOB *sig);
|
||||
NTSTATUS schannel_sign_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const uint8_t *data, size_t length,
|
||||
DATA_BLOB *sig);
|
||||
NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
bool do_seal,
|
||||
uint8_t *data, size_t length,
|
||||
DATA_BLOB *sig);
|
||||
|
||||
#endif
|
||||
|
@ -24,58 +24,89 @@
|
||||
#include "../libcli/auth/schannel.h"
|
||||
#include "../lib/crypto/crypto.h"
|
||||
|
||||
#define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }
|
||||
#define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 }
|
||||
static void netsec_offset_and_sizes(struct schannel_state *state,
|
||||
bool do_seal,
|
||||
uint32_t *_min_sig_size,
|
||||
uint32_t *_used_sig_size,
|
||||
uint32_t *_checksum_length,
|
||||
uint32_t *_confounder_ofs)
|
||||
{
|
||||
uint32_t min_sig_size = 24;
|
||||
uint32_t used_sig_size = 32;
|
||||
uint32_t checksum_length = 8;
|
||||
uint32_t confounder_ofs = 24;
|
||||
|
||||
if (do_seal) {
|
||||
min_sig_size += 8;
|
||||
}
|
||||
|
||||
if (_min_sig_size) {
|
||||
*_min_sig_size = min_sig_size;
|
||||
}
|
||||
|
||||
if (_used_sig_size) {
|
||||
*_used_sig_size = used_sig_size;
|
||||
}
|
||||
|
||||
if (_checksum_length) {
|
||||
*_checksum_length = checksum_length;
|
||||
}
|
||||
|
||||
if (_confounder_ofs) {
|
||||
*_confounder_ofs = confounder_ofs;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Encode or Decode the sequence number (which is symmetric)
|
||||
********************************************************************/
|
||||
static void netsec_deal_with_seq_num(struct schannel_state *state,
|
||||
const uint8_t packet_digest[8],
|
||||
uint8_t seq_num[8])
|
||||
static void netsec_do_seq_num(struct schannel_state *state,
|
||||
const uint8_t *checksum,
|
||||
uint32_t checksum_length,
|
||||
uint8_t seq_num[8])
|
||||
{
|
||||
static const uint8_t zeros[4];
|
||||
uint8_t sequence_key[16];
|
||||
uint8_t digest1[16];
|
||||
|
||||
hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1);
|
||||
hmac_md5(digest1, packet_digest, 8, sequence_key);
|
||||
hmac_md5(digest1, checksum, checksum_length, sequence_key);
|
||||
arcfour_crypt(seq_num, sequence_key, 8);
|
||||
|
||||
state->seq_num++;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
Calculate the key with which to encode the data payload
|
||||
********************************************************************/
|
||||
static void netsec_get_sealing_key(const uint8_t session_key[16],
|
||||
const uint8_t seq_num[8],
|
||||
uint8_t sealing_key[16])
|
||||
static void netsec_do_seal(struct schannel_state *state,
|
||||
const uint8_t seq_num[8],
|
||||
uint8_t confounder[8],
|
||||
uint8_t *data, uint32_t length)
|
||||
{
|
||||
uint8_t sealing_key[16];
|
||||
static const uint8_t zeros[4];
|
||||
uint8_t digest2[16];
|
||||
uint8_t sess_kf0[16];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
sess_kf0[i] = session_key[i] ^ 0xf0;
|
||||
sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
|
||||
}
|
||||
|
||||
hmac_md5(sess_kf0, zeros, 4, digest2);
|
||||
hmac_md5(digest2, seq_num, 8, sealing_key);
|
||||
}
|
||||
|
||||
arcfour_crypt(confounder, sealing_key, 8);
|
||||
arcfour_crypt(data, sealing_key, length);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Create a digest over the entire packet (including the data), and
|
||||
MD5 it with the session key.
|
||||
********************************************************************/
|
||||
static void schannel_digest(const uint8_t sess_key[16],
|
||||
const uint8_t netsec_sig[8],
|
||||
const uint8_t *confounder,
|
||||
const uint8_t *data, size_t data_len,
|
||||
uint8_t digest_final[16])
|
||||
static void netsec_do_sign(struct schannel_state *state,
|
||||
const uint8_t *confounder,
|
||||
const uint8_t *data, size_t data_len,
|
||||
uint8_t header[8],
|
||||
uint8_t *checksum)
|
||||
{
|
||||
uint8_t packet_digest[16];
|
||||
static const uint8_t zeros[4];
|
||||
@ -83,57 +114,88 @@ static void schannel_digest(const uint8_t sess_key[16],
|
||||
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, zeros, 4);
|
||||
MD5Update(&ctx, netsec_sig, 8);
|
||||
if (confounder) {
|
||||
SSVAL(header, 0, NL_SIGN_HMAC_MD5);
|
||||
SSVAL(header, 2, NL_SEAL_RC4);
|
||||
SSVAL(header, 4, 0xFFFF);
|
||||
SSVAL(header, 6, 0x0000);
|
||||
|
||||
MD5Update(&ctx, header, 8);
|
||||
MD5Update(&ctx, confounder, 8);
|
||||
} else {
|
||||
SSVAL(header, 0, NL_SIGN_HMAC_MD5);
|
||||
SSVAL(header, 2, NL_SEAL_NONE);
|
||||
SSVAL(header, 4, 0xFFFF);
|
||||
SSVAL(header, 6, 0x0000);
|
||||
|
||||
MD5Update(&ctx, header, 8);
|
||||
}
|
||||
MD5Update(&ctx, data, data_len);
|
||||
MD5Final(packet_digest, &ctx);
|
||||
|
||||
hmac_md5(sess_key, packet_digest, sizeof(packet_digest), digest_final);
|
||||
hmac_md5(state->creds->session_key,
|
||||
packet_digest, sizeof(packet_digest),
|
||||
checksum);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
unseal a packet
|
||||
*/
|
||||
NTSTATUS schannel_unseal_packet(struct schannel_state *state,
|
||||
NTSTATUS netsec_incoming_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
bool do_unseal,
|
||||
uint8_t *data, size_t length,
|
||||
const DATA_BLOB *sig)
|
||||
{
|
||||
uint8_t digest_final[16];
|
||||
uint8_t confounder[8];
|
||||
uint32_t min_sig_size = 0;
|
||||
uint8_t header[8];
|
||||
uint8_t checksum[32];
|
||||
uint32_t checksum_length = sizeof(checksum_length);
|
||||
uint8_t _confounder[8];
|
||||
uint8_t *confounder = NULL;
|
||||
uint32_t confounder_ofs = 0;
|
||||
uint8_t seq_num[8];
|
||||
uint8_t sealing_key[16];
|
||||
static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
|
||||
int ret;
|
||||
|
||||
if (sig->length != 32) {
|
||||
netsec_offset_and_sizes(state,
|
||||
do_unseal,
|
||||
&min_sig_size,
|
||||
NULL,
|
||||
&checksum_length,
|
||||
&confounder_ofs);
|
||||
|
||||
if (sig->length < min_sig_size) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
memcpy(confounder, sig->data+24, 8);
|
||||
if (do_unseal) {
|
||||
confounder = _confounder;
|
||||
memcpy(confounder, sig->data+confounder_ofs, 8);
|
||||
} else {
|
||||
confounder = NULL;
|
||||
}
|
||||
|
||||
RSIVAL(seq_num, 0, state->seq_num);
|
||||
SIVAL(seq_num, 4, state->initiator?0:0x80);
|
||||
|
||||
netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key);
|
||||
arcfour_crypt(confounder, sealing_key, 8);
|
||||
arcfour_crypt(data, sealing_key, length);
|
||||
if (do_unseal) {
|
||||
netsec_do_seal(state, seq_num,
|
||||
confounder,
|
||||
data, length);
|
||||
}
|
||||
|
||||
schannel_digest(state->creds->session_key,
|
||||
netsec_sig, confounder,
|
||||
data, length, digest_final);
|
||||
netsec_do_sign(state, confounder,
|
||||
data, length,
|
||||
header, checksum);
|
||||
|
||||
if (memcmp(digest_final, sig->data+16, 8) != 0) {
|
||||
dump_data_pw("calc digest:", digest_final, 8);
|
||||
dump_data_pw("wire digest:", sig->data+16, 8);
|
||||
ret = memcmp(checksum, sig->data+16, checksum_length);
|
||||
if (ret != 0) {
|
||||
dump_data_pw("calc digest:", checksum, checksum_length);
|
||||
dump_data_pw("wire digest:", sig->data+16, checksum_length);
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
netsec_deal_with_seq_num(state, digest_final, seq_num);
|
||||
netsec_do_seq_num(state, checksum, checksum_length, seq_num);
|
||||
|
||||
if (memcmp(seq_num, sig->data+8, 8) != 0) {
|
||||
ret = memcmp(seq_num, sig->data+8, 8);
|
||||
if (ret != 0) {
|
||||
dump_data_pw("calc seq num:", seq_num, 8);
|
||||
dump_data_pw("wire seq num:", sig->data+8, 8);
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
@ -142,128 +204,65 @@ NTSTATUS schannel_unseal_packet(struct schannel_state *state,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
check the signature on a packet
|
||||
*/
|
||||
NTSTATUS schannel_check_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const uint8_t *data, size_t length,
|
||||
const DATA_BLOB *sig)
|
||||
NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
bool do_seal,
|
||||
uint8_t *data, size_t length,
|
||||
DATA_BLOB *sig)
|
||||
{
|
||||
uint8_t digest_final[16];
|
||||
uint32_t min_sig_size = 0;
|
||||
uint32_t used_sig_size = 0;
|
||||
uint8_t header[8];
|
||||
uint8_t checksum[32];
|
||||
uint32_t checksum_length = sizeof(checksum_length);
|
||||
uint8_t _confounder[8];
|
||||
uint8_t *confounder = NULL;
|
||||
uint32_t confounder_ofs = 0;
|
||||
uint8_t seq_num[8];
|
||||
static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
|
||||
|
||||
/* w2k sends just 24 bytes and skip the confounder */
|
||||
if (sig->length != 32 && sig->length != 24) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
RSIVAL(seq_num, 0, state->seq_num);
|
||||
SIVAL(seq_num, 4, state->initiator?0:0x80);
|
||||
|
||||
dump_data_pw("seq_num:\n", seq_num, 8);
|
||||
dump_data_pw("sess_key:\n", state->creds->session_key, 16);
|
||||
|
||||
schannel_digest(state->creds->session_key,
|
||||
netsec_sig, NULL,
|
||||
data, length, digest_final);
|
||||
|
||||
netsec_deal_with_seq_num(state, digest_final, seq_num);
|
||||
|
||||
if (memcmp(seq_num, sig->data+8, 8) != 0) {
|
||||
dump_data_pw("calc seq num:", seq_num, 8);
|
||||
dump_data_pw("wire seq num:", sig->data+8, 8);
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (memcmp(digest_final, sig->data+16, 8) != 0) {
|
||||
dump_data_pw("calc digest:", digest_final, 8);
|
||||
dump_data_pw("wire digest:", sig->data+16, 8);
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
seal a packet
|
||||
*/
|
||||
NTSTATUS schannel_seal_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint8_t *data, size_t length,
|
||||
DATA_BLOB *sig)
|
||||
{
|
||||
uint8_t digest_final[16];
|
||||
uint8_t confounder[8];
|
||||
uint8_t seq_num[8];
|
||||
uint8_t sealing_key[16];
|
||||
static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
|
||||
|
||||
generate_random_buffer(confounder, 8);
|
||||
netsec_offset_and_sizes(state,
|
||||
do_seal,
|
||||
&min_sig_size,
|
||||
&used_sig_size,
|
||||
&checksum_length,
|
||||
&confounder_ofs);
|
||||
|
||||
RSIVAL(seq_num, 0, state->seq_num);
|
||||
SIVAL(seq_num, 4, state->initiator?0x80:0);
|
||||
|
||||
schannel_digest(state->creds->session_key,
|
||||
netsec_sig, confounder,
|
||||
data, length, digest_final);
|
||||
if (do_seal) {
|
||||
confounder = _confounder;
|
||||
generate_random_buffer(confounder, 8);
|
||||
} else {
|
||||
confounder = NULL;
|
||||
}
|
||||
|
||||
netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key);
|
||||
arcfour_crypt(confounder, sealing_key, 8);
|
||||
arcfour_crypt(data, sealing_key, length);
|
||||
netsec_do_sign(state, confounder,
|
||||
data, length,
|
||||
header, checksum);
|
||||
|
||||
netsec_deal_with_seq_num(state, digest_final, seq_num);
|
||||
if (do_seal) {
|
||||
netsec_do_seal(state, seq_num,
|
||||
confounder,
|
||||
data, length);
|
||||
}
|
||||
|
||||
(*sig) = data_blob_talloc(mem_ctx, NULL, 32);
|
||||
netsec_do_seq_num(state, checksum, checksum_length, seq_num);
|
||||
|
||||
memcpy(sig->data, netsec_sig, 8);
|
||||
(*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
|
||||
|
||||
memcpy(sig->data, header, 8);
|
||||
memcpy(sig->data+8, seq_num, 8);
|
||||
memcpy(sig->data+16, digest_final, 8);
|
||||
memcpy(sig->data+24, confounder, 8);
|
||||
memcpy(sig->data+16, checksum, checksum_length);
|
||||
|
||||
if (confounder) {
|
||||
memcpy(sig->data+confounder_ofs, confounder, 8);
|
||||
}
|
||||
|
||||
dump_data_pw("signature:", sig->data+ 0, 8);
|
||||
dump_data_pw("seq_num :", sig->data+ 8, 8);
|
||||
dump_data_pw("digest :", sig->data+16, 8);
|
||||
dump_data_pw("confound :", sig->data+24, 8);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
sign a packet
|
||||
*/
|
||||
NTSTATUS schannel_sign_packet(struct schannel_state *state,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const uint8_t *data, size_t length,
|
||||
DATA_BLOB *sig)
|
||||
{
|
||||
uint8_t digest_final[16];
|
||||
uint8_t seq_num[8];
|
||||
static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
|
||||
|
||||
RSIVAL(seq_num, 0, state->seq_num);
|
||||
SIVAL(seq_num, 4, state->initiator?0x80:0);
|
||||
|
||||
schannel_digest(state->creds->session_key,
|
||||
netsec_sig, NULL,
|
||||
data, length, digest_final);
|
||||
|
||||
netsec_deal_with_seq_num(state, digest_final, seq_num);
|
||||
|
||||
(*sig) = data_blob_talloc(mem_ctx, NULL, 32);
|
||||
|
||||
memcpy(sig->data, netsec_sig, 8);
|
||||
memcpy(sig->data+8, seq_num, 8);
|
||||
memcpy(sig->data+16, digest_final, 8);
|
||||
memset(sig->data+24, 0, 8);
|
||||
|
||||
dump_data_pw("signature:", sig->data+ 0, 8);
|
||||
dump_data_pw("seq_num :", sig->data+ 8, 8);
|
||||
dump_data_pw("digest :", sig->data+16, 8);
|
||||
dump_data_pw("confound :", sig->data+24, 8);
|
||||
dump_data_pw("digest :", sig->data+16, checksum_length);
|
||||
dump_data_pw("confound :", sig->data+confounder_ofs, 8);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
@ -676,6 +676,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p
|
||||
uint32 save_offset = prs_offset(current_pdu);
|
||||
struct schannel_state *schannel_auth =
|
||||
cli->auth->a_u.schannel_auth;
|
||||
uint8_t *data;
|
||||
uint32 data_len;
|
||||
DATA_BLOB blob;
|
||||
NTSTATUS status;
|
||||
@ -727,20 +728,24 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p
|
||||
dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
|
||||
}
|
||||
|
||||
data = (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN;
|
||||
|
||||
switch (cli->auth->auth_level) {
|
||||
case DCERPC_AUTH_LEVEL_PRIVACY:
|
||||
status = schannel_unseal_packet(schannel_auth,
|
||||
status = netsec_incoming_packet(schannel_auth,
|
||||
talloc_tos(),
|
||||
(uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
|
||||
true,
|
||||
data,
|
||||
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);
|
||||
status = netsec_incoming_packet(schannel_auth,
|
||||
talloc_tos(),
|
||||
false,
|
||||
data,
|
||||
data_len,
|
||||
&blob);
|
||||
break;
|
||||
default:
|
||||
status = NT_STATUS_INTERNAL_ERROR;
|
||||
@ -1948,18 +1953,20 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
|
||||
|
||||
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);
|
||||
status = netsec_outgoing_packet(sas,
|
||||
talloc_tos(),
|
||||
true,
|
||||
(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);
|
||||
status = netsec_outgoing_packet(sas,
|
||||
talloc_tos(),
|
||||
false,
|
||||
(uint8_t *)data_p,
|
||||
data_and_pad_len,
|
||||
&blob);
|
||||
break;
|
||||
default:
|
||||
status = NT_STATUS_INTERNAL_ERROR;
|
||||
|
@ -411,6 +411,7 @@ static bool create_next_pdu_schannel(pipes_struct *p)
|
||||
*/
|
||||
RPC_HDR_AUTH auth_info;
|
||||
DATA_BLOB blob;
|
||||
uint8_t *data;
|
||||
|
||||
/* Check it's the type of reply we were expecting to decode */
|
||||
|
||||
@ -427,20 +428,24 @@ static bool create_next_pdu_schannel(pipes_struct *p)
|
||||
return False;
|
||||
}
|
||||
|
||||
data = (uint8_t *)prs_data_p(&p->out_data.frag) + data_pos;
|
||||
|
||||
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);
|
||||
status = netsec_outgoing_packet(p->auth.a_u.schannel_auth,
|
||||
talloc_tos(),
|
||||
true,
|
||||
data,
|
||||
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);
|
||||
status = netsec_outgoing_packet(p->auth.a_u.schannel_auth,
|
||||
talloc_tos(),
|
||||
false,
|
||||
data,
|
||||
data_len + ss_padding_len,
|
||||
&blob);
|
||||
break;
|
||||
default:
|
||||
status = NT_STATUS_INTERNAL_ERROR;
|
||||
@ -2162,6 +2167,7 @@ bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss
|
||||
RPC_HDR_AUTH auth_info;
|
||||
DATA_BLOB blob;
|
||||
NTSTATUS status;
|
||||
uint8_t *data;
|
||||
|
||||
auth_len = p->hdr.auth_len;
|
||||
|
||||
@ -2215,20 +2221,24 @@ bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss
|
||||
dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
|
||||
}
|
||||
|
||||
data = (uint8_t *)prs_data_p(rpc_in)+RPC_HDR_REQ_LEN;
|
||||
|
||||
switch (auth_info.auth_level) {
|
||||
case DCERPC_AUTH_LEVEL_PRIVACY:
|
||||
status = schannel_unseal_packet(p->auth.a_u.schannel_auth,
|
||||
status = netsec_incoming_packet(p->auth.a_u.schannel_auth,
|
||||
talloc_tos(),
|
||||
(uint8_t *)prs_data_p(rpc_in)+RPC_HDR_REQ_LEN,
|
||||
true,
|
||||
data,
|
||||
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);
|
||||
status = netsec_incoming_packet(p->auth.a_u.schannel_auth,
|
||||
talloc_tos(),
|
||||
false,
|
||||
data,
|
||||
data_len,
|
||||
&blob);
|
||||
break;
|
||||
default:
|
||||
status = NT_STATUS_INTERNAL_ERROR;
|
||||
|
@ -282,48 +282,71 @@ static bool schannel_have_feature(struct gensec_security *gensec_security,
|
||||
return false;
|
||||
}
|
||||
|
||||
static NTSTATUS schannel_seal_packet_wrap(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint8_t *data, size_t length,
|
||||
const uint8_t *whole_pdu, size_t pdu_length,
|
||||
DATA_BLOB *sig)
|
||||
/*
|
||||
unseal a packet
|
||||
*/
|
||||
static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint8_t *data, size_t length,
|
||||
const uint8_t *whole_pdu, size_t pdu_length,
|
||||
const DATA_BLOB *sig)
|
||||
{
|
||||
struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
|
||||
struct schannel_state *state =
|
||||
talloc_get_type(gensec_security->private_data,
|
||||
struct schannel_state);
|
||||
|
||||
return schannel_seal_packet(state, mem_ctx, data, length, sig);
|
||||
return netsec_incoming_packet(state, mem_ctx, true,
|
||||
data, length, sig);
|
||||
}
|
||||
|
||||
static NTSTATUS schannel_sign_packet_wrap(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const uint8_t *data, size_t length,
|
||||
const uint8_t *whole_pdu, size_t pdu_length,
|
||||
DATA_BLOB *sig)
|
||||
/*
|
||||
check the signature on a packet
|
||||
*/
|
||||
static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const uint8_t *data, size_t length,
|
||||
const uint8_t *whole_pdu, size_t pdu_length,
|
||||
const DATA_BLOB *sig)
|
||||
{
|
||||
struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
|
||||
struct schannel_state *state =
|
||||
talloc_get_type(gensec_security->private_data,
|
||||
struct schannel_state);
|
||||
|
||||
return schannel_sign_packet(state, mem_ctx, data, length, sig);
|
||||
return netsec_incoming_packet(state, mem_ctx, false,
|
||||
data, length, sig);
|
||||
}
|
||||
/*
|
||||
seal a packet
|
||||
*/
|
||||
static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint8_t *data, size_t length,
|
||||
const uint8_t *whole_pdu, size_t pdu_length,
|
||||
DATA_BLOB *sig)
|
||||
{
|
||||
struct schannel_state *state =
|
||||
talloc_get_type(gensec_security->private_data,
|
||||
struct schannel_state);
|
||||
|
||||
return netsec_outgoing_packet(state, mem_ctx, true,
|
||||
data, length, sig);
|
||||
}
|
||||
|
||||
static NTSTATUS schannel_check_packet_wrap(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const uint8_t *data, size_t length,
|
||||
const uint8_t *whole_pdu, size_t pdu_length,
|
||||
const DATA_BLOB *sig)
|
||||
/*
|
||||
sign a packet
|
||||
*/
|
||||
static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const uint8_t *data, size_t length,
|
||||
const uint8_t *whole_pdu, size_t pdu_length,
|
||||
DATA_BLOB *sig)
|
||||
{
|
||||
struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
|
||||
struct schannel_state *state =
|
||||
talloc_get_type(gensec_security->private_data,
|
||||
struct schannel_state);
|
||||
|
||||
return schannel_check_packet(state, mem_ctx, data, length, sig);
|
||||
}
|
||||
|
||||
static NTSTATUS schannel_unseal_packet_wrap(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint8_t *data, size_t length,
|
||||
const uint8_t *whole_pdu, size_t pdu_length,
|
||||
const DATA_BLOB *sig)
|
||||
{
|
||||
struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
|
||||
|
||||
return schannel_unseal_packet(state, mem_ctx, data, length, sig);
|
||||
return netsec_outgoing_packet(state, mem_ctx, false,
|
||||
data, length, sig);
|
||||
}
|
||||
|
||||
static const struct gensec_security_ops gensec_schannel_security_ops = {
|
||||
@ -332,10 +355,10 @@ static const struct gensec_security_ops gensec_schannel_security_ops = {
|
||||
.client_start = schannel_client_start,
|
||||
.server_start = schannel_server_start,
|
||||
.update = schannel_update,
|
||||
.seal_packet = schannel_seal_packet_wrap,
|
||||
.sign_packet = schannel_sign_packet_wrap,
|
||||
.check_packet = schannel_check_packet_wrap,
|
||||
.unseal_packet = schannel_unseal_packet_wrap,
|
||||
.seal_packet = schannel_seal_packet,
|
||||
.sign_packet = schannel_sign_packet,
|
||||
.check_packet = schannel_check_packet,
|
||||
.unseal_packet = schannel_unseal_packet,
|
||||
.session_key = schannel_session_key,
|
||||
.session_info = schannel_session_info,
|
||||
.sig_size = schannel_sig_size,
|
||||
|
Loading…
Reference in New Issue
Block a user