forked from cory/tildefriends
		
	ssb: Allow encrypting/decrypting with the server identity as an admin.
This commit is contained in:
		@@ -1360,7 +1360,7 @@ static void _httpd_endpoint_save_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			|||||||
		user_app_t* user_app = _parse_user_app_from_path(request->path, "/save");
 | 
							user_app_t* user_app = _parse_user_app_from_path(request->path, "/save");
 | 
				
			||||||
		if (user_app)
 | 
							if (user_app)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (strcmp(user_string, user_app->user) == 0 || (strcmp(user_app->user, "core") == 0 && tf_ssb_db_user_has_permission(ssb, user_string, "administration")))
 | 
								if (strcmp(user_string, user_app->user) == 0 || (strcmp(user_app->user, "core") == 0 && tf_ssb_db_user_has_permission(ssb, NULL, user_string, "administration")))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				size_t path_length = strlen("path:") + strlen(user_app->app) + 1;
 | 
									size_t path_length = strlen("path:") + strlen(user_app->app) + 1;
 | 
				
			||||||
				char* app_path = tf_malloc(path_length);
 | 
									char* app_path = tf_malloc(path_length);
 | 
				
			||||||
@@ -1516,7 +1516,7 @@ static void _httpd_endpoint_delete_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			|||||||
		user_app_t* user_app = _parse_user_app_from_path(request->path, "/delete");
 | 
							user_app_t* user_app = _parse_user_app_from_path(request->path, "/delete");
 | 
				
			||||||
		if (user_app)
 | 
							if (user_app)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (strcmp(user_string, user_app->user) == 0 || (strcmp(user_app->user, "core") == 0 && tf_ssb_db_user_has_permission(ssb, user_string, "administration")))
 | 
								if (strcmp(user_string, user_app->user) == 0 || (strcmp(user_app->user, "core") == 0 && tf_ssb_db_user_has_permission(ssb, NULL, user_string, "administration")))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				size_t path_length = strlen("path:") + strlen(user_app->app) + 1;
 | 
									size_t path_length = strlen("path:") + strlen(user_app->app) + 1;
 | 
				
			||||||
				char* app_path = tf_malloc(path_length);
 | 
									char* app_path = tf_malloc(path_length);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								src/ssb.db.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/ssb.db.c
									
									
									
									
									
								
							@@ -2007,12 +2007,12 @@ bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id)
 | 
				
			|||||||
	return verified;
 | 
						return verified;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, const char* id, const char* permission)
 | 
					bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, sqlite3* db, const char* id, const char* permission)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	bool has_permission = false;
 | 
						bool has_permission = false;
 | 
				
			||||||
	sqlite3* db = tf_ssb_acquire_db_reader(ssb);
 | 
						sqlite3* reader = db ? db : tf_ssb_acquire_db_reader(ssb);
 | 
				
			||||||
	sqlite3_stmt* statement = NULL;
 | 
						sqlite3_stmt* statement = NULL;
 | 
				
			||||||
	if (sqlite3_prepare(db,
 | 
						if (sqlite3_prepare(reader,
 | 
				
			||||||
			"SELECT COUNT(*) FROM properties, json_each(properties.value -> 'permissions' -> ?) AS permission WHERE properties.id = 'core' AND properties.key = 'settings' AND "
 | 
								"SELECT COUNT(*) FROM properties, json_each(properties.value -> 'permissions' -> ?) AS permission WHERE properties.id = 'core' AND properties.key = 'settings' AND "
 | 
				
			||||||
			"permission.value = ?",
 | 
								"permission.value = ?",
 | 
				
			||||||
			-1, &statement, NULL) == SQLITE_OK)
 | 
								-1, &statement, NULL) == SQLITE_OK)
 | 
				
			||||||
@@ -2024,6 +2024,9 @@ bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, const char* id, const char* pe
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		sqlite3_finalize(statement);
 | 
							sqlite3_finalize(statement);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tf_ssb_release_db_reader(ssb, db);
 | 
						if (reader != db)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							tf_ssb_release_db_reader(ssb, reader);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return has_permission;
 | 
						return has_permission;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -448,11 +448,12 @@ bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id);
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
** Check if a user has a specific permission.
 | 
					** Check if a user has a specific permission.
 | 
				
			||||||
** @param ssb The SSB instance.
 | 
					** @param ssb The SSB instance.
 | 
				
			||||||
 | 
					** @param db Optional database instance.  If NULL, one will be acquired from ssb.
 | 
				
			||||||
** @param id The user ID.
 | 
					** @param id The user ID.
 | 
				
			||||||
** @param permission The name of the permission.
 | 
					** @param permission The name of the permission.
 | 
				
			||||||
