diff options
author | Yorhel <git@yorhel.nl> | 2021-03-27 12:51:44 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2021-03-27 12:51:44 +0100 |
commit | 6adb56aaa7636cc29e72cdf0c209394b6f1bca2f (patch) | |
tree | a6200eebf6eb52d000b20718a43ce969c10e4dd6 | |
parent | 9764c08be968b59f60541314a6994f6ac390529e (diff) |
Add tls_policy=force option
-rw-r--r-- | src/cc.c | 14 | ||||
-rw-r--r-- | src/doc.h | 11 | ||||
-rw-r--r-- | src/hub.c | 26 | ||||
-rw-r--r-- | src/vars.c | 2 |
4 files changed, 40 insertions, 13 deletions
@@ -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; } @@ -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" @@ -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; @@ -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 } }; |