Add support for linking using SSL certificate fingerprints as the link credential rather than the traditional server-password pair.

This commit is contained in:
William Pitcock 2010-12-13 23:14:00 -06:00
parent 07e14084eb
commit ff0cc1e616
6 changed files with 49 additions and 27 deletions

View file

@ -286,6 +286,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;

View file

@ -498,6 +498,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;

View file

@ -181,6 +181,7 @@ struct server_conf
char *host;
char *passwd;
char *spasswd;
char *certfp;
int port;
int flags;
int servers;

View file

@ -151,14 +151,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;

View file

@ -1242,9 +1242,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;
}
@ -1316,6 +1316,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)
{
@ -2090,6 +2099,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 },

View file

@ -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;
}
}
@ -761,15 +772,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
@ -1330,11 +1335,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