[balsa] IMAP code simplifications



commit a4325bcc7ef2180794ff2e12046bea3cafab6e90
Author: Albrecht Dreß <albrecht dress arcor de>
Date:   Tue Apr 11 17:50:02 2017 -0400

    IMAP code simplifications
    
    * Makefile.am: ensure libnetclient is built before libbalsa,
      so the imap test code can link properly
    * libbalsa/imap/Makefile.am: add libnetclient to include path, link test app against it
    * libbalsa/imap/auth-cram.c: use net_client_cram_calc(), and wipe sensitive data before free
    * libbalsa/imap/imap-auth.c: use g_base64_encode() instead of custom function
    * libbalsa/imap/auth-gssapi.c: ditto
    * libbalsa/imap/util.[hc]: remove custom base64 encode and decode stuff
    
    Signed-off-by: Peter Bloomfield <PeterBloomfield bellsouth net>

 Makefile.am                 |    2 +-
 libbalsa/imap/Makefile.am   |    2 +
 libbalsa/imap/auth-cram.c   |   45 +++++-------------
 libbalsa/imap/auth-gssapi.c |   19 +++++---
 libbalsa/imap/imap-auth.c   |    6 +--
 libbalsa/imap/util.c        |  106 -------------------------------------------
 libbalsa/imap/util.h        |    4 --
 7 files changed, 30 insertions(+), 154 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 7a412a3..09285f9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 #intl dir needed for tarball --disable-nls build.
 DISTCHECK_CONFIGURE_FLAGS="--disable-extra-mimeicons"
-SUBDIRS = po sounds images doc libbalsa libnetclient libinit_balsa src ui
+SUBDIRS = po sounds images doc libnetclient libbalsa libinit_balsa src ui
 # set tar in case it is not set by automake or make
 
 man_MANS=balsa.1
diff --git a/libbalsa/imap/Makefile.am b/libbalsa/imap/Makefile.am
index 875aaf1..ea9d16a 100644
--- a/libbalsa/imap/Makefile.am
+++ b/libbalsa/imap/Makefile.am
@@ -11,6 +11,7 @@ imap_tst_SOURCES = imap_tst.c
 
 imap_tst_LDADD = \
        libimap.a       \
+       ${top_srcdir}/libnetclient/libnetclient.a \
         $(BALSA_LIBS)
 
 #libimap_la_SOURCES =  
@@ -41,6 +42,7 @@ EXTRA_DIST = \
        libimap-marshal.list
 
 AM_CPPFLAGS = -I${top_builddir} -I${top_srcdir} -I${top_srcdir}/libbalsa \
+       -I${top_srcdir}/libnetclient \
        -I${top_srcdir}/libbalsa/imap \
        $(BALSA_CFLAGS)
 
diff --git a/libbalsa/imap/auth-cram.c b/libbalsa/imap/auth-cram.c
index 6d95fbc..c56e11a 100644
--- a/libbalsa/imap/auth-cram.c
+++ b/libbalsa/imap/auth-cram.c
@@ -27,7 +27,7 @@
 #include <glib.h>
 
 #include "imap-auth.h"
-#include "util.h"
+#include "net-client-utils.h"
 
 #include "imap_private.h"
 
@@ -37,11 +37,11 @@
 ImapResult
 imap_auth_cram(ImapMboxHandle* handle)
 {
-  char ibuf[LONG_STRING*2], obuf[LONG_STRING];
+  char ibuf[LONG_STRING*2];
+  gchar *auth_buf;
   unsigned cmdno;
-  int len, rc, ok;
+  int rc, ok;
   char *user = NULL, *pass = NULL;
-  gchar *digest;
 
   if (!imap_mbox_handle_can_do(handle, IMCAP_ACRAM_MD5))
     return IMAP_AUTH_UNAVAIL;
@@ -75,37 +75,16 @@ imap_auth_cram(ImapMboxHandle* handle)
     return IMAP_AUTH_FAILURE;
   }
   imap_mbox_gets(handle, ibuf, sizeof(ibuf)); /* check error */
-  if ((len = lit_conv_from_base64(obuf, ibuf)) <0) {
-    g_warning("Error decoding base64 response(%s), digit=%d:%d[%c]).\n", 
-             ibuf, len, ibuf[-len-1],ibuf[-len-1]);
-    return IMAP_AUTH_FAILURE;
-  }
-
-  obuf[len] = '\0';
+  auth_buf = net_client_cram_calc(ibuf, G_CHECKSUM_MD5, user, pass);
+  g_free(user);
+  memset(pass, 0, strlen(pass));
+  g_free(pass);
 
