--- Begin Message ---
Package: mod-proxy-msrpc
Version: 0.5-1
Severity: serious
Tags: sid + patch
Justification: FTBFS
User: debian-m...@lists.debian.org
Usertags: mips-patch
Hello,
Package mod-proxy-msrpc_0.5-1 FTBFS on mips and on other big-endian
architectures.
mips build log:
https://buildd.debian.org/status/fetch.php?pkg=mod-proxy-msrpc&arch=mips&ver=0.5-1&stamp=1399057058
There is a solution for this problem upstream.
I have created a patch using upstream fixes for big-endian.
A patch is attached.
With this patch applied, package builds successfully on mips.
Regards,
Jurica
--- mod-proxy-msrpc-0.5.orig/src/msrpc_pdu_parser.c
+++ mod-proxy-msrpc-0.5/src/msrpc_pdu_parser.c
@@ -72,6 +72,8 @@ static const char const *msrpc_rts_pdu_c
NULL,
};
+#define MSRPC_PDU_IS_LITTLE_ENDIAN (pdu->data_representation == MSRPC_PDU_DATA_REPRESENTATION_LITTLE_ENDIAN)
+
apr_status_t msrpc_pdu_get_length(const char *buf, apr_size_t *length)
{
msrpc_pdu_t *pdu = (msrpc_pdu_t *)buf;
@@ -81,7 +83,10 @@ apr_status_t msrpc_pdu_get_length(const
return APR_INCOMPLETE;
}
- *length = pdu->frag_length;
+ #ifdef DEBUG_MSRPC_PDU_PARSER
+ printf("data representation: 0x%08x\n", (uint32_t)pdu->data_representation);
+ #endif
+ *length = MSRPC_PDU_IS_LITTLE_ENDIAN ? pdu->frag_length : swap_bytes_uint16_t(pdu->frag_length);
return APR_SUCCESS;
}
@@ -110,11 +115,13 @@ apr_status_t msrpc_pdu_validate(const ch
if (error) *error = "PDU type";
return APR_FROM_OS_ERROR(EBADMSG);
}
- if (pdu->data_representation != 16) {
+ if ((pdu->data_representation != MSRPC_PDU_DATA_REPRESENTATION_LITTLE_ENDIAN) &&
+ (pdu->data_representation != MSRPC_PDU_DATA_REPRESENTATION_BIG_ENDIAN)) {
if (error) *error = "data representation";
return APR_FROM_OS_ERROR(EBADMSG);
}
- if (pdu->frag_length % 4 != 0) {
+ uint16_t frag_length = MSRPC_PDU_IS_LITTLE_ENDIAN ? pdu->frag_length : swap_bytes_uint16_t(pdu->frag_length);
+ if (frag_length % 4 != 0) {
if (error) *error = "unaligned length";
return APR_FROM_OS_ERROR(EBADMSG);
}
@@ -130,18 +137,24 @@ apr_status_t msrpc_pdu_get_rts_pdu_count
if (pdu->type != MSRPC_PDU_RTS) {
return APR_FROM_OS_ERROR(EINVAL);
}
- *count = pdu->rts_pdu_count;
+ *count = MSRPC_PDU_IS_LITTLE_ENDIAN ? pdu->rts_pdu_count : swap_bytes_uint16_t(pdu->rts_pdu_count);
return APR_SUCCESS;
}
-apr_size_t msrpc_rts_pdu_len(const msrpc_rts_pdu_t *pdu)
+unsigned int msrpc_rts_pdu_len(const msrpc_rts_pdu_t *pdu, uint32_t data_representation)
{
apr_size_t size = 0;
uint32_t conformance_count;
uint32_t addrtype;
+ uint32_t command;
assert(pdu != NULL);
- switch (pdu->command) {
+ command = (data_representation == MSRPC_PDU_DATA_REPRESENTATION_LITTLE_ENDIAN) ? pdu->command : swap_bytes_uint32_t(pdu->command);
+ #ifdef DEBUG_MSRPC_PDU_PARSER
+ printf("msrpc_rts_pdu_len: data representation: 0x%08x, command: 0x%08x\n", data_representation, command);
+ #endif
+
+ switch (command) {
case RTS_CMD_RECEIVE_WINDOW_SIZE:
case RTS_CMD_CONNECTION_TIMEOUT:
case RTS_CMD_CHANNEL_LIFETIME:
@@ -167,14 +180,22 @@ apr_size_t msrpc_rts_pdu_len(const msrpc
break;
case RTS_CMD_PADDING:
// see http://msdn.microsoft.com/en-us/library/cc244015.aspx
- conformance_count = pdu->u32[0];
+ if (data_representation == MSRPC_PDU_DATA_REPRESENTATION_LITTLE_ENDIAN) {
+ conformance_count = pdu->u32[0];
+ } else {
+ conformance_count = swap_bytes_uint32_t(pdu->u32[0]);
+ }
size = sizeof(pdu->command) + sizeof(conformance_count)
+ conformance_count;
break;
case RTS_CMD_CLIENT_ADDRESS:
// see http://msdn.microsoft.com/en-us/library/cc244004.aspx
// and http://msdn.microsoft.com/en-us/library/cc243993.aspx
- addrtype = pdu->u32[0];
+ if (data_representation == MSRPC_PDU_DATA_REPRESENTATION_LITTLE_ENDIAN) {
+ addrtype = pdu->u32[0];
+ } else {
+ addrtype = swap_bytes_uint32_t(pdu->u32[0]);
+ }
size = sizeof(pdu->command) + sizeof(addrtype);
switch (addrtype) {
case RTS_IPV4:
@@ -194,32 +215,33 @@ apr_size_t msrpc_rts_pdu_len(const msrpc
return size;
}
-apr_status_t msrpc_pdu_get_rts_pdu(const char *buf, unsigned int offset, msrpc_rts_pdu_t **rts_pdu, apr_size_t *len)
+apr_status_t msrpc_pdu_get_rts_pdu(const char *buf, unsigned int offset, msrpc_rts_pdu_t **rts_pdu, unsigned int *len)
{
assert(buf != NULL);
assert(rts_pdu != NULL);
msrpc_pdu_t *pdu = (msrpc_pdu_t *)buf;
+ uint16_t frag_length = MSRPC_PDU_IS_LITTLE_ENDIAN ? pdu->frag_length : swap_bytes_uint16_t(pdu->frag_length);
if (pdu->type != MSRPC_PDU_RTS) {
#ifdef DEBUG_MSRPC_PDU_PARSER
printf("No RTS PDU\n");
#endif
return APR_FROM_OS_ERROR(EINVAL);
}
- if (offsetof(msrpc_pdu_t, rts_pdu_buf) + offset >= pdu->frag_length) {
+ if (offsetof(msrpc_pdu_t, rts_pdu_buf) + offset >= frag_length) {
#ifdef DEBUG_MSRPC_PDU_PARSER
printf("Frag length shorter than offset\n");
#endif
return APR_FROM_OS_ERROR(EINVAL);
}
- apr_size_t pdusize = msrpc_rts_pdu_len((msrpc_rts_pdu_t *)(pdu->rts_pdu_buf + offset));
+ unsigned int pdusize = msrpc_rts_pdu_len((msrpc_rts_pdu_t *)(pdu->rts_pdu_buf + offset), pdu->data_representation);
if (pdusize == 0) {
#ifdef DEBUG_MSRPC_PDU_PARSER
printf("failed to parse RTS PDU\n");
#endif
return APR_FROM_OS_ERROR(EBADMSG);
}
- if (offsetof(msrpc_pdu_t, rts_pdu_buf) + offset + pdusize > pdu->frag_length) {
+ if (offsetof(msrpc_pdu_t, rts_pdu_buf) + offset + pdusize > frag_length) {
#ifdef DEBUG_MSRPC_PDU_PARSER
printf("RTS PDU length doesn't fit into frag length at the given offset\n");
#endif
@@ -240,21 +262,27 @@ const char *msrpc_pdu_get_name(const cha
return NULL;
}
-const char *msrpc_rts_pdu_get_command_name(msrpc_rts_pdu_t *pdu)
+const char *msrpc_rts_pdu_get_command_name(msrpc_rts_pdu_t *pdu, uint32_t data_representation)
{
+ uint32_t command;
+
assert(pdu);
- if (pdu->command <= RTS_CMD_PING_TRAFFIC_SENT_NOTIFY) {
- return msrpc_rts_pdu_command_name[pdu->command];
+ command = (data_representation == MSRPC_PDU_DATA_REPRESENTATION_LITTLE_ENDIAN) ? pdu->command : swap_bytes_uint32_t(pdu->command);
+ if (command <= RTS_CMD_PING_TRAFFIC_SENT_NOTIFY) {
+ return msrpc_rts_pdu_command_name[command];
}
return NULL;
}
apr_status_t msrpc_rts_get_virtual_channel_cookie(const char *buf, uuid_t **cookie, const char **error)
{
+ msrpc_pdu_t *pdu = (msrpc_pdu_t *)buf;
+ uint16_t rts_pdu_count;
+ apr_status_t rv;
+
assert(buf);
assert(cookie);
- msrpc_pdu_t *pdu = (msrpc_pdu_t *)buf;
if (pdu->type != MSRPC_PDU_RTS) {
if (error) *error = "not a RTS pdu";
return APR_FROM_OS_ERROR(EINVAL);
@@ -265,22 +293,30 @@ apr_status_t msrpc_rts_get_virtual_chann
return APR_FROM_OS_ERROR(EBADMSG);
}
- if ((pdu->rts_pdu_count != 4) &&
- (pdu->rts_pdu_count != 6)) {
+ rv = msrpc_pdu_get_rts_pdu_count(buf, &rts_pdu_count);
+ if (rv != APR_SUCCESS) {
+ if (error) *error = "unexpected error from msrpc_pdu_get_rts_pdu_count()";
+ return rv;
+ }
+
+ if ((rts_pdu_count != 4) &&
+ (rts_pdu_count != 6)) {
if (error) *error = "unexpected RTS command count";
return APR_FROM_OS_ERROR(EBADMSG);
}
unsigned int offset = 0;
msrpc_rts_pdu_t *rtspdu = NULL;
- apr_size_t rtspdulen = 0;
- apr_size_t rv = msrpc_pdu_get_rts_pdu(buf, offset, &rtspdu, &rtspdulen);
+ unsigned int rtspdulen = 0;
+ rv = msrpc_pdu_get_rts_pdu(buf, offset, &rtspdu, &rtspdulen);
if (rv != APR_SUCCESS) {
if (error) *error = "failed to get first RTS command";
return rv;
}
- if ((rtspdu->command != RTS_CMD_VERSION) &&
- (rtspdu->u32[0] != 1)) {
+ uint32_t command = MSRPC_PDU_IS_LITTLE_ENDIAN ? rtspdu->command : swap_bytes_uint32_t(rtspdu->command);
+ uint32_t rts_version = MSRPC_PDU_IS_LITTLE_ENDIAN ? rtspdu->u32[0] : swap_bytes_uint32_t(rtspdu->u32[0]);
+ if ((command != RTS_CMD_VERSION) &&
+ (rts_version != 1)) {
if (error) *error = "unexpected first RTS command or RTS version";
return APR_FROM_OS_ERROR(EBADMSG);
}
@@ -291,7 +327,8 @@ apr_status_t msrpc_rts_get_virtual_chann
if (error) *error = "failed to get second RTS command";
return rv;
}
- if (rtspdu->command != RTS_CMD_COOKIE) {
+ command = MSRPC_PDU_IS_LITTLE_ENDIAN ? rtspdu->command : swap_bytes_uint32_t(rtspdu->command);
+ if (command != RTS_CMD_COOKIE) {
if (error) *error = "unexpected second RTS command";
return APR_FROM_OS_ERROR(EBADMSG);
}
--- mod-proxy-msrpc-0.5.orig/src/msrpc_pdu_parser.h
+++ mod-proxy-msrpc-0.5/src/msrpc_pdu_parser.h
@@ -30,10 +30,10 @@ typedef struct msrpc_rts_pdu msrpc_rts_p
apr_status_t msrpc_pdu_get_length(const char *buf, apr_size_t *length);
apr_status_t msrpc_pdu_validate(const char *buf, const char **error);
apr_status_t msrpc_pdu_get_rts_pdu_count(const char *buf, uint16_t *count);
-apr_size_t msrpc_rts_pdu_len(const msrpc_rts_pdu_t *pdu);
-apr_status_t msrpc_pdu_get_rts_pdu(const char *buf, unsigned int offset, msrpc_rts_pdu_t **rts_pdu, apr_size_t *len);
+unsigned int msrpc_rts_pdu_len(const msrpc_rts_pdu_t *pdu, uint32_t data_representation);
+apr_status_t msrpc_pdu_get_rts_pdu(const char *buf, unsigned int offset, msrpc_rts_pdu_t **rts_pdu, unsigned int *len);
const char *msrpc_pdu_get_name(const char *buf);
-const char *msrpc_rts_pdu_get_command_name(msrpc_rts_pdu_t *pdu);
+const char *msrpc_rts_pdu_get_command_name(msrpc_rts_pdu_t *pdu, uint32_t data_representation);
apr_status_t msrpc_rts_get_virtual_channel_cookie(const char *buf, uuid_t **cookie, const char **error);
--- mod-proxy-msrpc-0.5.orig/src/msrpc_pdu_private.h
+++ mod-proxy-msrpc-0.5/src/msrpc_pdu_private.h
@@ -22,6 +22,12 @@
#include <netinet/in.h>
#include <uuid/uuid.h>
+#define MSRPC_PDU_DATA_REPRESENTATION_BIG_ENDIAN 0x10000000
+#define MSRPC_PDU_DATA_REPRESENTATION_LITTLE_ENDIAN 0x00000010
+#define swap_bytes_uint16_t(x) ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8))
+#define swap_bytes_uint32_t(x) ((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | \
+ (((x) & 0x00FF0000) >> 8) | (((x) & 0xFF000000) >> 24))
+
/* interpretation of such PDUs, see Microsoft's documentation:
* http://msdn.microsoft.com/en-us/library/cc244017.aspx (RTS PDU header)
* http://msdn.microsoft.com/en-us/library/cc244018.aspx (RTS PDU body)
--- mod-proxy-msrpc-0.5.orig/test/check_msrpc_pdu_parser.c
+++ mod-proxy-msrpc-0.5/test/check_msrpc_pdu_parser.c
@@ -67,9 +67,11 @@ const static test_msrpc_pdu_validate_t t
{ "\x06\x00\x14\x03\x10\x00\x00\x00\x0c\x00\x00\x00", "PDU version", APR_FROM_OS_ERROR(EBADMSG) },
{ "\x05\x01\x14\x03\x10\x00\x00\x00\x0c\x00\x00\x00", "PDU minor version", APR_FROM_OS_ERROR(EBADMSG) },
{ "\x05\x00\x15\x03\x10\x00\x00\x00\x0c\x00\x00\x00", "PDU type", APR_FROM_OS_ERROR(EBADMSG) },
- { "\x05\x00\x14\x03\x00\x00\x00\x10\x0c\x00\x00\x00", "data representation", APR_FROM_OS_ERROR(EBADMSG) },
+ { "\x05\x00\x14\x03\x01\x11\x11\x11\x0c\x00\x00\x00", "data representation", APR_FROM_OS_ERROR(EBADMSG) },
{ "\x05\x00\x14\x03\x10\x00\x00\x00\x0d\x00\x00\x00\x00", "unaligned length", APR_FROM_OS_ERROR(EBADMSG) },
{ "\x05\x00\x14\x03\x10\x00\x00\x00\x0c\x00\x00\x00", NULL, APR_SUCCESS },
+ // Caution: next is a synthetic test case, big endian data representation has not been seen in the wild:
+ { "\x05\x00\x14\x03\x00\x00\x00\x10\x00\x0c\x00\x00", NULL, APR_SUCCESS },
{ TESTDATA_INITIAL_PDU_IN, NULL, APR_SUCCESS },
{ TESTDATA_INITIAL_PDU_OUT, NULL, APR_SUCCESS },
};
@@ -89,32 +91,33 @@ const static test_msrpc_pdu_get_rts_pdu_
const static size_t testset_msrpc_pdu_get_rts_pdu_count_size = sizeof(testset_msrpc_pdu_get_rts_pdu_count) / sizeof(test_msrpc_pdu_get_rts_pdu_count_t);
typedef struct {
+ const char data_representation[4];
const char *data;
- apr_size_t expected_size;
+ unsigned int expected_size;
} test_msrpc_rts_pdu_len_t;
const static test_msrpc_rts_pdu_len_t testset_msrpc_rts_pdu_len[] = {
- { "\x00\x00\x00\x00", 8 },
- { "\x01\x00\x00\x00", 28 },
- { "\x02\x00\x00\x00", 8 },
- { "\x03\x00\x00\x00", 20 },
- { "\x04\x00\x00\x00", 8 },
- { "\x05\x00\x00\x00", 8 },
- { "\x06\x00\x00\x00", 8 },
- { "\x07\x00\x00\x00", 4 },
- { "\x08\x00\x00\x00\x00\x00\x00\x00", 8 },
- { "\x08\x00\x00\x00\x01\x00\x00\x00", 9 },
+ { "\x10\x00\x00\x00", "\x00\x00\x00\x00", 8 },
+ { "\x10\x00\x00\x00", "\x01\x00\x00\x00", 28 },
+ { "\x10\x00\x00\x00", "\x02\x00\x00\x00", 8 },
+ { "\x10\x00\x00\x00", "\x03\x00\x00\x00", 20 },
+ { "\x10\x00\x00\x00", "\x04\x00\x00\x00", 8 },
+ { "\x10\x00\x00\x00", "\x05\x00\x00\x00", 8 },
+ { "\x10\x00\x00\x00", "\x06\x00\x00\x00", 8 },
+ { "\x10\x00\x00\x00", "\x07\x00\x00\x00", 4 },
+ { "\x10\x00\x00\x00", "\x08\x00\x00\x00\x00\x00\x00\x00", 8 },
+ { "\x10\x00\x00\x00", "\x08\x00\x00\x00\x01\x00\x00\x00", 9 },
// checking whether all the bits from padding count are evaluated correctly:
- { "\x08\x00\x00\x00\x01\x02\x03\x04", 8 + 0x04030201 },
- { "\x09\x00\x00\x00", 4 },
- { "\x0a\x00\x00\x00", 4 },
- { "\x0b\x00\x00\x00\x00\x00\x00\x00", 8 + 4 + 12 }, // IPv4 address
- { "\x0b\x00\x00\x00\x01\x00\x00\x00", 8 + 16 + 12 }, // IPv6 address
- { "\x0b\x00\x00\x00\x03\x00\x00\x00", 0 }, // neither IPv4 nor IPv6 address
- { "\x0c\x00\x00\x00", 20 },
- { "\x0d\x00\x00\x00", 8 },
- { "\x0e\x00\x00\x00", 8 },
- { "\x0f\x00\x00\x00", 0 },
+ { "\x10\x00\x00\x00", "\x08\x00\x00\x00\x01\x02\x03\x04", 8 + 0x04030201 },
+ { "\x10\x00\x00\x00", "\x09\x00\x00\x00", 4 },
+ { "\x10\x00\x00\x00", "\x0a\x00\x00\x00", 4 },
+ { "\x10\x00\x00\x00", "\x0b\x00\x00\x00\x00\x00\x00\x00", 8 + 4 + 12 }, // IPv4 address
+ { "\x10\x00\x00\x00", "\x0b\x00\x00\x00\x01\x00\x00\x00", 8 + 16 + 12 }, // IPv6 address
+ { "\x10\x00\x00\x00", "\x0b\x00\x00\x00\x03\x00\x00\x00", 0 }, // neither IPv4 nor IPv6 address
+ { "\x10\x00\x00\x00", "\x0c\x00\x00\x00", 20 },
+ { "\x10\x00\x00\x00", "\x0d\x00\x00\x00", 8 },
+ { "\x10\x00\x00\x00", "\x0e\x00\x00\x00", 8 },
+ { "\x10\x00\x00\x00", "\x0f\x00\x00\x00", 0 },
};
const static size_t testset_msrpc_rts_pdu_len_size = sizeof(testset_msrpc_rts_pdu_len) / sizeof(test_msrpc_rts_pdu_len_t);
@@ -124,7 +127,7 @@ typedef struct {
int output_buffer_length;
apr_status_t expected_rv;
const char *expected_data;
- apr_size_t expected_length;
+ unsigned int expected_length;
} test_msrpc_pdu_get_rts_pdu_t;
const static test_msrpc_pdu_get_rts_pdu_t testset_msrpc_pdu_get_rts_pdu[] = {
@@ -167,7 +170,7 @@ const static size_t testset_msrpc_pdu_ge
typedef struct {
const char *data;
- apr_size_t rts_command_count;
+ unsigned int rts_command_count;
const char *name[7];
} test_msrpc_rts_pdu_get_command_name_t;
@@ -243,10 +246,11 @@ END_TEST
START_TEST (test_msrpc_rts_pdu_len)
{
+ uint32_t data_representation = *((uint32_t *)(testset_msrpc_rts_pdu_len[_i].data_representation));
const msrpc_rts_pdu_t *pdu = (const msrpc_rts_pdu_t *)testset_msrpc_rts_pdu_len[_i].data;
apr_size_t expected_size = testset_msrpc_rts_pdu_len[_i].expected_size;
- apr_size_t size = msrpc_rts_pdu_len(pdu);
+ apr_size_t size = msrpc_rts_pdu_len(pdu, data_representation);
fail_unless(size == expected_size, " for iteration %u\n"
"EXPECTED size: %lu, BUT GOT size: %lu", _i, expected_size, size);
}
@@ -256,7 +260,7 @@ START_TEST (test_msrpc_pdu_get_rts_pdu)
{
const test_msrpc_pdu_get_rts_pdu_t *testset = &testset_msrpc_pdu_get_rts_pdu[_i];
msrpc_rts_pdu_t *rtspdu = NULL;
- apr_size_t rtspdulen = 0;
+ unsigned int rtspdulen = 0;
apr_status_t rv = msrpc_pdu_get_rts_pdu(testset->data, testset->offset, &rtspdu, &rtspdulen);
fail_unless(testset->expected_rv == rv, " for iteration %u\n"
@@ -305,9 +309,10 @@ END_TEST
START_TEST (test_msrpc_rts_pdu_get_command_name)
{
const char *pdu = testset_msrpc_rts_pdu_get_command_name[_i].data;
- apr_size_t expected_command_count = testset_msrpc_rts_pdu_get_command_name[_i].rts_command_count;
+ uint32_t data_representation = ((msrpc_pdu_t *)pdu)->data_representation;
+ unsigned int expected_command_count = testset_msrpc_rts_pdu_get_command_name[_i].rts_command_count;
msrpc_rts_pdu_t *rtspdu = NULL;
- apr_size_t i, rtspdulen;
+ unsigned int i, rtspdulen;
unsigned int offset = 0;
apr_status_t rv;
@@ -315,7 +320,7 @@ START_TEST (test_msrpc_rts_pdu_get_comma
rv = msrpc_pdu_get_rts_pdu(pdu, offset, &rtspdu, &rtspdulen);
fail_unless(rv == APR_SUCCESS, " for iteration %u\n"
"EXPECTED rv 0, BUT GOT rv %u", _i, rv);
- const char *name = msrpc_rts_pdu_get_command_name(rtspdu);
+ const char *name = msrpc_rts_pdu_get_command_name(rtspdu, data_representation);
const char *expected_name = testset_msrpc_rts_pdu_get_command_name[_i].name[i];
if (name) {
if (!expected_name) {
--- End Message ---