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:
+19
-4
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user