diff --git a/doc/example.conf b/doc/example.conf index 8d2359b..e7fd1ca 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -347,6 +347,8 @@ connect "irc.uplink.com" { class = "server"; flags = compressed, topicburst; + #fingerprint = "c77106576abf7f9f90cca0f63874a60f2e40a64b"; + /* If the connection is IPv6, uncomment below. * Use 0::1, not ::1, for IPv6 localhost. */ #aftype = ipv6; diff --git a/doc/reference.conf b/doc/reference.conf index 539ee69..5d0d7d6 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -584,6 +584,12 @@ connect "irc.uplink.com" { send_password = "password"; accept_password = "anotherpassword"; + /* fingerprint: if specified, the server's client certificate + * fingerprint will be checked against the specified fingerprint + * below. + */ + #fingerprint = "c77106576abf7f9f90cca0f63874a60f2e40a64b"; + /* port: the port to connect to this server on */ port = 6666; diff --git a/include/s_newconf.h b/include/s_newconf.h index 1bf40cb..dde364d 100644 --- a/include/s_newconf.h +++ b/include/s_newconf.h @@ -187,6 +187,7 @@ struct server_conf char *host; char *passwd; char *spasswd; + char *certfp; int port; int flags; int servers; diff --git a/modules/core/m_server.c b/modules/core/m_server.c index c12f948..85ce154 100644 --- a/modules/core/m_server.c +++ b/modules/core/m_server.c @@ -150,14 +150,14 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char case -2: sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL, "Unauthorised server connection attempt from %s: " - "Bad password for server %s", + "Bad credentials for server %s", "[@255.255.255.255]", name); - ilog(L_SERVER, "Access denied, invalid password for server %s%s", + ilog(L_SERVER, "Access denied, invalid credentials for server %s%s", EmptyString(client_p->name) ? name : "", log_client_name(client_p, SHOW_IP)); - exit_client(client_p, client_p, client_p, "Invalid password."); + exit_client(client_p, client_p, client_p, "Invalid credentials."); return 0; /* NOT REACHED */ break; diff --git a/src/newconf.c b/src/newconf.c index 597dedb..65e28f8 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -1309,9 +1309,9 @@ conf_end_connect(struct TopConf *tc) return 0; } - if(EmptyString(yy_server->passwd) || EmptyString(yy_server->spasswd)) + if((EmptyString(yy_server->passwd) || EmptyString(yy_server->spasswd)) && EmptyString(yy_server->certfp)) { - conf_report_error("Ignoring connect block for %s -- missing password.", + conf_report_error("Ignoring connect block for %s -- no certfp or password credentials provided.", yy_server->name); return 0; } @@ -1383,6 +1383,15 @@ conf_set_connect_accept_password(void *data) yy_server->passwd = rb_strdup(data); } +static void +conf_set_connect_fingerprint(void *data) +{ + yy_server->certfp = rb_strdup((char *) data); + + /* force SSL to be enabled if fingerprint is enabled. */ + yy_server->flags |= SERVER_SSL; +} + static void conf_set_connect_port(void *data) { @@ -2164,6 +2173,7 @@ static struct ConfEntry conf_connect_table[] = { { "send_password", CF_QSTRING, conf_set_connect_send_password, 0, NULL }, { "accept_password", CF_QSTRING, conf_set_connect_accept_password, 0, NULL }, + { "fingerprint", CF_QSTRING, conf_set_connect_fingerprint, 0, NULL }, { "flags", CF_STRING | CF_FLIST, conf_set_connect_flags, 0, NULL }, { "host", CF_QSTRING, conf_set_connect_host, 0, NULL }, { "vhost", CF_QSTRING, conf_set_connect_vhost, 0, NULL }, diff --git a/src/s_serv.c b/src/s_serv.c index 5f272b0..79a318c 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -320,20 +320,31 @@ check_server(const char *name, struct Client *client_p) { error = -2; - if(ServerConfEncrypted(tmp_p)) + if(tmp_p->passwd) { - if(!strcmp(tmp_p->passwd, rb_crypt(client_p->localClient->passwd, - tmp_p->passwd))) + if(ServerConfEncrypted(tmp_p)) { - server_p = tmp_p; - break; + if(!strcmp(tmp_p->passwd, rb_crypt(client_p->localClient->passwd, + tmp_p->passwd))) + { + server_p = tmp_p; + break; + } + else + continue; } + else if(strcmp(tmp_p->passwd, client_p->localClient->passwd)) + continue; } - else if(!strcmp(tmp_p->passwd, client_p->localClient->passwd)) + + if(tmp_p->certfp) { - server_p = tmp_p; - break; + if(!client_p->certfp || strcasecmp(tmp_p->certfp, client_p->certfp) != 0) + continue; } + + server_p = tmp_p; + break; } } @@ -781,15 +792,9 @@ server_estab(struct Client *client_p) if(IsUnknown(client_p)) { - /* - * jdc -- 1. Use EmptyString(), not [0] index reference. - * 2. Check ->spasswd, not ->passwd. - */ - if(!EmptyString(server_p->spasswd)) - { - sendto_one(client_p, "PASS %s TS %d :%s", - server_p->spasswd, TS_CURRENT, me.id); - } + /* the server may be linking based on certificate fingerprint now. --nenolod */ + sendto_one(client_p, "PASS %s TS %d :%s", + EmptyString(server_p->spasswd) ? "*" : server_p->spasswd, TS_CURRENT, me.id); /* pass info to new server */ send_capabilities(client_p, default_server_capabs @@ -1350,11 +1355,9 @@ serv_connect_callback(rb_fde_t *F, int status, void *data) /* Next, send the initial handshake */ SetHandshake(client_p); - if(!EmptyString(server_p->spasswd)) - { - sendto_one(client_p, "PASS %s TS %d :%s", - server_p->spasswd, TS_CURRENT, me.id); - } + /* the server may be linking based on certificate fingerprint now. --nenolod */ + sendto_one(client_p, "PASS %s TS %d :%s", + EmptyString(server_p->spasswd) ? "*" : server_p->spasswd, TS_CURRENT, me.id); /* pass my info to the new server */ send_capabilities(client_p, default_server_capabs