-  /* The client makes note of the data and then responds with a string
-   * consisting of the user name, a space, and a 'digest'. The latter is
-   * computed by applying the keyed MD5 algorithm from [KEYED-MD5] where the
-   * key is a shared secret and the digested text is the timestamp (including
-   * angle-brackets).
-   * 
-   * Note: The user name shouldn't be quoted. Since the digest can't contain
-   *   spaces, there is no ambiguity. Some servers get this wrong, we'll work
-   *   around them when the bug report comes in. Until then, we'll remain
-   *   blissfully RFC-compliant.
-   */
-  digest = g_compute_hmac_for_string(G_CHECKSUM_MD5, (const guchar *) pass, strlen(pass), obuf, -1);
-  g_snprintf (obuf, sizeof (obuf), "%s %s", user, digest);
-  g_free(digest);
-  /* XXX - ibuf must be long enough to store the base64 encoding of obuf, 
-   * plus the additional debris
-   */
-  
-  lit_conv_to_base64(ibuf, obuf, strlen (obuf), sizeof(ibuf)-2);
-  strncat (ibuf, "\r\n", sizeof (ibuf) - strlen(ibuf) - 1);
-  imap_handle_write(handle, ibuf, strlen(ibuf));
+  imap_handle_write(handle, auth_buf, strlen(auth_buf));
+  imap_handle_write(handle, "\r\n", 2U);
   imap_handle_flush(handle);
-  g_free(user); g_free(pass); /* FIXME: clean passwd first */
+  memset(auth_buf, 0, strlen(auth_buf));
+  g_free(auth_buf);
   do
     rc = imap_cmd_step (handle, cmdno);
   while (rc == IMR_UNTAGGED);
