diff options
-rw-r--r-- | include/hostmask.h | 5 | ||||
-rw-r--r-- | modules/m_dline.c | 2 | ||||
-rw-r--r-- | modules/m_gline.c | 2 | ||||
-rw-r--r-- | modules/m_kline.c | 4 | ||||
-rw-r--r-- | modules/m_oper.c | 3 | ||||
-rw-r--r-- | modules/m_stats.c | 18 | ||||
-rw-r--r-- | modules/m_webirc.c | 3 | ||||
-rw-r--r-- | src/client.c | 4 | ||||
-rw-r--r-- | src/conf.c | 6 | ||||
-rw-r--r-- | src/conf_parser.y | 33 | ||||
-rw-r--r-- | src/hostmask.c | 20 | ||||
-rw-r--r-- | src/s_bsd.c | 2 | ||||
-rw-r--r-- | src/s_gline.c | 2 | ||||
-rw-r--r-- | src/s_serv.c | 6 | ||||
-rw-r--r-- | src/s_user.c | 4 |
15 files changed, 81 insertions, 33 deletions
diff --git a/include/hostmask.h b/include/hostmask.h index d1a23be..2ee62a3 100644 --- a/include/hostmask.h +++ b/include/hostmask.h @@ -80,8 +80,9 @@ extern void clear_out_address_conf(void); extern void hostmask_expire_temporary(void); extern struct MaskItem *find_address_conf(const char *, const char *, - struct irc_ssaddr *, int, char *); + struct irc_ssaddr *, int, char *, const char *); extern struct MaskItem *find_dline_conf(struct irc_ssaddr *, int); extern struct MaskItem *find_conf_by_address(const char *, struct irc_ssaddr *, - unsigned int, int, const char *, const char *, int); + unsigned int, int, const char *, const char *, int, + const char *); #endif /* INCLUDE_hostmask_h */ diff --git a/modules/m_dline.c b/modules/m_dline.c index 5667d44..2a5a281 100644 --- a/modules/m_dline.c +++ b/modules/m_dline.c @@ -114,7 +114,7 @@ remove_dline_match(const char *host) else piphost = NULL; - if ((conf = find_conf_by_address(host, piphost, CONF_DLINE, aftype, NULL, NULL, 0))) + if ((conf = find_conf_by_address(host, piphost, CONF_DLINE, aftype, NULL, NULL, 0, NULL))) { if (IsConfDatabase(conf)) { diff --git a/modules/m_gline.c b/modules/m_gline.c index b429351..2068dc6 100644 --- a/modules/m_gline.c +++ b/modules/m_gline.c @@ -144,7 +144,7 @@ remove_gline_match(const char *user, const char *host) else piphost = NULL; - if ((conf = find_conf_by_address(host, piphost, CONF_GLINE, aftype, user, NULL, 0))) + if ((conf = find_conf_by_address(host, piphost, CONF_GLINE, aftype, user, NULL, 0, NULL))) { if (IsConfDatabase(conf)) { diff --git a/modules/m_kline.c b/modules/m_kline.c index 10b23c0..4a00dda 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -152,7 +152,7 @@ remove_kline_match(const char *host, const char *user) else piphost = NULL; - if ((conf = find_conf_by_address(host, piphost, CONF_KLINE, aftype, user, NULL, 0))) + if ((conf = find_conf_by_address(host, piphost, CONF_KLINE, aftype, user, NULL, 0, NULL))) { if (IsConfDatabase(conf)) { @@ -196,7 +196,7 @@ already_placed_kline(struct Client *source_p, const char *luser, const char *lho else piphost = NULL; - if ((conf = find_conf_by_address(lhost, piphost, CONF_KLINE, aftype, luser, NULL, 0))) + if ((conf = find_conf_by_address(lhost, piphost, CONF_KLINE, aftype, luser, NULL, 0, NULL))) { if (warn) { diff --git a/modules/m_oper.c b/modules/m_oper.c index 24a8dac..a12a7e9 100644 --- a/modules/m_oper.c +++ b/modules/m_oper.c @@ -114,7 +114,8 @@ m_oper(struct Client *client_p, struct Client *source_p, } } - if (match_conf_password(password, conf)) + /* If we have valid certfp, don't check password */ + if (!EmptyString(conf->certfp) || match_conf_password(password, conf)) { if (attach_conf(source_p, conf) != 0) { diff --git a/modules/m_stats.c b/modules/m_stats.c index 023251c..0a760c5 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -943,10 +943,12 @@ stats_auth(struct Client *source_p, int parc, char *parv[]) &source_p->localClient->ip, CONF_CLIENT, source_p->localClient->aftype, source_p->username, - source_p->localClient->passwd, 1); + source_p->localClient->passwd, 1, + source_p->certfp); else conf = find_conf_by_address(source_p->host, NULL, CONF_CLIENT, - 0, source_p->username, NULL, 1); + 0, source_p->username, NULL, 1, + source_p->certfp); if (conf == NULL) return; @@ -1025,10 +1027,12 @@ stats_tklines(struct Client *source_p, int parc, char *parv[]) conf = find_conf_by_address(source_p->host, &source_p->localClient->ip, CONF_KLINE, source_p->localClient->aftype, - source_p->username, NULL, 1); + source_p->username, NULL, 1, + source_p->certfp); else conf = find_conf_by_address(source_p->host, NULL, CONF_KLINE, - 0, source_p->username, NULL, 1); + 0, source_p->username, NULL, 1, + source_p->certfp); if (!conf) return; @@ -1064,10 +1068,12 @@ stats_klines(struct Client *source_p, int parc, char *parv[]) conf = find_conf_by_address(source_p->host, &source_p->localClient->ip, CONF_KLINE, source_p->localClient->aftype, - source_p->username, NULL, 0); + source_p->username, NULL, 0, + source_p->certfp); else conf = find_conf_by_address(source_p->host, NULL, CONF_KLINE, - 0, source_p->username, NULL, 0); + 0, source_p->username, NULL, 0, + source_p->certfp); if (!conf) return; diff --git a/modules/m_webirc.c b/modules/m_webirc.c index 8a53b6b..635c521 100644 --- a/modules/m_webirc.c +++ b/modules/m_webirc.c @@ -63,7 +63,8 @@ mr_webirc(struct Client *client_p, struct Client *source_p, int parc, char *parv conf = find_address_conf(source_p->host, IsGotId(source_p) ? source_p->username : "webirc", &source_p->localClient->ip, - source_p->localClient->aftype, parv[1]); + source_p->localClient->aftype, parv[1], + source_p->certfp); if (conf == NULL || !IsConfClient(conf)) return 0; diff --git a/src/client.c b/src/client.c index cb18488..64e9f3a 100644 --- a/src/client.c +++ b/src/client.c @@ -368,7 +368,7 @@ check_conf_klines(void) { if ((conf = find_conf_by_address(client_p->host, &client_p->localClient->ip, CONF_GLINE, client_p->localClient->aftype, - client_p->username, NULL, 1))) + client_p->username, NULL, 1, client_p->certfp))) { conf_try_ban(client_p, conf); /* and go examine next fd/client_p */ @@ -378,7 +378,7 @@ check_conf_klines(void) if ((conf = find_conf_by_address(client_p->host, &client_p->localClient->ip, CONF_KLINE, client_p->localClient->aftype, - client_p->username, NULL, 1))) + client_p->username, NULL, 1, client_p->certfp))) { conf_try_ban(client_p, conf); continue; @@ -325,7 +325,8 @@ verify_access(struct Client *client_p) conf = find_address_conf(client_p->host, client_p->username, &client_p->localClient->ip, client_p->localClient->aftype, - client_p->localClient->passwd); + client_p->localClient->passwd, + client_p->certfp); } else { @@ -333,7 +334,8 @@ verify_access(struct Client *client_p) conf = find_address_conf(client_p->host,non_ident, &client_p->localClient->ip, client_p->localClient->aftype, - client_p->localClient->passwd); + client_p->localClient->passwd, + client_p->certfp); } if (conf != NULL) diff --git a/src/conf_parser.y b/src/conf_parser.y index 0a71741..e91f79d 100644 --- a/src/conf_parser.y +++ b/src/conf_parser.y @@ -1693,6 +1693,8 @@ auth_entry: IRCD_AUTH conf->passwd = xstrdup(block_state.rpass.buf); if (block_state.name.buf[0]) conf->name = xstrdup(block_state.name.buf); + if (block_state.cert.buf[0]) + conf->certfp = xstrdup(block_state.cert.buf); conf->flags = block_state.flags.value; conf->port = block_state.port.value; @@ -1705,6 +1707,7 @@ auth_entry: IRCD_AUTH auth_items: auth_items auth_item | auth_item; auth_item: auth_user | auth_passwd | auth_class | auth_flags | auth_spoof | auth_redir_serv | auth_redir_port | + auth_ssl_certificate_fingerprint | auth_encrypted | error ';' ; auth_user: USER '=' QSTRING ';' @@ -1719,6 +1722,12 @@ auth_passwd: PASSWORD '=' QSTRING ';' strlcpy(block_state.rpass.buf, yylval.string, sizeof(block_state.rpass.buf)); }; +auth_ssl_certificate_fingerprint: SSL_CERTIFICATE_FINGERPRINT '=' QSTRING ';' +{ + if (conf_parser_ctx.pass == 2) + strlcpy(block_state.cert.buf, yylval.string, sizeof(block_state.cert.buf)); +} + auth_class: CLASS '=' QSTRING ';' { if (conf_parser_ctx.pass == 2) @@ -2089,8 +2098,9 @@ connect_entry: CONNECT !block_state.host.buf[0]) break; - if (!block_state.rpass.buf[0] || - !block_state.spass.buf[0]) + if ((!block_state.rpass.buf[0] || + !block_state.spass.buf[0]) && + !block_state.cert.buf[0]) break; if (has_wildcards(block_state.name.buf) || @@ -2104,7 +2114,10 @@ connect_entry: CONNECT conf->host = xstrdup(block_state.host.buf); conf->name = xstrdup(block_state.name.buf); conf->passwd = xstrdup(block_state.rpass.buf); - conf->spasswd = xstrdup(block_state.spass.buf); + if (!block_state.spass.buf[0]) + conf->spasswd = xstrdup("certificate_auth"); + else + conf->spasswd = xstrdup(block_state.spass.buf); if (block_state.cert.buf[0]) conf->certfp = xstrdup(block_state.cert.buf); @@ -2383,7 +2396,7 @@ deny_reason: REASON '=' QSTRING ';' exempt_entry: EXEMPT '{' exempt_items '}' ';'; exempt_items: exempt_items exempt_item | exempt_item; -exempt_item: exempt_ip | error; +exempt_item: exempt_ip | exempt_ssl_certificate_fingerprint | error; exempt_ip: IP '=' QSTRING ';' { @@ -2399,6 +2412,18 @@ exempt_ip: IP '=' QSTRING ';' } }; +exempt_ssl_certificate_fingerprint: SSL_CERTIFICATE_FINGERPRINT '=' QSTRING ';' +{ + if (conf_parser_ctx.pass == 2) + { + struct MaskItem *conf = conf_make(CONF_EXEMPT); + + conf->certfp = xstrdup(yylval.string); + conf->host = xstrdup(yylval.string); + add_conf_by_address(CONF_EXEMPT, conf); + } +} + /*************************************************************************** * section gecos ***************************************************************************/ diff --git a/src/hostmask.c b/src/hostmask.c index 5c34013..220b5c6 100644 --- a/src/hostmask.c +++ b/src/hostmask.c @@ -455,7 +455,8 @@ get_mask_hash(const char *text) */ struct MaskItem * find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int type, - int fam, const char *username, const char *password, int do_match) + int fam, const char *username, const char *password, int do_match, + const char *certfp) { unsigned int hprecv = 0; dlink_node *ptr = NULL; @@ -481,6 +482,7 @@ find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int typ arec->masktype == HM_IPV6 && match_ipv6(addr, &arec->Mask.ipa.addr, arec->Mask.ipa.bits) && + (!arec->conf->certfp || (certfp && !strcmp(arec->conf->certfp, certfp))) && (!username || !cmpfunc(arec->username, username)) && (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL || match_conf_password(password, arec->conf))) @@ -506,6 +508,7 @@ find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int typ arec->masktype == HM_IPV4 && match_ipv4(addr, &arec->Mask.ipa.addr, arec->Mask.ipa.bits) && + (!arec->conf->certfp || (certfp && !strcmp(arec->conf->certfp, certfp))) && (!username || !cmpfunc(arec->username, username)) && (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL || match_conf_password(password, arec->conf))) @@ -531,6 +534,7 @@ find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int typ arec->precedence > hprecv && (arec->masktype == HM_HOST) && !cmpfunc(arec->Mask.hostname, name) && + (!arec->conf->certfp || (certfp && !strcmp(arec->conf->certfp, certfp))) && (!username || !cmpfunc(arec->username, username)) && (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL || match_conf_password(password, arec->conf))) @@ -553,6 +557,7 @@ find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int typ arec->precedence > hprecv && arec->masktype == HM_HOST && !cmpfunc(arec->Mask.hostname, name) && + (!arec->conf->certfp || (certfp && !strcmp(arec->conf->certfp, certfp))) && (!username || !cmpfunc(arec->username, username)) && (IsNeedPassword(arec->conf) || arec->conf->passwd == NULL || match_conf_password(password, arec->conf))) @@ -574,13 +579,14 @@ find_conf_by_address(const char *name, struct irc_ssaddr *addr, unsigned int typ */ struct MaskItem * find_address_conf(const char *host, const char *user, - struct irc_ssaddr *ip, int aftype, char *password) + struct irc_ssaddr *ip, int aftype, char *password, + const char *certfp) { struct MaskItem *authcnf = NULL, *killcnf = NULL; /* Find the best auth{} block... If none, return NULL -A1kmm */ if ((authcnf = find_conf_by_address(host, ip, CONF_CLIENT, aftype, user, - password, 1)) == NULL) + password, 1, certfp)) == NULL) return NULL; /* If they are exempt from K-lines, return the best auth{} block. -A1kmm */ @@ -588,7 +594,7 @@ find_address_conf(const char *host, const char *user, return authcnf; /* Find the best K-line... -A1kmm */ - killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1); + killcnf = find_conf_by_address(host, ip, CONF_KLINE, aftype, user, NULL, 1, NULL); /* * If they are K-lined, return the K-line. Otherwise, return the @@ -600,7 +606,7 @@ find_address_conf(const char *host, const char *user, if (IsConfExemptGline(authcnf)) return authcnf; - killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1); + killcnf = find_conf_by_address(host, ip, CONF_GLINE, aftype, user, NULL, 1, NULL); if (killcnf != NULL) return killcnf; @@ -618,11 +624,11 @@ find_dline_conf(struct irc_ssaddr *addr, int aftype) { struct MaskItem *eline; - eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1); + eline = find_conf_by_address(NULL, addr, CONF_EXEMPT, aftype, NULL, NULL, 1, NULL); if (eline != NULL) return eline; - return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1); + return find_conf_by_address(NULL, addr, CONF_DLINE, aftype, NULL, NULL, 1, NULL); } /* void add_conf_by_address(int, struct MaskItem *aconf) diff --git a/src/s_bsd.c b/src/s_bsd.c index aee198c..a800fac 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -279,7 +279,7 @@ ssl_handshake(int fd, struct Client *client_p) { unsigned int i = 0, n = 0; - if (X509_digest(cert, EVP_sha256(), md, &n)) + if (X509_digest(cert, EVP_sha1(), md, &n)) { for (; i < n; ++i) snprintf(buf + 2 * i, 3, "%02X", md[i]); diff --git a/src/s_gline.c b/src/s_gline.c index 0d788b4..887bebf 100644 --- a/src/s_gline.c +++ b/src/s_gline.c @@ -62,7 +62,7 @@ find_is_glined(const char *host, const char *user) else piphost = NULL; - return find_conf_by_address(host, piphost, CONF_GLINE, aftype, user, NULL, 0); + return find_conf_by_address(host, piphost, CONF_GLINE, aftype, user, NULL, 0, NULL); } /* expire_pending_glines() diff --git a/src/s_serv.c b/src/s_serv.c index c516fd9..66919bb 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -398,7 +398,9 @@ check_server(const char *name, struct Client *client_p) { error = -2; - if (!match_conf_password(client_p->localClient->passwd, conf)) + /* If no password configured, accept any (use fingerprint) */ + if (!EmptyString(conf->passwd) && + !match_conf_password(client_p->localClient->passwd, conf)) return -2; if (!EmptyString(conf->certfp)) @@ -900,7 +902,7 @@ ssl_server_handshake(fde_t *fd, struct Client *client_p) { unsigned int i = 0, n = 0; - if (X509_digest(cert, EVP_sha256(), md, &n)) + if (X509_digest(cert, EVP_sha1(), md, &n)) { for (; i < n; ++i) snprintf(buf + 2 * i, 3, "%02X", md[i]); diff --git a/src/s_user.c b/src/s_user.c index 1017c05..be041cf 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -1181,6 +1181,10 @@ user_welcome(struct Client *source_p) sendto_one(source_p, ":%s NOTICE %s :*** Connected securely via %s", me.name, source_p->name, ssl_get_cipher(source_p->localClient->fd.ssl)); + if (!EmptyString(source_p->certfp)) + sendto_one(source_p, + ":%s NOTICE %s: *** Your client certificate fingerprint is %s", + me.name, source_p->name, source_p->certfp); } #endif |