ssb: Allow encrypting/decrypting with the server identity as an admin.
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build Tilde Friends / Build-All (push) Successful in 16m45s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build Tilde Friends / Build-All (push) Successful in 16m45s
				
			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