Merge pull request #912 from schu/netops-ssl-error netops: be more careful with SSL errors
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 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 52 53 54 55 56 57 58 59
diff --git a/src/netops.c b/src/netops.c
index f622e0d..df502e6 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -55,8 +55,44 @@ static void net_set_error(const char *str)
static int ssl_set_error(gitno_ssl *ssl, int error)
{
int err;
+ unsigned long e;
+
err = SSL_get_error(ssl->ssl, error);
- giterr_set(GITERR_NET, "SSL error: %s", ERR_error_string(err, NULL));
+
+ assert(err != SSL_ERROR_WANT_READ);
+ assert(err != SSL_ERROR_WANT_WRITE);
+
+ switch (err) {
+ case SSL_ERROR_WANT_CONNECT:
+ case SSL_ERROR_WANT_ACCEPT:
+ giterr_set(GITERR_NET, "SSL error: connection failure\n");
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ giterr_set(GITERR_NET, "SSL error: x509 error\n");
+ break;
+ case SSL_ERROR_SYSCALL:
+ e = ERR_get_error();
+ if (e > 0) {
+ giterr_set(GITERR_NET, "SSL error: %s",
+ ERR_error_string(e, NULL));
+ break;
+ } else if (error < 0) {
+ giterr_set(GITERR_OS, "SSL error: syscall failure");
+ break;
+ }
+ giterr_set(GITERR_NET, "SSL error: received early EOF");
+ break;
+ case SSL_ERROR_SSL:
+ e = ERR_get_error();
+ giterr_set(GITERR_NET, "SSL error: %s",
+ ERR_error_string(e, NULL));
+ break;
+ case SSL_ERROR_NONE:
+ case SSL_ERROR_ZERO_RETURN:
+ default:
+ giterr_set(GITERR_NET, "SSL error: unknown error");
+ break;
+ }
return -1;
}
#endif
@@ -442,7 +478,7 @@ static int send_ssl(gitno_ssl *ssl, const char *msg, size_t len)
while (off < len) {
ret = SSL_write(ssl->ssl, msg + off, len - off);
- if (ret <= 0)
+ if (ret <= 0 && ret != SSL_ERROR_WANT_WRITE)
return ssl_set_error(ssl, ret);
off += ret;