/*********************************************************/ /* ptycon: a pty-console bridge */ /* Copyright (C) 2016--2017 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */ /*********************************************************/ #include #include #include #include "ptycon_daemon_impl.h" #include "ptycon_driver_impl.h" #define PTYC_VTBL_ELEMENTS PTYC_DAEMON_OPCODE_CAP - PTYC_DAEMON_OPCODE_BASE static ptyc_daemon_routine * ptyc_daemon_vtbl[PTYC_VTBL_ELEMENTS] = { ptyc_daemon_connect, 0, ptyc_daemon_signal, 0, 0, 0 }; static int ptyc_init_pidmap_target_symlink(struct ptyc_daemon_ctx * dctx) { int status; void * hkeydir; struct ptyc_driver_ctx_impl * ictx = ptyc_get_driver_ictx(dctx->driver_ctx); if ((status = ntapi->tt_create_keyed_object_directory( &hkeydir, NT_SYMBOLIC_LINK_ALL_ACCESS, ictx->rtdata->hpidmapdir, pe_get_current_process_id()))) return status; if ((status = ntapi->zw_set_information_object( hkeydir, NT_OBJECT_HANDLE_INFORMATION, &(nt_object_handle_information){0,0}, sizeof(nt_object_handle_information)))) return status; return ntapi->tt_create_keyed_object_directory_entry( &ictx->hntpipc, NT_SYMBOLIC_LINK_ALL_ACCESS, hkeydir, dctx->hport_daemon,0, pe_get_current_process_id()); } static int ptyc_init_ntpipc_target_symlink(struct ptyc_daemon_ctx * dctx) { struct ptyc_driver_ctx_impl * ictx = ptyc_get_driver_ictx(dctx->driver_ctx); return ntapi->tt_create_keyed_object_directory_entry( &ictx->hntpipc, NT_SYMBOLIC_LINK_ALL_ACCESS, ictx->rtdata->hntpipcdir, dctx->hport_daemon,0, pe_get_current_process_id()); } int32_t __stdcall ptyc_daemon_loop(void * ctx) { int status; struct ptyc_daemon_ctx * dctx; nt_rtdata * rtdata; nt_tty_port_msg inbuf; nt_tty_port_msg outbuf; nt_tty_port_msg * request; nt_tty_port_msg * reply; intptr_t port_id; int32_t opcode; if (ntapi->tt_get_runtime_data(&rtdata,0)) return NT_STATUS_INTERNAL_ERROR; dctx = (struct ptyc_daemon_ctx *)ctx; /* pidmap daemon symlink */ if ((status = ptyc_init_pidmap_target_symlink(dctx))) return status; /* ntpipc daemon symlink */ if ((status = ptyc_init_ntpipc_target_symlink(dctx))) return status; /* init */ request = &inbuf; ntapi->tt_aligned_block_memset( request,0,sizeof(*request)); /* get first message */ ntapi->zw_reply_wait_receive_port( dctx->hport_daemon, &port_id, 0,(nt_port_message *)request); /* message loop */ do { switch (request->header.msg_type) { case NT_LPC_REQUEST: case NT_LPC_DATAGRAM: opcode = request->ttyinfo.opcode; break; case NT_LPC_CONNECTION_REQUEST: opcode = PTYC_DAEMON_CONNECT; break; default: opcode = -1; break; } /* dispatch */ reply = &outbuf; ntapi->tt_aligned_block_memcpy( (uintptr_t *)reply, (uintptr_t *)request, sizeof(*reply)); reply->header.msg_type = NT_LPC_REPLY; if ((opcode >= PTYC_DAEMON_OPCODE_BASE) && (opcode < PTYC_DAEMON_OPCODE_CAP)) { reply->ttyinfo.exarg = (void *)request->header.client_id.process_id; opcode -= PTYC_DAEMON_OPCODE_BASE; if (ptyc_daemon_vtbl[opcode]) reply->ttyinfo.status = ptyc_daemon_vtbl[opcode](reply); else reply->ttyinfo.status = NT_STATUS_NOT_IMPLEMENTED; } else { reply->ttyinfo.exarg = NT_INVALID_HANDLE_VALUE; reply->ttyinfo.status = NT_STATUS_LPC_INVALID_CONNECTION_USAGE; } ntapi->tt_aligned_block_memset( request,0,sizeof(*request)); reply = reply->ttyinfo.exarg ? &outbuf : 0; if (!reply) ntapi->zw_reply_wait_receive_port( dctx->hport_daemon, &port_id, 0,&request->header); else if (reply->header.client_id.process_id == rtdata->cid_self.process_id) ntapi->zw_reply_wait_receive_port( dctx->hport_daemon, &port_id, &reply->header, &request->header); else { ntapi->zw_reply_port( dctx->hport_daemon, &reply->header); ntapi->zw_reply_wait_receive_port( dctx->hport_daemon, &port_id, 0,&request->header); } } while (request->header.msg_id); return NT_STATUS_INTERNAL_ERROR; }