Commit 65ac67fbbdb1a980aefb46bfdde918f43515acaf

Michael Schubert 2012-08-28T21:58:10

netops: be more careful with SSL errors SSL_get_error() allows to receive a result code for various SSL operations. Depending on the return value (see man (3) SSL_get_error) there might be additional information in the OpenSSL error queue. Return the queued message if available, otherwise set an error message corresponding to the return code.

diff --git a/src/netops.c b/src/netops.c
index a0d2bf3..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