** @return true If the user has the requested permission.
 | 
					** @return true If the user has the requested permission.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, const char* id, const char* permission);
 | 
					bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, sqlite3* db, const char* id, const char* permission);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
** An SQLite authorizer callback.  See https://www.sqlite.org/c3ref/set_authorizer.html for use.
 | 
					** An SQLite authorizer callback.  See https://www.sqlite.org/c3ref/set_authorizer.html for use.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								src/ssb.js.c
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								src/ssb.js.c
									
									
									
									
									
								
							@@ -368,9 +368,9 @@ typedef struct _swap_with_server_identity_t
 | 
				
			|||||||
static void _tf_ssb_swap_with_server_identity_work(tf_ssb_t* ssb, void* user_data)
 | 
					static void _tf_ssb_swap_with_server_identity_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	swap_with_server_identity_t* work = user_data;
 | 
						swap_with_server_identity_t* work = user_data;
 | 
				
			||||||
	if (tf_ssb_db_user_has_permission(ssb, work->user, "administration"))
 | 
						sqlite3* db = tf_ssb_acquire_db_writer(ssb);
 | 
				
			||||||
 | 
						if (tf_ssb_db_user_has_permission(ssb, db, work->user, "administration"))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		sqlite3* db = tf_ssb_acquire_db_writer(ssb);
 | 
					 | 
				
			||||||
		char* error = NULL;
 | 
							char* error = NULL;
 | 
				
			||||||
		if (sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &error) == SQLITE_OK)
 | 
							if (sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &error) == SQLITE_OK)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -404,12 +404,12 @@ static void _tf_ssb_swap_with_server_identity_work(tf_ssb_t* ssb, void* user_dat
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			work->error = error ? tf_strdup(error) : tf_strdup(sqlite3_errmsg(db));
 | 
								work->error = error ? tf_strdup(error) : tf_strdup(sqlite3_errmsg(db));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		tf_ssb_release_db_writer(ssb, db);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		work->error = tf_strdup("not administrator");
 | 
							work->error = tf_strdup("not administrator");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						tf_ssb_release_db_writer(ssb, db);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void _tf_ssb_swap_with_server_identity_after_work(tf_ssb_t* ssb, int status, void* user_data)
 | 
					static void _tf_ssb_swap_with_server_identity_after_work(tf_ssb_t* ssb, int status, void* user_data)
 | 
				
			||||||
@@ -480,7 +480,7 @@ static void _tf_ssb_getIdentities_visit(const char* identity, void* user_data)
 | 
				
			|||||||
static void _tf_ssb_get_identities_work(tf_ssb_t* ssb, void* user_data)
 | 
					static void _tf_ssb_get_identities_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	identities_visit_t* work = user_data;
 | 
						identities_visit_t* work = user_data;
 | 
				
			||||||
	if (tf_ssb_db_user_has_permission(ssb, work->user, "administration"))
 | 
						if (tf_ssb_db_user_has_permission(ssb, NULL, work->user, "administration"))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		char id[k_id_base64_len] = "";
 | 
							char id[k_id_base64_len] = "";
 | 
				
			||||||
		if (tf_ssb_whoami(ssb, id, sizeof(id)))
 | 
							if (tf_ssb_whoami(ssb, id, sizeof(id)))
 | 
				
			||||||
@@ -552,7 +552,7 @@ static void _tf_ssb_get_private_key_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	get_private_key_t* work = user_data;
 | 
						get_private_key_t* work = user_data;
 | 
				
			||||||
	work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, work->user, work->id, work->private_key, sizeof(work->private_key));
 | 
						work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, work->user, work->id, work->private_key, sizeof(work->private_key));
 | 
				
			||||||
	if (!work->got_private_key && tf_ssb_db_user_has_permission(ssb, work->user, "administration"))
 | 
						if (!work->got_private_key && tf_ssb_db_user_has_permission(ssb, NULL, work->user, "administration"))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, ":admin", work->id, work->private_key, sizeof(work->private_key));
 | 
							work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, ":admin", work->id, work->private_key, sizeof(work->private_key));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -658,7 +658,7 @@ static void _tf_ssb_getActiveIdentity_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			|||||||
		tf_ssb_db_identity_visit(ssb, request->name, _tf_ssb_getActiveIdentity_visit, request);
 | 
							tf_ssb_db_identity_visit(ssb, request->name, _tf_ssb_getActiveIdentity_visit, request);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!*request->identity && tf_ssb_db_user_has_permission(ssb, request->name, "administration"))
 | 
						if (!*request->identity && tf_ssb_db_user_has_permission(ssb, NULL, request->name, "administration"))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		tf_ssb_whoami(ssb, request->identity, sizeof(request->identity));
 | 
							tf_ssb_whoami(ssb, request->identity, sizeof(request->identity));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -742,7 +742,7 @@ static void _tf_ssb_getIdentityInfo_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	identity_info_work_t* request = user_data;
 | 
						identity_info_work_t* request = user_data;
 | 
				
			||||||
	char id[k_id_base64_len] = "";
 | 
						char id[k_id_base64_len] = "";
 | 
				
			||||||
	if (tf_ssb_db_user_has_permission(ssb, request->name, "administration"))
 | 
						if (tf_ssb_db_user_has_permission(ssb, NULL, request->name, "administration"))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (tf_ssb_whoami(ssb, id, sizeof(id)))
 | 
							if (tf_ssb_whoami(ssb, id, sizeof(id)))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -904,7 +904,7 @@ static void _tf_ssb_append_message_with_identity_get_key_work(tf_ssb_t* ssb, voi
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	append_message_t* work = user_data;
 | 
						append_message_t* work = user_data;
 | 
				
			||||||
	work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, work->user, work->id, work->private_key, sizeof(work->private_key));
 | 
						work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, work->user, work->id, work->private_key, sizeof(work->private_key));
 | 
				
			||||||
	if (!work->got_private_key && tf_ssb_db_user_has_permission(ssb, work->user, "administration"))
 | 
						if (!work->got_private_key && tf_ssb_db_user_has_permission(ssb, NULL, work->user, "administration"))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, ":admin", work->id, work->private_key, sizeof(work->private_key));
 | 
							work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, ":admin", work->id, work->private_key, sizeof(work->private_key));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1974,7 +1974,7 @@ enum
 | 
				
			|||||||
	k_max_private_message_recipients = 8
 | 
						k_max_private_message_recipients = 8
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool _tf_ssb_get_private_key_curve25519(sqlite3* db, const char* user, const char* identity, uint8_t out_private_key[static crypto_sign_SECRETKEYBYTES])
 | 
					static bool _tf_ssb_get_private_key_curve25519_internal(sqlite3* db, const char* user, const char* identity, uint8_t out_private_key[static crypto_sign_SECRETKEYBYTES])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!user || !identity)
 | 
						if (!user || !identity)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -2003,6 +2003,21 @@ static bool _tf_ssb_get_private_key_curve25519(sqlite3* db, const char* user, co
 | 
				
			|||||||
	return success;
 | 
						return success;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool _tf_ssb_get_private_key_curve25519(tf_ssb_t* ssb, sqlite3* db, const char* user, const char* identity, uint8_t out_private_key[static crypto_sign_SECRETKEYBYTES])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (_tf_ssb_get_private_key_curve25519_internal(db, user, identity, out_private_key))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tf_ssb_db_user_has_permission(ssb, db, user, "administration"))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return _tf_ssb_get_private_key_curve25519_internal(db, ":admin", identity, out_private_key);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct _private_message_encrypt_t
 | 
					typedef struct _private_message_encrypt_t
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char* signer_user;
 | 
						const char* signer_user;
 | 
				
			||||||
