ssb: Add an option to control whether we talk to strangers. #98
Some checks failed
Build Tilde Friends / Build-All (push) Failing after 43m57s

This commit is contained in:
Cory McWilliams 2025-01-20 13:35:28 -05:00
parent aa04ad2dc2
commit fca5d37b7e
3 changed files with 86 additions and 4 deletions

View File

@ -245,6 +245,7 @@ typedef struct _tf_ssb_t
bool is_room;
bool is_replicator;
bool is_peer_exchange;
bool talk_to_strangers;
char* room_name;
char seeds_host[256];
time_t last_seed_check;
@ -278,6 +279,8 @@ typedef struct _tf_ssb_connection_t
uv_timer_t linger_timer;
uv_timer_t activity_timer;
bool is_closing;
bool is_pending_stranger_check;
bool is_stranger;
tf_ssb_connection_t* tunnel_connection;
int32_t tunnel_request_number;
@ -374,6 +377,8 @@ static void _tf_ssb_start_update_settings(tf_ssb_t* ssb);
static void _tf_ssb_update_settings(tf_ssb_t* ssb);
static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t size);
static void _tf_ssb_connection_dispatch_scheduled(tf_ssb_connection_t* connection);
static bool _tf_ssb_connection_read_start(tf_ssb_connection_t* connection);
static bool _tf_ssb_connection_read_stop(tf_ssb_connection_t* connection);
static const char* _tf_ssb_connection_state_to_string(tf_ssb_state_t state)
{
@ -1418,6 +1423,52 @@ static bool _tf_ssb_is_already_connected(tf_ssb_t* ssb, uint8_t* id, tf_ssb_conn
return false;
}
static void _tf_ssb_connection_is_account_a_stranger_work(tf_ssb_connection_t* connection, void* user_data)
{
tf_ssb_t* ssb = connection->ssb;
char id[k_id_base64_len] = { 0 };
tf_ssb_id_bin_to_str(id, sizeof(id), connection->serverpub);
if (tf_ssb_db_get_latest_message_by_author(ssb, id, NULL, NULL, 0))
{
connection->is_stranger = false;
}
else
{
int64_t replication_hops = 2;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
tf_ssb_db_get_global_setting_int64(db, "replication_hops", &replication_hops);
tf_ssb_release_db_reader(ssb, db);
const char** identities = tf_ssb_db_get_all_visible_identities(ssb, replication_hops);
for (int i = 0; identities[i]; i++)
{
if (strcmp(id, identities[i]) == 0)
{
connection->is_stranger = false;
break;
}
}
tf_free((void*)identities);
}
}
static void _tf_ssb_connection_is_account_a_stranger_after_work(tf_ssb_connection_t* connection, int status, void* user_data)
{
connection->is_pending_stranger_check = false;
if (connection->is_stranger && !connection->ssb->talk_to_strangers)
{
tf_ssb_connection_close(connection, "Account is a stranger");
}
else
{
if (connection->tcp.data)
{
_tf_ssb_connection_read_start(connection);
}
_tf_ssb_notify_connections_changed(connection->ssb, k_tf_ssb_change_connect, connection);
}
}
static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* connection, const uint8_t* message, size_t len)
{
uint8_t nonce[crypto_secretbox_NONCEBYTES] = { 0 };
@ -1598,7 +1649,14 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne
{
uv_timer_stop(&connection->handshake_timer);
}
_tf_ssb_notify_connections_changed(connection->ssb, k_tf_ssb_change_connect, connection);
connection->is_pending_stranger_check = true;
connection->is_stranger = true;
if (connection->tcp.data)
{
_tf_ssb_connection_read_stop(connection);
}
tf_ssb_connection_run_work(connection, _tf_ssb_connection_is_account_a_stranger_work, _tf_ssb_connection_is_account_a_stranger_after_work, NULL);
}
static bool _tf_ssb_connection_recv_pop(tf_ssb_connection_t* connection, uint8_t* buffer, size_t size)
@ -2197,6 +2255,8 @@ static bool _tf_ssb_connection_read_start(tf_ssb_connection_t* connection)
tf_ssb_connection_close(connection, reason);
return false;
}
/* Process anything that might have already been queued before we stopped reading. */
uv_async_send(&connection->async);
return true;
}
@ -2795,10 +2855,13 @@ static void _tf_ssb_connection_finalizer(JSRuntime* runtime, JSValue value)
static void _tf_ssb_connection_process_message_async(uv_async_t* async)
{
tf_ssb_connection_t* connection = async->data;
/* The receive may initiate a close, so this order is important. */
if (_tf_ssb_connection_box_stream_recv(connection) && !connection->is_closing)
if (!connection->is_pending_stranger_check)
{
uv_async_send(&connection->async);
/* The receive may initiate a close, so this order is important. */
if (_tf_ssb_connection_box_stream_recv(connection) && !connection->is_closing)
{
uv_async_send(&connection->async);
}
}
}
@ -4324,6 +4387,7 @@ typedef struct _update_settings_t
bool is_room;
bool is_replicator;
bool is_peer_exchange;
bool talk_to_strangers;
char seeds_host[256];
char room_name[1024];
} update_settings_t;
@ -4335,9 +4399,11 @@ static void _tf_ssb_update_settings_work(tf_ssb_t* ssb, void* user_data)
update->is_room = true;
update->is_replicator = true;
update->is_peer_exchange = true;
update->talk_to_strangers = true;
tf_ssb_db_get_global_setting_bool(db, "room", &update->is_room);
tf_ssb_db_get_global_setting_bool(db, "replicator", &update->is_replicator);
tf_ssb_db_get_global_setting_bool(db, "peer_exchange", &update->is_peer_exchange);
tf_ssb_db_get_global_setting_bool(db, "talk_to_strangers", &update->talk_to_strangers);
tf_ssb_db_get_global_setting_string(db, "room_name", update->room_name, sizeof(update->room_name));
tf_ssb_db_get_global_setting_string(db, "seeds_host", update->seeds_host, sizeof(update->seeds_host));
tf_ssb_release_db_reader(ssb, db);
@ -4350,6 +4416,7 @@ static void _tf_ssb_update_settings_after_work(tf_ssb_t* ssb, int result, void*
tf_ssb_set_room_name(ssb, update->room_name);
tf_ssb_set_is_peer_exchange(ssb, update->is_peer_exchange);
tf_ssb_set_is_replicator(ssb, update->is_replicator);
ssb->talk_to_strangers = update->talk_to_strangers;
snprintf(ssb->seeds_host, sizeof(ssb->seeds_host), "%s", update->seeds_host);
_tf_ssb_start_update_settings(ssb);
tf_free(update);

View File

@ -524,6 +524,17 @@ bool tf_ssb_db_generate_invite(sqlite3* db, const char* id, const char* host, in
*/
bool tf_ssb_db_use_invite(sqlite3* db, const char* id);
/**
** Determine if an account is familiar, meaning it is local or within the given
** follow depth of the local accounts or we have already replicated data for
** it.
** @param db The database.
** @param id The identity.
** @param depth The follow depth.
** @return true if the account is familiar.
*/
bool tf_ssb_db_is_account_familiar(sqlite3* db, const char* id, int depth);
/**
** An SQLite authorizer callback. See https://www.sqlite.org/c3ref/set_authorizer.html for use.
** @param user_data User data registered with the authorizer.

View File

@ -358,6 +358,10 @@ static JSValue _util_defaultGlobalSettings(JSContext* context, JSValueConst this
.type = "boolean",
.description = "Periodically delete feeds that aren't visible from local accounts or related follows.",
.default_value = JS_FALSE },
{ .name = "talk_to_strangers",
.type = "boolean",
.description = "Whether connections are accepted from accounts that aren't in the replication range or otherwise already known.",
.default_value = JS_TRUE },
};
JSValue settings = JS_NewObject(context);