upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nostr.cpp29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/nostr.cpp b/src/nostr.cpp
index 47f001c..fbae1a6 100644
--- a/src/nostr.cpp
+++ b/src/nostr.cpp
@@ -6,6 +6,7 @@
6#include "headers.h" 6#include "headers.h"
7#include <openssl/ssl.h> 7#include <openssl/ssl.h>
8#include <openssl/err.h> 8#include <openssl/err.h>
9#include <openssl/x509.h>
9// We link libsecp256k1 statically (without this the header assumes DLL import). 10// We link libsecp256k1 statically (without this the header assumes DLL import).
10// Both makefiles also pass -DSECP256K1_STATIC; the guard keeps that from 11// Both makefiles also pass -DSECP256K1_STATIC; the guard keeps that from
11// warning while leaving this file correct if built without the flag. 12// warning while leaving this file correct if built without the flag.
@@ -568,11 +569,39 @@ public:
568 { 569 {
569 sslctx = SSL_CTX_new(TLS_client_method()); 570 sslctx = SSL_CTX_new(TLS_client_method());
570 if (!sslctx) return false; 571 if (!sslctx) return false;
572
573 // SSL_CTX_new defaults to SSL_VERIFY_NONE with no trust store
574 // loaded, so until now every wss:// relay connection was accepted
575 // without looking at the certificate at all -- any on-path
576 // attacker could impersonate a relay. Our own events are signed,
577 // so a MITM cannot forge them, but it could drop the rendezvous
578 // registration (leaving the pool unreachable to miners) or answer
579 // subscriptions with whatever it liked.
580 if (!SSL_CTX_set_default_verify_paths(sslctx))
581 return error("Nostr: no system CA store available, refusing %s", host.c_str());
582 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, NULL);
583 SSL_CTX_set_min_proto_version(sslctx, TLS1_2_VERSION);
584
571 ssl = SSL_new(sslctx); 585 ssl = SSL_new(sslctx);
586 if (!ssl) return false;
572 SSL_set_fd(ssl, (int)hSocket); 587 SSL_set_fd(ssl, (int)hSocket);
573 SSL_set_tlsext_host_name(ssl, host.c_str()); // SNI 588 SSL_set_tlsext_host_name(ssl, host.c_str()); // SNI
589
590 // Verifying the chain is not enough on its own: without this the
591 // relay could present any certificate a trusted CA ever issued,
592 // for any name. SSL_set1_host binds the check to the host we asked
593 // for.
594 if (!SSL_set1_host(ssl, host.c_str()))
595 return error("Nostr: cannot pin verification to %s", host.c_str());
596
574 if (SSL_connect(ssl) != 1) 597 if (SSL_connect(ssl) != 1)
598 {
599 long nVerify = SSL_get_verify_result(ssl);
600 if (nVerify != X509_V_OK)
601 return error("Nostr: certificate for %s rejected: %s",
602 host.c_str(), X509_verify_cert_error_string(nVerify));
575 return error("Nostr: TLS handshake with %s failed", host.c_str()); 603 return error("Nostr: TLS handshake with %s failed", host.c_str());
604 }
576 } 605 }
577 606
578 // WebSocket handshake (HTTP Upgrade) 607 // WebSocket handshake (HTTP Upgrade)