summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2009-09-11 02:52:25 +0200
committerGünther Deschner <gd@samba.org>2009-09-11 03:00:35 +0200
commitd258fb4d0dcd04899dede7f17c8658251c9cd5e7 (patch)
treec59f5a03297e3d75cf8deeff1dc3435ce55329ad /source3
parentcac5e64c0005549839b4bcf5c62422d4b20eba4f (diff)
downloadsamba-d258fb4d0dcd04899dede7f17c8658251c9cd5e7.tar.gz
samba-d258fb4d0dcd04899dede7f17c8658251c9cd5e7.tar.bz2
samba-d258fb4d0dcd04899dede7f17c8658251c9cd5e7.zip
s3-schannel: use NL_AUTH_SIGNATURE for schannel sign & seal (client & server).
Guenther
Diffstat (limited to 'source3')
-rw-r--r--source3/include/includes.h1
-rw-r--r--source3/include/proto.h4
-rw-r--r--source3/rpc_client/cli_pipe.c39
-rw-r--r--source3/rpc_parse/parse_prs.c118
-rw-r--r--source3/rpc_server/srv_pipe.c39
5 files changed, 118 insertions, 83 deletions
diff --git a/source3/include/includes.h b/source3/include/includes.h
index 92a37053ce..31dfc00545 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -653,6 +653,7 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx);
#include "privileges.h"
#include "rpc_misc.h"
#include "rpc_dce.h"
+#include "../librpc/gen_ndr/schannel.h"
#include "mapping.h"
#include "passdb.h"
#include "rpc_secdes.h"
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 9de77f9227..c51d4ee728 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -5691,11 +5691,11 @@ bool prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str);
bool prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_buf_size);
void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level,
enum schannel_direction direction,
- RPC_AUTH_SCHANNEL_CHK * verf,
+ struct NL_AUTH_SIGNATURE *verf,
char *data, size_t data_len);
bool schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level,
enum schannel_direction direction,
- RPC_AUTH_SCHANNEL_CHK * verf, char *data, size_t data_len);
+ struct NL_AUTH_SIGNATURE *verf, char *data, size_t data_len);
bool prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx);
bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx);
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 16fe9daca1..0c3fc946d4 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -670,12 +670,14 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p
uint8 *p_ss_padding_len)
{
RPC_HDR_AUTH auth_info;
- RPC_AUTH_SCHANNEL_CHK schannel_chk;
+ 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 =
cli->auth->a_u.schannel_auth;
uint32 data_len;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
|| cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
@@ -718,10 +720,17 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p
return NT_STATUS_BUFFER_TOO_SMALL;
}
- if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
- &schannel_chk, current_pdu, 0)) {
+ blob = data_blob_const(prs_data_p(current_pdu) + prs_offset(current_pdu), data_len);
+
+ ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), NULL, &schannel_chk,
+ (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_SIGNATURE);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
- return NT_STATUS_BUFFER_TOO_SMALL;
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &schannel_chk);
}
if (!schannel_decode(schannel_auth,
@@ -1905,10 +1914,12 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
prs_struct *outgoing_pdu)
{
RPC_HDR_AUTH auth_info;
- RPC_AUTH_SCHANNEL_CHK verf;
+ struct NL_AUTH_SIGNATURE verf;
struct schannel_auth_struct *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;
if (!sas) {
return NT_STATUS_INVALID_PARAMETER;
@@ -1949,12 +1960,20 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
return NT_STATUS_INVALID_PARAMETER;
}
+ 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)) {
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &verf);
+ }
+
/* Finally marshall the blob. */
- smb_io_rpc_auth_schannel_chk("",
- RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
- &verf,
- outgoing_pdu,
- 0);
+ if (!prs_copy_data_in(outgoing_pdu, (const char *)blob.data, blob.length)) {
+ return NT_STATUS_NO_MEMORY;
+ }
return NT_STATUS_OK;
}
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c
index 621ccf4bc9..d428c3aa9e 100644
--- a/source3/rpc_parse/parse_prs.c
+++ b/source3/rpc_parse/parse_prs.c
@@ -21,6 +21,7 @@
*/
#include "includes.h"
+#include "../librpc/gen_ndr/ndr_schannel.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_PARSE
@@ -1071,24 +1072,31 @@ bool prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_
static void schannel_digest(struct schannel_auth_struct *a,
enum pipe_auth_level auth_level,
- RPC_AUTH_SCHANNEL_CHK * verf,
+ struct NL_AUTH_SIGNATURE *verf,
char *data, size_t data_len,
uchar digest_final[16])
{
uchar whole_packet_digest[16];
uchar zeros[4];
struct MD5Context ctx3;
+ uint8_t sig[8];
ZERO_STRUCT(zeros);
+ ZERO_STRUCT(sig);
+
+ SSVAL(sig,0,verf->SignatureAlgorithm);
+ SSVAL(sig,2,verf->SealAlgorithm);
+ SSVAL(sig,4,verf->Pad);
+ SSVAL(sig,8,verf->Flags);
/* verfiy the signature on the packet by MD5 over various bits */
MD5Init(&ctx3);
/* use our sequence number, which ensures the packet is not
out of order */
MD5Update(&ctx3, zeros, sizeof(zeros));
- MD5Update(&ctx3, verf->sig, sizeof(verf->sig));
+ MD5Update(&ctx3, sig, 8);
if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
- MD5Update(&ctx3, verf->confounder, sizeof(verf->confounder));
+ MD5Update(&ctx3, verf->Confounder, sizeof(verf->Confounder));
}
MD5Update(&ctx3, (const unsigned char *)data, data_len);
MD5Final(whole_packet_digest, &ctx3);
@@ -1104,7 +1112,7 @@ static void schannel_digest(struct schannel_auth_struct *a,
********************************************************************/
static void schannel_get_sealing_key(struct schannel_auth_struct *a,
- RPC_AUTH_SCHANNEL_CHK *verf,
+ struct NL_AUTH_SIGNATURE *verf,
uchar sealing_key[16])
{
uchar zeros[4];
@@ -1125,7 +1133,7 @@ static void schannel_get_sealing_key(struct schannel_auth_struct *a,
dump_data_pw("digest2:\n", digest2, sizeof(digest2));
/* MD5 of the above result, plus 8 bytes of sequence number */
- hmac_md5(digest2, verf->seq_num, sizeof(verf->seq_num), sealing_key);
+ hmac_md5(digest2, verf->SequenceNumber, sizeof(verf->SequenceNumber), sealing_key);
dump_data_pw("sealing_key:\n", sealing_key, 16);
}
@@ -1134,7 +1142,7 @@ static void schannel_get_sealing_key(struct schannel_auth_struct *a,
********************************************************************/
static void schannel_deal_with_seq_num(struct schannel_auth_struct *a,
- RPC_AUTH_SCHANNEL_CHK *verf)
+ struct NL_AUTH_SIGNATURE *verf)
{
uchar zeros[4];
uchar sequence_key[16];
@@ -1145,33 +1153,13 @@ static void schannel_deal_with_seq_num(struct schannel_auth_struct *a,
hmac_md5(a->sess_key, zeros, sizeof(zeros), digest1);
dump_data_pw("(sequence key) digest1:\n", digest1, sizeof(digest1));
- hmac_md5(digest1, verf->packet_digest, 8, sequence_key);
+ hmac_md5(digest1, verf->Checksum, 8, sequence_key);
dump_data_pw("sequence_key:\n", sequence_key, sizeof(sequence_key));
- dump_data_pw("seq_num (before):\n", verf->seq_num, sizeof(verf->seq_num));
- arcfour_crypt(verf->seq_num, sequence_key, 8);
- dump_data_pw("seq_num (after):\n", verf->seq_num, sizeof(verf->seq_num));
-}
-
-/*******************************************************************
-creates an RPC_AUTH_SCHANNEL_CHK structure.
-********************************************************************/
-
-static bool init_rpc_auth_schannel_chk(RPC_AUTH_SCHANNEL_CHK * chk,
- const uchar sig[8],
- const uchar packet_digest[8],
- const uchar seq_num[8], const uchar confounder[8])
-{
- if (chk == NULL)
- return False;
-
- memcpy(chk->sig, sig, sizeof(chk->sig));
- memcpy(chk->packet_digest, packet_digest, sizeof(chk->packet_digest));
- memcpy(chk->seq_num, seq_num, sizeof(chk->seq_num));
- memcpy(chk->confounder, confounder, sizeof(chk->confounder));
-
- return True;
+ dump_data_pw("seq_num (before):\n", verf->SequenceNumber, sizeof(verf->SequenceNumber));
+ arcfour_crypt(verf->SequenceNumber, sequence_key, 8);
+ dump_data_pw("seq_num (after):\n", verf->SequenceNumber, sizeof(verf->SequenceNumber));
}
/*******************************************************************
@@ -1183,7 +1171,7 @@ static bool init_rpc_auth_schannel_chk(RPC_AUTH_SCHANNEL_CHK * chk,
void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level,
enum schannel_direction direction,
- RPC_AUTH_SCHANNEL_CHK * verf,
+ struct NL_AUTH_SIGNATURE *verf,
char *data, size_t data_len)
{
uchar digest_final[16];
@@ -1191,18 +1179,8 @@ void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
uchar seq_num[8];
static const uchar nullbytes[8] = { 0, };
- static const uchar schannel_seal_sig[8] = SCHANNEL_SEAL_SIGNATURE;
- static const uchar schannel_sign_sig[8] = SCHANNEL_SIGN_SIGNATURE;
- const uchar *schannel_sig = NULL;
-
DEBUG(10,("SCHANNEL: schannel_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
- if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
- schannel_sig = schannel_seal_sig;
- } else {
- schannel_sig = schannel_sign_sig;
- }
-
/* fill the 'confounder' with random data */
generate_random_buffer(confounder, sizeof(confounder));
@@ -1219,14 +1197,25 @@ void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
break;
}
- dump_data_pw("verf->seq_num:\n", seq_num, sizeof(verf->seq_num));
+ dump_data_pw("verf->SequenceNumber:\n", verf->SequenceNumber, sizeof(verf->SequenceNumber));
+
+ if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
+ verf->SealAlgorithm = NL_SEAL_RC4;
+ } else {
+ verf->SealAlgorithm = NL_SEAL_NONE;
+ }
+
+ verf->SignatureAlgorithm = NL_SIGN_HMAC_MD5;
+ verf->Pad = 0xffff;
+ verf->Flags = 0x0000;
+
+ memcpy(verf->SequenceNumber, seq_num, sizeof(verf->SequenceNumber));
+ memcpy(verf->Checksum, nullbytes, sizeof(verf->Checksum));
+ memcpy(verf->Confounder, confounder, sizeof(verf->Confounder));
- init_rpc_auth_schannel_chk(verf, schannel_sig, nullbytes,
- seq_num, confounder);
-
/* produce a digest of the packet to prove it's legit (before we seal it) */
schannel_digest(a, auth_level, verf, data, data_len, digest_final);
- memcpy(verf->packet_digest, digest_final, sizeof(verf->packet_digest));
+ memcpy(verf->Checksum, digest_final, sizeof(verf->Checksum));
if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
uchar sealing_key[16];
@@ -1235,10 +1224,10 @@ void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
schannel_get_sealing_key(a, verf, sealing_key);
/* encode the verification data */
- dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder));
- arcfour_crypt(verf->confounder, sealing_key, 8);
+ dump_data_pw("verf->Confounder:\n", verf->Confounder, sizeof(verf->Confounder));
+ arcfour_crypt(verf->Confounder, sealing_key, 8);
- dump_data_pw("verf->confounder_enc:\n", verf->confounder, sizeof(verf->confounder));
+ dump_data_pw("verf->Confounder_enc:\n", verf->Confounder, sizeof(verf->Confounder));
/* encode the packet payload */
dump_data_pw("data:\n", (const unsigned char *)data, data_len);
@@ -1262,7 +1251,7 @@ void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
bool schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level,
enum schannel_direction direction,
- RPC_AUTH_SCHANNEL_CHK * verf, char *data, size_t data_len)
+ struct NL_AUTH_SIGNATURE *verf, char *data, size_t data_len)
{
uchar digest_final[16];
@@ -1302,24 +1291,27 @@ bool schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
is used in the sealing stuff... */
schannel_deal_with_seq_num(a, verf);
- if (memcmp(verf->seq_num, seq_num, sizeof(seq_num))) {
+ if (memcmp(verf->SequenceNumber, seq_num, sizeof(seq_num))) {
/* don't even bother with the below if the sequence number is out */
/* The sequence number is MD5'ed with a key based on the whole-packet
digest, as supplied by the client. We check that it's a valid
checksum after the decode, below
*/
DEBUG(2, ("schannel_decode: FAILED: packet sequence number:\n"));
- dump_data(2, verf->seq_num, sizeof(verf->seq_num));
+ dump_data(2, verf->SequenceNumber, sizeof(verf->SequenceNumber));
DEBUG(2, ("should be:\n"));
dump_data(2, seq_num, sizeof(seq_num));
return False;
}
- if (memcmp(verf->sig, schannel_sig, sizeof(verf->sig))) {
+ if (memcmp(&verf->SignatureAlgorithm, &schannel_sig[0], 2) ||
+ memcmp(&verf->SealAlgorithm, &schannel_sig[2], 2) ||
+ memcmp(&verf->Pad, &schannel_sig[4], 2) ||
+ memcmp(&verf->Flags, &schannel_sig[6], 2)) {
/* Validate that the other end sent the expected header */
DEBUG(2, ("schannel_decode: FAILED: packet header:\n"));
- dump_data(2, verf->sig, sizeof(verf->sig));
+ dump_data(2, (const uint8_t *)verf, sizeof(schannel_sig));
DEBUG(2, ("should be:\n"));
dump_data(2, schannel_sig, sizeof(schannel_sig));
return False;
@@ -1332,12 +1324,12 @@ bool schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
schannel_get_sealing_key(a, verf, sealing_key);
/* extract the verification data */
- dump_data_pw("verf->confounder:\n", verf->confounder,
- sizeof(verf->confounder));
- arcfour_crypt(verf->confounder, sealing_key, 8);
+ dump_data_pw("verf->Confounder:\n", verf->Confounder,
+ sizeof(verf->Confounder));
+ arcfour_crypt(verf->Confounder, sealing_key, 8);
- dump_data_pw("verf->confounder_dec:\n", verf->confounder,
- sizeof(verf->confounder));
+ dump_data_pw("verf->Confounder_dec:\n", verf->Confounder,
+ sizeof(verf->Confounder));
/* extract the packet payload */
dump_data_pw("data :\n", (const unsigned char *)data, data_len);
@@ -1350,13 +1342,13 @@ bool schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
dump_data_pw("Calculated digest:\n", digest_final,
sizeof(digest_final));
- dump_data_pw("verf->packet_digest:\n", verf->packet_digest,
- sizeof(verf->packet_digest));
+ dump_data_pw("verf->Checksum:\n", verf->Checksum,
+ sizeof(verf->Checksum));
/* compare - if the client got the same result as us, then
it must know the session key */
- return (memcmp(digest_final, verf->packet_digest,
- sizeof(verf->packet_digest)) == 0);
+ return (memcmp(digest_final, verf->Checksum,
+ sizeof(verf->Checksum)) == 0);
}
/*******************************************************************
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 5df87e3b0b..7be0a0d2d2 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -407,7 +407,9 @@ static bool create_next_pdu_schannel(pipes_struct *p)
* Schannel processing.
*/
RPC_HDR_AUTH auth_info;
- RPC_AUTH_SCHANNEL_CHK verf;
+ struct NL_AUTH_SIGNATURE verf;
+ DATA_BLOB blob;
+ enum ndr_err_code ndr_err;
/* Check it's the type of reply we were expecting to decode */
@@ -429,10 +431,22 @@ static bool create_next_pdu_schannel(pipes_struct *p)
prs_data_p(&p->out_data.frag) + data_pos,
data_len + ss_padding_len);
- if (!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
- &verf, &p->out_data.frag, 0)) {
+ /* Finally marshall the blob. */
+
+ 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)) {
prs_mem_free(&p->out_data.frag);
- return False;
+ return false;
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &verf);
+ }
+
+ 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++;
@@ -2135,7 +2149,9 @@ bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss
uint32 auth_len;
uint32 save_offset = prs_offset(rpc_in);
RPC_HDR_AUTH auth_info;
- RPC_AUTH_SCHANNEL_CHK schannel_chk;
+ struct NL_AUTH_SIGNATURE schannel_chk;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
auth_len = p->hdr.auth_len;
@@ -2183,9 +2199,16 @@ bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss
return False;
}
- if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, &schannel_chk, rpc_in, 0)) {
- DEBUG(0,("failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
- return False;
+ blob = data_blob_const(prs_data_p(rpc_in) + prs_offset(rpc_in), data_len);
+
+ ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), NULL, &schannel_chk,
+ (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_SIGNATURE);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return false;
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &schannel_chk);
}
if (!schannel_decode(p->auth.a_u.schannel_auth,