From 1b75c29e3e175ad3ef4bc91a779b851dc76b9e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 2 Nov 2014 11:17:01 +0100 Subject: [PATCH] gitno: remove code which is no longer needed Most of the network-facing facilities have been copied to the socket and openssl streams. No code now uses these functions directly anymore, so we can now remove them. --- src/netops.c | 497 +---------------------------------------- src/netops.h | 10 +- src/openssl_stream.c | 3 +- src/socket_stream.c | 1 - src/transports/smart.c | 6 +- 5 files changed, 17 insertions(+), 500 deletions(-) diff --git a/src/netops.c b/src/netops.c index ab135c46b..6047cf1ac 100644 --- a/src/netops.c +++ b/src/netops.c @@ -4,27 +4,6 @@ * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ -#ifndef _WIN32 -# include -# include -# include -# include -# include -# include -# include -#else -# include -# include -# ifdef _MSC_VER -# pragma comment(lib, "ws2_32") -# endif -#endif - -#ifdef GIT_SSL -# include -# include -# include -#endif #include #include "git2/errors.h" @@ -36,122 +15,12 @@ #include "http_parser.h" #include "global.h" -#ifdef GIT_WIN32 -static void net_set_error(const char *str) -{ - int error = WSAGetLastError(); - char * win32_error = git_win32_get_error_message(error); - - if (win32_error) { - giterr_set(GITERR_NET, "%s: %s", str, win32_error); - git__free(win32_error); - } else { - giterr_set(GITERR_NET, str); - } -} -#else -static void net_set_error(const char *str) -{ - giterr_set(GITERR_NET, "%s: %s", str, strerror(errno)); -} -#endif - -#ifdef GIT_SSL -static int ssl_set_error(gitno_ssl *ssl, int error) -{ - int err; - unsigned long e; - - err = SSL_get_error(ssl->ssl, error); - - 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 - int gitno_recv(gitno_buffer *buf) { - if (buf->io) { - int ret; - ret = git_stream_read(buf->io, buf->data + buf->offset, buf->len - buf->offset); - if (ret < 0) - return -1; - - buf->offset += ret; - return ret; - } - return buf->recv(buf); } -#ifdef GIT_SSL -static int gitno__recv_ssl(gitno_buffer *buf) -{ - int ret; - - do { - ret = SSL_read(buf->socket->ssl.ssl, buf->data + buf->offset, buf->len - buf->offset); - } while (SSL_get_error(buf->socket->ssl.ssl, ret) == SSL_ERROR_WANT_READ); - - if (ret < 0) { - net_set_error("Error receiving socket data"); - return -1; - } - - buf->offset += ret; - return ret; -} -#endif - -static int gitno__recv(gitno_buffer *buf) -{ - int ret; - - ret = p_recv(buf->socket->socket, buf->data + buf->offset, buf->len - buf->offset, 0); - if (ret < 0) { - net_set_error("Error receiving socket data"); - return -1; - } - - buf->offset += ret; - return ret; -} - void gitno_buffer_setup_callback( - gitno_socket *socket, gitno_buffer *buf, char *data, size_t len, @@ -161,21 +30,21 @@ void gitno_buffer_setup_callback( buf->data = data; buf->len = len; buf->offset = 0; - buf->socket = socket; buf->recv = recv; buf->cb_data = cb_data; } -void gitno_buffer_setup(gitno_socket *socket, gitno_buffer *buf, char *data, size_t len) +static int recv_stream(gitno_buffer *buf) { -#ifdef GIT_SSL - if (socket->ssl.ssl) { - gitno_buffer_setup_callback(socket, buf, data, len, gitno__recv_ssl, NULL); - return; - } -#endif + git_stream *io = (git_stream *) buf->cb_data; + int ret; - gitno_buffer_setup_callback(socket, buf, data, len, gitno__recv, NULL); + ret = git_stream_read(io, buf->data + buf->offset, buf->len - buf->offset); + if (ret < 0) + return -1; + + buf->offset += ret; + return ret; } void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data, size_t len) @@ -184,7 +53,8 @@ void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data buf->data = data; buf->len = len; buf->offset = 0; - buf->io = st; + buf->recv = recv_stream; + buf->cb_data = st; } /* Consume up to ptr and move the rest of the buffer to the beginning */ @@ -210,24 +80,6 @@ void gitno_consume_n(gitno_buffer *buf, size_t cons) buf->offset -= cons; } -#ifdef GIT_SSL - -static int gitno_ssl_teardown(gitno_ssl *ssl) -{ - int ret; - - ret = SSL_shutdown(ssl->ssl); - if (ret < 0) - ret = ssl_set_error(ssl, ret); - else - ret = 0; - - SSL_free(ssl->ssl); - return ret; -} - -#endif - /* Match host names according to RFC 2818 rules */ int gitno__match_host(const char *pattern, const char *host) { @@ -267,333 +119,6 @@ int gitno__match_host(const char *pattern, const char *host) return -1; } -static int check_host_name(const char *name, const char *host) -{ - if (!strcasecmp(name, host)) - return 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; - X509_NAME *peer_name; - ASN1_STRING *str; - unsigned char *peer_cn = NULL; - int matched = -1, type = GEN_DNS; - GENERAL_NAMES *alts; - struct in6_addr addr6; - struct in_addr addr4; - void *addr; - int i = -1,j; - - if (SSL_get_verify_result(ssl->ssl) != X509_V_OK) { - giterr_set(GITERR_SSL, "The SSL certificate is invalid"); - return GIT_ECERTIFICATE; - } - - /* Try to parse the host as an IP address to see if it is */ - if (p_inet_pton(AF_INET, host, &addr4)) { - type = GEN_IPADD; - addr = &addr4; - } else { - if(p_inet_pton(AF_INET6, host, &addr6)) { - type = GEN_IPADD; - addr = &addr6; - } - } - - - 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); - if (alts) { - int num; - - num = sk_GENERAL_NAME_num(alts); - for (i = 0; i < num && matched != 1; i++) { - const GENERAL_NAME *gn = sk_GENERAL_NAME_value(alts, i); - const char *name = (char *) ASN1_STRING_data(gn->d.ia5); - size_t namelen = (size_t) ASN1_STRING_length(gn->d.ia5); - - /* Skip any names of a type we're not looking for */ - if (gn->type != type) - continue; - - if (type == GEN_DNS) { - /* If it contains embedded NULs, don't even try */ - if (memchr(name, '\0', namelen)) - continue; - - if (check_host_name(name, host) < 0) - matched = 0; - else - matched = 1; - } else if (type == GEN_IPADD) { - /* Here name isn't so much a name but a binary representation of the IP */ - matched = !!memcmp(name, addr, namelen); - } - } - } - GENERAL_NAMES_free(alts); - - if (matched == 0) - goto cert_fail_name; - - if (matched == 1) - return 0; - - /* If no alternative names are available, check the common name */ - peer_name = X509_get_subject_name(cert); - if (peer_name == NULL) - goto on_error; - - if (peer_name) { - /* Get the index of the last CN entry */ - while ((j = X509_NAME_get_index_by_NID(peer_name, NID_commonName, i)) >= 0) - i = j; - } - - if (i < 0) - goto on_error; - - str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(peer_name, i)); - if (str == NULL) - goto on_error; - - /* Work around a bug in OpenSSL whereby ASN1_STRING_to_UTF8 fails if it's already in utf-8 */ - if (ASN1_STRING_type(str) == V_ASN1_UTF8STRING) { - int size = ASN1_STRING_length(str); - - if (size > 0) { - peer_cn = OPENSSL_malloc(size + 1); - GITERR_CHECK_ALLOC(peer_cn); - memcpy(peer_cn, ASN1_STRING_data(str), size); - peer_cn[size] = '\0'; - } - } else { - int size = ASN1_STRING_to_UTF8(&peer_cn, str); - GITERR_CHECK_ALLOC(peer_cn); - if (memchr(peer_cn, '\0', size)) - goto cert_fail_name; - } - - if (check_host_name((char *)peer_cn, host) < 0) - goto cert_fail_name; - - OPENSSL_free(peer_cn); - - return 0; - -on_error: - OPENSSL_free(peer_cn); - return ssl_set_error(ssl, 0); - -cert_fail_name: - OPENSSL_free(peer_cn); - giterr_set(GITERR_SSL, "hostname does not match certificate"); - return GIT_ECERTIFICATE; -} - -static int ssl_setup(gitno_socket *socket, const char *host) -{ - int ret; - - if (git__ssl_ctx == NULL) { - giterr_set(GITERR_NET, "OpenSSL initialization failed"); - return -1; - } - - socket->ssl.ssl = SSL_new(git__ssl_ctx); - if (socket->ssl.ssl == NULL) - return ssl_set_error(&socket->ssl, 0); - - if((ret = SSL_set_fd(socket->ssl.ssl, socket->socket)) == 0) - return ssl_set_error(&socket->ssl, ret); - - if ((ret = SSL_connect(socket->ssl.ssl)) <= 0) - return ssl_set_error(&socket->ssl, ret); - - return verify_server_cert(&socket->ssl, host); -} -#endif - -static int gitno__close(GIT_SOCKET s) -{ -#ifdef GIT_WIN32 - if (SOCKET_ERROR == closesocket(s)) - return -1; - - if (0 != WSACleanup()) { - giterr_set(GITERR_OS, "Winsock cleanup failed"); - return -1; - } - - return 0; -#else - return close(s); -#endif -} - -int gitno_connect(gitno_socket *s_out, const char *host, const char *port, int flags) -{ - struct addrinfo *info = NULL, *p; - struct addrinfo hints; - GIT_SOCKET s = INVALID_SOCKET; - int ret; - -#ifdef GIT_WIN32 - /* on win32, the WSA context needs to be initialized - * before any socket calls can be performed */ - WSADATA wsd; - - if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { - giterr_set(GITERR_OS, "Winsock init failed"); - return -1; - } - - if (LOBYTE(wsd.wVersion) != 2 || HIBYTE(wsd.wVersion) != 2) { - WSACleanup(); - giterr_set(GITERR_OS, "Winsock init failed"); - return -1; - } -#endif - - /* Zero the socket structure provided */ - memset(s_out, 0x0, sizeof(gitno_socket)); - - memset(&hints, 0x0, sizeof(struct addrinfo)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; - - 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; - } - - for (p = info; p != NULL; p = p->ai_next) { - s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - - if (s == INVALID_SOCKET) { - net_set_error("error creating socket"); - break; - } - - if (connect(s, p->ai_addr, (socklen_t)p->ai_addrlen) == 0) - break; - - /* If we can't connect, try the next one */ - gitno__close(s); - s = INVALID_SOCKET; - } - - /* Oops, we couldn't connect to any address */ - if (s == INVALID_SOCKET && p == NULL) { - giterr_set(GITERR_OS, "Failed to connect to %s", host); - p_freeaddrinfo(info); - return -1; - } - - s_out->socket = s; - p_freeaddrinfo(info); - -#ifdef GIT_SSL - if ((flags & GITNO_CONNECT_SSL) && - (ret = ssl_setup(s_out, host)) < 0) - return ret; -#else - /* SSL is not supported */ - if (flags & GITNO_CONNECT_SSL) { - giterr_set(GITERR_OS, "SSL is not supported by this copy of libgit2."); - return -1; - } -#endif - - return 0; -} - -#ifdef GIT_SSL -static int gitno_send_ssl(gitno_ssl *ssl, const char *msg, size_t len, int flags) -{ - int ret; - size_t off = 0; - - GIT_UNUSED(flags); - - while (off < len) { - ret = SSL_write(ssl->ssl, msg + off, len - off); - if (ret <= 0 && ret != SSL_ERROR_WANT_WRITE) - return ssl_set_error(ssl, ret); - - off += ret; - } - - return off; -} -#endif - -int gitno_send(gitno_socket *socket, const char *msg, size_t len, int flags) -{ - int ret; - size_t off = 0; - -#ifdef GIT_SSL - if (socket->ssl.ssl) - return gitno_send_ssl(&socket->ssl, msg, len, flags); -#endif - - while (off < len) { - errno = 0; - ret = p_send(socket->socket, msg + off, len - off, flags); - if (ret < 0) { - net_set_error("Error sending data"); - return -1; - } - - off += ret; - } - - return (int)off; -} - -int gitno_close(gitno_socket *s) -{ -#ifdef GIT_SSL - if (s->ssl.ssl && - gitno_ssl_teardown(&s->ssl) < 0) - return -1; -#endif - - return gitno__close(s->socket); -} - -int gitno_select_in(gitno_buffer *buf, long int sec, long int usec) -{ - fd_set fds; - struct timeval tv; - - tv.tv_sec = sec; - tv.tv_usec = usec; - - FD_ZERO(&fds); - FD_SET(buf->socket->socket, &fds); - - /* The select(2) interface is silly */ - return select((int)buf->socket->socket + 1, &fds, NULL, NULL, &tv); -} - static const char *prefix_http = "http://"; static const char *prefix_https = "https://"; diff --git a/src/netops.h b/src/netops.h index fee6d82da..d5f0ca3f3 100644 --- a/src/netops.h +++ b/src/netops.h @@ -33,8 +33,6 @@ typedef struct gitno_buffer { char *data; size_t len; size_t offset; - git_stream *io; - gitno_socket *socket; int (*recv)(struct gitno_buffer *buffer); void *cb_data; } gitno_buffer; @@ -58,19 +56,13 @@ enum { */ int gitno__match_host(const char *pattern, const char *host); -void gitno_buffer_setup(gitno_socket *t, gitno_buffer *buf, char *data, size_t len); void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data, size_t len); -void gitno_buffer_setup_callback(gitno_socket *t, gitno_buffer *buf, char *data, size_t len, int (*recv)(gitno_buffer *buf), void *cb_data); +void gitno_buffer_setup_callback(gitno_buffer *buf, char *data, size_t len, int (*recv)(gitno_buffer *buf), void *cb_data); int gitno_recv(gitno_buffer *buf); void gitno_consume(gitno_buffer *buf, const char *ptr); void gitno_consume_n(gitno_buffer *buf, size_t cons); -int gitno_connect(gitno_socket *socket, const char *host, const char *port, int flags); -int gitno_send(gitno_socket *socket, const char *msg, size_t len, int flags); -int gitno_close(gitno_socket *s); -int gitno_select_in(gitno_buffer *buf, long int sec, long int usec); - typedef struct gitno_connection_data { char *host; char *port; diff --git a/src/openssl_stream.c b/src/openssl_stream.c index 4c8b02c8c..0893bcc9d 100644 --- a/src/openssl_stream.c +++ b/src/openssl_stream.c @@ -17,6 +17,7 @@ #include "posix.h" #include "stream.h" #include "socket_stream.h" +#include "netops.h" #include "git2/transport.h" static int ssl_set_error(SSL *ssl, int error) @@ -103,7 +104,7 @@ static int verify_server_cert(SSL *ssl, const char *host) if (SSL_get_verify_result(ssl) != X509_V_OK) { giterr_set(GITERR_SSL, "The SSL certificate is invalid"); - return -1; + return GIT_ECERTIFICATE; } /* Try to parse the host as an IP address to see if it is */ diff --git a/src/socket_stream.c b/src/socket_stream.c index 113b8f698..ce41fb640 100644 --- a/src/socket_stream.c +++ b/src/socket_stream.c @@ -99,7 +99,6 @@ int socket_connect(git_stream *stream) if ((ret = p_getaddrinfo(st->host, st->port, &hints, &info)) != 0) { giterr_set(GITERR_NET, - "Failed to resolve address for %s: %s", st->host, p_gai_strerror(ret)); return -1; } diff --git a/src/transports/smart.c b/src/transports/smart.c index d0f9c90e8..ec0ba3784 100644 --- a/src/transports/smart.c +++ b/src/transports/smart.c @@ -158,7 +158,7 @@ static int git_smart__connect( /* Save off the current stream (i.e. socket) that we are working with */ t->current_stream = stream; - gitno_buffer_setup_callback(NULL, &t->buffer, t->buffer_data, sizeof(t->buffer_data), git_smart__recv_cb, t); + gitno_buffer_setup_callback(&t->buffer, t->buffer_data, sizeof(t->buffer_data), git_smart__recv_cb, t); /* 2 flushes for RPC; 1 for stateful */ if ((error = git_smart__store_refs(t, t->rpc ? 2 : 1)) < 0) @@ -252,7 +252,7 @@ int git_smart__negotiation_step(git_transport *transport, void *data, size_t len if ((error = stream->write(stream, (const char *)data, len)) < 0) return error; - gitno_buffer_setup_callback(NULL, &t->buffer, t->buffer_data, sizeof(t->buffer_data), git_smart__recv_cb, t); + gitno_buffer_setup_callback(&t->buffer, t->buffer_data, sizeof(t->buffer_data), git_smart__recv_cb, t); return 0; } @@ -278,7 +278,7 @@ int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream /* Save off the current stream (i.e. socket) that we are working with */ t->current_stream = *stream; - gitno_buffer_setup_callback(NULL, &t->buffer, t->buffer_data, sizeof(t->buffer_data), git_smart__recv_cb, t); + gitno_buffer_setup_callback(&t->buffer, t->buffer_data, sizeof(t->buffer_data), git_smart__recv_cb, t); return 0; }