diff --git a/project/common.mk b/project/common.mk index 0fbf8de..7ef2ee9 100644 --- a/project/common.mk +++ b/project/common.mk @@ -2,6 +2,7 @@ API_SRCS = \ INTERNAL_SRCS = \ src/client/toks_client_connect.c \ + src/daemon/toks_daemon_acquire.c \ src/daemon/toks_daemon_connect.c \ src/daemon/toks_daemon_init.c \ src/daemon/toks_daemon_loop.c \ diff --git a/src/daemon/toks_daemon_acquire.c b/src/daemon/toks_daemon_acquire.c new file mode 100644 index 0000000..9d06826 --- /dev/null +++ b/src/daemon/toks_daemon_acquire.c @@ -0,0 +1,214 @@ +/*********************************************************/ +/* toksvc: a framework-native token broker service */ +/* Copyright (C) 2020 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.TOKSVC. */ +/*********************************************************/ + +#include +#include + +#include +#include "toksvc_daemon_impl.h" +#include "toksvc_driver_impl.h" + +static int32_t toks_daemon_client_wait(void * rapunzel) +{ + struct toks_token * token; + struct toks_client_ctx * client; + void * hduo[2]; + + token = (struct toks_token *)rapunzel; + client = &token->client; + + ntapi->zw_set_event(client->hswap,0); + ntapi->zw_close(client->hswap); + + hduo[0] = client->hprocess; + hduo[1] = client->halert; + + ntapi->zw_wait_for_multiple_objects( + 2,hduo, + NT_WAIT_ANY, + NT_SYNC_NON_ALERTABLE, + 0); + + ntapi->zw_close(client->hprocess); + ntapi->zw_close(client->hport); + ntapi->zw_close(client->halert); + + return ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + NT_STATUS_SUCCESS); +} + +static void toks_daemon_token_reset(struct toks_token * token) +{ + token->self = 0; + token->keys.key[0] = 0; + token->keys.key[1] = 0; + token->keys.key[2] = 0; + token->keys.key[3] = 0; + token->keys.key[4] = 0; + token->keys.key[5] = 0; +} + +static int32_t toks_daemon_token_instance( + struct toks_token * token, + struct toks_client_ctx * client) +{ + int32_t status; + nt_thread_params params; + + if ((status = ntapi->tt_create_private_event( + &client->hswap, + NT_NOTIFICATION_EVENT, + NT_EVENT_NOT_SIGNALED))) + return status; + + status = ntapi->tt_create_private_event( + &client->halert, + NT_NOTIFICATION_EVENT, + NT_EVENT_NOT_SIGNALED); + + if (status) { + ntapi->zw_close(client->hswap); + return status; + } + + token->self = token; + token->client.hprocess = client->hprocess; + token->client.hswap = client->hswap; + token->client.halert = client->halert; + token->client.cid.process_id = client->cid.process_id; + token->client.cid.thread_id = client->cid.thread_id; + + ntapi->tt_aligned_block_memset( + ¶ms,0,sizeof(params)); + + params.hprocess = NT_CURRENT_PROCESS_HANDLE; + params.start = toks_daemon_client_wait; + params.ext_ctx = token; + params.ext_ctx_size = sizeof(*token); + params.stack_size_commit = 4 * 1024; + params.stack_size_reserve = 4 * 1024; + params.creation_flags = NT_CREATE_LOCAL_THREAD; + + if ((status = ntapi->tt_create_thread(¶ms))) { + toks_daemon_token_reset(token); + ntapi->zw_close(client->hswap); + ntapi->zw_close(client->halert); + return status; + } + + status = ntapi->zw_wait_for_single_object( + client->hswap, + NT_SYNC_NON_ALERTABLE, + 0); + + if (status) { + toks_daemon_token_reset(token); + ntapi->zw_close(client->hswap); + ntapi->zw_close(client->halert); + return status; + } + + token->client.hinstance = params.hthread; + + return NT_STATUS_SUCCESS; +} + +int32_t __stdcall toks_daemon_acquire(struct toks_daemon_ctx * dctx) +{ + int32_t status; + nt_tty_port_msg * msg; + struct toks_client_ctx client; + nt_oa oa; + struct toks_token * token; + struct toks_token * tocap; + nt_timeout timeout; + nt_filetime pcnt; + + msg = &dctx->reply; + timeout.quad = (int64_t)msg->ttyinfo.exarg; + + client.hport = 0; + client.hprocess = 0; + client.hswap = 0; + client.cid.process_id = msg->header.client_id.process_id; + client.cid.thread_id = 0; + + oa.len = sizeof(oa); + oa.root_dir = 0; + oa.obj_name = 0; + oa.obj_attr = 0; + oa.sec_desc = 0; + oa.sec_qos = 0; + + (void)timeout; + + if ((status = ntapi->zw_open_process( + &client.hprocess, + NT_PROCESS_SYNCHRONIZE | NT_PROCESS_QUERY_INFORMATION, + &oa,&client.cid))) + return status; + + token = toks_get_driver_tokens(dctx->driver_ctx); + tocap = &token[toks_get_driver_ntokens(dctx->driver_ctx)]; + + for (; token->self && (tokenipcinfo.hevent) { + ntapi->zw_close(client.hprocess); + return NT_STATUS_TIMEOUT; + } + + if (token == tocap) { + ntapi->zw_close(client.hprocess); + return NT_STATUS_NOT_IMPLEMENTED; + } + + toks_query_performance_counters(dctx->driver_ctx,&pcnt); + + token->keys.key[0] = ntapi->tt_buffer_crc32( + msg->header.msg_id, + &pcnt,sizeof(pcnt)); + + token->keys.key[1] = ntapi->tt_buffer_crc32( + msg->header.msg_id, + &msg->header,sizeof(msg->header)); + + token->keys.key[2] = ntapi->tt_buffer_crc32( + msg->header.msg_id, + &msg->ipcinfo,sizeof(msg->ipcinfo)); + + token->keys.key[3] = ntapi->tt_buffer_crc32( + msg->header.msg_id, + &client,sizeof(client)); + + token->keys.key[4] = ntapi->tt_buffer_crc32( + msg->header.msg_id, + toks_get_driver_tokens(dctx->driver_ctx), + toks_get_driver_ntokens(dctx->driver_ctx) + * sizeof(struct toks_token)); + + token->keys.key[5] = ntapi->tt_buffer_crc32( + msg->header.msg_id, + &token->keys,sizeof(token->keys)); + + msg->ipcinfo.ipckeys[0] = token->keys.key[0]; + msg->ipcinfo.ipckeys[1] = token->keys.key[1]; + msg->ipcinfo.ipckeys[2] = token->keys.key[2]; + msg->ipcinfo.ipckeys[3] = token->keys.key[3]; + msg->ipcinfo.ipckeys[4] = token->keys.key[4]; + msg->ipcinfo.ipckeys[5] = token->keys.key[5]; + + if ((status = toks_daemon_token_instance(token,&client))) { + toks_daemon_token_reset(token); + ntapi->zw_close(client.hprocess); + return status; + } + + return NT_STATUS_SUCCESS; + +} diff --git a/src/daemon/toks_daemon_loop.c b/src/daemon/toks_daemon_loop.c index 93a8b8f..5abf3db 100644 --- a/src/daemon/toks_daemon_loop.c +++ b/src/daemon/toks_daemon_loop.c @@ -21,6 +21,7 @@ static toks_daemon_routine * toks_daemon_vtbl[TOKS_VTBL_ELEMENTS] = { TOKS_HANDLER(CONNECT, toks_daemon_connect), TOKS_HANDLER(TTYSIGNAL, toks_daemon_signal), + TOKS_HANDLER(ACQUIRE, toks_daemon_acquire), }; int32_t __stdcall toks_daemon_loop(void * ctx) diff --git a/src/internal/toksvc_daemon_impl.h b/src/internal/toksvc_daemon_impl.h index 377c391..83e43d3 100644 --- a/src/internal/toksvc_daemon_impl.h +++ b/src/internal/toksvc_daemon_impl.h @@ -12,6 +12,7 @@ enum toks_daemon_opcodes { TOKS_DAEMON_IPCSIGNAL, TOKS_DAEMON_SIGCHLD, TOKS_DAEMON_THREADEXIT, + TOKS_DAEMON_ACQUIRE, TOKS_DAEMON_OPCODE_CAP }; @@ -20,14 +21,17 @@ struct toks_driver_ctx; struct toks_client_ctx { void * hprocess; + void * hinstance; void * hport; void * hswap; + void * halert; nt_cid cid; }; struct toks_token { struct _nt_port_keys keys; struct toks_client_ctx client; + struct toks_token * self; }; typedef int32_t __stdcall toks_daemon_routine(struct toks_daemon_ctx *); @@ -54,5 +58,6 @@ int32_t __stdcall toks_daemon_loop(void *); int32_t __stdcall toks_daemon_connect(struct toks_daemon_ctx *); int32_t __stdcall toks_daemon_signal(struct toks_daemon_ctx *); +int32_t __stdcall toks_daemon_acquire(struct toks_daemon_ctx *); #endif