From ff31db8473bde2af86e2adae0c86448231d34765 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Wed, 17 Feb 2010 06:41:41 -0600 Subject: [PATCH] Add support for client certificate fingerprints in o:lines. --- doc/example.conf | 6 ++++++ doc/reference.conf | 6 ++++++ include/s_newconf.h | 1 + modules/m_oper.c | 19 +++++++++++++++++++ src/newconf.c | 7 +++++++ 5 files changed, 39 insertions(+) diff --git a/doc/example.conf b/doc/example.conf index b00a29f9..83016838 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -240,6 +240,12 @@ operator "god" { */ #umodes = locops, servnotice, operwall, wallop; + /* fingerprint: if specified, the oper's client certificate + * fingerprint will be checked against the specified fingerprint + * below. + */ + #fingerprint = "c77106576abf7f9f90cca0f63874a60f2e40a64b"; + /* snomask: specific server notice mask on oper up. * If this is specified an oper will not be given oper_snomask. */ diff --git a/doc/reference.conf b/doc/reference.conf index 53297d11..b9afb80d 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -441,6 +441,12 @@ operator "god" { */ #rsa_public_key_file = "/usr/local/ircd/etc/oper.pub"; + /* fingerprint: if specified, the oper's client certificate + * fingerprint will be checked against the specified fingerprint + * below. + */ + #fingerprint = "c77106576abf7f9f90cca0f63874a60f2e40a64b"; + /* umodes: the specific umodes this oper gets when they oper. * If this is specified an oper will not be given oper_umodes * These are described above oper_only_umodes in general {}; diff --git a/include/s_newconf.h b/include/s_newconf.h index bee3df7d..03e887d2 100644 --- a/include/s_newconf.h +++ b/include/s_newconf.h @@ -112,6 +112,7 @@ struct oper_conf char *username; char *host; char *passwd; + char *certfp; int flags; int umodes; diff --git a/modules/m_oper.c b/modules/m_oper.c index 061a9b71..fdaef300 100644 --- a/modules/m_oper.c +++ b/modules/m_oper.c @@ -115,6 +115,25 @@ m_oper(struct Client *client_p, struct Client *source_p, int parc, const char *p return 0; } + if (oper_p->certfp != NULL) + { + if (source_p->certfp == NULL || strcasecmp(source_p->certfp, oper_p->certfp)) + { + sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name); + ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s) -- client certificate fingerprint mismatch", + name, source_p->name, + source_p->username, source_p->host, source_p->sockhost); + + if(ConfigFileEntry.failed_oper_notice) + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Failed OPER attempt - client certificate fingerprint mismatch by %s (%s@%s)", + source_p->name, source_p->username, source_p->host); + } + return 0; + } + } + if(match_oper_password(password, oper_p)) { oper_up(source_p, oper_p); diff --git a/src/newconf.c b/src/newconf.c index 3cf15c6d..782ed1aa 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -615,6 +615,12 @@ conf_set_oper_flags(void *data) set_modes_from_table(&yy_oper->flags, "flag", oper_table, args); } +static void +conf_set_oper_fingerprint(void *data) +{ + yy_oper->certfp = rb_strdup((char *) data); +} + static void conf_set_oper_privset(void *data) { @@ -2039,6 +2045,7 @@ static struct ConfEntry conf_operator_table[] = { "snomask", CF_QSTRING, conf_set_oper_snomask, 0, NULL }, { "user", CF_QSTRING, conf_set_oper_user, 0, NULL }, { "password", CF_QSTRING, conf_set_oper_password, 0, NULL }, + { "fingerprint", CF_QSTRING, conf_set_oper_fingerprint, 0, NULL }, { "\0", 0, NULL, 0, NULL } };