diff --git a/example/daemon/www/js/connection_view.js b/example/daemon/www/js/connection_view.js index 37c0247..6dde718 100644 --- a/example/daemon/www/js/connection_view.js +++ b/example/daemon/www/js/connection_view.js @@ -6,20 +6,51 @@ export class ConnectionView { this.element = document.createElement("div"); + const a = document.createElement("div"); + this.element.appendChild(a); + const urlLabel = document.createElement("span"); urlLabel.textContent = "URL:"; - this.element.appendChild(urlLabel); + a.appendChild(urlLabel); this.urlTextbox = document.createElement("input"); this.urlTextbox.type = "text"; this.urlTextbox.value = window.location.href.replace(/^http/, "ws"); - this.element.appendChild(this.urlTextbox); + a.appendChild(this.urlTextbox); this.connectButton = document.createElement("input"); this.connectButton.type = "button"; this.connectButton.value = "connect"; this.connectButton.addEventListener("click", () => { this._onConnectButtonClicked(); }); - this.element.appendChild(this.connectButton); + a.appendChild(this.connectButton); + + + const b = document.createElement("div"); + this.element.appendChild(b); + + const usernameLabel = document.createElement("span"); + usernameLabel.textContent = "user:"; + b.appendChild(usernameLabel); + + this.usernameTextbox = document.createElement("input"); + this.usernameTextbox.type = "text"; + this.usernameTextbox.value = "bob"; + b.appendChild(this.usernameTextbox); + + const passwordLabel = document.createElement("span"); + passwordLabel.textContent = "user:"; + b.appendChild(passwordLabel); + + this.passwordTextbox = document.createElement("input"); + this.passwordTextbox.type = "password"; + this.passwordTextbox.value = "secret"; + b.appendChild(this.passwordTextbox); + + this.authenticateButton = document.createElement("input"); + this.authenticateButton.type = "button"; + this.authenticateButton.value = "authenticate"; + this.authenticateButton.addEventListener("click", () => { this._onAuthenticateButtonClicked(); }); + b.appendChild(this.authenticateButton); } _onConnectButtonClicked() { @@ -32,6 +63,15 @@ export class ConnectionView { } } + _onAuthenticateButtonClicked() { + if (this._client.isConnected()) { + const username = this.usernameTextbox.value; + const password = this.passwordTextbox.value; + + this._client.authenticate("username", { username, password }); + } + } + _onConnectionOpened() { this.connectButton.value = "disconnect"; } diff --git a/example/daemon/www/js/webfuse/client.js b/example/daemon/www/js/webfuse/client.js index 7c1b2bb..8a3ae7f 100644 --- a/example/daemon/www/js/webfuse/client.js +++ b/example/daemon/www/js/webfuse/client.js @@ -24,6 +24,19 @@ export class Client { }; } + authenticate(type ,credentials) { + const request = { + "method": "authenticate", + "params": [type, credentials], + "id": 42 + }; + + this._ws.send(JSON.stringify(request)); + console.log(request); + + // ToDo: make response usable + } + disconnect() { if (this._ws) { this._ws.close(); @@ -58,6 +71,7 @@ export class Client { } } catch (ex) { + console.log(message.data); // swallow } } diff --git a/example/provider/main.c b/example/provider/main.c index a3d6adb..33290cd 100644 --- a/example/provider/main.c +++ b/example/provider/main.c @@ -268,7 +268,7 @@ static void fs_open( } else { - wfp_respond_error(request, WF_BAD_NOACCESS); + wfp_respond_error(request, WF_BAD_ACCESS_DENIED); } } else diff --git a/include/webfuse/core/status.h b/include/webfuse/core/status.h index 9ce425d..7b3c95f 100644 --- a/include/webfuse/core/status.h +++ b/include/webfuse/core/status.h @@ -10,7 +10,7 @@ #define WF_BAD_FORMAT 5 #define WF_BAD_NOENTRY 101 -#define WF_BAD_NOACCESS 102 +#define WF_BAD_ACCESS_DENIED 102 typedef int wf_status; diff --git a/lib/webfuse/adapter/impl/jsonrpc/request.c b/lib/webfuse/adapter/impl/jsonrpc/request.c index fb9878a..e016e1c 100644 --- a/lib/webfuse/adapter/impl/jsonrpc/request.c +++ b/lib/webfuse/adapter/impl/jsonrpc/request.c @@ -43,6 +43,12 @@ void wf_impl_jsonrpc_request_dispose( free(request); } +void * wf_impl_jsonrpc_request_get_userdata( + struct wf_impl_jsonrpc_request * request) +{ + return request->user_data; +} + void wf_impl_jsonrpc_respond( struct wf_impl_jsonrpc_request * request, diff --git a/lib/webfuse/adapter/impl/jsonrpc/request.h b/lib/webfuse/adapter/impl/jsonrpc/request.h index d196779..7d26228 100644 --- a/lib/webfuse/adapter/impl/jsonrpc/request.h +++ b/lib/webfuse/adapter/impl/jsonrpc/request.h @@ -33,6 +33,9 @@ extern struct wf_impl_jsonrpc_request * wf_impl_jsonrpc_request_create( extern void wf_impl_jsonrpc_request_dispose( struct wf_impl_jsonrpc_request * request); +extern void * wf_impl_jsonrpc_request_get_userdata( + struct wf_impl_jsonrpc_request * request); + extern void wf_impl_jsonrpc_respond( struct wf_impl_jsonrpc_request * request, json_t * result); diff --git a/lib/webfuse/adapter/impl/server_protocol.c b/lib/webfuse/adapter/impl/server_protocol.c index 673415e..0e89437 100644 --- a/lib/webfuse/adapter/impl/server_protocol.c +++ b/lib/webfuse/adapter/impl/server_protocol.c @@ -7,6 +7,7 @@ #include "webfuse/core/util.h" #include "webfuse/adapter/impl/filesystem.h" +#include "webfuse/adapter/impl/credentials.h" #include "webfuse/adapter/impl/jsonrpc/request.h" static int wf_impl_server_protocol_callback( @@ -107,10 +108,36 @@ void wf_impl_server_protocol_init_lws( static void wf_impl_server_protocol_authenticate( struct wf_impl_jsonrpc_request * request, char const * WF_UNUSED_PARAM(method_name), - json_t * WF_UNUSED_PARAM(params), + json_t * params, void * WF_UNUSED_PARAM(user_data)) { - wf_impl_jsonrpc_respond_error(request, WF_BAD_NOTIMPLEMENTED); + bool result = false; + + json_t * type_holder = json_array_get(params, 0); + json_t * creds_holder = json_array_get(params, 1); + + if (json_is_string(type_holder) && json_is_object(creds_holder)) + { + char const * type = json_string_value(type_holder); + struct wf_credentials creds; + + wf_impl_credentials_init(&creds, type, creds_holder); + struct wf_impl_session * session = wf_impl_jsonrpc_request_get_userdata(request); + result = wf_impl_session_authenticate(session, &creds); + + wf_impl_credentials_cleanup(&creds); + } + + + if (result) + { + json_t * result = json_object(); + wf_impl_jsonrpc_respond(request, result); + } + else + { + wf_impl_jsonrpc_respond_error(request, WF_BAD_ACCESS_DENIED); + } } bool wf_impl_server_protocol_init( diff --git a/lib/webfuse/adapter/impl/session.c b/lib/webfuse/adapter/impl/session.c index 46254a7..b45027d 100644 --- a/lib/webfuse/adapter/impl/session.c +++ b/lib/webfuse/adapter/impl/session.c @@ -16,7 +16,7 @@ static bool wf_impl_session_send( struct wf_impl_session * session = user_data; struct wf_message * message = wf_message_create(request); - bool result = (session->is_authenticated) && (NULL != session->wsi); + bool result = (session->is_authenticated || wf_impl_jsonrpc_is_response(request)) && (NULL != session->wsi); if (result) { @@ -59,11 +59,13 @@ void wf_impl_session_cleanup( session->server = NULL; } -void wf_impl_session_authenticate( +bool wf_impl_session_authenticate( struct wf_impl_session * session, struct wf_credentials * creds) { session->is_authenticated = wf_impl_authenticators_authenticate(session->authenticators, creds); + + return session->is_authenticated; } void wf_impl_session_onwritable( diff --git a/lib/webfuse/adapter/impl/session.h b/lib/webfuse/adapter/impl/session.h index a945b4f..116e196 100644 --- a/lib/webfuse/adapter/impl/session.h +++ b/lib/webfuse/adapter/impl/session.h @@ -41,7 +41,7 @@ extern void wf_impl_session_init( struct wf_impl_timeout_manager * timeout_manager, struct wf_impl_jsonrpc_server * server); -extern void wf_impl_session_authenticate( +extern bool wf_impl_session_authenticate( struct wf_impl_session * session, struct wf_credentials * creds); diff --git a/lib/webfuse/core/status.c b/lib/webfuse/core/status.c index c7ea0de..9eb9964 100644 --- a/lib/webfuse/core/status.c +++ b/lib/webfuse/core/status.c @@ -12,7 +12,7 @@ case WF_BAD_BUSY: return -ENOENT; case WF_BAD_FORMAT: return -ENOENT; case WF_BAD_NOENTRY: return -ENOENT; - case WF_BAD_NOACCESS: return -EACCES; + case WF_BAD_ACCESS_DENIED: return -EACCES; default: return -ENOENT; } } @@ -28,7 +28,7 @@ char const * wf_status_tostring(wf_status status) case WF_BAD_BUSY: return "Bad (busy)"; case WF_BAD_FORMAT: return "Bad (format)"; case WF_BAD_NOENTRY: return "Bad (no entry)"; - case WF_BAD_NOACCESS: return "Bad (no access)"; + case WF_BAD_ACCESS_DENIED: return "Bad (access denied)"; default: return "Bad (unknown)"; } }