@@ -2025,7 +2040,7 @@ static void _tf_ssb_private_message_encrypt_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 };
 | 
						uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 };
 | 
				
			||||||
	sqlite3* db = tf_ssb_acquire_db_reader(ssb);
 | 
						sqlite3* db = tf_ssb_acquire_db_reader(ssb);
 | 
				
			||||||
	bool found = _tf_ssb_get_private_key_curve25519(db, work->signer_user, work->signer_identity, private_key);
 | 
						bool found = _tf_ssb_get_private_key_curve25519(ssb, db, work->signer_user, work->signer_identity, private_key);
 | 
				
			||||||
	tf_ssb_release_db_reader(ssb, db);
 | 
						tf_ssb_release_db_reader(ssb, db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (found)
 | 
						if (found)
 | 
				
			||||||
@@ -2214,7 +2229,7 @@ static void _tf_ssb_private_message_decrypt_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 };
 | 
						uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 };
 | 
				
			||||||
	sqlite3* db = tf_ssb_acquire_db_reader(ssb);
 | 
						sqlite3* db = tf_ssb_acquire_db_reader(ssb);
 | 
				
			||||||
	bool found = _tf_ssb_get_private_key_curve25519(db, work->user, work->identity, private_key);
 | 
						bool found = _tf_ssb_get_private_key_curve25519(ssb, db, work->user, work->identity, private_key);
 | 
				
			||||||
	tf_ssb_release_db_reader(ssb, db);
 | 
						tf_ssb_release_db_reader(ssb, db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (found)
 | 
						if (found)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user