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 6f69b6c..9521519 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 98342df..a8f0058 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 4705d33..193364d 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -942,10 +942,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; @@ -1024,10 +1026,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; @@ -1063,10 +1067,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; @@ -324,7 +324,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 { @@ -332,7 +333,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 9d4c28a..987962e 100644 --- a/src/conf_parser.y +++ b/src/conf_parser.y @@ -1700,6 +1700,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; @@ -1712,6 +1714,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 ';' @@ -1726,6 +1729,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) @@ -2096,8 +2105,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) || @@ -2111,7 +2121,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); @@ -2390,7 +2403,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 ';' { @@ -2406,6 +2419,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 5d29109..2fa8280 100644 --- a/src/hostmask.c +++ b/src/hostmask.c @@ -457,7 +457,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; @@ -483,6 +484,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))) @@ -508,6 +510,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))) @@ -533,6 +536,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))) @@ -555,6 +559,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))) @@ -576,13 +581,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 */ @@ -590,7 +596,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 @@ -602,7 +608,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; @@ -620,11 +626,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 99c516e..5aeaf30 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -278,7 +278,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 b47acd3..9e861a4 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -1179,6 +1179,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 |