summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2021-03-27 12:51:44 +0100
committerYorhel <git@yorhel.nl>2021-03-27 12:51:44 +0100
commit6adb56aaa7636cc29e72cdf0c209394b6f1bca2f (patch)
treea6200eebf6eb52d000b20718a43ce969c10e4dd6
parent9764c08be968b59f60541314a6994f6ac390529e (diff)
Add tls_policy=force option
-rw-r--r--src/cc.c14
-rw-r--r--src/doc.h11
-rw-r--r--src/hub.c26
-rw-r--r--src/vars.c2
4 files changed, 40 insertions, 13 deletions
diff --git a/src/cc.c b/src/cc.c
index 4af08b8..79f7490 100644
--- a/src/cc.c
+++ b/src/cc.c
@@ -828,6 +828,20 @@ static void handle_id(cc_t *cc, hub_user_t *u) {
return;
}
+ // Because tls_policy is a hub-local setting, we can only verify TLS settings
+ // for incoming connections once we know from which hub this connection came.
+ // The check is perhaps a bit late, but better disconnect late than never.
+ if(cc->tls && var_get_int(cc->hub->id, VAR_tls_policy) == VAR_TLSP_DISABLE) {
+ g_set_error_literal(&(cc->err), 1, 0, "TLS connection");
+ cc_disconnect(cc, FALSE);
+ return;
+ }
+ if(!cc->tls && var_get_int(cc->hub->id, VAR_tls_policy) == VAR_TLSP_FORCE) {
+ g_set_error_literal(&(cc->err), 1, 0, "non-TLS connection");
+ cc_disconnect(cc, FALSE);
+ return;
+ }
+
cc->slot_granted = db_users_get(u->hub->id, u->name) & DB_USERFLAG_GRANT ? TRUE : FALSE;
}
diff --git a/src/doc.h b/src/doc.h
index 0427ba3..9ba60ae 100644
--- a/src/doc.h
+++ b/src/doc.h
@@ -591,18 +591,17 @@ static const doc_set_t doc_sets[] = {
" note that, even if you set this to `prefer', encryption is still only used"
" when the client on the other side of the connection also supports it."
},
-{ "tls_policy", 1, "<disabled|allow|prefer>",
+{ "tls_policy", 1, "<disabled|allow|prefer|force>",
"Set the policy for secure client-to-client connections. Setting this to"
" `disabled' disables TLS support for client connections, but still allows"
" you to connect to TLS-enabled hubs. `allow' will allow the use of TLS if"
" the other client requests this, but ncdc itself will not request TLS when"
- " connecting to others. Setting this to `prefer' tells ncdc to also request"
- " TLS when connecting to others.\n\n"
+ " connecting to others, `prefer' tells ncdc to request TLS when connecting to"
+ " others. Setting this to 'force' will disallow non-TLS connections and also"
+ " requires that the hub connection itself is TLS.\n\n"
"The use of TLS for client connections usually results in less optimal"
" performance when uploading and downloading, but is quite effective at"
- " avoiding protocol-specific traffic shaping that some ISPs may do. Also note"
- " that, even if you set this to `prefer', TLS will only be used if the"
- " connecting party also supports it."
+ " avoiding protocol-specific traffic shaping that some ISPs may do."
},
{ "tls_priority", 0, "<string>",
"Set the GnuTLS priority string used for all TLS-enabled connections. See the"
diff --git a/src/hub.c b/src/hub.c
index a31973d..ba3c38e 100644
--- a/src/hub.c
+++ b/src/hub.c
@@ -567,9 +567,9 @@ void hub_opencc(hub_t *hub, hub_user_t *u) {
base32_encode_dat(nonce, token, 8);
}
- guint16 wanttls = var_get_int(hub->id, VAR_tls_policy) == VAR_TLSP_PREFER;
+ int tlspolicy = var_get_int(hub->id, VAR_tls_policy);
int port = listen_hub_tcp(hub->id);
- gboolean usetls = wanttls && u->hastls;
+ gboolean usetls = tlspolicy == VAR_TLSP_FORCE || (tlspolicy == VAR_TLSP_PREFER && u->hastls);
char *adcproto = !usetls ? "ADC/1.0" : u->hasadc0 ? "ADCS/0.10" : "ADCS/1.0";
// we're active, send CTM
@@ -1059,7 +1059,7 @@ static void adc_sch(hub_t *hub, adc_cmd_t *cmd) {
// Many ways to say the same thing
#define is_adcs_proto(p) (strcmp(p, "ADCS/1.0") == 0 || strcmp(p, "ADCS/0.10") == 0 || strcmp(p, "ADC0/0.10") == 0)
#define is_adc_proto(p) (strcmp(p, "ADC/1.0") == 0 || strcmp(p, "ADC/0.10") == 0)
-#define is_valid_proto(p) (is_adc_proto(p) || is_adcs_proto(p))
+#define is_valid_proto(pol, p) ((pol) == VAR_TLSP_DISABLE ? is_adc_proto(p) : (pol) == VAR_TLSP_FORCE ? is_adcs_proto(p) : is_adc_proto(p) || is_adcs_proto(p))
static void adc_handle(net_t *net, char *msg, int _len) {
hub_t *hub = net_handle(net);
@@ -1197,7 +1197,7 @@ static void adc_handle(net_t *net, char *msg, int _len) {
case ADCC_CTM:
if(cmd.argc < 3 || cmd.type != 'D' || cmd.dest != hub->sid)
g_message("Invalid message from %s: %s", net_remoteaddr(hub->net), msg);
- else if(var_get_int(hub->id, VAR_tls_policy) == VAR_TLSP_DISABLE ? !is_adc_proto(cmd.argv[0]) : !is_valid_proto(cmd.argv[0])) {
+ else if(!is_valid_proto(var_get_int(hub->id, VAR_tls_policy), cmd.argv[0])) {
GString *r = adc_generate('D', ADCC_STA, hub->sid, cmd.source);
g_string_append(r, " 141 Unknown\\sprotocol");
adc_append(r, "PR", cmd.argv[0]);
@@ -1226,7 +1226,7 @@ static void adc_handle(net_t *net, char *msg, int _len) {
case ADCC_RCM:
if(cmd.argc < 2 || cmd.type != 'D' || cmd.dest != hub->sid)
g_message("Invalid message from %s: %s", net_remoteaddr(hub->net), msg);
- else if(var_get_int(hub->id, VAR_tls_policy) == VAR_TLSP_DISABLE ? !is_adc_proto(cmd.argv[0]) : !is_valid_proto(cmd.argv[0])) {
+ else if(!is_valid_proto(var_get_int(hub->id, VAR_tls_policy), cmd.argv[0])) {
GString *r = adc_generate('D', ADCC_STA, hub->sid, cmd.source);
g_string_append(r, " 141 Unknown\\protocol");
adc_append(r, "PR", cmd.argv[0]);
@@ -1686,6 +1686,10 @@ static void nmdc_handle(net_t *net, char *cmd, int _len) {
if(yuri_parse(addr, &uri) != 0 || *uri.scheme || uri.port == 0 ||
uri.hosttype == YURI_DOMAIN || *uri.path || *uri.query || *uri.fragment)
g_message("Invalid host:port in $ConnectToMe (%s)", addr);
+ else if(*tls && var_get_int(hub->id, VAR_tls_policy) == VAR_TLSP_DISABLE)
+ g_message("$ConnectToMe from (%s) requires TLS, but TLS has been disabled in our tls_policy", addr);
+ else if(!*tls && var_get_int(hub->id, VAR_tls_policy) == VAR_TLSP_FORCE)
+ g_message("$ConnectToMe from (%s) without TLS, but TLS is required according to our tls_policy", addr);
else
cc_nmdc_connect(cc_create(hub), uri.host, uri.port, var_get(hub->id, VAR_local_address), *tls ? TRUE : FALSE);
}
@@ -1704,11 +1708,13 @@ static void nmdc_handle(net_t *net, char *cmd, int _len) {
g_message("Received a $RevConnectToMe for someone else (to %s from %s)", me, other);
else if(!u)
g_message("Received a $RevConnectToMe from someone not on the hub.");
+ else if(!u->hastls && var_get_int(hub->id, VAR_tls_policy) == VAR_TLSP_FORCE)
+ g_message("Received a $RevConnectToMe from client that does not support TLS.");
else if(listen_hub_active(hub->id)) {
// Unlike with ADC, the client sending the $RCTM can not indicate it
// wants to use TLS or not, so the decision is with us. Let's require
- // tls_policy to be PREFER here.
- int usetls = u->hastls && var_get_int(hub->id, VAR_tls_policy) == VAR_TLSP_PREFER;
+ // tls_policy to be PREFER or FORCE here.
+ int usetls = u->hastls && (var_get_int(hub->id, VAR_tls_policy) & (VAR_TLSP_PREFER|VAR_TLSP_FORCE));
int port = listen_hub_tcp(hub->id);
net_writef(hub->net, net_is_ipv6(hub->net) ? "$ConnectToMe %s [%s]:%d%s|" : "$ConnectToMe %s %s:%d%s|",
other, hub_ip(hub), port, usetls ? "S" : "");
@@ -1953,6 +1959,12 @@ void hub_connect(hub_t *hub) {
hub->adc = strncmp(addr.scheme, "adc", 3) == 0;
hub->tls = strcmp(addr.scheme, "adcs") == 0 || strcmp(addr.scheme, "nmdcs") == 0;
+ if(!hub->tls && var_get_int(hub->id, VAR_tls_policy) == VAR_TLSP_FORCE) {
+ ui_mf(hub->tab, 0, "Refusing to connect to %s; tls_priority is set to 'force' but this is not a TLS address.", oaddr);
+ free(addr.buf);
+ return;
+ }
+
if(hub->reconnect_timer) {
g_source_remove(hub->reconnect_timer);
hub->reconnect_timer = 0;
diff --git a/src/vars.c b/src/vars.c
index 1c8ac0c..910331d 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -742,12 +742,14 @@ static char *p_sendfile(const char *val, GError **err) {
#define VAR_TLSP_DISABLE 1
#define VAR_TLSP_ALLOW 2
#define VAR_TLSP_PREFER 4
+#define VAR_TLSP_FORCE 8
#endif
static flag_option_t var_tls_policy_ops[] = {
{ VAR_TLSP_DISABLE, "disabled" },
{ VAR_TLSP_ALLOW, "allow" },
{ VAR_TLSP_PREFER, "prefer" },
+ { VAR_TLSP_FORCE, "force" },
{ 0 }
};