diff --git a/libbalsa/imap/auth-gssapi.c b/libbalsa/imap/auth-gssapi.c
index 5a19707..7da29b3 100644
--- a/libbalsa/imap/auth-gssapi.c
+++ b/libbalsa/imap/auth-gssapi.c
@@ -218,6 +218,7 @@ ag_get_token(gss_ctx_id_t *context, gss_name_t target, gss_buffer_t sec_token,
     OM_uint32 state, min_stat;
     gss_buffer_desc send_token;
     unsigned cflags;
+    gchar *b64buf;
     
     *client_token = '\0';
     state = gss_init_sec_context
@@ -229,8 +230,9 @@ ag_get_token(gss_ctx_id_t *context, gss_name_t target, gss_buffer_t sec_token,
     if (state != GSS_S_COMPLETE && state != GSS_S_CONTINUE_NEEDED)
         return state;
 
-    lit_conv_to_base64(client_token, send_token.value, send_token.length,
-                       token_sz);
+    b64buf = g_base64_encode(send_token.value, send_token.length);
+    strncpy(client_token, b64buf, (size_t) token_sz);
+    g_free(b64buf);
     gss_release_buffer(&min_stat, &send_token);
     return state;
 }
@@ -240,8 +242,12 @@ ag_parse_request(ImapMboxHandle *handle, char *buf, ssize_t buf_sz,
                  gss_buffer_desc *request)
 {
     char line[LONG_STRING];
+    guchar *rawbuf;
+
     sio_gets(handle->sio, line, LONG_STRING); /* FIXME: error checking */
-    request->length = lit_conv_from_base64(buf, line);
+    rawbuf = g_base64_decode(line, &request->length);
+    memcpy(buf, rawbuf, request->length);
+    g_free(rawbuf);
     request->value = buf;
 }
 
@@ -261,6 +267,7 @@ ag_negotiate_parameters(ImapMboxHandle *handle, const char * user,
     char server_conf_flags;
     unsigned char *t;
     unsigned long buf_size;
+    gchar *b64buf;
 
     ag_parse_request(handle, buf, sizeof(buf), &request_buf);
     state = gss_unwrap(&min_stat, context, &request_buf, &send_token,
@@ -307,9 +314,9 @@ ag_negotiate_parameters(ImapMboxHandle *handle, const char * user,
         return FALSE;
     }
     
-    lit_conv_to_base64(buf, send_token.value, send_token.length,
-                       sizeof(buf));
-    sio_printf(handle->sio, "%s\r\n", buf); imap_handle_flush(handle);
+    b64buf = g_base64_encode(send_token.value, send_token.length);
+    sio_printf(handle->sio, "%s\r\n", b64buf); imap_handle_flush(handle);
+    g_free(b64buf);
     
     WAIT_FOR_PROMPT(*rc,handle,cmdno,buf,sizeof(buf));
     if (*rc == IMR_RESPOND)
diff --git a/libbalsa/imap/imap-auth.c b/libbalsa/imap/imap-auth.c
index 35de1ff..adaa7d4 100644
--- a/libbalsa/imap/imap-auth.c
+++ b/libbalsa/imap/imap-auth.c
@@ -114,7 +114,7 @@ imap_auth_sasl(ImapMboxHandle* handle, ImapCapability cap,
 {
   char *msg = NULL, *msg64;
   ImapResponse rc;
-  int msglen, msg64len;
+  int msglen;
   unsigned cmdno;
   gboolean sasl_ir;
   
@@ -127,9 +127,7 @@ imap_auth_sasl(ImapMboxHandle* handle, ImapCapability cap,
     return IMAP_AUTH_CANCELLED;
   }
   
-  msg64len = 2*(msglen+2);
-  msg64 = g_malloc(msg64len);
-  lit_conv_to_base64(msg64, msg, msglen, msg64len);
+  msg64 = g_base64_encode((const guchar *) msg, msglen);
   g_free(msg);
 
   if(sasl_ir) { /* save one RTT */
diff --git a/libbalsa/imap/util.c b/libbalsa/imap/util.c
index a24748b..c9bd089 100644
--- a/libbalsa/imap/util.c
+++ b/libbalsa/imap/util.c
@@ -133,112 +133,6 @@ imap_next_word(char *s)
   return s;
 }
   
-#define BAD     -1
-#define base64val(c) Index_64[(unsigned int)(c)]
-static char B64Chars[64] = {
-  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
-  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
-  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
-  't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
-  '8', '9', '+', '/'
-};
-
-static int Index_64[128] = {
-    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
-    52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
-    -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
-    15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
-    -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
-    41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
-};
-
-/* raw bytes to null-terminated base 64 string */
-void
-lit_conv_to_base64(char *out, const char *in, size_t len, size_t olen)
-{
-  unsigned char in0, in1, in2;
-
-  while (len >= 3 && olen > 10)
-  {
-    in0 = in[0];
-    *out++ = B64Chars[in0 >> 2];
-    in1 = in[1];
-    *out++ = B64Chars[((in0 << 4) & 0x30) | (in1 >> 4)];
-    in2 = in[2];
-    *out++ = B64Chars[((in1 << 2) & 0x3c) | (in2 >> 6)];
-    *out++ = B64Chars[in2 & 0x3f];
-    olen  -= 4;
-    len   -= 3;
-    in    += 3;
-  }
-
-  /* clean up remainder */
-  if (len > 0 && olen > 4)
-  {
-    unsigned char fragment;
-
-    in0 = in[0];
-    *out++ = B64Chars[in0 >> 2];
-    fragment = (in0 << 4) & 0x30;
-    if (len > 1) {
-      in1 = in[1];
-      fragment |= in1 >> 4;
-      *out++ = B64Chars[fragment];
-      *out++ = B64Chars[(in1 << 2) & 0x3c];
-    } else {
-      *out++ = B64Chars[fragment];
-      *out++ = '=';
-    }
-    *out++ = '=';
-  }
-  *out = '\0';
-}
-
-
-/* Convert '\0'-terminated base 64 string to raw bytes.
- * Returns length of returned buffer, or -1 on error */
-int
-lit_conv_from_base64(char *out, const char *in)
-{
-  int len = 0, idx=0;
-  register unsigned char digit1, digit2, digit3, digit4;
-
-  do {
-    digit1 = in[idx];
-    if (digit1 > 127 || base64val (digit1) == BAD)
-      return -1-idx;
-    digit2 = in[idx+1];
-    if (digit2 > 127 || base64val (digit2) == BAD)
-      return -2-idx;
-    digit3 = in[idx+2];
-    if (digit3 > 127 || ((digit3 != '=') && (base64val (digit3) == BAD)))
-      return -3-idx;
-    digit4 = in[idx+3];
-    if (digit4 > 127 || ((digit4 != '=') && (base64val (digit4) == BAD)))
-      return -4-idx;
-    idx += 4;
-
-    /* digits are already sanity-checked */
-    *out++ = (base64val(digit1) << 2) | (base64val(digit2) >> 4);
-    len++;
-    if (digit3 != '=')
-    {
-      *out++ = ((base64val(digit2) << 4) & 0xf0) | (base64val(digit3) >> 2);
-      len++;
-      if (digit4 != '=')
-      {
-       *out++ = ((base64val(digit3) << 6) & 0xc0) | base64val(digit4);
-       len++;
-      }
-    }
-  }
-  while (in[idx] && in[idx] != 13 && digit4 != '=');
-
-  return len;
-}
-
 
 /* ===================================================================
  * UTF-7 conversion routines as in RFC 2192
diff --git a/libbalsa/imap/util.h b/libbalsa/imap/util.h
index c748b13..583399d 100644
--- a/libbalsa/imap/util.h
+++ b/libbalsa/imap/util.h
@@ -22,10 +22,6 @@ void imap_unquote_string(char *s);
 char* imap_next_word(char *s);
 char* imap_skip_atom(char *s);
 
-void lit_conv_to_base64(char *out, const char *in, 
-                        size_t len, size_t olen);
-int lit_conv_from_base64(char *out, const char *in);
-
 char* imap_mailbox_to_utf8(const char *src);
 char* imap_utf8_to_mailbox(const char *src);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]