diff options
Diffstat (limited to 'source3/rpc_parse/parse_prs.c')
-rw-r--r-- | source3/rpc_parse/parse_prs.c | 286 |
1 files changed, 0 insertions, 286 deletions
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 09263b45d4..edccded6c6 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -1066,292 +1066,6 @@ bool prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_ } /******************************************************************* - Create a digest over the entire packet (including the data), and - MD5 it with the session key. - ********************************************************************/ - -static void schannel_digest(struct schannel_auth_struct *a, - enum dcerpc_AuthLevel auth_level, - 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,6,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, sig, 8); - if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { - MD5Update(&ctx3, verf->Confounder, sizeof(verf->Confounder)); - } - MD5Update(&ctx3, (const unsigned char *)data, data_len); - MD5Final(whole_packet_digest, &ctx3); - dump_data_pw("whole_packet_digest:\n", whole_packet_digest, sizeof(whole_packet_digest)); - - /* MD5 this result and the session key, to prove that - only a valid client could had produced this */ - hmac_md5(a->sess_key, whole_packet_digest, sizeof(whole_packet_digest), digest_final); -} - -/******************************************************************* - Calculate the key with which to encode the data payload - ********************************************************************/ - -static void schannel_get_sealing_key(struct schannel_auth_struct *a, - struct NL_AUTH_SIGNATURE *verf, - uchar sealing_key[16]) -{ - uchar zeros[4]; - uchar digest2[16]; - uchar sess_kf0[16]; - int i; - - ZERO_STRUCT(zeros); - - for (i = 0; i < sizeof(sess_kf0); i++) { - sess_kf0[i] = a->sess_key[i] ^ 0xf0; - } - - dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0)); - - /* MD5 of sess_kf0 and 4 zero bytes */ - hmac_md5(sess_kf0, zeros, 0x4, digest2); - dump_data_pw("digest2:\n", digest2, sizeof(digest2)); - - /* MD5 of the above result, plus 8 bytes of sequence number */ - hmac_md5(digest2, verf->SequenceNumber, sizeof(verf->SequenceNumber), sealing_key); - dump_data_pw("sealing_key:\n", sealing_key, 16); -} - -/******************************************************************* - Encode or Decode the sequence number (which is symmetric) - ********************************************************************/ - -static void schannel_deal_with_seq_num(struct schannel_auth_struct *a, - struct NL_AUTH_SIGNATURE *verf) -{ - uchar zeros[4]; - uchar sequence_key[16]; - uchar digest1[16]; - - ZERO_STRUCT(zeros); - - hmac_md5(a->sess_key, zeros, sizeof(zeros), digest1); - dump_data_pw("(sequence key) digest1:\n", digest1, sizeof(digest1)); - - 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->SequenceNumber, sizeof(verf->SequenceNumber)); - arcfour_crypt(verf->SequenceNumber, sequence_key, 8); - dump_data_pw("seq_num (after):\n", verf->SequenceNumber, sizeof(verf->SequenceNumber)); -} - -/******************************************************************* - Encode a blob of data using the schannel alogrithm, also produceing - a checksum over the original data. We currently only support - signing and sealing togeather - the signing-only code is close, but not - quite compatible with what MS does. - ********************************************************************/ - -void schannel_encode(struct schannel_auth_struct *a, enum dcerpc_AuthLevel auth_level, - enum schannel_direction direction, - struct NL_AUTH_SIGNATURE *verf, - char *data, size_t data_len) -{ - uchar digest_final[16]; - uchar confounder[8]; - uchar seq_num[8]; - static const uchar nullbytes[8] = { 0, }; - - DEBUG(10,("SCHANNEL: schannel_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); - - /* fill the 'confounder' with random data */ - generate_random_buffer(confounder, sizeof(confounder)); - - dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); - - RSIVAL(seq_num, 0, a->seq_num); - - switch (direction) { - case SENDER_IS_INITIATOR: - SIVAL(seq_num, 4, 0x80); - break; - case SENDER_IS_ACCEPTOR: - SIVAL(seq_num, 4, 0x0); - break; - } - - dump_data_pw("verf->SequenceNumber:\n", verf->SequenceNumber, sizeof(verf->SequenceNumber)); - - if (auth_level == DCERPC_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)); - - /* 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->Checksum, digest_final, sizeof(verf->Checksum)); - - if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { - uchar sealing_key[16]; - - /* get the key to encode the data with */ - 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_enc:\n", verf->Confounder, sizeof(verf->Confounder)); - - /* encode the packet payload */ - dump_data_pw("data:\n", (const unsigned char *)data, data_len); - arcfour_crypt((unsigned char *)data, sealing_key, data_len); - dump_data_pw("data_enc:\n", (const unsigned char *)data, data_len); - } - - /* encode the sequence number (key based on packet digest) */ - /* needs to be done after the sealing, as the original version - is used in the sealing stuff... */ - schannel_deal_with_seq_num(a, verf); - - return; -} - -/******************************************************************* - Decode a blob of data using the schannel alogrithm, also verifiying - a checksum over the original data. We currently can verify signed messages, - as well as decode sealed messages - ********************************************************************/ - -bool schannel_decode(struct schannel_auth_struct *a, enum dcerpc_AuthLevel auth_level, - enum schannel_direction direction, - struct NL_AUTH_SIGNATURE *verf, char *data, size_t data_len) -{ - uchar digest_final[16]; - - 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; - - uchar seq_num[8]; - - DEBUG(10,("SCHANNEL: schannel_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); - - if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { - schannel_sig = schannel_seal_sig; - } else { - schannel_sig = schannel_sign_sig; - } - - /* Create the expected sequence number for comparison */ - RSIVAL(seq_num, 0, a->seq_num); - - switch (direction) { - case SENDER_IS_INITIATOR: - SIVAL(seq_num, 4, 0x80); - break; - case SENDER_IS_ACCEPTOR: - SIVAL(seq_num, 4, 0x0); - break; - } - - DEBUG(10,("SCHANNEL: schannel_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); - dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); - - dump_data_pw("seq_num:\n", seq_num, sizeof(seq_num)); - - /* extract the sequence number (key based on supplied packet digest) */ - /* needs to be done before the sealing, as the original version - is used in the sealing stuff... */ - schannel_deal_with_seq_num(a, verf); - - 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->SequenceNumber, sizeof(verf->SequenceNumber)); - DEBUG(2, ("should be:\n")); - dump_data(2, seq_num, sizeof(seq_num)); - - return False; - } - - 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, (const uint8_t *)verf, sizeof(schannel_sig)); - DEBUG(2, ("should be:\n")); - dump_data(2, schannel_sig, sizeof(schannel_sig)); - return False; - } - - if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { - uchar sealing_key[16]; - - /* get the key to extract the data with */ - 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_dec:\n", verf->Confounder, - sizeof(verf->Confounder)); - - /* extract the packet payload */ - dump_data_pw("data :\n", (const unsigned char *)data, data_len); - arcfour_crypt((unsigned char *)data, sealing_key, data_len); - dump_data_pw("datadec:\n", (const unsigned char *)data, data_len); - } - - /* digest includes 'data' after unsealing */ - schannel_digest(a, auth_level, verf, data, data_len, digest_final); - - dump_data_pw("Calculated digest:\n", digest_final, - sizeof(digest_final)); - 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->Checksum, - sizeof(verf->Checksum)) == 0); -} - -/******************************************************************* creates a new prs_struct containing a DATA_BLOB ********************************************************************/ bool prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx) |