};
#pragma pack(pop)
-/* signature structure, v1 or v2 */
-#pragma pack(push, 1)
-union wire_msg_signature {
- struct {
- uint32_t version;
- uint8_t random_pad[4];
- uint8_t checksum[4];
- uint32_t seq_num;
- } v1;
- struct {
- uint32_t version;
- uint8_t checksum[8];
- uint32_t seq_num;
- } v2;
-};
-#pragma pack(pop)
-
/* Version information.
* Used only for debugging and usually placed as the head of the payload when
* used */
};
#pragma pack(pop)
+/* signature structure, v1 or v2 */
+#pragma pack(push, 1)
+union wire_msg_signature {
+ struct {
+ uint32_t version;
+ uint32_t random_pad;
+ uint32_t checksum;
+ uint32_t seq_num;
+ } v1;
+ struct {
+ uint32_t version;
+ uint64_t checksum;
+ uint32_t seq_num;
+ } v2;
+};
+#pragma pack(pop)
+
/* the max username is 20 chars, max NB domain len is 15, so 128 should be
* plenty including conversion to UTF8 using max lenght for each code point
*/
struct ntlm_buffer *message,
struct ntlm_buffer *signature)
{
- uint32_t ver;
struct ntlm_buffer key = { sign_key->data, sign_key->length };
+ union wire_msg_signature *msg_sig;
uint32_t le_seq;
uint8_t le8seq[8];
struct ntlm_buffer seq = { le8seq, 4 };
struct ntlm_buffer rc4res;
int ret;
+ msg_sig = (union wire_msg_signature *)signature->data;
if (signature->length != 16) {
return EINVAL;
}
if (ret) return ret;
/* put version */
- ver = htole32(NTLMSSP_MESSAGE_SIGNATURE_VERSION);
- memcpy(signature->data, &ver, 4);
+ msg_sig->v2.version = htole32(NTLMSSP_MESSAGE_SIGNATURE_VERSION);
/* put actual MAC */
if (keyex) {
rc4buf.data = hmac.data;
rc4buf.length = 8;
/* and put it in the middle of the output signature */
- rc4res.data = &signature->data[4];
+ rc4res.data = (uint8_t *)&msg_sig->v2.checksum;
rc4res.length = 8;
ret = RC4_UPDATE(handle, &rc4buf, &rc4res);
if (ret) return ret;
} else {
- memcpy(&signature->data[4], hmac.data, 8);
+ memcpy(&msg_sig->v2.checksum, hmac.data, 8);
}
/* put used seq_num */
- memcpy(&signature->data[12], seq.data, 4);
+ msg_sig->v2.seq_num = le_seq;
+
+ return 0;
+}
+
+static int ntlmv1_sign(struct ntlm_rc4_handle *handle,
+ uint32_t random_pad, uint32_t seq_num,
+ struct ntlm_buffer *message,
+ struct ntlm_buffer *signature)
+{
+ union wire_msg_signature *msg_sig;
+ uint32_t rc4buf[3];
+ struct ntlm_buffer payload;
+ struct ntlm_buffer result;
+ int ret;
+
+ msg_sig = (union wire_msg_signature *)signature->data;
+ if (signature->length != 16) {
+ return EINVAL;
+ }
+
+ rc4buf[0] = 0;
+ rc4buf[1] = htole32(CRC32(0, message));
+ rc4buf[2] = htole32(seq_num);
+
+ payload.data = (uint8_t *)rc4buf;
+ payload.length = 12;
+ result.data = (uint8_t *)&msg_sig->v1.random_pad;
+ result.length = 12;
+ ret = RC4_UPDATE(handle, &payload, &result);
+ if (ret) return ret;
+
+ msg_sig->v1.version = htole32(NTLMSSP_MESSAGE_SIGNATURE_VERSION);
+ msg_sig->v1.random_pad = random_pad;
return 0;
}
(flags & NTLMSSP_NEGOTIATE_KEY_EXCH),
message, signature);
} else if (flags & NTLMSSP_NEGOTIATE_SIGN) {
- /* FIXME: needs an implementation of CRC32 maybe use zlib ? */
+ return ntlmv1_sign(handle, 0, seq_num, message, signature);
} else if (flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) {
uint32_t le_seq = htole32(seq_num);
memcpy(signature->data, &le_seq, 4);
{
int ret;
- if (!((flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)
- && (flags & NTLMSSP_NEGOTIATE_SEAL))) {
- /* we only support v2 for now as we can't sign w/o session security
- * anyway */
- return ENOTSUP;
- }
+ if (flags & NTLMSSP_NEGOTIATE_SEAL) {
+ ret = RC4_UPDATE(handle, message, output);
+ if (ret) return ret;
- ret = RC4_UPDATE(handle, message, output);
- if (ret) return ret;
+ if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) {
+ return ntlmv2_sign(sign_key, seq_num, handle,
+ (flags & NTLMSSP_NEGOTIATE_KEY_EXCH),
+ message, signature);
+ } else {
+ return ntlmv1_sign(handle, 0, seq_num, message, signature);
+ }
+ }
- return ntlmv2_sign(sign_key, seq_num, handle,
- (flags & NTLMSSP_NEGOTIATE_KEY_EXCH),
- message, signature);
+ return ENOTSUP;
}
int ntlm_unseal(struct ntlm_rc4_handle *handle, uint32_t flags,
struct ntlm_buffer Signature;
};
+/* Basic GSS_WrapEx V1 Test Data */
+struct t_gsswrapex_data T_GSSWRAPv1noESS = {
+ (
+ NTLMSSP_NEGOTIATE_56 |
+ NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL
+ ),
+ 0,
+ {
+ .data = (uint8_t *)"\x50\x00\x6c\x00\x61\x00\x69\x00"
+ "\x6e\x00\x74\x00\x65\x00\x78\x00\x74\x00",
+ .length = 18
+ },
+ {
+ .data = {
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55
+ },
+ .length = 16
+ },
+ {
+ .data = { 0 },
+ .length = 0
+ },
+ {
+ .data = { 0 },
+ .length = 0
+ },
+ {
+ .data = (uint8_t *)"\x56\xfe\x04\xd8\x61\xf9\x31\x9a"
+ "\xf0\xd7\x23\x8a\x2e\x3b\x4d\x45\x7f\xb8",
+ .length = 18
+ },
+ {
+ .data = (uint8_t *)"\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x09\xdc\xd1\xdf\x2e\x45\x9d\x36",
+ .length = 16
+ },
+};
+
/* GSS_WrapEx V1 Extended Session Security Test Data */
struct t_gsswrapex_data T_GSSWRAPEXv1 = {
(
&seal_send_handle, &seal_recv_handle);
if (ret) return ret;
- if (memcmp(seal_send_key.data, data->ClientSealKey.data, 16) != 0) {
- fprintf(stderr, "Client Sealing Keys differ!\n");
- fprintf(stderr, "expected:\n%s",
- hex_to_dump(data->ClientSealKey.data, 16));
- fprintf(stderr, "obtained:\n%s",
- hex_to_dump(seal_send_key.data, sign_send_key.length));
- ret = EINVAL;
+ if (data->ClientSealKey.length) {
+ if (memcmp(seal_send_key.data, data->ClientSealKey.data,
+ data->ClientSealKey.length) != 0) {
+ fprintf(stderr, "Client Sealing Keys differ!\n");
+ fprintf(stderr, "expected:\n%s",
+ hex_to_dump(data->ClientSealKey.data,
+ data->ClientSealKey.length));
+ fprintf(stderr, "obtained:\n%s",
+ hex_to_dump(seal_send_key.data, sign_send_key.length));
+ ret = EINVAL;
+ }
}
- if (memcmp(sign_send_key.data, data->ClientSignKey.data, 16) != 0) {
- fprintf(stderr, "Client Signing Keys differ!\n");
- fprintf(stderr, "expected:\n%s",
- hex_to_dump(data->ClientSignKey.data, 16));
- fprintf(stderr, "obtained:\n%s",
- hex_to_dump(sign_send_key.data, sign_send_key.length));
- ret = EINVAL;
+ if (data->ClientSignKey.length) {
+ if (memcmp(sign_send_key.data, data->ClientSignKey.data,
+ data->ClientSignKey.length) != 0) {
+ fprintf(stderr, "Client Signing Keys differ!\n");
+ fprintf(stderr, "expected:\n%s",
+ hex_to_dump(data->ClientSignKey.data,
+ data->ClientSignKey.length));
+ fprintf(stderr, "obtained:\n%s",
+ hex_to_dump(sign_send_key.data, sign_send_key.length));
+ ret = EINVAL;
+ }
}
if (ret) return ret;
ret = test_EncodeAuthenticateMessageV2(ctx);
fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
+ fprintf(stdout, "Test sealing a Message with No Extended Security\n");
+ ret = test_GSS_Wrap_EX(ctx, &T_GSSWRAPv1noESS);
+ fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
+
fprintf(stdout, "Test sealing a Message with NTLMv1 Extended Security\n");
ret = test_GSS_Wrap_EX(ctx, &T_GSSWRAPEXv1);
fprintf(stdout, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));