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 6ec1ddabff
commit 5ac470475d
6 changed files with 49 additions and 27 deletions

View File

@ -347,6 +347,8 @@ connect "irc.uplink.com" {
class = "server"; class = "server";
flags = compressed, topicburst; flags = compressed, topicburst;
#fingerprint = "c77106576abf7f9f90cca0f63874a60f2e40a64b";
/* If the connection is IPv6, uncomment below. /* If the connection is IPv6, uncomment below.
* Use 0::1, not ::1, for IPv6 localhost. */ * Use 0::1, not ::1, for IPv6 localhost. */
#aftype = ipv6; #aftype = ipv6;

View File

@ -584,6 +584,12 @@ connect "irc.uplink.com" {
send_password = "password"; send_password = "password";
accept_password = "anotherpassword"; 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: the port to connect to this server on */
port = 6666; port = 6666;

View File

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

View File

@ -150,14 +150,14 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char
case -2: case -2:
sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL, sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL,
"Unauthorised server connection attempt from %s: " "Unauthorised server connection attempt from %s: "
"Bad password for server %s", "Bad credentials for server %s",
"[@255.255.255.255]", name); "[@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 : "", EmptyString(client_p->name) ? name : "",
log_client_name(client_p, SHOW_IP)); 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; return 0;
/* NOT REACHED */ /* NOT REACHED */
break; break;

View File

@ -1309,9 +1309,9 @@ conf_end_connect(struct TopConf *tc)
return 0; 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); yy_server->name);
return 0; return 0;
} }
@ -1383,6 +1383,15 @@ conf_set_connect_accept_password(void *data)
yy_server->passwd = rb_strdup(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 static void
conf_set_connect_port(void *data) 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 }, { "send_password", CF_QSTRING, conf_set_connect_send_password, 0, NULL },
{ "accept_password", CF_QSTRING, conf_set_connect_accept_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 }, { "flags", CF_STRING | CF_FLIST, conf_set_connect_flags, 0, NULL },
{ "host", CF_QSTRING, conf_set_connect_host, 0, NULL }, { "host", CF_QSTRING, conf_set_connect_host, 0, NULL },
{ "vhost", CF_QSTRING, conf_set_connect_vhost, 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; error = -2;
if(ServerConfEncrypted(tmp_p)) if(tmp_p->passwd)
{ {
if(!strcmp(tmp_p->passwd, rb_crypt(client_p->localClient->passwd, if(ServerConfEncrypted(tmp_p))
tmp_p->passwd)))
{ {
server_p = tmp_p; if(!strcmp(tmp_p->passwd, rb_crypt(client_p->localClient->passwd,
break; 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; if(!client_p->certfp || strcasecmp(tmp_p->certfp, client_p->certfp) != 0)
break; continue;
} }
server_p = tmp_p;
break;
} }
} }
@ -781,15 +792,9 @@ server_estab(struct Client *client_p)
if(IsUnknown(client_p)) if(IsUnknown(client_p))
{ {
/* /* the server may be linking based on certificate fingerprint now. --nenolod */
* jdc -- 1. Use EmptyString(), not [0] index reference. sendto_one(client_p, "PASS %s TS %d :%s",
* 2. Check ->spasswd, not ->passwd. EmptyString(server_p->spasswd) ? "*" : server_p->spasswd, TS_CURRENT, me.id);
*/
if(!EmptyString(server_p->spasswd))
{
sendto_one(client_p, "PASS %s TS %d :%s",
server_p->spasswd, TS_CURRENT, me.id);
}
/* pass info to new server */ /* pass info to new server */
send_capabilities(client_p, default_server_capabs 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 */ /* Next, send the initial handshake */
SetHandshake(client_p); SetHandshake(client_p);
if(!EmptyString(server_p->spasswd)) /* the server may be linking based on certificate fingerprint now. --nenolod */
{ sendto_one(client_p, "PASS %s TS %d :%s",
sendto_one(client_p, "PASS %s TS %d :%s", EmptyString(server_p->spasswd) ? "*" : server_p->spasswd, TS_CURRENT, me.id);
server_p->spasswd, TS_CURRENT, me.id);
}
/* pass my info to the new server */ /* pass my info to the new server */
send_capabilities(client_p, default_server_capabs send_capabilities(client_p, default_server_capabs