[balsa] Avoid rare but possible cycles in call graphs



commit 9eccb133c33385836b3441524de4d36d25caa270
Author: Pawel Salek <pawsa0 gmail com>
Date:   Sat Dec 19 11:59:24 2020 +0100

    Avoid rare but possible cycles in call graphs
    
    Under certain conditions, two capability functions could create
    a cycle calling each other. Avoid that.
    Also, check the connection state before proceeding with authentication.

 ChangeLog                     |  6 ++++++
 libbalsa/imap/imap-auth.c     |  3 ++-
 libbalsa/imap/imap-commands.c | 36 ++++++++++++++----------------------
 3 files changed, 22 insertions(+), 23 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index bdccfd38d..ba67f1fc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2020-12-19  Pawel Salek  <pawsa0 gmail com>
+
+    * libbalsa/imap/imap-auth.c: catch errors mid authentication process.
+    * libbalsa/imap/imap-commands.c: simplify CAPABILITY handling
+    to prevent infinite loops.
+
 2020-12-06  Peter Bloomfield  <pbloomfield bellsouth net>
 
        * meson.build: Define the FORTIFY_SOURCE macro only if the
diff --git a/libbalsa/imap/imap-auth.c b/libbalsa/imap/imap-auth.c
index d94ca3dd4..d0f098540 100644
--- a/libbalsa/imap/imap-auth.c
+++ b/libbalsa/imap/imap-auth.c
@@ -61,10 +61,11 @@ imap_authenticate(ImapMboxHandle* handle)
 
   for(authenticator = imap_authenticators_arr;
       *authenticator; authenticator++) {
+    if (!imap_mbox_is_connected(handle)) { return IMAP_AUTH_CANCELLED; }
     if ((r = (*authenticator)(handle)) 
         != IMAP_AUTH_UNAVAIL) {
       if (r == IMAP_SUCCESS)
-       imap_mbox_handle_set_state(handle, IMHS_AUTHENTICATED);
+        imap_mbox_handle_set_state(handle, IMHS_AUTHENTICATED);
       return r;
     }
   }
diff --git a/libbalsa/imap/imap-commands.c b/libbalsa/imap/imap-commands.c
index 09319c760..38d9c6987 100644
--- a/libbalsa/imap/imap-commands.c
+++ b/libbalsa/imap/imap-commands.c
@@ -110,36 +110,28 @@ need_fetch_view_set(unsigned i, struct fetch_data_set* fd)
 
 
 /* 6.1.1 CAPABILITY Command */
-/* imap_check_capability: make sure we can log in to this server. */
-static gboolean
-imap_check_capability(ImapMboxHandle* handle)
-{
-  IMAP_REQUIRED_STATE3_U(handle, IMHS_CONNECTED, IMHS_AUTHENTICATED,
-                       IMHS_SELECTED, FALSE);
-  if (imap_cmd_exec(handle, "CAPABILITY") != IMR_OK)
-    return FALSE;
-
-  if (!(imap_mbox_handle_can_do(handle, IMCAP_IMAP4) ||
-        imap_mbox_handle_can_do(handle, IMCAP_IMAP4REV1))) {
-    g_warning("IMAP4rev1 required but not provided.");
-    return FALSE;
-  }  
-  return TRUE;
-}
-
 int
 imap_mbox_handle_can_do(ImapMboxHandle* handle, ImapCapability cap)
 {
+  IMAP_REQUIRED_STATE3_U(handle, IMHS_CONNECTED, IMHS_AUTHENTICATED,
+                         IMHS_SELECTED, IMR_BAD);
   if(cap == IMCAP_FETCHBODY)
     return handle->can_fetch_body;
 
   /* perhaps it already has capabilities? */
-  if(!handle->has_capabilities)
-    imap_check_capability(handle);
+  if(!handle->has_capabilities) {
+    /* If we request CAPABILITY, we have the definitive answer
+     * regardless of the response.
+     */
+    handle->has_capabilities = TRUE;
+    imap_cmd_exec(handle, "CAPABILITY");
+    if (!(handle->capabilities[IMCAP_IMAP4] ||
+          handle->capabilities[IMCAP_IMAP4REV1])) {
+      g_warning("IMAP4rev1 required but not provided.");
+    }
+  }
 
-  if(cap<IMCAP_MAX)
-    return handle->capabilities[cap];
-  else return 0;
+  return (cap<IMCAP_MAX) ? handle->capabilities[cap] : 0;
 }
 
 


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