summaryrefslogtreecommitdiff
path: root/src/netops.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/netops.c')
-rw-r--r--src/netops.c68
1 files changed, 36 insertions, 32 deletions
diff --git a/src/netops.c b/src/netops.c
index ad27d84cf..adbae61c4 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -13,6 +13,7 @@
# include <netinet/in.h>
# include <arpa/inet.h>
#else
+# include <winsock2.h>
# include <ws2tcpip.h>
# ifdef _MSC_VER
# pragma comment(lib, "ws2_32")
@@ -33,6 +34,7 @@
#include "posix.h"
#include "buffer.h"
#include "http_parser.h"
+#include "global.h"
#ifdef GIT_WIN32
static void net_set_error(const char *str)
@@ -157,7 +159,7 @@ void gitno_buffer_setup_callback(
void gitno_buffer_setup(gitno_socket *socket, gitno_buffer *buf, char *data, size_t len)
{
#ifdef GIT_SSL
- if (socket->ssl.ctx) {
+ if (socket->ssl.ssl) {
gitno_buffer_setup_callback(socket, buf, data, len, gitno__recv_ssl, NULL);
return;
}
@@ -202,12 +204,13 @@ static int gitno_ssl_teardown(gitno_ssl *ssl)
ret = 0;
SSL_free(ssl->ssl);
- SSL_CTX_free(ssl->ctx);
return ret;
}
+#endif
+
/* Match host names according to RFC 2818 rules */
-static int match_host(const char *pattern, const char *host)
+int gitno__match_host(const char *pattern, const char *host)
{
for (;;) {
char c = tolower(*pattern++);
@@ -230,9 +233,9 @@ static int match_host(const char *pattern, const char *host)
while(*host) {
char h = tolower(*host);
if (c == h)
- return match_host(pattern, host++);
+ return gitno__match_host(pattern, host++);
if (h == '.')
- return match_host(pattern, host);
+ return gitno__match_host(pattern, host);
host++;
}
return -1;
@@ -250,12 +253,14 @@ static int check_host_name(const char *name, const char *host)
if (!strcasecmp(name, host))
return 0;
- if (match_host(name, host) < 0)
+ if (gitno__match_host(name, host) < 0)
return -1;
return 0;
}
+#ifdef GIT_SSL
+
static int verify_server_cert(gitno_ssl *ssl, const char *host)
{
X509 *cert;
@@ -287,6 +292,10 @@ static int verify_server_cert(gitno_ssl *ssl, const char *host)
cert = SSL_get_peer_certificate(ssl->ssl);
+ if (!cert) {
+ giterr_set(GITERR_SSL, "the server did not provide a certificate");
+ return -1;
+ }
/* Check the alternative names */
alts = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
@@ -321,7 +330,7 @@ static int verify_server_cert(gitno_ssl *ssl, const char *host)
GENERAL_NAMES_free(alts);
if (matched == 0)
- goto cert_fail;
+ goto cert_fail_name;
if (matched == 1)
return 0;
@@ -358,11 +367,11 @@ static int verify_server_cert(gitno_ssl *ssl, const char *host)
int size = ASN1_STRING_to_UTF8(&peer_cn, str);
GITERR_CHECK_ALLOC(peer_cn);
if (memchr(peer_cn, '\0', size))
- goto cert_fail;
+ goto cert_fail_name;
}
if (check_host_name((char *)peer_cn, host) < 0)
- goto cert_fail;
+ goto cert_fail_name;
OPENSSL_free(peer_cn);
@@ -372,28 +381,22 @@ on_error:
OPENSSL_free(peer_cn);
return ssl_set_error(ssl, 0);
-cert_fail:
+cert_fail_name:
OPENSSL_free(peer_cn);
- giterr_set(GITERR_SSL, "Certificate host name check failed");
- return -1;
+ giterr_set(GITERR_SSL, "hostname does not match certificate");
+ return GIT_ECERTIFICATE;
}
-static int ssl_setup(gitno_socket *socket, const char *host, int flags)
+static int ssl_setup(gitno_socket *socket, const char *host)
{
int ret;
- SSL_library_init();
- SSL_load_error_strings();
- socket->ssl.ctx = SSL_CTX_new(SSLv23_method());
- if (socket->ssl.ctx == NULL)
- return ssl_set_error(&socket->ssl, 0);
-
- SSL_CTX_set_mode(socket->ssl.ctx, SSL_MODE_AUTO_RETRY);
- SSL_CTX_set_verify(socket->ssl.ctx, SSL_VERIFY_NONE, NULL);
- if (!SSL_CTX_set_default_verify_paths(socket->ssl.ctx))
- return ssl_set_error(&socket->ssl, 0);
+ if (git__ssl_ctx == NULL) {
+ giterr_set(GITERR_NET, "OpenSSL initialization failed");
+ return -1;
+ }
- socket->ssl.ssl = SSL_new(socket->ssl.ctx);
+ socket->ssl.ssl = SSL_new(git__ssl_ctx);
if (socket->ssl.ssl == NULL)
return ssl_set_error(&socket->ssl, 0);
@@ -403,9 +406,6 @@ static int ssl_setup(gitno_socket *socket, const char *host, int flags)
if ((ret = SSL_connect(socket->ssl.ssl)) <= 0)
return ssl_set_error(&socket->ssl, ret);
- if (GITNO_CONNECT_SSL_NO_CHECK_CERT & flags)
- return 0;
-
return verify_server_cert(&socket->ssl, host);
}
#endif
@@ -458,7 +458,7 @@ int gitno_connect(gitno_socket *s_out, const char *host, const char *port, int f
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;
- if ((ret = p_getaddrinfo(host, port, &hints, &info)) < 0) {
+ if ((ret = p_getaddrinfo(host, port, &hints, &info)) != 0) {
giterr_set(GITERR_NET,
"Failed to resolve address for %s: %s", host, p_gai_strerror(ret));
return -1;
@@ -491,8 +491,9 @@ int gitno_connect(gitno_socket *s_out, const char *host, const char *port, int f
p_freeaddrinfo(info);
#ifdef GIT_SSL
- if ((flags & GITNO_CONNECT_SSL) && ssl_setup(s_out, host, flags) < 0)
- return -1;
+ if ((flags & GITNO_CONNECT_SSL) &&
+ (ret = ssl_setup(s_out, host)) < 0)
+ return ret;
#else
/* SSL is not supported */
if (flags & GITNO_CONNECT_SSL) {
@@ -530,7 +531,7 @@ int gitno_send(gitno_socket *socket, const char *msg, size_t len, int flags)
size_t off = 0;
#ifdef GIT_SSL
- if (socket->ssl.ctx)
+ if (socket->ssl.ssl)
return gitno_send_ssl(&socket->ssl, msg, len, flags);
#endif
@@ -551,7 +552,7 @@ int gitno_send(gitno_socket *socket, const char *msg, size_t len, int flags)
int gitno_close(gitno_socket *s)
{
#ifdef GIT_SSL
- if (s->ssl.ctx &&
+ if (s->ssl.ssl &&
gitno_ssl_teardown(&s->ssl) < 0)
return -1;
#endif
@@ -715,6 +716,9 @@ int gitno_extract_url_parts(
if (u.field_set & (1 << UF_PATH)) {
*path = git__substrdup(_path, u.field_data[UF_PATH].len);
GITERR_CHECK_ALLOC(*path);
+ } else {
+ giterr_set(GITERR_NET, "invalid url, missing path");
+ return GIT_EINVALIDSPEC;
}
if (u.field_set & (1 << UF_USERINFO)) {