commit 6c959c3ee4bba035e6ad0e8e71cb7526f503e43b
Author: Oswald Buddenhagen <[email protected]>
Date:   Sat Dec 13 18:01:52 2014 +0100

    fix handling of unsolicited BYE responses
    
    they can come in at any time, after which we must expect the connection
    to be closed (and not complain about it).

 src/drv_imap.c |   49 +++++++++++++++++++++++++----------------------
 src/socket.c   |   19 ++++++-----------
 src/socket.h   |    9 ++++++++
 3 files changed, 42 insertions(+), 35 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index f52992d..7f8f821 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1203,10 +1203,9 @@ imap_socket_read( void *aux )
        imap_store_t *ctx = (imap_store_t *)aux;
        struct imap_cmd *cmdp, **pcmdp;
        char *cmd, *arg, *arg1, *p;
-       int resp, resp2, tag, greeted;
+       int resp, resp2, tag;
        conn_iovec_t iov[2];
 
-       greeted = ctx->greeting;
        for (;;) {
                if (ctx->parse_list_sts.level) {
                        resp = parse_list_continue( ctx, 0 );
@@ -1236,18 +1235,30 @@ imap_socket_read( void *aux )
                                break;
                        }
 
-                       if (!strcmp( "NAMESPACE", arg )) {
-                               resp = parse_list( ctx, cmd, 
parse_namespace_rsp );
-                               goto listret;
-                       } else if (ctx->greeting == GreetingPending && !strcmp( 
"PREAUTH", arg )) {
-                               ctx->greeting = GreetingPreauth;
+                       if (ctx->greeting == GreetingPending && !strcmp( 
"PREAUTH", arg )) {
                                parse_response_code( ctx, 0, cmd );
+                               ctx->greeting = GreetingPreauth;
+                         dogreet:
+                               imap_ref( ctx );
+                               imap_open_store_greeted( ctx );
+                               if (imap_deref( ctx ))
+                                       return;
                        } else if (!strcmp( "OK", arg )) {
-                               ctx->greeting = GreetingOk;
                                parse_response_code( ctx, 0, cmd );
+                               if (ctx->greeting == GreetingPending) {
+                                       ctx->greeting = GreetingOk;
+                                       goto dogreet;
+                               }
                        } else if (!strcmp( "BYE", arg )) {
-                               ctx->greeting = GreetingBad;
-                               parse_response_code( ctx, 0, cmd );
+                               if (ctx->conn.state != SCK_CLOSING) {
+                                       ctx->conn.state = SCK_CLOSING;
+                                       ctx->greeting = GreetingBad;
+                                       error( "IMAP error: unexpected BYE 
response: %s\n", cmd );
+                               }
+                               /* We just wait for the server to close the 
connection now. */
+                       } else if (ctx->greeting == GreetingPending) {
+                               error( "IMAP error: bogus greeting response 
%s\n", arg );
+                               break;
                        } else if (!strcmp( "NO", arg )) {
                                warn( "Warning from IMAP server: %s\n", cmd );
                        } else if (!strcmp( "BAD", arg )) {
@@ -1257,6 +1268,9 @@ imap_socket_read( void *aux )
                        } else if (!strcmp( "LIST", arg )) {
                                resp = parse_list( ctx, cmd, parse_list_rsp );
                                goto listret;
+                       } else if (!strcmp( "NAMESPACE", arg )) {
+                               resp = parse_list( ctx, cmd, 
parse_namespace_rsp );
+                               goto listret;
                        } else if ((arg1 = next_arg( &cmd ))) {
                                if (!strcmp( "EXISTS", arg1 ))
                                        ctx->gen.count = atoi( arg );
@@ -1270,12 +1284,6 @@ imap_socket_read( void *aux )
                                error( "IMAP error: unrecognized untagged 
response '%s'\n", arg );
                                break; /* this may mean anything, so prefer not 
to spam the log */
                        }
-                       if (greeted == GreetingPending) {
-                               imap_ref( ctx );
-                               imap_open_store_greeted( ctx );
-                               if (imap_deref( ctx ))
-                                       return;
-                       }
                        continue;
                } else if (!ctx->in_progress) {
                        error( "IMAP error: unexpected reply: %s %s\n", arg, 
cmd ? cmd : "" );
@@ -1462,6 +1470,7 @@ imap_cleanup( void )
        for (ctx = unowned; ctx; ctx = nctx) {
                nctx = ctx->next;
                set_bad_callback( ctx, (void (*)(void *))imap_cancel_store, ctx 
);
+               ((imap_store_t *)ctx)->conn.state = SCK_CLOSING;
                imap_exec( (imap_store_t *)ctx, 0, imap_cleanup_p2, "LOGOUT" );
        }
 }
@@ -1470,7 +1479,7 @@ static void
 imap_cleanup_p2( imap_store_t *ctx,
                  struct imap_cmd *cmd ATTR_UNUSED, int response )
 {
-       if (response != RESP_CANCEL)
+       if (response == RESP_NO)
                imap_cancel_store( &ctx->gen );
 }
 
@@ -1583,12 +1592,6 @@ imap_open_store_tlsstarted1( int ok, void *aux )
 static void
 imap_open_store_greeted( imap_store_t *ctx )
 {
-       if (ctx->greeting == GreetingBad) {
-               error( "IMAP error: unknown greeting response\n" );
-               imap_open_store_bail( ctx );
-               return;
-       }
-
        if (!ctx->caps)
                imap_exec( ctx, 0, imap_open_store_p2, "CAPABILITY" );
        else
diff --git a/src/socket.c b/src/socket.c
index b300910..56e041a 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -43,14 +43,6 @@
 # include <openssl/x509v3.h>
 #endif
 
-enum {
-       SCK_CONNECTING,
-#ifdef HAVE_LIBSSL
-       SCK_STARTTLS,
-#endif
-       SCK_READY
-};
-
 static void
 socket_fail( conn_t *conn )
 {
@@ -74,10 +66,12 @@ ssl_return( const char *func, conn_t *conn, int ret )
        case SSL_ERROR_SYSCALL:
        case SSL_ERROR_SSL:
                if (!(err = ERR_get_error())) {
-                       if (ret == 0)
-                               error( "Socket error: secure %s %s: unexpected 
EOF\n", func, conn->name );
-                       else
+                       if (ret == 0) {
+                               if (conn->state != SCK_CLOSING)
+                                       error( "Socket error: secure %s %s: 
unexpected EOF\n", func, conn->name );
+                       } else {
                                sys_error( "Socket error: secure %s %s", func, 
conn->name );
+                       }
                } else {
                        error( "Socket error: secure %s %s: %s\n", func, 
conn->name, ERR_error_string( err, 0 ) );
                }
@@ -588,7 +582,8 @@ do_read( conn_t *sock, char *buf, int len )
                        sys_error( "Socket error: read from %s", sock->name );
                        socket_fail( sock );
                } else if (!n) {
-                       error( "Socket error: read from %s: unexpected EOF\n", 
sock->name );
+                       if (sock->state != SCK_CLOSING)
+                               error( "Socket error: read from %s: unexpected 
EOF\n", sock->name );
                        socket_fail( sock );
                        return -1;
                }
diff --git a/src/socket.h b/src/socket.h
index a420e49..20c3033 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -29,6 +29,15 @@
 #include <zlib.h>
 #endif
 
+enum {
+       SCK_CONNECTING,
+#ifdef HAVE_LIBSSL
+       SCK_STARTTLS,
+#endif
+       SCK_READY,
+       SCK_CLOSING
+};
+
 #ifdef HAVE_LIBSSL
 typedef struct ssl_st SSL;
 typedef struct ssl_ctx_st SSL_CTX;

------------------------------------------------------------------------------
New Year. New Location. New Benefits. New Data Center in Ashburn, VA.
GigeNET is offering a free month of service with a new server in Ashburn.
Choose from 2 high performing configs, both with 100TB of bandwidth.
Higher redundancy.Lower latency.Increased capacity.Completely compliant.
http://p.sf.net/sfu/gigenet
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to