diff --git a/src/httpd.js.c b/src/httpd.js.c index 49cb9cea..d6cc1e5d 100644 --- a/src/httpd.js.c +++ b/src/httpd.js.c @@ -1066,6 +1066,7 @@ typedef struct _login_request_t JSValue jwt; const char* name; const char* error; + const char* settings; const char* code_of_conduct; bool have_administrator; bool session_is_new; @@ -1260,25 +1261,6 @@ static bool _is_name_valid(const char* name) return true; } -static void _visit_auth_identity(const char* identity, void* user_data) -{ - if (!*(char*)user_data) - { - snprintf((char*)user_data, k_id_base64_len, "%s", identity); - } -} - -static bool _get_auth_private_key(tf_ssb_t* ssb, uint8_t* out_private_key) -{ - char id[k_id_base64_len] = { 0 }; - tf_ssb_db_identity_visit(ssb, ":admin", _visit_auth_identity, id); - if (*id) - { - return tf_ssb_db_identity_get_private_key(ssb, ":admin", id, out_private_key, crypto_sign_SECRETKEYBYTES); - } - return false; -} - static const char* _make_session_jwt(tf_ssb_t* ssb, const char* name) { if (!name || !*name) @@ -1309,17 +1291,16 @@ static const char* _make_session_jwt(tf_ssb_t* ssb, const char* name) char signature_base64[256] = { 0 }; uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 }; - if (_get_auth_private_key(ssb, private_key)) + tf_ssb_get_private_key(ssb, private_key, sizeof(private_key)); + + if (crypto_sign_detached(signature, &signature_length, (const uint8_t*)payload_base64, strlen(payload_base64), private_key) == 0) { - if (crypto_sign_detached(signature, &signature_length, (const uint8_t*)payload_base64, strlen(payload_base64), private_key) == 0) - { - sodium_bin2base64(signature_base64, sizeof(signature_base64), signature, sizeof(signature), sodium_base64_VARIANT_URLSAFE_NO_PADDING); - size_t size = strlen(header_base64) + 1 + strlen(payload_base64) + 1 + strlen(signature_base64) + 1; - result = tf_malloc(size); - snprintf(result, size, "%s.%s.%s", header_base64, payload_base64, signature_base64); - } - sodium_memzero(private_key, sizeof(private_key)); + sodium_bin2base64(signature_base64, sizeof(signature_base64), signature, sizeof(signature), sodium_base64_VARIANT_URLSAFE_NO_PADDING); + size_t size = strlen(header_base64) + 1 + strlen(payload_base64) + 1 + strlen(signature_base64) + 1; + result = tf_malloc(size); + snprintf(result, size, "%s.%s.%s", header_base64, payload_base64, signature_base64); } + sodium_memzero(private_key, sizeof(private_key)); JS_FreeCString(context, payload_string); JS_FreeValue(context, payload_json); @@ -1335,19 +1316,31 @@ static bool _verify_password(const char* password, const char* hash) return out_hash && strcmp(hash, out_hash) == 0; } -static const char* _get_code_of_conduct(tf_ssb_t* ssb) +static void _httpd_endpoint_login_get_code_of_conduct_work(tf_ssb_t* ssb, void* user_data) { - JSContext* context = tf_ssb_get_context(ssb); - const char* settings = tf_ssb_db_get_property(ssb, "core", "settings"); - JSValue settings_value = settings ? JS_ParseJSON(context, settings, strlen(settings), NULL) : JS_UNDEFINED; - JSValue code_of_conduct_value = JS_GetPropertyStr(context, settings_value, "code_of_conduct"); - const char* code_of_conduct = JS_ToCString(context, code_of_conduct_value); - const char* result = tf_strdup(code_of_conduct); - JS_FreeCString(context, code_of_conduct); - JS_FreeValue(context, code_of_conduct_value); - JS_FreeValue(context, settings_value); - tf_free((void*)settings); - return result; + login_request_t* login = user_data; + login->settings = tf_ssb_db_get_property(ssb, "core", "settings"); + +} + +static void _httpd_endpoint_login_get_code_of_conduct_after_work(tf_ssb_t* ssb, int status, void* user_data) +{ + login_request_t* login = user_data; + if (login->settings) + { + JSContext* context = tf_ssb_get_context(ssb); + JSValue settings_value = JS_ParseJSON(context, login->settings, strlen(login->settings), NULL); + JSValue code_of_conduct_value = JS_GetPropertyStr(context, settings_value, "code_of_conduct"); + const char* code_of_conduct = JS_ToCString(context, code_of_conduct_value); + const char* result = tf_strdup(code_of_conduct); + JS_FreeCString(context, code_of_conduct); + JS_FreeValue(context, code_of_conduct_value); + JS_FreeValue(context, settings_value); + tf_free((void*)login->settings); + login->settings = NULL; + login->code_of_conduct = result; + } + tf_file_read(login->request->user_data, "core/auth.html", _httpd_endpoint_login_file_read_callback, login); } static bool _make_administrator_if_first(tf_ssb_t* ssb, const char* account_name_copy, bool may_become_first_admin) @@ -1547,7 +1540,6 @@ static void _httpd_endpoint_login(tf_http_request_t* request) tf_http_request_ref(request); login_request_t* login = tf_malloc(sizeof(login_request_t)); - const char* code_of_conduct = _get_code_of_conduct(ssb); *login = (login_request_t) { .request = request, .name = account_name_copy, @@ -1555,11 +1547,10 @@ static void _httpd_endpoint_login(tf_http_request_t* request) .error = login_error, .session_cookie = send_session, .session_is_new = session_is_new, - .code_of_conduct = code_of_conduct, .have_administrator = have_administrator, }; - tf_file_read(request->user_data, "core/auth.html", _httpd_endpoint_login_file_read_callback, login); + tf_ssb_run_work(ssb, _httpd_endpoint_login_get_code_of_conduct_work, _httpd_endpoint_login_get_code_of_conduct_after_work, login); jwt = JS_UNDEFINED; account_name_copy = NULL; } diff --git a/src/ssb.db.c b/src/ssb.db.c index a7e6f5a8..caa84241 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -1087,6 +1087,8 @@ bool tf_ssb_db_identity_create(tf_ssb_t* ssb, const char* user, uint8_t* out_pub if (out_private_key) { tf_ssb_id_str_to_bin(out_private_key, private); + /* HACK: tf_ssb_id_str_to_bin only produces 32 bytes even though the full private key is 32 + 32. */ + tf_ssb_id_str_to_bin(out_private_key + crypto_sign_PUBLICKEYBYTES, public); } return true; }