Mailing List Archive

DomainKeys & DKIM Endian'ness bug
I believe I have run across a bug in the experimental Domainkey (dk.c) &
DKIM (dkim-exim.c) support in Exim. This bug only effects Big Endian (
http://en.wikipedia.org/wiki/Endianness ) machines (in my case Sun Sparc).

The code between the two is very similar, hence the same bug. In the
dk_receive_getc ( / dkim_receive_getc), it wants to get a character from
Exim and pass it to the respective dk/dkim routine...

int dkbuff[6] = {256,256,256,256,256,256};

/* receive_getc() wrapper that feeds DK while Exim reads
the message. */
int dk_receive_getc(void) {
int i;
int c = receive_getc();

if (dk_context != NULL) {
/* Send oldest byte */
if ((dkbuff[0] < 256) && (dk_internal_status == DK_STAT_OK)) {
dk_internal_status = dk_message(dk_context, CUS &dkbuff[0], 1);
.
.
.
/* Send remaining bytes from input which are still in the buffer. */
for (i=0;i<6;i++)
if (dkbuff[i] < 256)
dk_internal_status = dk_message(dk_context, CUS &dkbuff[i], 1);

the problem is the definition of dkbuff - i.e. int. On Big Endian
machines, &dkbuff[something] returns the address of the most significant
byte!!, always 0.

I have two potential "fixes":

1) Put the int into a real char, and pass the address of the char...

int dkbuff[6] = {256,256,256,256,256,256};

/* receive_getc() wrapper that feeds DK while Exim reads
the message. */
int dk_receive_getc(void) {
int i;
int c = receive_getc();

if (dk_context != NULL) {
/* Send oldest byte */
if ((dkbuff[0] < 256) && (dk_internal_status == DK_STAT_OK)) {
unsigned char s = dkbuff[0];
dk_internal_status = dk_message(dk_context, CUS &s, 1);
.
.
.
/* Send remaining bytes from input which are still in the buffer. */
for (i=0;i<6;i++)
if (dkbuff[i] < 256) {
unsigned char s = dkbuff[i];
dk_internal_status = dk_message(dk_context, CUS &s, 1);
}

2) Fix-up the address being sent...

#ifdef _BIG_ENDIAN
#define ENDIAN_OFFSET sizeof( int ) - 1
#else
#define ENDIAN_OFFSET 0
#endif
.
.
.
int dkbuff[6] = {256,256,256,256,256,256};

/* receive_getc() wrapper that feeds DK while Exim reads
the message. */
int dk_receive_getc(void) {
int i;
int c = receive_getc();

if (dk_context != NULL) {
/* Send oldest byte */
if ((dkbuff[0] < 256) && (dk_internal_status == DK_STAT_OK)) {
dk_internal_status = dk_message(dk_context, CUS &dkbuff[0] +
ENDIAN_OFFSET, 1);
.
.
.
/* Send remaining bytes from input which are still in the buffer. */
for (i=0;i<6;i++)
if (dkbuff[i] < 256)
dk_internal_status = dk_message(dk_context, CUS &dkbuff[i] +
ENDIAN_OFFSET, 1);

I think I like #1 better, but I'm not sure.

I was hoping that the maintainer's of this code might have some additional

insight and could possibly point me at other places where endian'ness
might be an issue.

Thanks,

Dan


--
## List details at http://lists.exim.org/mailman/listinfo/exim-dev Exim details at http://www.exim.org/ ##
Re: DomainKeys & DKIM Endian'ness bug [ In reply to ]
Dan_Mitton@YMP.GOV schrieb:

> I think I like #1 better, but I'm not sure.

Me too :)

> I was hoping that the maintainer's of this code might have some additional
> insight and could possibly point me at other places where endian'ness
> might be an issue.

I'll fix this tonight, and do a quick check on the rest of the code, but
I guess that's all there is to it. Not much more byte-pushing going on
in there.

Thanks for the detective work!

/tom

--
## List details at http://lists.exim.org/mailman/listinfo/exim-dev Exim details at http://www.exim.org/ ##