summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/hostmask.h5
-rw-r--r--modules/m_dline.c2
-rw-r--r--modules/m_gline.c2
-rw-r--r--modules/m_kline.c4
-rw-r--r--modules/m_oper.c3
-rw-r--r--modules/m_stats.c18
-rw-r--r--modules/m_webirc.c3
-rw-r--r--src/client.c4
-rw-r--r--src/conf.c6
-rw-r--r--src/conf_parser.y33
-rw-r--r--src/hostmask.c20
-rw-r--r--src/s_bsd.c2
-rw-r--r--src/s_gline.c2
-rw-r--r--src/s_serv.c6
-rw-r--r--src/s_user.c4
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;
diff --git a/src/conf.c b/src/conf.c
index ca93b9e..8c459d7 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -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