-
-
Save dennwc/de336c848695232aab72c06b943349ab to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# HG changeset patch | |
# User dennwc@dennwc-ThinkPad-X270 | |
# Date 1554055927 -10800 | |
# Sun Mar 31 21:12:07 2019 +0300 | |
# Branch alpn | |
# Node ID ffcbdcb6ebb1b074d49a01e18bb2f4f20b8c62f0 | |
# Parent 3f1c58b88912114e43777999b3a2761a893f745e | |
initial support for alpn | |
diff -r 3f1c58b88912 -r ffcbdcb6ebb1 dcpp/BufferedSocket.cpp | |
--- a/dcpp/BufferedSocket.cpp Sun Feb 10 22:15:36 2019 +0100 | |
+++ b/dcpp/BufferedSocket.cpp Sun Mar 31 21:12:07 2019 +0300 | |
@@ -113,7 +113,7 @@ | |
void BufferedSocket::connect(const string& aAddress, const string& aPort, const string& localPort, NatRoles natRole, bool secure, bool allowUntrusted, bool proxy, const string& expKP) { | |
dcdebug("BufferedSocket::connect() %p\n", (void*)this); | |
- unique_ptr<Socket> s(secure ? new SSLSocket(natRole == NAT_SERVER ? CryptoManager::SSL_SERVER : CryptoManager::SSL_CLIENT, allowUntrusted, expKP) : new Socket(Socket::TYPE_TCP)); | |
+ unique_ptr<Socket> s(secure ? new SSLSocket(natRole == NAT_SERVER ? CryptoManager::SSL_SERVER : CryptoManager::SSL_CLIENT_ALPN, allowUntrusted, expKP) : new Socket(Socket::TYPE_TCP)); | |
s->setLocalIp4(CONNSETTING(BIND_ADDRESS)); | |
s->setLocalIp6(CONNSETTING(BIND_ADDRESS6)); | |
diff -r 3f1c58b88912 -r ffcbdcb6ebb1 dcpp/CryptoManager.cpp | |
--- a/dcpp/CryptoManager.cpp Sun Feb 10 22:15:36 2019 +0100 | |
+++ b/dcpp/CryptoManager.cpp Sun Mar 31 21:12:07 2019 +0300 | |
@@ -34,6 +34,11 @@ | |
namespace dcpp { | |
+unsigned char alpn_protos[] = { | |
+ 3, 'a', 'd', 'c', | |
+ 4, 'n', 'm', 'd', 'c', | |
+}; | |
+ | |
void* CryptoManager::tmpKeysMap[KEY_LAST] = { NULL, NULL, NULL }; | |
CriticalSection* CryptoManager::cs = NULL; | |
int CryptoManager::idxVerifyData = 0; | |
@@ -53,11 +58,12 @@ | |
SSL_load_error_strings(); | |
clientContext.reset(SSL_CTX_new(SSLv23_client_method())); | |
+ clientALPNContext.reset(SSL_CTX_new(SSLv23_client_method())); | |
serverContext.reset(SSL_CTX_new(SSLv23_server_method())); | |
idxVerifyData = SSL_get_ex_new_index(0, idxVerifyDataName, NULL, NULL, NULL); | |
- if(clientContext && serverContext) { | |
+ if(clientContext && clientALPNContext && serverContext) { | |
// Check that openssl rng has been seeded with enough data | |
sslRandCheck(); | |
@@ -72,6 +78,8 @@ | |
const char ciphersuites[] = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-RSA-AES128-SHA:AES128-SHA"; | |
SSL_CTX_set_options(clientContext, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); | |
SSL_CTX_set_cipher_list(clientContext, ciphersuites); | |
+ SSL_CTX_set_options(clientALPNContext, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); | |
+ SSL_CTX_set_cipher_list(clientALPNContext, ciphersuites); | |
SSL_CTX_set_options(serverContext, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); | |
SSL_CTX_set_cipher_list(serverContext, ciphersuites); | |
@@ -87,7 +95,10 @@ | |
SSL_CTX_set_tmp_rsa_callback(serverContext, CryptoManager::tmp_rsa_cb); | |
SSL_CTX_set_verify(clientContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); | |
+ SSL_CTX_set_verify(clientALPNContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); | |
SSL_CTX_set_verify(serverContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); | |
+ | |
+ SSL_CTX_set_alpn_protos(clientALPNContext, alpn_protos, sizeof(alpn_protos)); | |
} | |
} | |
@@ -99,6 +110,7 @@ | |
ERR_remove_thread_state(NULL); | |
clientContext.reset(); | |
+ clientALPNContext.reset(); | |
serverContext.reset(); | |
for(int i = KEY_FIRST; i != KEY_RSA_2048; ++i) { | |
@@ -356,7 +368,7 @@ | |
} | |
void CryptoManager::loadCertificates() noexcept { | |
- if(!clientContext || !serverContext) | |
+ if(!clientContext || !clientALPNContext || !serverContext) | |
return; | |
keyprint.clear(); | |
@@ -383,7 +395,8 @@ | |
if( | |
!ssl::SSL_CTX_use_certificate_file(serverContext, cert.c_str(), SSL_FILETYPE_PEM) || | |
- !ssl::SSL_CTX_use_certificate_file(clientContext, cert.c_str(), SSL_FILETYPE_PEM) | |
+ !ssl::SSL_CTX_use_certificate_file(clientContext, cert.c_str(), SSL_FILETYPE_PEM) || | |
+ !ssl::SSL_CTX_use_certificate_file(clientALPNContext, cert.c_str(), SSL_FILETYPE_PEM) | |
) { | |
LogManager::getInstance()->message(_("Failed to load certificate file")); | |
return; | |
@@ -391,7 +404,8 @@ | |
if( | |
!ssl::SSL_CTX_use_PrivateKey_file(serverContext, key.c_str(), SSL_FILETYPE_PEM) || | |
- !ssl::SSL_CTX_use_PrivateKey_file(clientContext, key.c_str(), SSL_FILETYPE_PEM) | |
+ !ssl::SSL_CTX_use_PrivateKey_file(clientContext, key.c_str(), SSL_FILETYPE_PEM) || | |
+ !ssl::SSL_CTX_use_PrivateKey_file(clientALPNContext, key.c_str(), SSL_FILETYPE_PEM) | |
) { | |
LogManager::getInstance()->message(_("Failed to load private key")); | |
return; | |
@@ -404,6 +418,7 @@ | |
for(auto& i: certs) { | |
if( | |
SSL_CTX_load_verify_locations(clientContext, i.c_str(), NULL) != SSL_SUCCESS || | |
+ SSL_CTX_load_verify_locations(clientALPNContext, i.c_str(), NULL) != SSL_SUCCESS || | |
SSL_CTX_load_verify_locations(serverContext, i.c_str(), NULL) != SSL_SUCCESS | |
) { | |
LogManager::getInstance()->message(str(F_("Failed to load trusted certificate from %1%") % Util::addBrackets(i))); | |
@@ -459,6 +474,7 @@ | |
SSL_CTX* CryptoManager::getSSLContext(SSLContext wanted) { | |
switch(wanted) { | |
case SSL_CLIENT: return clientContext; | |
+ case SSL_CLIENT_ALPN: return clientALPNContext; | |
case SSL_SERVER: return serverContext; | |
default: return NULL; | |
} | |
diff -r 3f1c58b88912 -r ffcbdcb6ebb1 dcpp/CryptoManager.h | |
--- a/dcpp/CryptoManager.h Sun Feb 10 22:15:36 2019 +0100 | |
+++ b/dcpp/CryptoManager.h Sun Mar 31 21:12:07 2019 +0300 | |
@@ -50,6 +50,7 @@ | |
enum SSLContext { | |
SSL_CLIENT, | |
+ SSL_CLIENT_ALPN, | |
SSL_SERVER | |
}; | |
@@ -84,6 +85,7 @@ | |
virtual ~CryptoManager(); | |
ssl::SSL_CTX clientContext; | |
+ ssl::SSL_CTX clientALPNContext; | |
ssl::SSL_CTX serverContext; | |
void sslRandCheck(); | |
diff -r 3f1c58b88912 -r ffcbdcb6ebb1 dcpp/SSLSocket.cpp | |
--- a/dcpp/SSLSocket.cpp Sun Feb 10 22:15:36 2019 +0100 | |
+++ b/dcpp/SSLSocket.cpp Sun Mar 31 21:12:07 2019 +0300 | |
@@ -67,6 +67,26 @@ | |
if(ret == 1) { | |
dcdebug("Connected to SSL server using %s as %s\n", | |
SSL_get_cipher(ssl), SSL_is_server(ssl) ? "server" : "client"); | |
+ | |
+ if (SSL_is_server(ssl)) return true; | |
+ | |
+ // protocol negotiation (ALPN) | |
+ const unsigned char* negotiated = 0; | |
+ unsigned int len = 0; | |
+ SSL_get0_alpn_selected(ssl, &negotiated, &len); | |
+ if (len == 0) { | |
+ // negotiation failed, use default | |
+ proto = PROTO_DEFAULT; | |
+ return true | |
+ } | |
+ if (len == 3 && !memcmp(negotiated, "adc", len)) { | |
+ proto = PROTO_ADC; | |
+ } else if (len == 4 && !memcmp(negotiated, "nmdc", len)) { | |
+ proto = PROTO_NMDC; | |
+ } else { | |
+ proto = PROTO_DEFAULT; | |
+ } | |
+ dcdebug("ALPN negotiated %.*s (%d)\n", len, protocol, proto); | |
return true; | |
} | |
if(!waitWant(ret, millis)) { | |
diff -r 3f1c58b88912 -r ffcbdcb6ebb1 dcpp/Socket.cpp | |
--- a/dcpp/Socket.cpp Sun Feb 10 22:15:36 2019 +0100 | |
+++ b/dcpp/Socket.cpp Sun Mar 31 21:12:07 2019 +0300 | |
@@ -250,6 +250,10 @@ | |
if(sock6.valid()) setBlocking2(sock6, block); | |
} | |
+Protocol Socket::getNextProtocol() noexcept { | |
+ return proto; | |
+} | |
+ | |
socket_t Socket::create(const addrinfo& ai) { | |
return setSock(check([&] { return ::socket(ai.ai_family, ai.ai_socktype, ai.ai_protocol); }), ai.ai_family); | |
} | |
diff -r 3f1c58b88912 -r ffcbdcb6ebb1 dcpp/Socket.h | |
--- a/dcpp/Socket.h Sun Feb 10 22:15:36 2019 +0100 | |
+++ b/dcpp/Socket.h Sun Mar 31 21:12:07 2019 +0300 | |
@@ -89,7 +89,13 @@ | |
TYPE_UDP = IPPROTO_UDP | |
}; | |
- explicit Socket(SocketType type) : type(type) { } | |
+ enum Protocol { | |
+ PROTO_DEFAULT = 0, | |
+ PROTO_NMDC = 1, | |
+ PROTO_ADC = 2 | |
+ } | |
+ | |
+ explicit Socket(SocketType type) : type(type), proto(PROTO_DEFAULT) { } | |
virtual ~Socket() { } | |
@@ -174,6 +180,8 @@ | |
int getSocketOptInt(int option); | |
void setSocketOpt(int option, int value); | |
+ Protocol getNextProtocol(); | |
+ | |
virtual bool isSecure() const noexcept { return false; } | |
virtual bool isTrusted() const noexcept { return false; } | |
virtual string getCipherName() const noexcept { return Util::emptyString; } | |
@@ -217,6 +225,8 @@ | |
static addr udpAddr; | |
static socklen_t udpAddrLen; | |
+ Protocol proto; | |
+ | |
private: | |
void socksAuth(uint32_t timeout); | |
socket_t setSock(socket_t s, int af); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment