Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(WIP) Add new feature: irc server public key fingerprint pinning #1789

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions eggdrop.conf
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,8 @@ server add you.need.to.change.this 6667
server add another.example.com 6669 password
server add 2001:db8:618:5c0:263:: 6669 password
server add ssl.example.net +7000
# For tls ports the servers public key sha256 fingerprint can be pinned:
server add example.org +6697,55:88:55:88:55:88:55:88:55:88:55:88:55:88:55:88:55:88:55:88:55:88:55:88:55:88:55:88:55:88:55:88

#### CAP Features ####
# This section controls IRCv3 capabilities supported natively by Eggdrop. You
Expand Down
3 changes: 3 additions & 0 deletions src/eggdrop.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,9 @@ struct dcc_t {
struct dupwait_info *dupwait;
int ident_sock;
void *other;
#ifdef TLS
char *fingerprint;
#endif
} u; /* Special use depending on type */
};

Expand Down
6 changes: 6 additions & 0 deletions src/mod/server.mod/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,12 @@ static int add_server(const char *name, const char *port, const char *pass)
x->port = atoi(port);
#ifdef TLS
x->ssl = (port[0] == '+') ? 1 : 0;
char *fingerprint;
if (x->ssl && (fingerprint = strchr(port + 1, ',')) && fingerprint[1]) {
x->fingerprint = nmalloc(strlen(fingerprint) + 1);
strcpy(x->fingerprint, fingerprint + 1);
} else
x->fingerprint = NULL;
#endif
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/mod/server.mod/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@

struct server_list {
struct server_list *next;

char *name;
int port;
#ifdef TLS
int ssl;
char *fingerprint;
#endif
char *pass;
char *realname;
Expand Down
15 changes: 10 additions & 5 deletions src/mod/server.mod/servmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1966,20 +1966,20 @@ static void connect_server(void)

#ifdef IPV6
if (inet_pton(AF_INET6, botserver, buf)) {
len += egg_snprintf(s, sizeof s, "%s [%s]", IRC_SERVERTRY, botserver);
len += snprintf(s, sizeof s, "%s [%s]", IRC_SERVERTRY, botserver);
} else {
#endif
len += egg_snprintf(s, sizeof s, "%s %s", IRC_SERVERTRY, botserver);
len += snprintf(s, sizeof s, "%s %s", IRC_SERVERTRY, botserver);
#ifdef IPV6
}
#endif

#ifdef TLS
len += egg_snprintf(s + len, sizeof s - len, ":%s%d",
use_ssl ? "+" : "", botserverport);
len += snprintf(s + len, sizeof s - len, ":%s%u", use_ssl ? "+" : "",
botserverport);
dcc[servidx].ssl = use_ssl;
#else
len += egg_snprintf(s + len, sizeof s - len, ":%d", botserverport);
len += snprintf(s + len, sizeof s - len, ":%u", botserverport);
#endif
putlog(LOG_SERV, "*", "%s", s);
dcc[servidx].port = botserverport;
Expand All @@ -2003,6 +2003,11 @@ static void connect_server(void)
dcc[servidx].u.dns->dns_type = RES_IPBYHOST;
dcc[servidx].u.dns->type = &SERVER_SOCKET;
dcc[servidx].status |= STAT_SERV;
#ifdef TLS
printf("DEBUG: here fingerprint needs to be set to dcc_t entry, so, that tls.c:ssl_info()->sock->dcc->fingerprint can be used, not implemented yet\n");
// if (fingerprint)
// dcc[servidx].u.fingerprint = fingerprint;
#endif

if (server_cycle_wait)
/* Back to 1st server & set wait time.
Expand Down
39 changes: 35 additions & 4 deletions src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,25 +648,31 @@ static void ssl_showcert(X509 *cert, const int loglev)
} else
putlog(loglev, "*", "TLS: cannot get issuer name from certificate!");

/* Fingerprints */
/* Certificate fingerprints */
if (X509_digest(cert, EVP_sha1(), md, &len)) {
buf = OPENSSL_buf2hexstr(md, len);
putlog(loglev, "*", "TLS: certificate SHA1 Fingerprint: %s", buf);
OPENSSL_free(buf);
}
if (X509_digest(cert, EVP_sha256(), md, &len)) {
buf = OPENSSL_buf2hexstr(md, len);
putlog(loglev, "*", "TLS: certificate SHA-256 Fingerprint: %s", buf);
putlog(loglev, "*", "TLS: certificate SHA256 Fingerprint: %s", buf);
OPENSSL_free(buf);
}


/* Validity time */
from = ssl_printtime(X509_get_notBefore(cert));
to = ssl_printtime(X509_get_notAfter(cert));
putlog(loglev, "*", "TLS: certificate valid from %s to %s", from, to);
nfree(from);
nfree(to);

/* Public key fingerprint */
if (X509_pubkey_digest(cert, EVP_sha256(), md, &len)) {
buf = OPENSSL_buf2hexstr(md, len);
putlog(loglev, "*", "TLS: public key SHA256 Fingerprint: %s", buf);
OPENSSL_free(buf);
}
}

/* Certificate validation callback
Expand Down Expand Up @@ -768,6 +774,29 @@ static void ssl_info(const SSL *ssl, int where, int ret)
/* Callback for completed handshake. Cheaper and more convenient than
using H_tls */
sock = SSL_get_fd(ssl);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
cert = SSL_get0_peer_certificate(ssl);
#else
cert = SSL_get_peer_certificate(ssl);
#endif

/* Verify public key fingerprint */
int idx = findanyidx(sock);
if (dcc[idx].u.fingerprint) {
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int len;
if (X509_pubkey_digest(cert, EVP_sha256(), md, &len)) {
char *fingerprint2 = OPENSSL_buf2hexstr(md, len);
OPENSSL_free(fingerprint2);
}
printf("DEBUG: Verifying public key fingerprint not implemented yet: %s\n", dcc[idx].u.fingerprint);
// if (crypto_verify(fingerprint, fingerprint2)); /* verify not successful */
// MAYBE THIS IS NOT THE RIGHT PLACE AT ALL TO VERIFY AND/OR SHUTDOWN THEN connection
// MAYBE WE NEED TO DO IT AT A LATER POINT? BUT WE WANT MOST LOGIC / PROCEEDIGN TO STOP HERE ALREADY
// SSL_shutdown(ssl);
// close(sock);
}

if (data->cb)
data->cb(sock);
/* Call TLS binds. We allow scripts to take over or disable displaying of
Expand All @@ -778,9 +807,11 @@ static void ssl_info(const SSL *ssl, int where, int ret)
putlog(data->loglevel, "*", "TLS: handshake successful. Secure connection "
"established.");

if ((cert = SSL_get_peer_certificate(ssl))) {
if (cert) {
ssl_showcert(cert, LOG_DEBUG);
#if OPENSSL_VERSION_NUMBER < 0x30000000L
X509_free(cert);
#endif
}
else
putlog(data->loglevel, "*", "TLS: peer did not present a certificate");
Expand Down
Loading