diff --git a/include/toksvc/toksvc.h b/include/toksvc/toksvc.h index bc1b9b1..47568a0 100644 --- a/include/toksvc/toksvc.h +++ b/include/toksvc/toksvc.h @@ -168,6 +168,22 @@ struct toks_service_info { int32_t loglevel; }; +struct toks_token_info { + int32_t tokpid; + int32_t tsyspid; + uint32_t keys[6]; + uint32_t meta[6]; + uint32_t pad; +}; + +struct toks_token_ctx { + int32_t allocated; + int32_t available; + int32_t tused; + int32_t tfree; + struct toks_token_info toks[]; +}; + struct toks_error_info { const struct toks_driver_ctx * edctx; const struct toks_unit_ctx * euctx; diff --git a/src/daemon/toks_daemon_ioctl.c b/src/daemon/toks_daemon_ioctl.c index 7dc04d2..90d46b2 100644 --- a/src/daemon/toks_daemon_ioctl.c +++ b/src/daemon/toks_daemon_ioctl.c @@ -111,6 +111,249 @@ static int32_t toks_daemon_ioctl_log_service_info(struct toks_daemon_ctx * dctx) return NT_STATUS_SUCCESS; } +static int32_t toks_daemon_ioctl_get_token_info(struct toks_daemon_ctx * dctx) +{ + int32_t status; + void * hprocess; + void * hfile; + void * hrfile; + void * addr; + char * mark; + size_t size; + int32_t idx; + nt_oa oa; + nt_sd_common_buffer sd; + nt_iosb iosb; + nt_unicode_string path; + nt_large_integer asize; + struct toks_token * token; + struct toks_token_ctx * tctx; + struct toks_token_info * tinfo; + struct toks_token_sctx stctx; + uint32_t access; + uint32_t access_owner; + uint32_t access_group; + uint32_t access_other; + uint32_t access_admin; + uint32_t keys[4]; + wchar16_t name[37]; + + /* service info */ + toks_daemon_ioctl_get_service_info(dctx); + + /* hprocess */ + oa.len = sizeof(nt_oa); + oa.root_dir = 0; + oa.obj_name = 0; + oa.obj_attr = 0; + oa.sec_desc = 0; + oa.sec_qos = 0; + + if ((status = ntapi->zw_open_process( + &hprocess, + NT_PROCESS_SYNCHRONIZE + | NT_PROCESS_DUP_HANDLE + | NT_PROCESS_QUERY_INFORMATION, + &oa,&dctx->request.header.client_id))) + return status; + + /* sd */ + access_owner = NT_GENERIC_READ | NT_GENERIC_WRITE; + access_group = NT_SEC_READ_CONTROL | NT_FILE_READ_ATTRIBUTES; + access_other = NT_SEC_READ_CONTROL | NT_FILE_READ_ATTRIBUTES; + + access_owner |= NT_SEC_STANDARD_RIGHTS_ALL; + access_admin = access_owner; + + ntapi->acl_init_common_descriptor( + &sd,0,0,0,0, + access_owner,access_group,access_other, + access_admin,access_owner, + 0); + + /* name */ + toks_query_performance_counters( + dctx->driver_ctx, + &dctx->pcnt); + + keys[0] = ntapi->tt_buffer_crc32( + dctx->noise, + &dctx->pcnt,sizeof(dctx->pcnt)); + + keys[1] = ntapi->tt_buffer_crc32( + keys[0], + &dctx->request.header,sizeof(dctx->request.header)); + + keys[2] = ntapi->tt_buffer_crc32( + keys[1], + toks_get_driver_tokens(dctx->driver_ctx), + toks_get_driver_ntokens(dctx->driver_ctx) + * sizeof(struct toks_token)); + + keys[3] = ntapi->tt_buffer_crc32( + keys[2], + dctx,sizeof(*dctx)); + + name[0] = '.'; + name[9] = '.'; + name[18] = '.'; + name[27] = '.'; + name[36] = 0; + + ntapi->tt_uint32_to_hex_utf16(keys[0],&name[1]); + ntapi->tt_uint32_to_hex_utf16(keys[1],&name[10]); + ntapi->tt_uint32_to_hex_utf16(keys[2],&name[19]); + ntapi->tt_uint32_to_hex_utf16(keys[3],&name[28]); + + /* path */ + path.strlen = 36 * sizeof(wchar16_t); + path.maxlen = 0; + path.buffer = name; + + /* oa */ + oa.len = sizeof(nt_oa); + oa.root_dir = toks_get_driver_tmpfs(dctx->driver_ctx); + oa.obj_name = &path; + oa.obj_attr = 0; + oa.sec_desc = &sd.sd; + oa.sec_qos = 0; + + /* access */ + access = NT_SEC_SYNCHRONIZE | NT_SEC_DELETE; + access |= NT_FILE_READ_DATA | NT_FILE_READ_ATTRIBUTES; + access |= NT_FILE_WRITE_DATA | NT_FILE_WRITE_ATTRIBUTES; + + /* alloc_size */ + asize.quad = __offsetof(struct toks_token_ctx,toks); + asize.quad += sizeof(struct toks_token_info) * dctx->utokens; + + /* create temporary file */ + status = ntapi->zw_create_file( + &hfile, + access,&oa,&iosb,&asize, + NT_FILE_ATTRIBUTE_NORMAL, + 0,NT_FILE_CREATE, + NT_FILE_NON_DIRECTORY_FILE + | NT_FILE_SYNCHRONOUS_IO_ALERT + | NT_FILE_DELETE_ON_CLOSE, + 0,0); + + if (status) { + ntapi->zw_close(hprocess); + return status; + } + + /* buffer */ + if (dctx->utokens <= 512) { + tctx = 0; + addr = &stctx; + size = asize.quad; + tinfo = stctx.toks; + + stctx.allocated = toks_get_driver_atokens(dctx->driver_ctx); + stctx.available = toks_get_driver_ntokens(dctx->driver_ctx); + stctx.tused = dctx->utokens; + stctx.tfree = dctx->ftokens; + } else { + size = asize.quad; + addr = toks_calloc(1,size); + + if (!addr) { + ntapi->zw_close(hfile); + ntapi->zw_close(hprocess); + return NT_STATUS_MEMORY_NOT_ALLOCATED; + } + + tctx = (struct toks_token_ctx *)addr; + tinfo = stctx.toks; + + tctx->allocated = toks_get_driver_atokens(dctx->driver_ctx); + tctx->available = toks_get_driver_ntokens(dctx->driver_ctx); + tctx->tused = dctx->utokens; + tctx->tfree = dctx->ftokens; + } + + /* token info */ + token = toks_get_driver_tokens(dctx->driver_ctx); + + for (idx=0; idxutokens; token++) { + if (token->self) { + tinfo->tokpid = token->client.tokpid; + tinfo->tsyspid = token->client.cid.process_id; + tinfo->pad = 0; + + tinfo->keys[0] = token->keys.key[0]; + tinfo->keys[1] = token->keys.key[1]; + tinfo->keys[2] = token->keys.key[2]; + tinfo->keys[3] = token->keys.key[3]; + tinfo->keys[4] = token->keys.key[4]; + tinfo->keys[5] = token->keys.key[5]; + + tinfo->meta[0] = token->meta.key[0]; + tinfo->meta[1] = token->meta.key[1]; + tinfo->meta[2] = token->meta.key[2]; + tinfo->meta[3] = token->meta.key[3]; + tinfo->meta[4] = token->meta.key[4]; + tinfo->meta[5] = token->meta.key[5]; + + idx++; + tinfo++; + } + } + + /* write */ + for (mark=addr; size; size-=iosb.info) { + status = ntapi->zw_write_file( + hfile,0,0,0, + &iosb,addr,size, + 0,0); + + switch (status) { + case NT_STATUS_SUCCESS: + mark += iosb.info; + addr = mark; + break; + + default: + ntapi->zw_close(hfile); + ntapi->zw_close(hprocess); + + if (tctx) + toks_free(tctx); + + return status; + } + } + + /* buffer */ + if (tctx) + toks_free(tctx); + + /* remote handle */ + status = ntapi->zw_duplicate_object( + NT_CURRENT_PROCESS_HANDLE, + hfile, + hprocess, + &hrfile, + 0,0, + NT_DUPLICATE_SAME_ACCESS + | NT_DUPLICATE_SAME_ATTRIBUTES); + + + ntapi->zw_close(hfile); + ntapi->zw_close(hprocess); + + switch (status) { + case NT_STATUS_SUCCESS: + dctx->reply.ttyinfo.exarg = hrfile; + return NT_STATUS_SUCCESS; + + default: + dctx->reply.ttyinfo.exarg = 0; + return status; + } +} + static int32_t toks_daemon_ioctl_log_token_info(struct toks_daemon_ctx * dctx) { toks_log_token_info(dctx); @@ -138,6 +381,9 @@ int32_t __stdcall toks_daemon_ioctl(struct toks_daemon_ctx * dctx) case TOKS_IOCTL_LOG_SERVICE_INFO: return toks_daemon_ioctl_log_service_info(dctx); + case TOKS_IOCTL_GET_TOKEN_INFO: + return toks_daemon_ioctl_get_token_info(dctx); + case TOKS_IOCTL_LOG_TOKEN_INFO: return toks_daemon_ioctl_log_token_info(dctx); diff --git a/src/internal/toksvc_daemon_impl.h b/src/internal/toksvc_daemon_impl.h index 9430274..41dcc5c 100644 --- a/src/internal/toksvc_daemon_impl.h +++ b/src/internal/toksvc_daemon_impl.h @@ -3,6 +3,7 @@ #include #include +#include enum toks_daemon_opcodes { TOKS_DAEMON_OPCODE_BASE = 0x20000, @@ -37,6 +38,14 @@ struct toks_client_ctx { nt_cid cid; }; +struct toks_token_sctx { + int32_t allocated; + int32_t available; + int32_t tused; + int32_t tfree; + struct toks_token_info toks[512]; +}; + struct toks_token { struct toks_token * self; struct toks_client_ctx client; diff --git a/src/internal/toksvc_driver_impl.h b/src/internal/toksvc_driver_impl.h index 8b112fe..818dd02 100644 --- a/src/internal/toksvc_driver_impl.h +++ b/src/internal/toksvc_driver_impl.h @@ -326,6 +326,13 @@ static inline int toks_get_driver_csyspid(const struct toks_driver_ctx * dctx) return ictx->csyspid; } +static inline void * toks_get_driver_tmpfs(const struct toks_driver_ctx * dctx) +{ + struct toks_driver_ctx_impl * ictx; + ictx = toks_get_driver_ictx(dctx); + return ictx->htmpfs; +} + static inline char * toks_get_driver_refstr(const struct toks_driver_ctx * dctx) { struct toks_driver_ctx_impl * ictx;