[balsa] Work around Gmail bugs; modernize SSL cert checking.



commit b89f99cf6dada6275e688944124203ca1f90f29a
Author: Pawel Salek <pawsa0 gmail com>
Date:   Sun Jul 25 22:33:20 2010 +0200

    Work around Gmail bugs; modernize SSL cert checking.
    
    * libbalsa/imap/imap-handle.c: work around buggy Gmail.
    * libbalsa/imap/imap-tls.c: change openssl api used for cert checks.
    * src/balsa-mime-widget-message.c: warn the user when no embedded
      message info available.

 ChangeLog                       |    7 ++++
 libbalsa/imap/imap-handle.c     |   63 +++++++++++++++++++++++---------
 libbalsa/imap/imap-tls.c        |   77 +++++++++++++++------------------------
 src/balsa-mime-widget-message.c |   11 +++++-
 4 files changed, 91 insertions(+), 67 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 47d5f07..50c7979 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2010-07-25  Pawel Salek
+
+	* libbalsa/imap/imap-handle.c: work around buggy Gmail.
+	* libbalsa/imap/imap-tls.c: change openssl api used for cert checks.
+	* src/balsa-mime-widget-message.c: warn the user when no embedded
+	message info available.
+
 2010-07-14  Peter Bloomfield
 
 	Install dialog to ask the user before selecting a different
diff --git a/libbalsa/imap/imap-handle.c b/libbalsa/imap/imap-handle.c
index 7b65b6a..0ecdc81 100644
--- a/libbalsa/imap/imap-handle.c
+++ b/libbalsa/imap/imap-handle.c
@@ -3329,7 +3329,23 @@ ir_envelope(struct siobuf *sio, ImapEnvelope *env)
   int c;
   char *date, *str;
 
