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).
This commit is contained in:
parent
4f3ef54f3a
commit
6c959c3ee4
|
@ -1203,10 +1203,9 @@ imap_socket_read( void *aux )
|
||||||
imap_store_t *ctx = (imap_store_t *)aux;
|
imap_store_t *ctx = (imap_store_t *)aux;
|
||||||
struct imap_cmd *cmdp, **pcmdp;
|
struct imap_cmd *cmdp, **pcmdp;
|
||||||
char *cmd, *arg, *arg1, *p;
|
char *cmd, *arg, *arg1, *p;
|
||||||
int resp, resp2, tag, greeted;
|
int resp, resp2, tag;
|
||||||
conn_iovec_t iov[2];
|
conn_iovec_t iov[2];
|
||||||
|
|
||||||
greeted = ctx->greeting;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (ctx->parse_list_sts.level) {
|
if (ctx->parse_list_sts.level) {
|
||||||
resp = parse_list_continue( ctx, 0 );
|
resp = parse_list_continue( ctx, 0 );
|
||||||
|
@ -1236,18 +1235,30 @@ imap_socket_read( void *aux )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp( "NAMESPACE", arg )) {
|
if (ctx->greeting == GreetingPending && !strcmp( "PREAUTH", arg )) {
|
||||||
resp = parse_list( ctx, cmd, parse_namespace_rsp );
|
parse_response_code( ctx, 0, cmd );
|
||||||
goto listret;
|
|
||||||
} else if (ctx->greeting == GreetingPending && !strcmp( "PREAUTH", arg )) {
|
|
||||||
ctx->greeting = GreetingPreauth;
|
ctx->greeting = GreetingPreauth;
|
||||||
parse_response_code( ctx, 0, cmd );
|
dogreet:
|
||||||
|
imap_ref( ctx );
|
||||||
|
imap_open_store_greeted( ctx );
|
||||||
|
if (imap_deref( ctx ))
|
||||||
|
return;
|
||||||
} else if (!strcmp( "OK", arg )) {
|
} else if (!strcmp( "OK", arg )) {
|
||||||
ctx->greeting = GreetingOk;
|
|
||||||
parse_response_code( ctx, 0, cmd );
|
parse_response_code( ctx, 0, cmd );
|
||||||
|
if (ctx->greeting == GreetingPending) {
|
||||||
|
ctx->greeting = GreetingOk;
|
||||||
|
goto dogreet;
|
||||||
|
}
|
||||||
} else if (!strcmp( "BYE", arg )) {
|
} else if (!strcmp( "BYE", arg )) {
|
||||||
ctx->greeting = GreetingBad;
|
if (ctx->conn.state != SCK_CLOSING) {
|
||||||
parse_response_code( ctx, 0, cmd );
|
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 )) {
|
} else if (!strcmp( "NO", arg )) {
|
||||||
warn( "Warning from IMAP server: %s\n", cmd );
|
warn( "Warning from IMAP server: %s\n", cmd );
|
||||||
} else if (!strcmp( "BAD", arg )) {
|
} else if (!strcmp( "BAD", arg )) {
|
||||||
|
@ -1257,6 +1268,9 @@ imap_socket_read( void *aux )
|
||||||
} else if (!strcmp( "LIST", arg )) {
|
} else if (!strcmp( "LIST", arg )) {
|
||||||
resp = parse_list( ctx, cmd, parse_list_rsp );
|
resp = parse_list( ctx, cmd, parse_list_rsp );
|
||||||
goto listret;
|
goto listret;
|
||||||
|
} else if (!strcmp( "NAMESPACE", arg )) {
|
||||||
|
resp = parse_list( ctx, cmd, parse_namespace_rsp );
|
||||||
|
goto listret;
|
||||||
} else if ((arg1 = next_arg( &cmd ))) {
|
} else if ((arg1 = next_arg( &cmd ))) {
|
||||||
if (!strcmp( "EXISTS", arg1 ))
|
if (!strcmp( "EXISTS", arg1 ))
|
||||||
ctx->gen.count = atoi( arg );
|
ctx->gen.count = atoi( arg );
|
||||||
|
@ -1270,12 +1284,6 @@ imap_socket_read( void *aux )
|
||||||
error( "IMAP error: unrecognized untagged response '%s'\n", arg );
|
error( "IMAP error: unrecognized untagged response '%s'\n", arg );
|
||||||
break; /* this may mean anything, so prefer not to spam the log */
|
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;
|
continue;
|
||||||
} else if (!ctx->in_progress) {
|
} else if (!ctx->in_progress) {
|
||||||
error( "IMAP error: unexpected reply: %s %s\n", arg, cmd ? cmd : "" );
|
error( "IMAP error: unexpected reply: %s %s\n", arg, cmd ? cmd : "" );
|
||||||
|
@ -1462,6 +1470,7 @@ imap_cleanup( void )
|
||||||
for (ctx = unowned; ctx; ctx = nctx) {
|
for (ctx = unowned; ctx; ctx = nctx) {
|
||||||
nctx = ctx->next;
|
nctx = ctx->next;
|
||||||
set_bad_callback( ctx, (void (*)(void *))imap_cancel_store, ctx );
|
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" );
|
imap_exec( (imap_store_t *)ctx, 0, imap_cleanup_p2, "LOGOUT" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1470,7 +1479,7 @@ static void
|
||||||
imap_cleanup_p2( imap_store_t *ctx,
|
imap_cleanup_p2( imap_store_t *ctx,
|
||||||
struct imap_cmd *cmd ATTR_UNUSED, int response )
|
struct imap_cmd *cmd ATTR_UNUSED, int response )
|
||||||
{
|
{
|
||||||
if (response != RESP_CANCEL)
|
if (response == RESP_NO)
|
||||||
imap_cancel_store( &ctx->gen );
|
imap_cancel_store( &ctx->gen );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1583,12 +1592,6 @@ imap_open_store_tlsstarted1( int ok, void *aux )
|
||||||
static void
|
static void
|
||||||
imap_open_store_greeted( imap_store_t *ctx )
|
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)
|
if (!ctx->caps)
|
||||||
imap_exec( ctx, 0, imap_open_store_p2, "CAPABILITY" );
|
imap_exec( ctx, 0, imap_open_store_p2, "CAPABILITY" );
|
||||||
else
|
else
|
||||||
|
|
19
src/socket.c
19
src/socket.c
|
@ -43,14 +43,6 @@
|
||||||
# include <openssl/x509v3.h>
|
# include <openssl/x509v3.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum {
|
|
||||||
SCK_CONNECTING,
|
|
||||||
#ifdef HAVE_LIBSSL
|
|
||||||
SCK_STARTTLS,
|
|
||||||
#endif
|
|
||||||
SCK_READY
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
socket_fail( conn_t *conn )
|
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_SYSCALL:
|
||||||
case SSL_ERROR_SSL:
|
case SSL_ERROR_SSL:
|
||||||
if (!(err = ERR_get_error())) {
|
if (!(err = ERR_get_error())) {
|
||||||
if (ret == 0)
|
if (ret == 0) {
|
||||||
error( "Socket error: secure %s %s: unexpected EOF\n", func, conn->name );
|
if (conn->state != SCK_CLOSING)
|
||||||
else
|
error( "Socket error: secure %s %s: unexpected EOF\n", func, conn->name );
|
||||||
|
} else {
|
||||||
sys_error( "Socket error: secure %s %s", func, conn->name );
|
sys_error( "Socket error: secure %s %s", func, conn->name );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error( "Socket error: secure %s %s: %s\n", func, conn->name, ERR_error_string( err, 0 ) );
|
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 );
|
sys_error( "Socket error: read from %s", sock->name );
|
||||||
socket_fail( sock );
|
socket_fail( sock );
|
||||||
} else if (!n) {
|
} 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 );
|
socket_fail( sock );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,15 @@
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SCK_CONNECTING,
|
||||||
|
#ifdef HAVE_LIBSSL
|
||||||
|
SCK_STARTTLS,
|
||||||
|
#endif
|
||||||
|
SCK_READY,
|
||||||
|
SCK_CLOSING
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
typedef struct ssl_st SSL;
|
typedef struct ssl_st SSL;
|
||||||
typedef struct ssl_ctx_st SSL_CTX;
|
typedef struct ssl_ctx_st SSL_CTX;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user