]> Pileus Git - ~andy/fetchmail/blobdiff - rpa.c
Merge branch 'legacy_63'
[~andy/fetchmail] / rpa.c
diff --git a/rpa.c b/rpa.c
index 4643076dd77ddb22216b4428c3383e0791b9c69e..3f236ce945c40f56154aa9e75fc033b62e2519ef 100644 (file)
--- a/rpa.c
+++ b/rpa.c
@@ -9,18 +9,24 @@
 
   The sole entry point is POP3_auth_rpa()
 
+  For license terms, see the file COPYING in this directory.
+
  ***********************************************************************/
 
 #include  "config.h"
 
 #if defined(POP3_ENABLE) && defined(RPA_ENABLE)
 #include  <stdio.h>
+#include  <stdlib.h>
 #include  <unistd.h>
 #include  <ctype.h>
+#include  <string.h>
+#include  <sys/types.h>
 
 #include  "socket.h"
 #include  "fetchmail.h"
-#include  "md5.h"
+#include  "fm_md5.h"
+#include  "gettext.h"
 
 #ifdef TESTMODE
 extern unsigned char line1[];
@@ -30,23 +36,21 @@ extern unsigned char line3[];
 extern int linecount;
 #endif
 
-#ifndef NO_PROTO
-  /* prototypes for internal functions */
-  static int  POP3_rpa_resp(unsigned char* argbuf, int socket );
-  static void LenAppend(unsigned char** pptr, int len);
-  static int  LenSkip(unsigned char** pptr, int rxlen);
-  static int  DecBase64(unsigned char* bufp);
-  static void EncBase64(unsigned char* bufp, int len);
-  static void ToUnicode(unsigned char** pptr, unsigned char delim,
-                       unsigned char* buf, int* plen, int conv);
-  static int  SetRealmService(unsigned char* bufp);
-  static void GenChallenge(unsigned char* buf, int len);
-  static int  DigestPassphrase(unsigned char* passphrase,
+/* prototypes for internal functions */
+static int  POP3_rpa_resp(char* argbuf, int socket );
+static void LenAppend(char** pptr, int len);
+static int  LenSkip(char** pptr, int rxlen);
+static int  DecBase64(char* bufp);
+static void EncBase64(char* bufp, int len);
+static void ToUnicode(char** pptr, char delim, unsigned char* buf, int* plen,
+                       int conv);
+static int  SetRealmService(char* bufp);
+static void GenChallenge(unsigned char* buf, int len);
+static int  DigestPassphrase(char* passphrase,
                               unsigned char* rbuf, int unicodeit);
-  static void CompUserResp();
-  static int  CheckUserAuth();
-  static void md5(unsigned char* in, int len, unsigned char* out);
-#endif
+static void CompUserResp(void);
+static int  CheckUserAuth(void);
+static void md5(const void* in, int len, unsigned char* out);
 
 /* RPA protocol definitions */
 
@@ -103,23 +107,23 @@ unsigned char   Kus[Kusl];                  /* Session key           */
   globals:       read outlevel.
  *********************************************************************/
 
-int POP3_auth_rpa (unsigned char *userid, unsigned char *passphrase, int socket)
+int POP3_auth_rpa (char *userid, char *passphrase, int socket)
 {
     int      ok,rxlen,verh,verl,i,rll;
-    unsigned char buf [POPBUFSIZE];
-    unsigned char *bufp;
+    char buf [POPBUFSIZE];
+    char *bufp;
     int      status,aulin,kuslin;
-    char* stdec[4] = { "Success" ,
-                     "Restricted user (something wrong with account)" ,
-                     "Invalid userid or passphrase" ,
-                     "Deity error" };
+    const char* stdec[4] = { N_("Success") ,
+                      N_("Restricted user (something wrong with account)") ,
+                      N_("Invalid userid or passphrase") ,
+                      N_("Deity error") };
 
     /* Initiate RPA authorisation */
 
     SockPrintf(socket,"AUTH RPA\r\n");
 
-    if (outlevel == O_VERBOSE)
-       fprintf(stderr,"> AUTH RPA\n");
+    if (outlevel >= O_MONITOR)
+       report(stdout, "> AUTH RPA\n");
 
     /* Create unicode user name in Nu.              */
     /* Create MD5 digest of user's passphrase in Pu */
@@ -132,8 +136,8 @@ int POP3_auth_rpa (unsigned char *userid, unsigned char *passphrase, int socket)
 
     if ((ok = POP3_rpa_resp(buf,socket)) != 0)
     {
-       if (outlevel > O_SILENT && outlevel < O_VERBOSE)
-           fprintf(stderr,"%s\n",buf);
+       if (outlevel > O_SILENT && outlevel < O_MONITOR)
+           report(stdout, "%s\n",buf);
 
        return(ok);
     }
@@ -154,18 +158,18 @@ int POP3_auth_rpa (unsigned char *userid, unsigned char *passphrase, int socket)
 #ifndef TESTMODE
     SockPrintf(socket,"%s\r\n",buf);
 #endif
-    if (outlevel == O_VERBOSE)
-       fprintf(stderr,"> %s\n",buf);
+    if (outlevel >= O_MONITOR)
+       report(stdout, "> %s\n",buf);
     if ((ok = POP3_rpa_resp(buf,socket)) != 0)
     {
-       if (outlevel > O_SILENT && outlevel < O_VERBOSE)
-           fprintf(stderr,"%s\n",buf);
+       if (outlevel > O_SILENT && outlevel < O_MONITOR)
+           report(stdout, "%s\n",buf);
        return(ok);
     }
     if ((rxlen = DecBase64(buf)) == 0)
     {
        if (outlevel > O_SILENT)
-           fprintf(stderr,"RPA token 2: Base64 decode error\n");
+           report(stderr, GT_("RPA token 2: Base64 decode error\n"));
        return(PS_RPA);
     }
     bufp = buf;
@@ -174,36 +178,37 @@ int POP3_auth_rpa (unsigned char *userid, unsigned char *passphrase, int socket)
 
     /* Interpret Token 2 */
 
-    verh = *(bufp++); verl = *(bufp++);
-    if (outlevel == O_VERBOSE)
-       fprintf(stderr,"Service chose RPA version %d.%d\n",verh,verl);
-    Csl  = *(bufp++);
+    verh = (unsigned char)*(bufp++); verl = (unsigned char)*(bufp++);
+    if (outlevel >= O_DEBUG)
+       report(stdout, GT_("Service chose RPA version %d.%d\n"),verh,verl);
+    Csl  = (unsigned char)*(bufp++);
     memcpy(Cs, bufp, Csl);
     bufp += Csl;
-    if (outlevel == O_VERBOSE)
+    if (outlevel >= O_DEBUG)
     {
-       fprintf(stderr,"Service challenge (l=%d):",Csl);
-       for (i=0; i<Csl; i++) fprintf(stderr," %02X",Cs[i]);
-       fprintf(stderr,"\n");
+       report(stdout, GT_("Service challenge (l=%d):\n"),Csl);
+       for (i=0; i<Csl; i++)
+           report_build(stdout, "%02X ",Cs[i]);
+       report_complete(stdout, "\n");
     }
     memcpy(Ts, bufp, Tsl);
     Ts[Tsl] = 0;
     bufp += Tsl;
-    if (outlevel == O_VERBOSE)
-       fprintf(stderr,"Service timestamp %s\n",Ts);
-    rll = *(bufp++) << 8; rll = rll | *(bufp++);
+    if (outlevel >= O_DEBUG)
+       report(stdout, GT_("Service timestamp %s\n"),Ts);
+    rll = (unsigned char)*(bufp++) << 8; rll = rll | (unsigned char)*(bufp++);
     if ((bufp-buf+rll) != rxlen)
     {
        if (outlevel > O_SILENT)
-           fprintf(stderr,"RPA token 2 length error\n");
+           report(stderr, GT_("RPA token 2 length error\n"));
        return(PS_RPA);
     }
-    if (outlevel == O_VERBOSE)
-       fprintf(stderr,"Realm list: %s\n",bufp);
+    if (outlevel >= O_DEBUG)
+       report(stdout, GT_("Realm list: %s\n"),bufp);
     if (SetRealmService(bufp) != 0)
     {
        if (outlevel > O_SILENT)
-           fprintf(stderr,"RPA error in service@realm string\n");
+           report(stderr, GT_("RPA error in service@realm string\n"));
        return(PS_RPA);
     }
 
@@ -213,126 +218,131 @@ int POP3_auth_rpa (unsigned char *userid, unsigned char *passphrase, int socket)
     *(bufp++) = HDR;
     LenAppend(&bufp, 11+2+strlen(userid)+1+Cul+1+Rul );
     memcpy(bufp, MECH, 11); bufp += 11;
-  *(bufp++) = 0;
-  *(bufp++) = strlen(userid);
-  memcpy(bufp,userid,strlen(userid)); bufp += strlen(userid);
-  GenChallenge(Cu,Cul);
-  *(bufp++) = Cul;
-  memcpy(bufp, Cu, Cul);  bufp += Cul;
-  CompUserResp();
-  *(bufp++) = Rul;
-  memcpy(bufp, Ru, Rul);  bufp += Rul;
-
-  /* Send Token 3, receive Token 4 */
-
-  EncBase64(buf,bufp-buf);
+    *(bufp++) = 0;
+    *(bufp++) = strlen(userid);
+    memcpy(bufp,userid,strlen(userid)); bufp += strlen(userid);
+    GenChallenge(Cu,Cul);
+    *(bufp++) = Cul;
+    memcpy(bufp, Cu, Cul);  bufp += Cul;
+    CompUserResp();
+    *(bufp++) = Rul;
+    memcpy(bufp, Ru, Rul);  bufp += Rul;
+
+    /* Send Token 3, receive Token 4 */
+
+    EncBase64(buf,bufp-buf);
 #ifndef TESTMODE
-  SockPrintf(socket,"%s\r\n",buf);
+    SockPrintf(socket,"%s\r\n",buf);
 #endif
-  if (outlevel == O_VERBOSE)
-    fprintf(stderr,"> %s\n",buf);
-  if ((ok = POP3_rpa_resp(buf,socket)) != 0)
+    if (outlevel >= O_MONITOR)
+       report(stdout, "> %s\n",buf);
+    if ((ok = POP3_rpa_resp(buf,socket)) != 0)
     {
-    if (outlevel > O_SILENT && outlevel < O_VERBOSE)
-      fprintf(stderr,"%s\n",buf);
-    return(ok);
+       if (outlevel > O_SILENT && outlevel < O_MONITOR)
+           report(stdout, "%s\n",buf);
+       return(ok);
     }
-  if ((rxlen = DecBase64(buf)) == 0)
+    if ((rxlen = DecBase64(buf)) == 0)
     {
-    if (outlevel > O_SILENT)
-      fprintf(stderr,"RPA token 4: Base64 decode error\n");
-    return(PS_RPA);
+       if (outlevel > O_SILENT)
+           report(stderr, GT_("RPA token 4: Base64 decode error\n"));
+       return(PS_RPA);
     }
-  bufp = buf;
-  if (LenSkip(&bufp,rxlen) == 0) return(PS_RPA);
+    bufp = buf;
+    if (LenSkip(&bufp,rxlen) == 0) return(PS_RPA);
 
-  /* Interpret Token 4 */
+    /* Interpret Token 4 */
 
-  aulin = *(bufp++);
-  if (outlevel == O_VERBOSE)
+    aulin = (unsigned char)*(bufp++);
+    if (outlevel >= O_DEBUG)
     {
-    fprintf(stderr,"User authentication (l=%d):",aulin);
-    for (i=0; i<aulin; i++) fprintf(stderr," %02X",bufp[i]);
-    fprintf(stderr,"\n");
+       report(stdout, GT_("User authentication (l=%d):\n"),aulin);
+       for (i=0; i<aulin; i++)
+           report_build(stdout, "%02X ",bufp[i]);
+       report_complete(stdout, "\n");
     }
-  if (aulin == Aul) memcpy(Au, bufp, Aul);
-  bufp += aulin;
-  kuslin = *(bufp++);
-  if (kuslin == Kusl) memcpy(Kusu, bufp, Kusl); /* blinded */
-  bufp += kuslin;
-  if (verh == 3)
+    if (aulin == Aul) memcpy(Au, bufp, Aul);
+    bufp += aulin;
+    kuslin = *(bufp++);
+    if (kuslin == Kusl) memcpy(Kusu, bufp, Kusl); /* blinded */
+    bufp += kuslin;
+    if (verh == 3)
     {
-    status = *(bufp++);
-    if (outlevel == O_VERBOSE)
-      fprintf(stderr,"RPA status: %02X\n",status);
+       status = *(bufp++);
+       if (outlevel >= O_DEBUG)
+           report(stdout, GT_("RPA status: %02X\n"),status);
     }
-  else status = 0;
-  if ((bufp - buf) != rxlen)
+    else status = 0;
+    if ((bufp - buf) != rxlen)
     {
-    if (outlevel > O_SILENT)
-      fprintf(stderr,"RPA token 4 length error\n");
-    return(PS_RPA);
+       if (outlevel > O_SILENT)
+           report(stderr, GT_("RPA token 4 length error\n"));
+       return(PS_RPA);
     }
-  if (status != 0)
+    if (status != 0)
     {
-    if (outlevel > O_SILENT)
-      if (status < 4)
-        fprintf(stderr,"RPA rejects you: %s\n",stdec[status]);
-      else
-        fprintf(stderr,"RPA rejects you, reason unknown\n");
-    return(PS_AUTHFAIL);
+       if (outlevel > O_SILENT) {
+           if (status < 4) {
+               report(stderr, GT_("RPA rejects you: %s\n"),GT_(stdec[status]));
+           } else {
+               report(stderr, GT_("RPA rejects you, reason unknown\n"));
+           }
+       }
+       return(PS_AUTHFAIL);
     }
-  if (Aul != aulin)
+    if (Aul != aulin)
     {
-    fprintf(stderr,"RPA User Authentication length error: %d\n",aulin);
-    return(PS_RPA);
+       report(stderr, 
+              GT_("RPA User Authentication length error: %d\n"),aulin);
+       return(PS_RPA);
     }
-  if (Kusl != kuslin)
+    if (Kusl != kuslin)
     {
-    fprintf(stderr,"RPA Session key length error: %d\n",kuslin);
-    return(PS_RPA);
+       report(stderr, GT_("RPA Session key length error: %d\n"),kuslin);
+       return(PS_RPA);
     }
-  if (CheckUserAuth() != 0)
+    if (CheckUserAuth() != 0)
     {
-    if (outlevel > O_SILENT)
-      fprintf(stderr,"RPA _service_ auth fail. Spoof server?\n");
-    return(PS_AUTHFAIL);
+       if (outlevel > O_SILENT)
+           report(stderr, GT_("RPA _service_ auth fail. Spoof server?\n"));
+       return(PS_AUTHFAIL);
     }
-  if (outlevel == O_VERBOSE)
+    if (outlevel >= O_DEBUG)
     {
-    fprintf(stderr,"Session key established:");
-    for (i=0; i<Kusl; i++) fprintf(stderr," %02X",Kus[i]);
-    fprintf(stderr,"\n");
+       report(stdout, GT_("Session key established:\n"));
+       for (i=0; i<Kusl; i++)
+           report_build(stdout, "%02X ",Kus[i]);
+       report_complete(stdout, "\n");
     }
 
-  /* Assemble Token 5 in buf and send (not in ver 2 though)  */
-  /* Version 3.0 definitely replies with +OK to this. I have */
-  /* no idea what sort of response previous versions gave.   */
+    /* Assemble Token 5 in buf and send (not in ver 2 though)  */
+    /* Version 3.0 definitely replies with +OK to this. I have */
+    /* no idea what sort of response previous versions gave.   */
 
-  if (verh != 2)
+    if (verh != 2)
     {
-    bufp      = buf;
-    *(bufp++) = HDR;
-    LenAppend(&bufp, 1 );
-    *(bufp++) = 0x42;
-    EncBase64(buf,bufp-buf);
+       bufp      = buf;
+       *(bufp++) = HDR;
+       LenAppend(&bufp, 1 );
+       *(bufp++) = 0x42;
+       EncBase64(buf,bufp-buf);
 #ifndef TESTMODE
-    SockPrintf(socket,"%s\r\n",buf);
+       SockPrintf(socket,"%s\r\n",buf);
 #endif
-    if (outlevel == O_VERBOSE)
-      fprintf(stderr,"> %s\n",buf);
-    if ((ok = POP3_rpa_resp(buf,socket)) != 0)
-      {
-      if (outlevel > O_SILENT && outlevel < O_VERBOSE)
-        fprintf(stderr,"%s\n",buf);
-      return(ok);
-      }
+       if (outlevel >= O_MONITOR)
+           report(stdout, "> %s\n",buf);
+       if ((ok = POP3_rpa_resp(buf,socket)) != 0)
+       {
+           if (outlevel > O_SILENT && outlevel < O_MONITOR)
+               report(stdout, "%s\n",buf);
+           return(ok);
+       }
     }
 
-  if (outlevel > O_SILENT)
-    fprintf(stderr,"RPA authorisation complete\n");
+    if (outlevel > O_SILENT)
+       report(stdout, GT_("RPA authorisation complete\n"));
 
-  return(PS_SUCCESS);
+    return(PS_SUCCESS);
 }
 
 
@@ -349,46 +359,47 @@ int POP3_auth_rpa (unsigned char *userid, unsigned char *passphrase, int socket)
   globals:       reads outlevel.
  *********************************************************************/
 
-static int POP3_rpa_resp (argbuf,socket)
-unsigned char *argbuf;
-int socket;
+static int POP3_rpa_resp (char *argbuf, int socket)
 {
-  int ok;
-  char buf [POPBUFSIZE];
-  char *bufp;
-  int sockrc;
-  fprintf(stderr, "Get response\n");
+    int ok;
+    char buf [POPBUFSIZE];
+    char *bufp;
+    int sockrc;
+
+    if (outlevel >= O_DEBUG)
+       report(stdout,  GT_("Get response\n"));
 #ifndef TESTMODE
-  sockrc = gen_recv(socket, buf, sizeof(buf));
+    sockrc = gen_recv(socket, buf, sizeof(buf));
 #else
-  linecount++;
-  if (linecount == 1) strcpy(buf,line1);
-  if (linecount == 2) strcpy(buf,line2);
-  if (linecount == 3) strcpy(buf,line3);
-/*  fprintf(stderr,"--> "); fflush(stderr);  */
+    linecount++;
+    if (linecount == 1) strcpy(buf,line1);
+    if (linecount == 2) strcpy(buf,line2);
+    if (linecount == 3) strcpy(buf,line3);
+/*  report(stdout, "--> "); fflush(stderr);  */
 /*  scanf("%s",&buf)                         */
-  sockrc = PS_SUCCESS;
+    sockrc = PS_SUCCESS;
 #endif
-  if (sockrc == PS_SUCCESS) {
-    bufp = buf;
-    if ((*buf) == '+')
-      {
-      bufp++;
+    if (sockrc == PS_SUCCESS) {
+       bufp = buf;
+       if ((*buf) == '+')
+       {
+           bufp++;
 /*      if (*bufp == ' ') bufp++; */
-      if (argbuf != NULL)
-        strcpy(argbuf,bufp);
-      ok=0;
-      }
-    else if (strcmp(buf,"-ERR") == 0)
-      ok = PS_ERROR;
-    else ok = PS_PROTOCOL;
-
-  }
-  else
-    ok = PS_SOCKET;
-  fprintf(stderr, "Get response return %d [%s]\n", ok, buf);
-  buf[sockrc] = 0;
-  return(ok);
+           if (argbuf != NULL)
+               strcpy(argbuf,bufp);
+           ok=0;
+       }
+       else if (strcmp(buf,"-ERR") == 0)
+           ok = PS_ERROR;
+       else ok = PS_PROTOCOL;
+
+    }
+    else
+       ok = PS_SOCKET;
+    if (outlevel >= O_DEBUG)
+       report(stdout,  GT_("Get response return %d [%s]\n"), ok, buf);
+    buf[sockrc] = 0;
+    return(ok);
 }
 
 /*********************************************************************
@@ -405,24 +416,24 @@ int socket;
   globals:       none
  *********************************************************************/
 
-static void LenAppend(pptr,len)
-unsigned char **pptr;
-int  len;
+static void LenAppend(char **pptr_, int len)
 {
-  if (len < 0x80)
+    unsigned char **pptr = (unsigned char **)pptr_;
+
+    if (len < 0x80)
     {
-    **pptr = len; (*pptr)++;
+       **pptr = len; (*pptr)++;
     }
-  else if (len < 0x100)
+    else if (len < 0x100)
     {
-    **pptr = 0x81; (*pptr)++;
-    **pptr = len;  (*pptr)++;
+       **pptr = 0x81; (*pptr)++;
+       **pptr = len;  (*pptr)++;
     }
-  else
+    else
     {
-    **pptr = 0x82;       (*pptr)++;
-    **pptr = len >> 8;   (*pptr)++;
-    **pptr = len & 0xFF; (*pptr)++;
+       **pptr = 0x82;       (*pptr)++;
+       **pptr = len >> 8;   (*pptr)++;
+       **pptr = len & 0xFF; (*pptr)++;
     }
 }
 
@@ -439,52 +450,51 @@ int  len;
   globals:       reads outlevel.
  *********************************************************************/
 
-int LenSkip(pptr,rxlen)
-unsigned char **pptr;
-int rxlen;
+int LenSkip(char **pptr, int rxlen)
 {
-  int len;
-  unsigned char *save;
-  save = *pptr;
-  if (**pptr != HDR)
+    int len;
+    char *save;
+    save = *pptr;
+    if ((unsigned char)**pptr != HDR)
     {
-    if (outlevel > O_SILENT) fprintf(stderr,"Hdr not 60\n");
-    return(0);
+       if (outlevel > O_SILENT)
+           report(stderr, GT_("Hdr not 60\n"));
+       return(0);
     }
-  (*pptr)++;
-  if (((**pptr) & 0x80) == 0 )
+    (*pptr)++;
+    if (((unsigned char)(**pptr) & 0x80) == 0 )
     {
-    len = **pptr; (*pptr)++;
+       len = (unsigned char)**pptr; (*pptr)++;
     }
-  else if ((**pptr) == 0x81)
+    else if ((unsigned char)(**pptr) == 0x81)
     {
-    len = *(*pptr+1); (*pptr) += 2;
+       len = (unsigned char)*(*pptr+1); (*pptr) += 2;
     }
-  else if ((**pptr) == 0x82)
+    else if ((unsigned char)(**pptr) == 0x82)
     {
-    len = ((*(*pptr+1)) << 8) | *(*pptr+2);
-    (*pptr) += 3;
+       len = ((unsigned char)(*(*pptr+1)) << 8) | (unsigned char)*(*pptr+2);
+       (*pptr) += 3;
     }
-  else len = 0;
-  if (len==0)
+    else len = 0;
+    if (len==0)
     {
-    if (outlevel>O_SILENT)
-      fprintf(stderr,"Token length error\n");
+       if (outlevel>O_SILENT)
+           report(stderr, GT_("Token length error\n"));
     }
-  else if (((*pptr-save)+len) != rxlen)
+    else if (((*pptr-save)+len) != rxlen)
     {
-    if (outlevel>O_SILENT)
-      fprintf(stderr,"Token Length %d disagrees with rxlen %d\n",len,rxlen);
-    len = 0;
+       if (outlevel>O_SILENT)
+           report(stderr, GT_("Token Length %d disagrees with rxlen %d\n"),len,rxlen);
+       len = 0;
     }
-  else if (memcmp(*pptr,MECH,11))
+    else if (memcmp(*pptr,MECH,11))
     {
-    if (outlevel > O_SILENT)
-      fprintf(stderr,"Mechanism field incorrect\n");
-    len = 0;
+       if (outlevel > O_SILENT)
+           report(stderr, GT_("Mechanism field incorrect\n"));
+       len = 0;
     }
-  else (*pptr) += 11;  /* Skip mechanism field */
-  return(len);
+    else (*pptr) += 11;  /* Skip mechanism field */
+    return(len);
 }
 
 /*********************************************************************
@@ -500,47 +510,46 @@ int rxlen;
   globals:       reads outlevel.
  *********************************************************************/
 
-static int DecBase64(bufp)
-unsigned char *bufp;
+static int DecBase64(char *bufp)
 {
-  unsigned int   new, bits=0, cnt=0, i, part=0;
-  unsigned char  ch;
-  unsigned char* outp=bufp;
-  unsigned char* inp=bufp;
-  while((ch=*(inp++)) != 0)
-    {
-    if ((ch != '=') && (ch != ' ') && (ch != '\n') && (ch != '\r'))
-      {
-      if      ((ch>='A') && (ch <= 'Z'))   new = ch - 'A';
-      else if ((ch>='a') && (ch <= 'z'))   new = ch - 'a' + 26;
-      else if ((ch>='0') && (ch <= '9'))   new = ch - '0' + 52;
-      else if ( ch=='+'                )   new = 62;
-      else if ( ch=='/'                )   new = 63;
-      else {
-       fprintf(stderr, "dec64 error at char %d: %x\n", inp - bufp, ch);
-       return(0);
-      }
-      part=((part & 0x3F)*64) + new;
-      bits += 6;
-      if (bits >= 8)
-        {
-        bits -= 8;
-        *outp = (part >> bits);
-        cnt++; outp++;
-        }
-      }
-    }
-  if (outlevel == O_VERBOSE)
-    {
-    fprintf(stderr,"Inbound binary data:\n");
-    for (i=0; i<cnt; i++)
-      {
-      fprintf(stderr," %02X",bufp[i]);
-      if (((i % 16)==15) || (i==(cnt-1)))
-        fprintf(stderr,"\n");
-      }
-    }
-  return(cnt);
+    unsigned int   newx, bits=0, cnt=0, i, part=0;
+    unsigned char  ch;
+    char* outp=bufp;
+    char* inp=bufp;
+    while((ch=(unsigned char)*(inp++)) != 0)
+    {
+       if ((ch != '=') && (ch != ' ') && (ch != '\n') && (ch != '\r'))
+       {
+           if      ((ch>='A') && (ch <= 'Z'))   newx = ch - 'A';
+           else if ((ch>='a') && (ch <= 'z'))   newx = ch - 'a' + 26;
+           else if ((ch>='0') && (ch <= '9'))   newx = ch - '0' + 52;
+           else if ( ch=='+'                )   newx = 62;
+           else if ( ch=='/'                )   newx = 63;
+           else {
+               report(stderr,  GT_("dec64 error at char %d: %x\n"), (int)(inp - bufp), ch);
+               return(0);
+           }
+           part=((part & 0x3F)*64) + newx;
+           bits += 6;
+           if (bits >= 8)
+           {
+               bits -= 8;
+               *outp = (part >> bits);
+               cnt++; outp++;
+           }
+       }
+    }
+    if (outlevel >= O_MONITOR)
+    {
+       report(stdout, GT_("Inbound binary data:\n"));
+       for (i=0; i<cnt; i++)
+       {
+           report_build(stdout, "%02X ",(unsigned char)bufp[i]);
+           if (((i % 16)==15) || (i==(cnt-1)))
+               report_complete(stdout, "\n");
+       }
+    }
+    return(cnt);
 }
 
 /*********************************************************************
@@ -559,40 +568,38 @@ unsigned char *bufp;
   globals:       reads outlevel;
  *********************************************************************/
 
-static void EncBase64(bufp,len)
-unsigned char *bufp;
-int  len;
+static void EncBase64(char *bufp, int len)
 {
-  unsigned char* outp;
-  unsigned char  c1,c2,c3;
-  char x[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-  int  i;
-
-  if (outlevel == O_VERBOSE)
-    {
-    fprintf(stderr,"Outbound data:\n");
-    for (i=0; i<len; i++)
-      {
-      fprintf(stderr," %02X",bufp[i]);
-      if (((i % 16)==15) || (i==(len-1)))
-        fprintf(stderr,"\n");
-      }
-    }
-  outp = bufp + (((len-1)/3)*4);
-  *(outp+4) = 0;
-  /* So we can do the update in place, start at the far end! */
-  for (i=((len-1)/3)*3; i>=0; i-=3)
-    {
-    c1 = bufp[i];
-    if ((i+1) < len) c2 = bufp[i+1]; else c2=0;
-    if ((i+2) < len) c3 = bufp[i+2]; else c3=0;
-    *(outp) = x[c1/4];
-    *(outp+1) = x[((c1 & 3)*16) + (c2/16)];
-    if ((i+1) < len) *(outp+2) = x[((c2 & 0x0F)*4) + (c3/64)];
-      else *(outp+2) = '=';
-    if ((i+2) < len) *(outp+3) = x[c3 & 0x3F];
-      else *(outp+3) = '=';
-    outp -= 4;
+    char* outp;
+    unsigned char  c1,c2,c3;
+    char x[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    int  i;
+
+    if (outlevel >= O_MONITOR)
+    {
+       report(stdout, GT_("Outbound data:\n"));
+       for (i=0; i<len; i++)
+       {
+           report_build(stdout, "%02X ",(unsigned char)bufp[i]);
+           if (((i % 16)==15) || (i==(len-1)))
+               report_complete(stdout, "\n");
+       }
+    }
+    outp = bufp + (((len-1)/3)*4);
+    *(outp+4) = 0;
+    /* So we can do the update in place, start at the far end! */
+    for (i=((len-1)/3)*3; i>=0; i-=3)
+    {
+       c1 = (unsigned char)bufp[i];
+       if ((i+1) < len) c2 = (unsigned char)bufp[i+1]; else c2=0;
+       if ((i+2) < len) c3 = (unsigned char)bufp[i+2]; else c3=0;
+       *(outp) = x[c1/4];
+       *(outp+1) = x[((c1 & 3)*16) + (c2/16)];
+       if ((i+1) < len) *(outp+2) = x[((c2 & 0x0F)*4) + (c3/64)];
+       else *(outp+2) = '=';
+       if ((i+2) < len) *(outp+3) = x[c3 & 0x3F];
+       else *(outp+3) = '=';
+       outp -= 4;
     }
 }
 
@@ -613,37 +620,38 @@ int  len;
   globals:       reads outlevel;
  *********************************************************************/
 
-static void ToUnicode(pptr,delim,buf,plen,conv)
-unsigned char **pptr; /* input string  */
-unsigned char delim;
-unsigned char *buf;   /* output buffer */
-int  *plen;
-int conv;
+static void ToUnicode(char **pptr /* input string*/,
+       char delim, unsigned char *buf /* output buffer */,
+       int *plen, int conv)
 {
-  unsigned char *p;
-  int i;
-  *plen = 0; p=buf;
-  while ( ((**pptr)!=delim) && ((**pptr)!=0) && ((*plen)<STRMAX) )
-    {
-    *(p++) = 0;
-    if (conv)
-      *(p++) = tolower(**pptr);
-    else
-      *(p++) = (**pptr);
-    (*plen) += 2;
-    (*pptr)++;
+    unsigned char *p;
+    int i;
+    *plen = 0; p=buf;
+    while ( ((**pptr)!=delim) && ((**pptr)!=0) && ((*plen)<STRMAX) )
+    {
+       *(p++) = 0;
+       if (conv)
+           *(p++) = tolower((unsigned char)**pptr);
+       else
+           *(p++) = (**pptr);
+       (*plen) += 2;
+       (*pptr)++;
     }
-  if ( ((**pptr)!=delim) && ((**pptr)!=0) && ((*plen)==STRMAX) )
+    if ( ((**pptr)!=delim) && ((**pptr)!=0) && ((*plen)==STRMAX) )
     {
-    if (outlevel > O_SILENT)
-      fprintf(stderr,"RPA String too long\n");
-    *plen = 0;
+       if (outlevel > O_SILENT)
+           report(stderr, GT_("RPA String too long\n"));
+       *plen = 0;
     }
-  if (outlevel == O_VERBOSE)
+    if (outlevel >= O_DEBUG)
     {
-    fprintf(stderr,"Unicode:");
-    for (i=0; i<(*plen); i++) fprintf(stderr,"%02X ",buf[i]);
-    fprintf(stderr,"\n");
+       report(stdout, GT_("Unicode:\n"));
+       for (i=0; i<(*plen); i++)
+       {
+           report_build(stdout, "%02X ",buf[i]);
+           if (((i % 16)==15) || (i==((*plen)-1)))
+               report_complete(stdout, "\n");
+       }
     }
 }
 
@@ -660,19 +668,18 @@ int conv;
                  writes Ns Nsl Nr Nrl
  *********************************************************************/
 
-static int SetRealmService(bufp)
-unsigned char* bufp;
+static int SetRealmService(char *bufp)
 {
-  /* For the moment we pick the first available realm. It would */
-  /* make more sense to verify that the realm which the user    */
-  /* has given (as part of id) is in the list, and select it's  */
-  /* corresponding service name.                                */
-  ToUnicode(&bufp, '@', Ns, &Nsl, 1);  /* Service    */
-  bufp++;                              /* Skip the @ */
-  ToUnicode(&bufp, ' ', Nr, &Nrl, 1);  /* Realm name */
-  if ((Nrl == 0) || (Nsl == 0))
-    return(PS_RPA);
-  return(0);
+    /* For the moment we pick the first available realm. It would */
+    /* make more sense to verify that the realm which the user    */
+    /* has given (as part of id) is in the list, and select it's  */
+    /* corresponding service name.                                */
+    ToUnicode(&bufp, '@', Ns, &Nsl, 1);  /* Service    */
+    bufp++;                              /* Skip the @ */
+    ToUnicode(&bufp, ' ', Nr, &Nrl, 1);  /* Realm name */
+    if ((Nrl == 0) || (Nsl == 0))
+       return(PS_RPA);
+    return(0);
 }
 
 /*********************************************************************
@@ -689,30 +696,36 @@ unsigned char* bufp;
                  reads /dev/random
  *********************************************************************/
 
-static void GenChallenge(buf,len)
-unsigned char *buf;
-int  len;
+static void GenChallenge(unsigned char *buf, int len)
 {
-  int  i;
-  FILE *devrandom;
-  devrandom = fopen("/dev/urandom","rb");
-  if (devrandom == NULL)
+    int  i;
+    FILE *devrandom;
+
+    devrandom = fopen("/dev/urandom","rb");
+    if (devrandom == NULL && outlevel > O_SILENT)
     {
-    if (outlevel > O_SILENT)
-      fprintf(stderr,"RPA Failed open of /dev/random. This shouldn't\n");
-      fprintf(stderr,"    prevent you logging in, but means you\n");
-      fprintf(stderr,"    cannot be sure you are talking to the\n");
-      fprintf(stderr,"    service that you think you are (replay\n");
-      fprintf(stderr,"    attacks by a dishonest service are possible.)\n");
+       report(stdout, GT_("RPA Failed open of /dev/urandom. This shouldn't\n"));
+       report(stdout, GT_("    prevent you logging in, but means you\n"));
+       report(stdout, GT_("    cannot be sure you are talking to the\n"));
+       report(stdout, GT_("    service that you think you are (replay\n"));
+       report(stdout, GT_("    attacks by a dishonest service are possible.)\n"));
     }
-  for (i=0; i<len; i++) buf[i] = fgetc(devrandom);
-//  for (i=0; i<len; i++) buf[i] = random();
-  fclose(devrandom);
-  if (outlevel == O_VERBOSE)
+
+    for(i=0; i<len; i++)
+       buf[i] = devrandom ? fgetc(devrandom) : random();
+
+    if (devrandom)
+       fclose(devrandom);      /* should be safe, file mode was "r" */
+
+    if (outlevel >= O_DEBUG)
     {
-    fprintf(stderr,"User challenge:");
-    for (i=0; i<len; i++) fprintf(stderr," %02X",buf[i]);
-    fprintf(stderr,"\n");
+       report(stdout, GT_("User challenge:\n"));
+       for (i=0; i<len; i++)
+         {
+         report_build(stdout, "%02X ",buf[i]);
+         if (((i % 16)==15) || (i==(len-1)))
+           report_complete(stdout, "\n");
+         }
     }
 }
 
@@ -732,30 +745,24 @@ int  len;
                  writes Pu.
  *********************************************************************/
 
-static int DigestPassphrase(passphrase,rbuf,unicodeit)
-unsigned char *passphrase;
-unsigned char *rbuf;
-int unicodeit;
+static int DigestPassphrase(char *passphrase,unsigned char *rbuf,
+       int unicodeit)
 {
-  int   len;
-  unsigned char  workarea[STRMAX];
-  unsigned char* ptr;
+    int   len;
+    unsigned char  workarea[STRMAX];
+    char* ptr;
 
-  if (unicodeit)  /* Option in spec. Yuck. */
-    {
-    ptr = passphrase;
-    ToUnicode(&ptr, '\0', workarea, &len, 0); /* No case conv here */
-    if (len == 0)
-      return(PS_SYNTAX);
-    ptr = workarea;
-    }
-  else
+    if (unicodeit)  /* Option in spec. Yuck. */
     {
-    ptr = rbuf;
-    len = strlen(passphrase);
+       ptr = passphrase;
+       ToUnicode(&ptr, '\0', workarea, &len, 0); /* No case conv here */
+       if (len == 0)
+           return(PS_SYNTAX);
+       md5(workarea,len,rbuf);
     }
-  md5(ptr,len,rbuf);
-  return(0);
+    else
+       md5(rbuf,strlen(passphrase),rbuf);
+    return(0);
 }
 
 /*********************************************************************
@@ -771,21 +778,21 @@ int unicodeit;
                  writes Ru.
  *********************************************************************/
 
-static void CompUserResp()
+static void CompUserResp(void)
 {
-  unsigned char  workarea[Pul+48+STRMAX*5+Tsl+Pul];
-  unsigned char* p;
-  p = workarea;
-  memcpy(p , Pu,  Pul); p += Pul;
-  memset(p , '\0', 48); p += 48;
-  memcpy(p , Nu,  Nul); p += Nul;
-  memcpy(p , Ns,  Nsl); p += Nsl;
-  memcpy(p , Nr,  Nrl); p += Nrl;
-  memcpy(p , Cu,  Cul); p += Cul;
-  memcpy(p , Cs,  Csl); p += Csl;
-  memcpy(p , Ts,  Tsl); p += Tsl;
-  memcpy(p , Pu,  Pul); p += Pul;
-  md5(workarea,p-workarea,Ru);
+    unsigned char  workarea[Pul+48+STRMAX*5+Tsl+Pul];
+    unsigned char* p;
+    p = workarea;
+    memcpy(p , Pu,  Pul); p += Pul;
+    memset(p , '\0', 48); p += 48;
+    memcpy(p , Nu,  Nul); p += Nul;
+    memcpy(p , Ns,  Nsl); p += Nsl;
+    memcpy(p , Nr,  Nrl); p += Nrl;
+    memcpy(p , Cu,  Cul); p += Cul;
+    memcpy(p , Cs,  Csl); p += Csl;
+    memcpy(p , Ts,  Tsl); p += Tsl;
+    memcpy(p , Pu,  Pul); p += Pul;
+    md5(workarea,p-workarea,Ru);
 }
 
 /*********************************************************************
@@ -803,43 +810,43 @@ static void CompUserResp()
                  writes Ru.
  *********************************************************************/
 
-static int CheckUserAuth()
+static int CheckUserAuth(void)
 {
-  unsigned char  workarea[Pul+48+STRMAX*7+Tsl+Pul];
-  unsigned char* p;
-  unsigned char  md5ans[16];
-  int i;
+    unsigned char  workarea[Pul+48+STRMAX*7+Tsl+Pul];
+    unsigned char* p;
+    unsigned char  md5ans[16];
+    int i;
     /* Create unobscured Kusu */
-  p = workarea;
-  memcpy(p , Pu,  Pul); p += Pul;
-  memset(p , '\0', 48); p += 48;
-  memcpy(p , Ns,  Nsl); p += Nsl;
-  memcpy(p , Nu,  Nul); p += Nul;
-  memcpy(p , Nr,  Nrl); p += Nrl;
-  memcpy(p , Cs,  Csl); p += Csl;
-  memcpy(p , Cu,  Cul); p += Cul;
-  memcpy(p , Ts,  Tsl); p += Tsl;
-  memcpy(p , Pu,  Pul); p += Pul;
-  md5(workarea,p-workarea,md5ans);
-  for (i=0; i<16; i++) Kus[i] = Kusu[i] ^ md5ans[i];
+    p = workarea;
+    memcpy(p , Pu,  Pul); p += Pul;
+    memset(p , '\0', 48); p += 48;
+    memcpy(p , Ns,  Nsl); p += Nsl;
+    memcpy(p , Nu,  Nul); p += Nul;
+    memcpy(p , Nr,  Nrl); p += Nrl;
+    memcpy(p , Cs,  Csl); p += Csl;
+    memcpy(p , Cu,  Cul); p += Cul;
+    memcpy(p , Ts,  Tsl); p += Tsl;
+    memcpy(p , Pu,  Pul); p += Pul;
+    md5(workarea,p-workarea,md5ans);
+    for (i=0; i<16; i++) Kus[i] = Kusu[i] ^ md5ans[i];
     /* Compute Au from our information */
-  p = workarea;
-  memcpy(p , Pu,  Pul); p += Pul;
-  memset(p , '\0', 48); p += 48;
-  memcpy(p , Ns,  Nsl); p += Nsl;
-  memcpy(p , Nu,  Nul); p += Nul;
-  memcpy(p , Nr,  Nrl); p += Nrl;
-  memcpy(p , Kusu,Kusl);p += Kusl;
-  memcpy(p , Cs,  Csl); p += Csl;
-  memcpy(p , Cu,  Cul); p += Cul;
-  memcpy(p , Ts,  Tsl); p += Tsl;
-  memcpy(p , Kus, Kusl);p += Kusl;
-  memcpy(p , Pu,  Pul); p += Pul;
-  md5(workarea,p-workarea,md5ans);
+    p = workarea;
+    memcpy(p , Pu,  Pul); p += Pul;
+    memset(p , '\0', 48); p += 48;
+    memcpy(p , Ns,  Nsl); p += Nsl;
+    memcpy(p , Nu,  Nul); p += Nul;
+    memcpy(p , Nr,  Nrl); p += Nrl;
+    memcpy(p , Kusu,Kusl);p += Kusl;
+    memcpy(p , Cs,  Csl); p += Csl;
+    memcpy(p , Cu,  Cul); p += Cul;
+    memcpy(p , Ts,  Tsl); p += Tsl;
+    memcpy(p , Kus, Kusl);p += Kusl;
+    memcpy(p , Pu,  Pul); p += Pul;
+    md5(workarea,p-workarea,md5ans);
     /* Compare the two */
-  for (i=0; i<16; i++)
-    if (Au[i] != md5ans[i]) return(PS_RPA);
-  return(0);
+    for (i=0; i<16; i++)
+       if (Au[i] != md5ans[i]) return(PS_RPA);
+    return(0);
 }
 
 /*********************************************************************
@@ -854,31 +861,33 @@ static int CheckUserAuth()
   globals:       reads outlevel
  *********************************************************************/
 
-static void md5(in,len,out)
-unsigned char*    in;
-int      len;
-unsigned char*    out;
+static void md5(const void *in_,int len,unsigned char *out)
 {
-  int      i;
-  MD5_CTX  md5context;
-
-  if (outlevel == O_VERBOSE)
-    {
-    fprintf(stderr,"MD5 being applied to data block:\n");
-    for (i=0; i<len; i++)
-      {
-      fprintf(stderr," %02X",in[i]);
-      if (((i % 16)==15) || (i==(len-1))) fprintf(stderr,"\n");
-      }
-    }
-  MD5Init(   &md5context );
-  MD5Update( &md5context, in, len );
-  MD5Final(  out, &md5context );
-  if (outlevel == O_VERBOSE)
-    {
-    fprintf(stderr,"MD5 result is: ");
-    for (i=0; i<16; i++) fprintf(stderr,"%02X ",out[i]);
-    fprintf(stderr,"\n");
+    int      i;
+    MD5_CTX  md5context;
+    const unsigned char *in = (const unsigned char *)in_;
+
+    if (outlevel >= O_DEBUG)
+    {
+       report(stdout, GT_("MD5 being applied to data block:\n"));
+       for (i=0; i<len; i++)
+       {
+           report_build(stdout, "%02X ",in[i]);
+           if (((i % 16)==15) || (i==(len-1)))
+               report_complete(stdout, "\n");
+       }
+    }
+    MD5Init(   &md5context );
+    MD5Update( &md5context, in, len );
+    MD5Final(  out, &md5context );
+    if (outlevel >= O_DEBUG)
+    {
+       report(stdout, GT_("MD5 result is:\n"));
+       for (i=0; i<16; i++)
+       {
+           report_build(stdout, "%02X ",out[i]);
+       }
+       report_complete(stdout, "\n");
     }
 }
 #endif /* POP3_ENABLE && RPA_ENABLE */