-  if( (c=sio_getc(sio)) != '(') return IMR_PROTOCOL;
+  c=sio_getc(sio);
+
+#define GMAIL_BUG_20100725 1
+#if GMAIL_BUG_20100725 == 1
+  /* GMAIL returns sometimes NIL instead of the envelope. */
+  if (c == 'N') {
+      printf("GMail message/rfc822 bug detected.\n");      
+      env = NULL;
+      if (sio_getc(sio) == 'I' &&
+          sio_getc(sio) == 'L') return IMR_PARSE;
+  }
+#endif /* GMAIL_BUG_20100725 */
+  if( c != '(') {
+      printf("envelope's ( expected but got '%c'\n", c);
+      return IMR_PROTOCOL;
+  }
+
   date = imap_get_nstring(sio);
   if(date) {
     if(env) env->date = g_mime_utils_header_decode_date(date, NULL);
@@ -3707,7 +3723,8 @@ ir_body_extension (struct siobuf *sio, ImapBody * body)
 
 enum _ImapBodyExtensibility {
     IMB_NON_EXTENSIBLE,
-    IMB_EXTENSIBLE
+    IMB_EXTENSIBLE,
+    IMB_EXTENSIBLE_BUGGY_GMAIL
 };
 typedef enum _ImapBodyExtensibility ImapBodyExtensibility;
 
@@ -3805,8 +3822,8 @@ ir_body_ext_1part (struct siobuf *sio, ImapBody * body,
 
   if (type == IMB_NON_EXTENSIBLE)
     return IMR_PROTOCOL;
-#define GMAIL_BUG_20080601
-#ifdef GMAIL_BUG_20080601
+#define GMAIL_BUG_20080601 1
+#if GMAIL_BUG_20080601
   /* GMail sends number of lines on some parts like application/pgp-signature */
   { int c = sio_getc(sio);
     if(c == -1)
@@ -3823,19 +3840,22 @@ ir_body_ext_1part (struct siobuf *sio, ImapBody * body,
   }
 #endif
   /* body_fld_md5 = nstring */
-  str = imap_get_nstring (sio);
-  if (body && str)
-    body->ext.onepart.md5 = str;
-  else
-    g_free (str);
-
-  /* [SP */
-  if (sio_getc (sio) != ' ')
-    {
-      sio_ungetc (sio);
-      return IMR_OK;
-    }
-
+  if (type == IMB_EXTENSIBLE_BUGGY_GMAIL)
+    str = NULL;
+  else {
+    str = imap_get_nstring (sio);
+    if (body && str)
+        body->ext.onepart.md5 = str;
+    else
+        g_free (str);
+
+    /* [SP */
+    if (sio_getc(sio) != ' ')
+      {
+        sio_ungetc (sio);
+        return IMR_OK;
+     }
+  }
   /* body_fld_dsp */
   rc = ir_body_fld_dsp (sio, body);
   if (rc != IMR_OK)
@@ -3974,6 +3994,10 @@ ir_body_type_1part (struct siobuf *sio, ImapBody * body,
 	return IMR_PROTOCOL;
       env = body ? imap_envelope_new () : NULL;
       rc = ir_envelope (sio, env);
+#if GMAIL_BUG_20100725
+      if (rc == IMR_PARSE)
+          break;
+#endif /* GMAIL_BUG_20100725 */
       if (rc != IMR_OK)
 	{
 	  if (env)
@@ -3981,7 +4005,7 @@ ir_body_type_1part (struct siobuf *sio, ImapBody * body,
 	  return rc;
 	}
       if (sio_getc (sio) != ' ')
-	return IMR_PROTOCOL;
+        return IMR_PROTOCOL;
       if (body)
 	{
 	  b = imap_body_new ();
@@ -4014,7 +4038,12 @@ ir_body_type_1part (struct siobuf *sio, ImapBody * body,
     }
 
   /* body-ext-1part] */
+#if GMAIL_BUG_20100725
+  rc = ir_body_ext_1part (sio, body,
+                          (rc == IMR_PARSE ? IMB_EXTENSIBLE_BUGGY_GMAIL : type));
+#else  /* GMAIL_BUG_20100725 */
   rc = ir_body_ext_1part (sio, body, type);
+#endif /* GMAIL_BUG_20100725 */
   if (rc != IMR_OK)
     return rc;
 
diff --git a/libbalsa/imap/imap-tls.c b/libbalsa/imap/imap-tls.c
index ce5be11..dfc6cce 100644
--- a/libbalsa/imap/imap-tls.c
+++ b/libbalsa/imap/imap-tls.c
@@ -237,9 +237,11 @@ imap_check_server_identity(SSL *ssl, const char *host,
   long vfy_result;
   X509 *cert;
   X509_NAME *subj;
-  int ok, extcount, i, j, stack_len, host_len;
+  int ok, i, host_len;
   gchar *colon;
-  
+  int has_extension_with_dns_name = 0;
+  STACK_OF(GENERAL_NAME) *altnames;
+
   if(!host)
     return 0;
   /* Check whether the certificate matches the server. */
@@ -250,71 +252,50 @@ imap_check_server_identity(SSL *ssl, const char *host,
   colon = strchr(host, ':');
   host_len = colon ? colon - host : (int)strlen(host);
   ok = 0;
-  extcount = X509_get_ext_count(cert);
-  for(i=0; i<extcount; i++) {
-    const char *extstr;
-    X509_EXTENSION *ext = X509_get_ext(cert, i);
 
-    extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
+  altnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
 
-    if(strcmp(extstr, "subjectAltName") == 0) {
-#if (OPENSSL_VERSION_NUMBER > 0x00908000L)
-      const unsigned char *data;
-#else
-      unsigned char *data;
-#endif
-      STACK_OF(CONF_VALUE) *val;
-      CONF_VALUE           *nval;
-#if (OPENSSL_VERSION_NUMBER >= 0x01000000L)
-      const X509V3_EXT_METHOD *meth;
-#else
-      X509V3_EXT_METHOD    *meth;
-#endif
-      void *ext_str = NULL;
-
-      if( !(meth = X509V3_EXT_get(ext)) )
-        break;
-      data = ext->value->data;
-
-#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
-      if (meth->it)
-        ext_str = ASN1_item_d2i (NULL, &data, ext->value->length,
-                                 ASN1_ITEM_ptr (meth->it));
-      else
-        ext_str = meth->d2i (NULL, &data, ext->value->length);
-#else
-      ext_str = meth->d2i(NULL, &data, ext->value->length);
-#endif
-      val = meth->i2v(meth, ext_str, NULL);
+  if (altnames) {
+    for (i=0; i< sk_GENERAL_NAME_num(altnames); i++) {
+      const GENERAL_NAME *name = sk_GENERAL_NAME_value(altnames, i);
+
+      /* We handle only GEN_DNS. GEN_IP (certificates for IP numbers)
+         are too weird to be real in IMAP case. */
+      if (name->type == GEN_DNS) {
+        const ASN1_IA5STRING *ia5 = name->d.ia5;
+        const char *name = (const char*)ia5->data;
+        has_extension_with_dns_name = 1;
 
-      stack_len = sk_CONF_VALUE_num(val);
-      for(j=0; j<stack_len; j++) {
-        nval = sk_CONF_VALUE_value(val, j);
-        if(strcmp(nval->name, "DNS") == 0 &&
-           host_matches_domain(host, nval->value, host_len)) {
+        if (strlen(name) == (size_t)ia5->length &&
+            host_matches_domain(host, name, host_len)) {
+          /* printf("verified name using extension\n"); */
           ok = 1;
           break;
         }
       }
     }
-    if(ok)
-      break;
+    sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
   }
-  if(!ok) { /* matching by subjectAltName failed, try commonName */
+
+  if (!has_extension_with_dns_name) {
     char data[256];
     size_t name_len;
     if( (subj = X509_get_subject_name(cert)) &&
         (name_len = 
-         X509_NAME_get_text_by_NID(subj, NID_commonName, data, sizeof(data)))){
+         X509_NAME_get_text_by_NID(subj, NID_commonName,
+                                   data, sizeof(data)))){
       data[sizeof(data)-1] = 0;
 
       /* Remember to check whether there was no truncation or NUL
          characters embedded in the text. */
       if(name_len == strlen(data) &&
-         host_matches_domain(host, data, host_len))
+         host_matches_domain(host, data, host_len)) {
         ok =1;
+        /* printf("verified name using common name\n"); */
+      }
     }
   }
+
   X509_free(cert);
   if(ok)
     vfy_result = SSL_get_verify_result(ssl);
@@ -323,8 +304,8 @@ imap_check_server_identity(SSL *ssl, const char *host,
 
   if(vfy_result == X509_V_OK)
     return 1;
-  /* There was a problem with the verification, one has to leave it up to the
-   * application what to do with this.
+  /* There was a problem with the verification, one has to leave it up
+   * to the application what to do with this.
    */
   ok = 0;
   if(user_cb)
diff --git a/src/balsa-mime-widget-message.c b/src/balsa-mime-widget-message.c
index a669c02..193560f 100644
--- a/src/balsa-mime-widget-message.c
+++ b/src/balsa-mime-widget-message.c
@@ -643,7 +643,9 @@ balsa_mime_widget_message_set_headers(BalsaMessage * bm, BalsaMimeWidget *mw,
     GtkTextView *view;
 
     balsa_mime_widget_message_set_headers_d(bm, mw, part->embhdrs, part->parts,
-                                            part->embhdrs->subject);
+                                            part->embhdrs
+                                            ? part->embhdrs->subject
+                                            : NULL );
     if (!(widget = mw->header_widget))
 	return;
     view = bm_header_widget_get_text_view(widget);
@@ -698,7 +700,12 @@ balsa_mime_widget_message_set_headers_d(BalsaMessage * bm,
     bmwm_buffer_set_prefs(buffer);
 
     gtk_text_buffer_set_text(buffer, "", 0);
-    g_return_if_fail(headers);
+    if (!headers) {
+        /* Gmail sometimes fails to do that. */
+        add_header_gchar(bm, view, "subject", _("Error:"),
+                         _("IMAP server did not report message structure"));
+        return;
+    }
 
     if (bm->shown_headers == HEADERS_NONE) {
 	gtk_widget_hide(widget);



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