const wauthn_pubkey_cred_creation_options_s *options,
wauthn_mc_callbacks_s *callbacks)
{
-
if (client_data == nullptr || options == nullptr || callbacks == nullptr ||
callbacks->response_callback == nullptr)
return WAUTHN_ERROR_INVALID_PARAMETER;
return try_catch([&]() -> int {
-
std::shared_ptr<ClientRequest> request
= std::make_shared<ClientRequest>(WebAuthnCall::MAKE_CREDENTIAL);
- LogDebug("sendRequest");
+ LogDebug("Calling to make credential..");
// TODO: send client_data, options
//if (request->sendRequest(client_data, options)).failed())
if (request->sendRequest(std::string("sendRequest(MC) to server")).failed())
std::thread worker([request, callbacks, cred]{cb_worker(request, callbacks, cred);});
worker.detach();
LogDebug("Main thread OUT");
-
return WAUTHN_ERROR_NONE;
});
}
const wauthn_pubkey_cred_request_options_s *options,
wauthn_ga_callbacks_s *callbacks)
{
-
if (client_data == nullptr || options == nullptr || callbacks == nullptr ||
callbacks->response_callback == nullptr)
return WAUTHN_ERROR_INVALID_PARAMETER;
std::shared_ptr<ClientRequest> request
= std::make_shared<ClientRequest>(WebAuthnCall::GET_ASSERTION);
- LogDebug("getAssertion");
+ LogDebug("Calling to get assertion..");
/* TODO: send client_data, options */
//if (request->sendRequest(client_data, options)).failed())
if (request->sendRequest(std::string("getAssertion(GA) to server")).failed())
wauthn_pubkey_credential_assertion_s *cred = NULL;
std::thread worker([request, callbacks, cred]{cb_worker(request, callbacks, cred);});
worker.detach();
-
LogDebug("Main thread OUT");
return WAUTHN_ERROR_NONE;
});
int wauthn_cancel()
{
- // TODO
- return WAUTHN_ERROR_NONE;
+ return try_catch([&]() -> int {
+ std::shared_ptr<ClientRequest> request
+ = std::make_shared<ClientRequest>(WebAuthnCall::CANCEL);
+ LogDebug("Calling to cancel..");
+ if (request->sendRequest().failed())
+ LogError("Error on cancel request, RET: " << wauthn_error_to_string(request->getStatus()));
+ return request->getStatus();
+ });
}
\ No newline at end of file
*/
-#include <sys/socket.h>
#include <webauthn-log.h>
#include <serialization.h>
#include <protocols.h>
#include <unistd.h>
#include <webauthn-hal.h>
#include <webauthn-types.h>
+#define SMACK_LABEL_LEN 255
/* Test code start */
void wah_make_credential(const wauthn_client_data_s *client_data,
if (options == NULL)
LogError("options is null");
- sleep(3);
+ sleep(2);
callbacks->qrcode_callback(std::string("FIDO:/..mc....").c_str(), callbacks->user_data);
- sleep(3);
+ sleep(2);
callbacks->response_callback(NULL, WAUTHN_ERROR_NONE, callbacks->user_data);
}
if (options == NULL)
LogError("options is null");
- sleep(3);
+ sleep(2);
callbacks->qrcode_callback(std::string("FIDO:/..ga....").c_str(), callbacks->user_data);
- sleep(3);
+ sleep(2);
callbacks->response_callback(NULL, WAUTHN_ERROR_NONE, callbacks->user_data);
}
+
+int wah_cancel()
+{
+ return WAUTHN_ERROR_NONE;
+}
/* Test code end */
namespace WA {
LogDebug("Writing response with sock: " << userData->connectionID.sock);
userData->service->getSocketmanager()->Write(userData->connectionID, std::move(buffer));
+ userData->service->unsetBusy();
}
void cb_ga_on_response(const wauthn_pubkey_credential_assertion_s *pubkey_cred,
LogDebug("Writing response with sock: " << userData->connectionID.sock);
userData->service->getSocketmanager()->Write(userData->connectionID, std::move(buffer));
+ userData->service->unsetBusy();
}
Service::Service(){}
void Service::mcWorker(SocketManager::ConnectionID connectionID)
{
- LogDebug("IN mcWorker thread, connectionID: " << connectionID.sock);
-
- //sleep(3);
-
+ LogDebug("IN mcWorker thread, connectionID: " << connectionID.sock);
wauthn_mc_callbacks_s *callbacks = NULL;
callbacks = (wauthn_mc_callbacks_s*) calloc(1, sizeof(wauthn_mc_callbacks_s));
callbacks->qrcode_callback = cb_display_qrcode;
callbacks->user_data = user_data;
wah_make_credential(NULL, NULL, callbacks);
-
- //sleep(3);
LogDebug("Worker thread OUT");
}
void Service::gaWorker(SocketManager::ConnectionID connectionID)
{
LogDebug("IN gaWorker thread, connectionID: " << connectionID.sock);
-
- //sleep(3);
-
wauthn_ga_callbacks_s *callbacks = NULL;
callbacks = (wauthn_ga_callbacks_s*) calloc(1, sizeof(wauthn_ga_callbacks_s));
callbacks->qrcode_callback = cb_display_qrcode;
callbacks->user_data = user_data;
wah_get_assertion(NULL, NULL, callbacks);
-
- //sleep(3);
LogDebug("Worker thread OUT");
}
Throw(ServiceException::InvalidAction);
}
// if we reach this point, the protocol is OK
- //LogDebug("Closing socket after the protocol is Done.");
- //return m_serviceManager->Close(msg.connectionID);
LogDebug("Protocol is Done.");
return;
} Catch(MessageBuffer::Exception::Base) {
} catch (...) {
LogError("Unknown exception");
}
-
- //LogError("Closing socket because of error");
- //m_serviceManager->Close(msg.connectionID);
}
void Service::processMakeCredential(
SocketManager::ConnectionID connectionID,
MessageBuffer &buffer)
{
- /* Test Code Start */
- pid_t pid = getpid();
-
- LogDebug("PID: " << pid);
-
- ucred clientCred;
- socklen_t length = sizeof(ucred);
- if (0 > getsockopt(connectionID.sock, SOL_SOCKET, SO_PEERCRED, &clientCred, &length)) {
- LogError("getsockopt failed");
- //return -1;
- }
- LogDebug("Client PID: " << clientCred.pid);
-
-
+ // busy check
+ // cred setting
std::string recvStr;
Deserialization::Deserialize(buffer, recvStr);
LogDebug("Receive :" << recvStr);
+ // TODO: recv client_data, options
buffer.ModeStreaming();
int ret = WAUTHN_ERROR_NONE;
+ int isBusy = checkBusyAndSet(connectionID);
+
+ if (-1 == isBusy)
+ {
+ LogError("Error on checkBusyAndSet");
+ ret = WAUTHN_ERROR_UNKNOWN;
+ }
+ else if (1 == isBusy)
+ {
+ LogError("Server is Busy");
+ ret = WAUTHN_ERROR_NOT_ALLOWED;
+ }
+
Serialization::Serialize(buffer, ret);
LogDebug("Writing ret");
m_serviceManager->Write(connectionID, std::move(buffer));
- std::thread worker(&Service::mcWorker, this, connectionID);
- worker.detach();
- LogDebug("Main thread Done");
-
- /* Test Code End */
+ if (0 == isBusy)
+ {
+ LogDebug("Creating worker thread..");
+ std::thread worker(&Service::mcWorker, this, connectionID);
+ worker.detach();
+ LogDebug("Main thread is Done");
+ }
}
void Service::processGetAssertion(SocketManager::ConnectionID connectionID,
std::string recvStr;
Deserialization::Deserialize(buffer, recvStr);
LogDebug("Receive :" << recvStr);
+ // TODO: recv client_data, options
buffer.ModeStreaming();
int ret = WAUTHN_ERROR_NONE;
+ int isBusy = checkBusyAndSet(connectionID);
+
+ if (-1 == isBusy)
+ {
+ LogError("Error on checkBusyAndSet");
+ ret = WAUTHN_ERROR_UNKNOWN;
+ }
+ else if (1 == isBusy)
+ {
+ LogError("Server is Busy");
+ ret = WAUTHN_ERROR_NOT_ALLOWED;
+ }
+
Serialization::Serialize(buffer, ret);
LogDebug("Writing ret");
m_serviceManager->Write(connectionID, std::move(buffer));
- std::thread worker(&Service::gaWorker, this, connectionID);
- worker.detach();
- LogDebug("Main thread Done");
-
- /* Test Code End */
+ if (0 == isBusy)
+ {
+ LogDebug("Creating worker thread..");
+ std::thread worker(&Service::gaWorker, this, connectionID);
+ worker.detach();
+ LogDebug("Main thread is Done");
+ }
}
void Service::processCancel(SocketManager::ConnectionID connectionID,
MessageBuffer &buffer)
{
- /* Test Code Start */
LogDebug("socket: " << connectionID.sock);
buffer.ModeStreaming();
- /* Test Code End */
+ int ret = WAUTHN_ERROR_NONE;
+ int isBusy = checkBusyAndCred(connectionID);
+ if (-1 == isBusy)
+ {
+ LogError("Error on checkBusyAndCred");
+ ret = WAUTHN_ERROR_UNKNOWN;
+ }
+ else if (1 == isBusy)
+ {
+ LogDebug("Calling HAL for cancel");
+ ret = wah_cancel();
+ }
+ else
+ {
+ LogError("The cancellation request is not allowed");
+ ret = WAUTHN_ERROR_NOT_ALLOWED;
+ }
+
+ Serialization::Serialize(buffer, ret);
+ LogDebug("Writing ret");
+ m_serviceManager->Write(connectionID, std::move(buffer));
+}
+
+int Service::checkBusyAndCred(SocketManager::ConnectionID connectionID)
+{
+ std::lock_guard<std::mutex> ulock(m_isBusyMutex);
+ if (isBusy)
+ {
+ Cred nowCreds;
+ int ret = getCredentials(connectionID, &nowCreds);
+ if (-1 == ret)
+ {
+ LogError("Error on get credentials");
+ return -1;
+ }
+ if (credentials.smack == nowCreds.smack && credentials.cred.pid == nowCreds.cred.pid)
+ {
+ LogDebug("Service is Busy and Credentials are matched");
+ return 1;
+ }
+ else
+ {
+ LogError("Credentials are not matched");
+ return 0;
+ }
+ }
+ else
+ {
+ LogError("Server is not Busy");
+ return 0;
+ }
+}
+
+int Service::checkBusyAndSet(SocketManager::ConnectionID connectionID)
+{
+ std::lock_guard<std::mutex> ulock(m_isBusyMutex);
+ if (isBusy)
+ return 1;
+ else{
+ isBusy = true;
+ int ret = setCredentials(connectionID);
+ if (-1 == ret)
+ {
+ LogError("Error on set credentials");
+ return -1;
+ }
+ LogDebug("Return not Busy after Set Busy");
+ return 0;
+ }
+}
+
+void Service::unsetBusy()
+{
+ std::lock_guard<std::mutex> ulock(m_isBusyMutex);
+ isBusy = false;
+ LogDebug("Set not Busy");
+}
+
+int Service::setCredentials(SocketManager::ConnectionID connectionID)
+{
+ return getCredentials(connectionID, &credentials);
+}
+
+int Service::getCredentials(SocketManager::ConnectionID connectionID, Cred *creds)
+{
+ socklen_t length = sizeof(ucred);
+ if (0 > getsockopt(connectionID.sock, SOL_SOCKET, SO_PEERCRED, &creds->cred, &length)) {
+ LogError("getsockopt for get pid failed");
+ return -1;
+ }
+ LogDebug("Client PID: " << creds->cred.pid);
+
+ std::vector<char> result(SMACK_LABEL_LEN + 1);
+ length = SMACK_LABEL_LEN;
+ if (0 != getsockopt(connectionID.sock, SOL_SOCKET, SO_PEERSEC, result.data(), &length))
+ {
+ return -1;
+ LogError("getsockopt for get smack label failed");
+ }
+ creds->smack.assign(result.data(), length);
+ LogDebug("Client Smack: " << creds->smack);
+ return 0;
}
} // namespace WebAuthn
#pragma once
+#include <sys/socket.h>
#include <message-buffer.h>
#include <socket-manager.h>
#include <protocols.h>
+#include <mutex>
namespace WA {
SocketManager::ConnectionID connectionID;
MessageBuffer buffer;
};
+struct Cred {
+ std::string smack;
+ ucred cred;
+};
class Service final
{
/**
* Handle request from a client
*
- * @param conn Socket connection information
* @param msg A message
*/
void processEvent(Event &&msg);
SocketManager *getSocketmanager();
+ void unsetBusy();
//void Service::cbQRCode(const char *qr_contents, void *user_data);
private:
/**
* Process making credential
+ * @param connectionID Socket information for the connection
* @param buffer Input/output message buffer
*/
void processMakeCredential(
/**
* Process getting assertion
+ * @param connectionID Socket information for the connection
* @param buffer Input/output message buffer
*/
void processGetAssertion(
/**
* Process cancelling current event
+ * @param connectionID Socket information for the connection
* @param buffer Input/output message buffer
*/
void processCancel(
SocketManager::ConnectionID connectionID,
MessageBuffer &buffer);
+ /**
+ * Worker thread for make credential request
+ * @param connectionID Socket information for the connection
+ */
void mcWorker(SocketManager::ConnectionID connectionID);
+
+ /**
+ * Worker thread for get assertion request
+ * @param connectionID Socket information for the connection
+ */
void gaWorker(SocketManager::ConnectionID connectionID);
+
+ int checkBusyAndSet(SocketManager::ConnectionID connectionID);
+ int checkBusyAndCred(SocketManager::ConnectionID connectionID);
+ int setCredentials(SocketManager::ConnectionID connectionID);
+ int getCredentials(SocketManager::ConnectionID connectionID, Cred *creds);
+
+ bool isBusy = false;
+ std::mutex m_isBusyMutex;
+ Cred credentials;
};
} // namespace WebAuthn