[exim-dev] DomainKeys & DKIM Endian'ness bug

Top Page
Delete this message
Reply to this message
Author: Dan_Mitton
Date:  
To: exim-dev
Subject: [exim-dev] 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