1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-04 22:23:13 +02:00

Warn when SSL/TLS certificate is expired or expires soon (<7d).

Since an expired certificate usually means that users cannot connect
we will actively warn all IRCOps about this situation twice a day.
This commit is contained in:
Bram Matthys
2020-10-11 14:53:40 +02:00
parent 8619d1e763
commit 6778b3e26d
5 changed files with 119 additions and 18 deletions
+19 -4
View File
@@ -549,10 +549,6 @@ extern void *safe_alloc(size_t size);
extern char *our_strdup(const char *str);
extern char *our_strldup(const char *str, size_t max);
extern MODFUNC char *tls_get_cipher(SSL *ssl);
extern TLSOptions *get_tls_options_for_client(Client *acptr);
extern int outdated_tls_client(Client *acptr);
extern char *outdated_tls_client_build_string(char *pattern, Client *acptr);
extern long config_checkval(char *value, unsigned short flags);
extern void config_status(FORMAT_STRING(const char *format), ...) __attribute__((format(printf,1,2)));
extern void init_random();
@@ -753,6 +749,25 @@ extern MODVAR void (*labeled_response_force_end)(void);
extern MODVAR void (*kick_user)(MessageTag *mtags, Channel *channel, Client *client, Client *victim, char *comment);
/* /Efuncs */
/* SSL/TLS functions */
extern int early_init_ssl();
extern int init_ssl();
extern int ssl_handshake(Client *); /* Handshake the accpeted con.*/
extern int ssl_client_handshake(Client *, ConfigItem_link *); /* and the initiated con.*/
extern int ircd_SSL_accept(Client *acptr, int fd);
extern int ircd_SSL_connect(Client *acptr, int fd);
extern int SSL_smart_shutdown(SSL *ssl);
extern void ircd_SSL_client_handshake(int, int, void *);
extern void SSL_set_nonblocking(SSL *s);
extern SSL_CTX *init_ctx(TLSOptions *tlsoptions, int server);
extern MODFUNC char *tls_get_cipher(SSL *ssl);
extern TLSOptions *get_tls_options_for_client(Client *acptr);
extern int outdated_tls_client(Client *acptr);
extern char *outdated_tls_client_build_string(char *pattern, Client *acptr);
extern int check_certificate_expiry_ctx(SSL_CTX *ctx, char **errstr);
extern EVENT(tls_check_expiry);
/* End of SSL/TLS functions */
extern void parse_message_tags_default_handler(Client *client, char **str, MessageTag **mtag_list);
extern char *mtags_to_string_default_handler(MessageTag *m, Client *client);
extern void *labeled_response_save_context_default_handler(void);
-12
View File
@@ -2011,18 +2011,6 @@ extern MODVAR SSL_CTX *ctx;
extern MODVAR SSL_CTX *ctx_server;
extern MODVAR SSL_CTX *ctx_client;
extern SSL_METHOD *meth;
extern int early_init_ssl();
extern int init_ssl();
extern int ssl_handshake(Client *); /* Handshake the accpeted con.*/
extern int ssl_client_handshake(Client *, ConfigItem_link *); /* and the initiated con.*/
extern int ircd_SSL_accept(Client *acptr, int fd);
extern int ircd_SSL_connect(Client *acptr, int fd);
extern int SSL_smart_shutdown(SSL *ssl);
extern void ircd_SSL_client_handshake(int, int, void *);
extern void SSL_set_nonblocking(SSL *s);
extern SSL_CTX *init_ctx(TLSOptions *tlsoptions, int server);
#define TLS_PROTOCOL_TLSV1 0x0001
#define TLS_PROTOCOL_TLSV1_1 0x0002
#define TLS_PROTOCOL_TLSV1_2 0x0004
+1
View File
@@ -240,4 +240,5 @@ void SetupEvents(void)
EventAdd(NULL, "check_deadsockets", check_deadsockets, NULL, 1000, 0);
EventAdd(NULL, "handshake_timeout", handshake_timeout, NULL, 1000, 0);
EventAdd(NULL, "try_connections", try_connections, NULL, 2000, 0);
EventAdd(NULL, "tls_check_expiry", tls_check_expiry, NULL, 86400/2, 0);
}
+1
View File
@@ -1902,6 +1902,7 @@ void postconf(void)
postconf_fixes();
do_weird_shun_stuff();
isupport_init(); /* for all the 005 values that changed.. */
tls_check_expiry(NULL);
}
int isanyserverlinked(void)
+98 -2
View File
@@ -36,9 +36,10 @@ extern HWND hwIRCDWnd;
#define SAFE_SSL_ACCEPT 3
#define SAFE_SSL_CONNECT 4
/* Forward declarations */
static int fatal_ssl_error(int ssl_error, int where, int my_errno, Client *client);
extern int cipher_check(SSL_CTX *ctx, char **errstr);
extern int certificate_quality_check(SSL_CTX *ctx, char **errstr);
int cipher_check(SSL_CTX *ctx, char **errstr);
int certificate_quality_check(SSL_CTX *ctx, char **errstr);
/* The SSL structures */
SSL_CTX *ctx_server;
@@ -1040,6 +1041,8 @@ int verify_certificate(SSL *ssl, char *hostname, char **errstr)
if (SSL_get_verify_result(ssl) != X509_V_OK)
{
// FIXME: there are actually about 25+ different possible errors,
// this is only the most common one:
strlcpy(buf, "Certificate is not issued by a trusted Certificate Authority", sizeof(buf));
if (errstr)
*errstr = buf;
@@ -1333,3 +1336,96 @@ char *outdated_tls_client_build_string(char *pattern, Client *client)
buildvarstring(pattern, buf, sizeof(buf), name, value);
return buf;
}
int check_certificate_expiry_ctx(SSL_CTX *ctx, char **errstr)
{
static char errbuf[512];
SSL *ssl;
X509 *cert;
const ASN1_TIME *cert_expiry_time;
int days_expiry = 0, seconds_expiry = 0;
long duration;
*errstr = NULL;
ssl = SSL_new(ctx);
if (!ssl)
return 0;
cert = SSL_get_certificate(ssl);
if (!cert)
{
SSL_free(ssl);
return 0;
}
/* get certificate time */
cert_expiry_time = X509_get0_notAfter(cert);
/* calculate difference */
ASN1_TIME_diff(&days_expiry, &seconds_expiry, cert_expiry_time, NULL);
duration = (days_expiry * 86400) + seconds_expiry;
/* certificate expiry? */
if ((days_expiry > 0) || (seconds_expiry > 0))
{
snprintf(errbuf, sizeof(errbuf), "certificate expired %s ago", pretty_time_val(duration));
SSL_free(ssl);
*errstr = errbuf;
return 1;
} else
/* or near-expiry? */
if (((days_expiry < 0) || (seconds_expiry < 0)) && (days_expiry > -7))
{
snprintf(errbuf, sizeof(errbuf), "certificate will expire in %s", pretty_time_val(0 - duration));
SSL_free(ssl);
*errstr = errbuf;
return 1;
}
/* All good */
SSL_free(ssl);
return 0;
}
void check_certificate_expiry_tlsoptions_and_warn(TLSOptions *tlsoptions)
{
SSL_CTX *ctx;
int ret;
char *errstr = NULL;
ctx = init_ctx(tlsoptions, 1);
if (!ctx)
return;
if (check_certificate_expiry_ctx(ctx, &errstr))
{
sendto_umode_global(UMODE_OPER, "Warning: TLS certificate '%s': %s", tlsoptions->certificate_file, errstr);
ircd_log(LOG_ERROR, "[warning] TLS certificate '%s': %s", tlsoptions->certificate_file, errstr);
}
SSL_CTX_free(ctx);
}
EVENT(tls_check_expiry)
{
ConfigItem_listen *listen;
ConfigItem_sni *sni;
ConfigItem_link *link;
/* set block */
check_certificate_expiry_tlsoptions_and_warn(iConf.tls_options);
for (listen = conf_listen; listen; listen = listen->next)
if (listen->tls_options)
check_certificate_expiry_tlsoptions_and_warn(listen->tls_options);
/* sni::tls-options.... */
for (sni = conf_sni; sni; sni = sni->next)
if (sni->tls_options)
check_certificate_expiry_tlsoptions_and_warn(sni->tls_options);
/* link::outgoing::tls-options.... */
for (link = conf_link; link; link = link->next)
if (link->tls_options)
check_certificate_expiry_tlsoptions_and_warn(link->tls_options);
}