|
|
5e5175 |
/*********************************************************/
|
|
|
5e5175 |
/* toksvc: a framework-native token broker service */
|
|
|
d91fa0 |
/* Copyright (C) 2020 SysDeer Technologies, LLC */
|
|
|
5e5175 |
/* Released under GPLv2 and GPLv3; see COPYING.TOKSVC. */
|
|
|
5e5175 |
/*********************************************************/
|
|
|
5e5175 |
|
|
|
5e5175 |
#include <psxtypes/psxtypes.h>
|
|
|
5e5175 |
#include <ntapi/ntapi.h>
|
|
|
5e5175 |
|
|
|
5e5175 |
#include <toksvc/toksvc.h>
|
|
|
5e5175 |
#include "toksvc_daemon_impl.h"
|
|
|
5e5175 |
#include "toksvc_driver_impl.h"
|
|
|
f2a689 |
#include "toksvc_log_impl.h"
|
|
|
5e5175 |
|
|
|
d6a03d |
#define TOKS_VTBL_ELEMENTS TOKS_DAEMON_OPCODE_CAP - TOKS_DAEMON_OPCODE_BASE
|
|
|
d6a03d |
|
|
|
d6a03d |
#define TOKS_OPCODE_IDX(IDX) TOKS_DAEMON_ ## IDX - TOKS_DAEMON_OPCODE_BASE
|
|
|
d6a03d |
#define TOKS_HANDLER(IDX,fn) [TOKS_OPCODE_IDX(IDX)] = fn
|
|
|
d6a03d |
|
|
|
5e5175 |
|
|
|
5e5175 |
static toks_daemon_routine * toks_daemon_vtbl[TOKS_VTBL_ELEMENTS] = {
|
|
|
d6a03d |
TOKS_HANDLER(CONNECT, toks_daemon_connect),
|
|
|
d27132 |
TOKS_HANDLER(CIDQUERY, toks_daemon_cidquery),
|
|
|
d6a03d |
TOKS_HANDLER(TTYSIGNAL, toks_daemon_signal),
|
|
|
44e933 |
TOKS_HANDLER(ACQUIRE, toks_daemon_acquire),
|
|
|
c78a06 |
TOKS_HANDLER(RELEASE, toks_daemon_release),
|
|
|
3034d1 |
TOKS_HANDLER(CANCEL, toks_daemon_cancel),
|
|
|
5ab1f5 |
TOKS_HANDLER(ABORT, toks_daemon_abort),
|
|
|
e6c547 |
TOKS_HANDLER(IOCTL, toks_daemon_ioctl),
|
|
|
5e5175 |
};
|
|
|
5e5175 |
|
|
|
3e9813 |
static toks_daemon_routine * toks_client_vtbl[TOKS_VTBL_ELEMENTS] = {
|
|
|
3e9813 |
TOKS_HANDLER(CONNECT, toks_daemon_connect),
|
|
|
d27132 |
TOKS_HANDLER(CIDQUERY, toks_daemon_cidquery),
|
|
|
3e9813 |
TOKS_HANDLER(TTYSIGNAL, toks_daemon_signal),
|
|
|
3e9813 |
};
|
|
|
3e9813 |
|
|
|
91f3f7 |
static const nt_guid g_pidmap = NT_PROCESS_GUID_PIDMAP;
|
|
|
91f3f7 |
static const wchar16_t p_pidmap[6] = NT_PROCESS_OBJDIR_PREFIX_PIDMAP;
|
|
|
3187cb |
|
|
|
91f3f7 |
static const nt_guid g_ntpipc = NT_PROCESS_GUID_NTPIPC;
|
|
|
91f3f7 |
static const wchar16_t p_ntpipc[6] = NT_PROCESS_OBJDIR_PREFIX_NTPIPC;
|
|
|
3187cb |
|
|
|
35e873 |
static void toks_daemon_ctrlpid_abort(struct toks_daemon_ctx * dctx)
|
|
|
35e873 |
{
|
|
|
35e873 |
void * hport;
|
|
|
35e873 |
struct _nt_tty_sync_msg msg;
|
|
|
35e873 |
|
|
|
35e873 |
hport = dctx->hport_internal_client;
|
|
|
35e873 |
|
|
|
35e873 |
ntapi->tt_aligned_block_memset(
|
|
|
35e873 |
&msg,0,sizeof(msg));
|
|
|
35e873 |
|
|
|
35e873 |
msg.header.msg_type = NT_LPC_NEW_MESSAGE;
|
|
|
35e873 |
msg.header.data_size = sizeof(msg.data);
|
|
|
35e873 |
msg.header.msg_size = sizeof(msg);
|
|
|
35e873 |
msg.data.ttyinfo.opcode = TOKS_DAEMON_ABORT;
|
|
|
35e873 |
|
|
|
35e873 |
ntapi->zw_request_wait_reply_port(
|
|
|
35e873 |
hport,&msg,&msg;;
|
|
|
35e873 |
}
|
|
|
35e873 |
|
|
|
35e873 |
static int32_t toks_daemon_ctrlpid_wait(void * rapunzel)
|
|
|
35e873 |
{
|
|
|
35e873 |
struct toks_daemon_ctx * dctx;
|
|
|
35e873 |
|
|
|
35e873 |
dctx = (struct toks_daemon_ctx *)rapunzel;
|
|
|
35e873 |
|
|
|
35e873 |
ntapi->zw_set_event(
|
|
|
35e873 |
dctx->hswap,0);
|
|
|
35e873 |
|
|
|
35e873 |
ntapi->zw_wait_for_single_object(
|
|
|
35e873 |
dctx->hctrl,
|
|
|
35e873 |
NT_SYNC_NON_ALERTABLE,
|
|
|
35e873 |
0);
|
|
|
35e873 |
|
|
|
35e873 |
toks_daemon_ctrlpid_abort(dctx);
|
|
|
35e873 |
|
|
|
35e873 |
return ntapi->zw_terminate_thread(
|
|
|
35e873 |
NT_CURRENT_THREAD_HANDLE,
|
|
|
35e873 |
NT_STATUS_REMOTE_DISCONNECT);
|
|
|
35e873 |
|
|
|
35e873 |
}
|
|
|
35e873 |
|
|
|
35e873 |
static int32_t toks_daemon_ctrlpid_instance(struct toks_daemon_ctx * dctx)
|
|
|
35e873 |
{
|
|
|
35e873 |
int32_t status;
|
|
|
35e873 |
nt_thread_params params;
|
|
|
35e873 |
nt_cid cid;
|
|
|
35e873 |
nt_oa oa;
|
|
|
35e873 |
|
|
|
35e873 |
if ((dctx->ctrlpid == 0) && (dctx->csyspid == 0))
|
|
|
35e873 |
return NT_STATUS_SUCCESS;
|
|
|
35e873 |
|
|
|
35e873 |
if (dctx->ctrlpid) {
|
|
|
35e873 |
dctx->reqtokpid = dctx->ctrlpid;
|
|
|
35e873 |
|
|
|
35e873 |
if ((status = toks_daemon_pidopen(dctx)))
|
|
|
35e873 |
return status;
|
|
|
35e873 |
|
|
|
35e873 |
dctx->csyspid = dctx->reqsyspid;
|
|
|
35e873 |
}
|
|
|
35e873 |
|
|
|
35e873 |
oa.len = sizeof(oa);
|
|
|
35e873 |
oa.root_dir = 0;
|
|
|
35e873 |
oa.obj_name = 0;
|
|
|
35e873 |
oa.obj_attr = 0;
|
|
|
35e873 |
oa.sec_desc = 0;
|
|
|
35e873 |
oa.sec_qos = 0;
|
|
|
35e873 |
|
|
|
35e873 |
cid.process_id = dctx->csyspid;
|
|
|
35e873 |
cid.thread_id = 0;
|
|
|
35e873 |
|
|
|
35e873 |
if ((status = ntapi->zw_open_process(
|
|
|
35e873 |
&dctx->hctrl,
|
|
|
35e873 |
NT_PROCESS_SYNCHRONIZE,
|
|
|
35e873 |
&oa,&cid)))
|
|
|
35e873 |
return status;
|
|
|
35e873 |
|
|
|
35e873 |
if ((status = ntapi->tt_create_private_event(
|
|
|
35e873 |
&dctx->hswap,
|
|
|
35e873 |
NT_NOTIFICATION_EVENT,
|
|
|
35e873 |
NT_EVENT_NOT_SIGNALED)))
|
|
|
35e873 |
return status;
|
|
|
35e873 |
|
|
|
35e873 |
ntapi->tt_aligned_block_memset(
|
|
|
35e873 |
¶ms,0,sizeof(params));
|
|
|
35e873 |
|
|
|
35e873 |
params.hprocess = NT_CURRENT_PROCESS_HANDLE;
|
|
|
35e873 |
params.start = toks_daemon_ctrlpid_wait;
|
|
|
35e873 |
params.arg = dctx;
|
|
|
35e873 |
params.stack_size_commit = 4 * 1024;
|
|
|
35e873 |
params.stack_size_reserve = 4 * 1024;
|
|
|
35e873 |
params.creation_flags = NT_CREATE_LOCAL_THREAD;
|
|
|
35e873 |
|
|
|
35e873 |
if ((status = ntapi->tt_create_thread(¶ms))) {
|
|
|
35e873 |
ntapi->zw_close(dctx->hctrl);
|
|
|
35e873 |
ntapi->zw_close(dctx->hswap);
|
|
|
35e873 |
return status;
|
|
|
35e873 |
}
|
|
|
35e873 |
|
|
|
35e873 |
status = ntapi->zw_wait_for_single_object(
|
|
|
35e873 |
dctx->hswap,
|
|
|
35e873 |
NT_SYNC_NON_ALERTABLE,
|
|
|
35e873 |
0);
|
|
|
35e873 |
|
|
|
35e873 |
ntapi->zw_close(dctx->hswap);
|
|
|
35e873 |
ntapi->zw_close(params.hthread);
|
|
|
35e873 |
|
|
|
35e873 |
if (status) {
|
|
|
35e873 |
ntapi->zw_close(dctx->hctrl);
|
|
|
35e873 |
return status;
|
|
|
35e873 |
}
|
|
|
35e873 |
|
|
|
35e873 |
return NT_STATUS_SUCCESS;
|
|
|
35e873 |
}
|
|
|
35e873 |
|
|
|
3187cb |
static int toks_server_init_pidmap_object_directory(nt_rtdata * rtdata)
|
|
|
3187cb |
{
|
|
|
3187cb |
return rtdata->hpidmapdir
|
|
|
3187cb |
? NT_STATUS_SUCCESS
|
|
|
3187cb |
: ntapi->tt_open_ipc_object_directory(
|
|
|
3187cb |
&rtdata->hpidmapdir,
|
|
|
3187cb |
NT_SEC_READ_CONTROL
|
|
|
3187cb |
| NT_DIRECTORY_QUERY
|
|
|
3187cb |
| NT_DIRECTORY_TRAVERSE
|
|
|
3187cb |
| NT_DIRECTORY_CREATE_OBJECT
|
|
|
3187cb |
| NT_DIRECTORY_CREATE_SUBDIRECTORY,
|
|
|
3187cb |
p_pidmap,&g_pidmap);
|
|
|
3187cb |
}
|
|
|
3187cb |
|
|
|
3187cb |
static int toks_server_init_ntpipc_object_directory(nt_rtdata * rtdata)
|
|
|
3187cb |
{
|
|
|
3187cb |
return rtdata->hntpipcdir
|
|
|
3187cb |
? NT_STATUS_SUCCESS
|
|
|
3187cb |
: ntapi->tt_open_ipc_object_directory(
|
|
|
3187cb |
&rtdata->hntpipcdir,
|
|
|
3187cb |
NT_SEC_READ_CONTROL
|
|
|
3187cb |
| NT_DIRECTORY_QUERY
|
|
|
3187cb |
| NT_DIRECTORY_TRAVERSE
|
|
|
3187cb |
| NT_DIRECTORY_CREATE_OBJECT
|
|
|
3187cb |
| NT_DIRECTORY_CREATE_SUBDIRECTORY,
|
|
|
3187cb |
p_ntpipc,&g_ntpipc);
|
|
|
3187cb |
}
|
|
|
3187cb |
|
|
|
3187cb |
static int toks_init_pidmap_target_symlink(struct toks_daemon_ctx * dctx)
|
|
|
3187cb |
{
|
|
|
3187cb |
int status;
|
|
|
3187cb |
void * hkeydir;
|
|
|
3187cb |
|
|
|
3187cb |
struct toks_driver_ctx_impl * ictx = toks_get_driver_ictx(dctx->driver_ctx);
|
|
|
3187cb |
|
|
|
3187cb |
if ((status = ntapi->tt_create_keyed_object_directory(
|
|
|
3187cb |
&hkeydir,
|
|
|
3187cb |
NT_SYMBOLIC_LINK_ALL_ACCESS,
|
|
|
3187cb |
ictx->rtdata->hpidmapdir,
|
|
|
3187cb |
pe_get_current_process_id())))
|
|
|
3187cb |
return status;
|
|
|
3187cb |
|
|
|
3187cb |
if ((status = ntapi->zw_set_information_object(
|
|
|
3187cb |
hkeydir,
|
|
|
3187cb |
NT_OBJECT_HANDLE_INFORMATION,
|
|
|
3187cb |
&(nt_object_handle_information){0,0},
|
|
|
3187cb |
sizeof(nt_object_handle_information))))
|
|
|
3187cb |
return status;
|
|
|
3187cb |
|
|
|
3187cb |
return ntapi->tt_create_keyed_object_directory_entry(
|
|
|
3187cb |
&ictx->hntpipc,
|
|
|
3187cb |
NT_SYMBOLIC_LINK_ALL_ACCESS,
|
|
|
3187cb |
hkeydir,
|
|
|
3187cb |
dctx->hport_daemon,0,
|
|
|
3187cb |
pe_get_current_process_id());
|
|
|
3187cb |
}
|
|
|
3187cb |
|
|
|
3187cb |
static int toks_init_ntpipc_target_symlink(struct toks_daemon_ctx * dctx)
|
|
|
3187cb |
{
|
|
|
3187cb |
struct toks_driver_ctx_impl * ictx = toks_get_driver_ictx(dctx->driver_ctx);
|
|
|
3187cb |
|
|
|
3187cb |
return ntapi->tt_create_keyed_object_directory_entry(
|
|
|
3187cb |
&ictx->hntpipc,
|
|
|
3187cb |
NT_SYMBOLIC_LINK_ALL_ACCESS,
|
|
|
3187cb |
ictx->rtdata->hntpipcdir,
|
|
|
3187cb |
dctx->hport_daemon,0,
|
|
|
3187cb |
pe_get_current_process_id());
|
|
|
3187cb |
}
|
|
|
3187cb |
|
|
|
5e5175 |
int32_t __stdcall toks_daemon_loop(void * ctx)
|
|
|
5e5175 |
{
|
|
|
5e5175 |
struct toks_daemon_ctx * dctx;
|
|
|
3e9813 |
toks_daemon_routine ** svcvtbl;
|
|
|
5e5175 |
nt_rtdata * rtdata;
|
|
|
5e5175 |
|
|
|
5e5175 |
nt_tty_port_msg * request;
|
|
|
5e5175 |
nt_tty_port_msg * reply;
|
|
|
5e5175 |
|
|
|
5e5175 |
intptr_t port_id;
|
|
|
5e5175 |
int32_t opcode;
|
|
|
35e873 |
int32_t status;
|
|
|
5e5175 |
|
|
|
8cf1b0 |
/* runtime data */
|
|
|
5e5175 |
if (ntapi->tt_get_runtime_data(&rtdata,0))
|
|
|
5e5175 |
return NT_STATUS_INTERNAL_ERROR;
|
|
|
5e5175 |
|
|
|
8cf1b0 |
/* daemon context and controlling (system) process */
|
|
|
5e5175 |
dctx = (struct toks_daemon_ctx *)ctx;
|
|
|
5e5175 |
|
|
|
35e873 |
dctx->ctrlpid = toks_get_driver_ctrlpid(dctx->driver_ctx);
|
|
|
35e873 |
dctx->csyspid = toks_get_driver_csyspid(dctx->driver_ctx);
|
|
|
971724 |
dctx->ftokens = toks_get_driver_ntokens(dctx->driver_ctx);
|
|
|
35e873 |
|
|
|
3e9813 |
svcvtbl = (dctx->driver_ctx->cctx->drvflags & TOKS_DRIVER_MODE_SERVER)
|
|
|
3e9813 |
? toks_daemon_vtbl
|
|
|
3e9813 |
: toks_client_vtbl;
|
|
|
3e9813 |
|
|
|
35e873 |
if (svcvtbl == toks_daemon_vtbl)
|
|
|
35e873 |
if ((status = toks_daemon_ctrlpid_instance(dctx)))
|
|
|
35e873 |
ntapi->zw_terminate_process(
|
|
|
35e873 |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
35e873 |
status);
|
|
|
35e873 |
|
|
|
8cf1b0 |
/* service synchronization */
|
|
|
8cf1b0 |
if (rtdata->hsync) {
|
|
|
8cf1b0 |
ntapi->zw_set_event(rtdata->hsync,0);
|
|
|
8cf1b0 |
ntapi->zw_close(rtdata->hsync);
|
|
|
8cf1b0 |
}
|
|
|
8cf1b0 |
|
|
|
f029ca |
/* service info */
|
|
|
e8e83b |
if (svcvtbl == toks_daemon_vtbl)
|
|
|
e8e83b |
toks_log_service_info(dctx);
|
|
|
f029ca |
|
|
|
3187cb |
/* pidmap object directory */
|
|
|
3187cb |
if ((status = toks_server_init_pidmap_object_directory(rtdata)))
|
|
|
3187cb |
return status;
|
|
|
3187cb |
|
|
|
3187cb |
/* pidmap daemon symlink */
|
|
|
3187cb |
if ((status = toks_init_pidmap_target_symlink(dctx)))
|
|
|
3187cb |
return status;
|
|
|
3187cb |
|
|
|
3187cb |
/* ntpipc object directory */
|
|
|
3187cb |
if ((status = toks_server_init_ntpipc_object_directory(rtdata)))
|
|
|
3187cb |
return status;
|
|
|
3187cb |
|
|
|
3187cb |
/* ntpipc daemon symlink */
|
|
|
3187cb |
if ((status = toks_init_ntpipc_target_symlink(dctx)))
|
|
|
3187cb |
return status;
|
|
|
3187cb |
|
|
|
5e5175 |
/* init */
|
|
|
9985a1 |
request = &dctx->request;
|
|
|
9985a1 |
reply = &dctx->reply;
|
|
|
9985a1 |
|
|
|
5e5175 |
ntapi->tt_aligned_block_memset(
|
|
|
5e5175 |
request,0,sizeof(*request));
|
|
|
5e5175 |
|
|
|
5e5175 |
/* get first message */
|
|
|
5e5175 |
ntapi->zw_reply_wait_receive_port(
|
|
|
5e5175 |
dctx->hport_daemon,
|
|
|
5e5175 |
&port_id,
|
|
|
5e5175 |
0,(nt_port_message *)request);
|
|
|
5e5175 |
|
|
|
5e5175 |
/* message loop */
|
|
|
5e5175 |
do {
|
|
|
5e5175 |
switch (request->header.msg_type) {
|
|
|
5e5175 |
case NT_LPC_REQUEST:
|
|
|
5e5175 |
case NT_LPC_DATAGRAM:
|
|
|
5e5175 |
opcode = request->ttyinfo.opcode;
|
|
|
5e5175 |
break;
|
|
|
5e5175 |
|
|
|
5e5175 |
case NT_LPC_CONNECTION_REQUEST:
|
|
|
5e5175 |
opcode = TOKS_DAEMON_CONNECT;
|
|
|
5e5175 |
break;
|
|
|
5e5175 |
|
|
|
5e5175 |
default:
|
|
|
5e5175 |
opcode = -1;
|
|
|
5e5175 |
break;
|
|
|
5e5175 |
}
|
|
|
5e5175 |
|
|
|
5e5175 |
/* dispatch */
|
|
|
0c1a80 |
dctx->opcode = opcode;
|
|
|
9e552e |
dctx->noise++;
|
|
|
0c1a80 |
|
|
|
8b933d |
request->syncinfo.ipcsvc.keys.padding = 0;
|
|
|
cc692f |
|
|
|
cc692f |
if (svcvtbl == toks_daemon_vtbl)
|
|
|
cc692f |
toks_log_lpc_request(
|
|
|
cc692f |
dctx,request);
|
|
|
cc692f |
|
|
|
5e5175 |
ntapi->tt_aligned_block_memcpy(
|
|
|
5e5175 |
(uintptr_t *)reply,
|
|
|
5e5175 |
(uintptr_t *)request,
|
|
|
5e5175 |
sizeof(*reply));
|
|
|
5e5175 |
|
|
|
5e5175 |
reply->header.msg_type = NT_LPC_REPLY;
|
|
|
5e5175 |
|
|
|
e6c547 |
switch (opcode) {
|
|
|
e6c547 |
case TOKS_DAEMON_IOCTL:
|
|
|
e6c547 |
break;
|
|
|
e6c547 |
|
|
|
e6c547 |
default:
|
|
|
e6c547 |
reply->ttyinfo.opdata = reply->header.msg_id;
|
|
|
e6c547 |
}
|
|
|
e6c547 |
|
|
|
5e5175 |
if ((opcode >= TOKS_DAEMON_OPCODE_BASE) && (opcode < TOKS_DAEMON_OPCODE_CAP)) {
|
|
|
5e5175 |
opcode -= TOKS_DAEMON_OPCODE_BASE;
|
|
|
e6c547 |
reply->ttyinfo.status = svcvtbl[opcode]
|
|
|
e6c547 |
? svcvtbl[opcode](dctx)
|
|
|
e6c547 |
: NT_STATUS_NOT_IMPLEMENTED;
|
|
|
5e5175 |
} else {
|
|
|
5e5175 |
reply->ttyinfo.status = NT_STATUS_LPC_INVALID_CONNECTION_USAGE;
|
|
|
5e5175 |
}
|
|
|
5e5175 |
|
|
|
982902 |
if (svcvtbl == toks_daemon_vtbl)
|
|
|
982902 |
toks_log_lpc_reply(
|
|
|
982902 |
dctx,reply);
|
|
|
982902 |
|
|
|
5e5175 |
ntapi->tt_aligned_block_memset(
|
|
|
5e5175 |
request,0,sizeof(*request));
|
|
|
5e5175 |
|
|
|
e6c547 |
if (!reply->ttyinfo.opdata)
|
|
|
5e5175 |
ntapi->zw_reply_wait_receive_port(
|
|
|
5e5175 |
dctx->hport_daemon,
|
|
|
5e5175 |
&port_id,
|
|
|
5e5175 |
0,&request->header);
|
|
|
5e5175 |
else if (reply->header.client_id.process_id == rtdata->cid_self.process_id)
|
|
|
5e5175 |
ntapi->zw_reply_wait_receive_port(
|
|
|
5e5175 |
dctx->hport_daemon,
|
|
|
5e5175 |
&port_id,
|
|
|
5e5175 |
&reply->header,
|
|
|
5e5175 |
&request->header);
|
|
|
5e5175 |
else {
|
|
|
5e5175 |
ntapi->zw_reply_port(
|
|
|
5e5175 |
dctx->hport_daemon,
|
|
|
5e5175 |
&reply->header);
|
|
|
5e5175 |
|
|
|
5e5175 |
ntapi->zw_reply_wait_receive_port(
|
|
|
5e5175 |
dctx->hport_daemon,
|
|
|
5e5175 |
&port_id,
|
|
|
5e5175 |
0,&request->header);
|
|
|
5e5175 |
}
|
|
|
5e5175 |
} while (request->header.msg_id);
|
|
|
5e5175 |
|
|
|
5e5175 |
return NT_STATUS_INTERNAL_ERROR;
|
|
|
5e5175 |
}
|