Blame src/driver/toks_amain.c

8b5736
/*********************************************************/
8b5736
/*  toksvc: a framework-native token broker service      */
d91fa0
/*  Copyright (C) 2020  SysDeer Technologies, LLC        */
8b5736
/*  Released under GPLv2 and GPLv3; see COPYING.TOKSVC.  */
8b5736
/*********************************************************/
8b5736
8b5736
#include <ntapi/ntapi.h>
8b5736
#include <stdio.h>
8b5736
#include <unistd.h>
8b5736
8b5736
#include <toksvc/toksvc.h>
8b5736
#include "toksvc_init_impl.h"
8b5736
#include "toksvc_driver_impl.h"
8b5736
#include "toksvc_dprintf_impl.h"
8b5736
#include "toksvc_nolibc_impl.h"
b27e56
#include "toksvc_log_impl.h"
8b5736
8b5736
#ifndef TOKS_DRIVER_FLAGS
8b5736
#define TOKS_DRIVER_FLAGS	TOKS_DRIVER_VERBOSITY_ERRORS \
3e9813
				| TOKS_DRIVER_DAEMON_ALWAYS   \
8b5736
				| TOKS_DRIVER_VERBOSITY_USAGE
8b5736
#endif
8b5736
8b5736
static const char vermsg[] = "%s%s%s (git://midipix.org/toksvc): "
8b5736
			     "version %s%d.%d.%d%s.\n"
8b5736
			     "[commit reference: %s%s%s]\n";
8b5736
8b5736
static const char * const toks_ver_color[6] = {
8b5736
		"\x1b[1m\x1b[35m","\x1b[0m",
8b5736
		"\x1b[1m\x1b[32m","\x1b[0m",
8b5736
		"\x1b[1m\x1b[34m","\x1b[0m"
8b5736
};
8b5736
8b5736
static const char * const toks_ver_plain[6] = {
8b5736
		"","",
8b5736
		"","",
8b5736
		"",""
8b5736
};
8b5736
8b5736
static ssize_t toks_version(struct toks_driver_ctx * dctx)
8b5736
{
8b5736
	const struct toks_source_version * verinfo;
8b5736
	const char * const * verclr;
8b5736
8b5736
	verinfo = toks_source_version();
8b5736
	verclr  = isatty(STDOUT_FILENO) ? toks_ver_color : toks_ver_plain;
8b5736
8b5736
	return toks_dprintf(
8b5736
			STDOUT_FILENO,vermsg,
8b5736
			verclr[0],dctx->program,verclr[1],
8b5736
			verclr[2],verinfo->major,verinfo->minor,
8b5736
			verinfo->revision,verclr[3],
8b5736
			verclr[4],verinfo->commit,verclr[5]);
8b5736
}
8b5736
eb3ecd
static ssize_t toks_output_service_info(const struct toks_service_info * svcinfo)
0b7161
{
0b7161
	char guidstr[40];
0b7161
0b7161
	toks_uuid_to_string(
0b7161
		&svcinfo->uuid,
0b7161
		&guidstr);
0b7161
0b7161
	return toks_dprintf(STDOUT_FILENO,
0b7161
		"toks_uuid:%s\n"
0b7161
		"toks_syspid:%d\n"
0b7161
		"toks_systid:%d\n"
0b7161
		"toks_ctrlpid:%d\n"
0b7161
		"toks_csyspid:%d\n"
0b7161
		"toks_allocated:%d\n"
0b7161
		"toks_available:%d\n"
91a57a
		"toks_pending:%d\n"
bf3927
		"toks_tused:%d\n"
bf3927
		"toks_tfree:%d\n"
0b7161
		"toks_loglevel:%d\n",
0b7161
		guidstr,
0b7161
		svcinfo->syspid,
0b7161
		svcinfo->systid,
0b7161
		svcinfo->ctrlpid,
0b7161
		svcinfo->csyspid,
0b7161
		svcinfo->allocated,
0b7161
		svcinfo->available,
91a57a
		svcinfo->pending,
bf3927
		svcinfo->tused,
bf3927
		svcinfo->tfree,
0b7161
		svcinfo->loglevel);
0b7161
}
0b7161
eb3ecd
static void toks_output_token_info(const struct toks_token_ctx * tokctx)
eb3ecd
{
eb3ecd
	int                             idx;
eb3ecd
	const struct toks_token_info *  tinfo;
eb3ecd
	char                            path[2048];
eb3ecd
533a8c
	toks_dprintf(STDOUT_FILENO,"toks_tokens:{%s",
533a8c
		tokctx->tused ? "\n" : "");
eb3ecd
eb3ecd
	for (idx=0,tinfo=tokctx->tokens; idx<tokctx->tused; tinfo++) {
eb3ecd
		toks_log_get_arbitrary_process_name(
eb3ecd
			&(nt_cid){.process_id=tinfo->tsyspid,.thread_id=0},
eb3ecd
			path,sizeof(path));
eb3ecd
eb3ecd
		toks_dprintf(STDOUT_FILENO,
eb3ecd
			"\t{"
eb3ecd
			".token_no=%d, "
eb3ecd
			".token_id=%08X-%08X-%08X-%08X-%08X-%08X, "
eb3ecd
			".token_pid=%d, "
eb3ecd
			".token_syspid=%d, "
eb3ecd
			".token_refstr=``%s''}\n"
eb3ecd
			"\t\t"
eb3ecd
			".client_image=%s\n",
eb3ecd
			++idx,
eb3ecd
			tinfo->keys[0],
eb3ecd
			tinfo->keys[1],
eb3ecd
			tinfo->keys[2],
eb3ecd
			tinfo->keys[3],
eb3ecd
			tinfo->keys[4],
eb3ecd
			tinfo->keys[5],
eb3ecd
			tinfo->tokpid,
eb3ecd
			tinfo->tsyspid,
eb3ecd
			tinfo->meta,
eb3ecd
			path);
eb3ecd
	}
eb3ecd
eb3ecd
	toks_dprintf(STDOUT_FILENO,"}\n");
533a8c
533a8c
	toks_dprintf(STDOUT_FILENO,"toks_waiters:{%s",
533a8c
		tokctx->pending ? "\n" : "");
533a8c
533a8c
	for (idx=0; idx<tokctx->pending; tinfo++) {
533a8c
		toks_log_get_arbitrary_process_name(
533a8c
			&(nt_cid){.process_id=tinfo->tsyspid,.thread_id=0},
533a8c
			path,sizeof(path));
533a8c
533a8c
		toks_dprintf(STDOUT_FILENO,
533a8c
			"\t{"
533a8c
			".waiter_no=%d, "
533a8c
			".token_id=%08X-%08X-%08X-%08X-%08X-%08X, "
533a8c
			".token_pid=%d, "
533a8c
			".token_syspid=%d, "
533a8c
			".token_refstr=``%s''}\n"
533a8c
			"\t\t"
533a8c
			".client_image=%s\n",
533a8c
			++idx,
533a8c
			tinfo->keys[0],
533a8c
			tinfo->keys[1],
533a8c
			tinfo->keys[2],
533a8c
			tinfo->keys[3],
533a8c
			tinfo->keys[4],
533a8c
			tinfo->keys[5],
533a8c
			tinfo->tokpid,
533a8c
			tinfo->tsyspid,
533a8c
			tinfo->meta,
533a8c
			path);
533a8c
	}
533a8c
533a8c
	toks_dprintf(STDOUT_FILENO,"}\n");
eb3ecd
}
eb3ecd
8b5736
static int toks_exit(struct toks_driver_ctx * dctx, int nerrors)
8b5736
{
8b5736
	toks_free_driver_ctx(dctx);
8b5736
	return nerrors ? 2 : 0;
8b5736
}
8b5736
8b5736
int toks_main(char ** argv, char ** envp)
8b5736
{
8b5736
	int				ret;
b27e56
	int32_t				status;
8b5736
	struct toks_driver_ctx *	dctx;
2dcff1
	struct toks_token_string	toks;
0b7161
	struct toks_service_info	svcinfo;
eb3ecd
	struct toks_server_snapshot *	snapshot;
8b5736
8b5736
	if ((ret = toks_init()))
8b5736
		return ret;
8b5736
8b5736
	if ((ret = toks_get_driver_ctx(argv,envp,TOKS_DRIVER_FLAGS,&dctx)))
8b5736
		return (ret == TOKS_USAGE)
8b5736
			? !argv || !argv[0] || !argv[1]
8b5736
			: 2;
8b5736
8b5736
	if (dctx->cctx->drvflags & TOKS_DRIVER_VERSION)
8b5736
		if ((toks_version(dctx)) < 0)
8b5736
			return toks_exit(dctx,2);
8b5736
2dcff1
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_ACQUIRE) {
b27e56
		ret = (status = toks_client_acquire(dctx))
02451d
			? 2 : 0;
02451d
b27e56
		switch (status) {
b27e56
			case NT_STATUS_SUCCESS:
b27e56
				break;
b27e56
b27e56
			case NT_STATUS_TIMEOUT:
b27e56
				toks_dprintf(STDERR_FILENO,
b27e56
					"%s: the operataion timed out [0x%x].\n",
b27e56
					toks_log_basename(argv[0]),status);
b27e56
				break;
b27e56
b27e56
			default:
b27e56
				toks_dprintf(STDERR_FILENO,
b27e56
					"%s: the operataion has failed [0x%x].\n",
b27e56
					toks_log_basename(argv[0]),status);
b27e56
		}
b27e56
2dcff1
		if (ret == 0) {
2dcff1
			toks_client_token_to_str(dctx,&toks);
2dcff1
			toks_dprintf(STDOUT_FILENO,"%s\n",toks.token);
2dcff1
		}
2dcff1
	}
2dcff1
867b30
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_RELEASE) {
867b30
		ret = toks_client_release(dctx)
867b30
			? 2 : 0;
867b30
867b30
		if (ret == 0) {
867b30
			toks_client_token_to_str(dctx,&toks);
867b30
			toks_dprintf(STDOUT_FILENO,"token %s has been released\n",toks.token);
867b30
		}
867b30
867b30
		if (ret == 2) {
867b30
			toks_dprintf(STDERR_FILENO,"error: invalid token");
867b30
		}
867b30
	}
867b30
bd4f0c
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_NTOKENS_GET) {
bd4f0c
		toks_dprintf(STDOUT_FILENO,
bd4f0c
			"toks_ntokens:%d\n",
bd4f0c
			toks_get_driver_ntokens(dctx));
bd4f0c
	}
bd4f0c
0f44d8
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_NTOKENS_SET) {
0f44d8
		status = toks_service_ioctl(
0f44d8
			dctx,TOKS_IOCTL_SET_TOKEN_COUNT,
0f44d8
			&(uintptr_t){toks_get_driver_ntokens(dctx)},
0f44d8
			0);
0f44d8
0f44d8
		ret = status ? 2 : 0;
0f44d8
0f44d8
		switch (status) {
0f44d8
			case NT_STATUS_SUCCESS:
0f44d8
				toks_dprintf(STDERR_FILENO,
0f44d8
					"%s: the service's ntokens parameter "
0f44d8
					"was successfully set to %d\n",
0f44d8
					toks_log_basename(argv[0]),
0f44d8
					toks_get_driver_ntokens(dctx));
0f44d8
				break;
0f44d8
0f44d8
			default:
0f44d8
				toks_dprintf(STDERR_FILENO,
0f44d8
					"%s: the TOKS_IOCTL_SET_TOKEN_COUNT "
0f44d8
					"ioctl operataion has failed "
0f44d8
					"(check the system's documentation) [0x%x].",
0f44d8
					toks_log_basename(argv[0]),status);
0f44d8
		}
0f44d8
	}
0f44d8
7f4116
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_LOGLEVEL_GET) {
7f4116
		toks_dprintf(STDOUT_FILENO,
7f4116
			"toks_loglevel:%d\n",
7f4116
			dctx->cctx->loglevel);
7f4116
	}
7f4116
7f4116
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_LOGLEVEL_SET) {
7f4116
		status = toks_service_ioctl(
7f4116
			dctx,TOKS_IOCTL_SET_LOG_LEVEL,
7f4116
			&(uintptr_t){dctx->cctx->loglevel},
7f4116
			0);
7f4116
7f4116
		ret = status ? 2 : 0;
7f4116
7f4116
		switch (status) {
7f4116
			case NT_STATUS_SUCCESS:
7f4116
				toks_dprintf(STDERR_FILENO,
7f4116
					"%s: the service's log-level parameter "
7f4116
					"was successfully set to %d\n",
7f4116
					toks_log_basename(argv[0]),
7f4116
					dctx->cctx->loglevel);
7f4116
				break;
7f4116
7f4116
			default:
7f4116
				toks_dprintf(STDERR_FILENO,
7f4116
					"%s: the TOKS_IOCTL_SET_LOG_LEVEL "
7f4116
					"ioctl operataion has failed "
7f4116
					"(check the system's documentation) [0x%x].",
7f4116
					toks_log_basename(argv[0]),status);
7f4116
		}
7f4116
	}
7f4116
0b7161
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_SVCINFO_GET) {
0b7161
		status = toks_client_query_service(dctx,&svcinfo);
0b7161
		ret    = status ? 2 : 0;
0b7161
0b7161
		switch (status) {
0b7161
			case NT_STATUS_SUCCESS:
0b7161
				toks_output_service_info(&svcinfo);
0b7161
				break;
0b7161
0b7161
			default:
0b7161
				toks_dprintf(STDERR_FILENO,
0b7161
					"%s: the TOKS_IOCTL_GET_SERVICE_INFO "
0b7161
					"ioctl operataion has failed "
0b7161
					"(check the system's documentation) [0x%x].",
0b7161
					toks_log_basename(argv[0]),status);
0b7161
		}
0b7161
	}
0b7161
0b7161
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_SVCINFO_LOG) {
0b7161
		status = toks_service_ioctl(dctx,TOKS_IOCTL_LOG_SERVICE_INFO,0,0);
0b7161
		ret    = status ? 2 : 0;
0b7161
0b7161
		switch (status) {
0b7161
			case NT_STATUS_SUCCESS:
0b7161
				toks_dprintf(STDERR_FILENO,
0b7161
					"%s: a service info log record "
0b7161
					"was successfully created\n",
0b7161
					toks_log_basename(argv[0]));
0b7161
				break;
0b7161
0b7161
			default:
0b7161
				toks_dprintf(STDERR_FILENO,
0b7161
					"%s: the TOKS_IOCTL_LOG_SERVICE_INFO "
0b7161
					"ioctl operataion has failed "
0b7161
					"(check the system's documentation) [0x%x].",
0b7161
					toks_log_basename(argv[0]),status);
0b7161
		}
0b7161
	}
0b7161
eb3ecd
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_TOKINFO_GET) {
eb3ecd
		status = toks_get_server_snapshot(dctx,&snapshot);
eb3ecd
		ret    = status ? 2 : 0;
eb3ecd
eb3ecd
		switch (status) {
eb3ecd
			case NT_STATUS_SUCCESS:
eb3ecd
				toks_output_service_info(&snapshot->svcinfo);
eb3ecd
				toks_output_token_info(snapshot->tokctx);
eb3ecd
				toks_free_server_snapshot(snapshot);
eb3ecd
				break;
eb3ecd
eb3ecd
			default:
eb3ecd
				toks_dprintf(STDERR_FILENO,
eb3ecd
					"%s: the TOKS_IOCTL_GET_TOKEN_INFO "
eb3ecd
					"ioctl operataion has failed "
eb3ecd
					"(check the system's documentation) [0x%x].",
eb3ecd
					toks_log_basename(argv[0]),status);
eb3ecd
		}
eb3ecd
	}
eb3ecd
5e0b43
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_TOKINFO_LOG) {
5e0b43
		status = toks_service_ioctl(dctx,TOKS_IOCTL_LOG_TOKEN_INFO,0,0);
5e0b43
		ret    = status ? 2 : 0;
5e0b43
5e0b43
		switch (status) {
5e0b43
			case NT_STATUS_SUCCESS:
5e0b43
				toks_dprintf(STDERR_FILENO,
5e0b43
					"%s: a service info log record, "
5e0b43
					"followed by a info table for currently "
5e0b43
					"allocated tokens, was successfully created\n",
5e0b43
					toks_log_basename(argv[0]));
5e0b43
				break;
5e0b43
5e0b43
			default:
5e0b43
				toks_dprintf(STDERR_FILENO,
5e0b43
					"%s: the TOKS_IOCTL_LOG_TOKEN_INFO "
5e0b43
					"ioctl operataion has failed "
5e0b43
					"(check the system's documentation) [0x%x].",
5e0b43
					toks_log_basename(argv[0]),status);
5e0b43
		}
5e0b43
	}
5e0b43
255212
	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_ABORT) {
255212
		ret = (status = toks_service_abort(dctx))
255212
			? 2 : 0;
255212
255212
		switch (status) {
255212
			case NT_STATUS_SUCCESS:
255212
				toks_dprintf(STDERR_FILENO,
255212
					"%s: the server responded with no error.\n",
255212
					toks_log_basename(argv[0]),status);
255212
				break;
255212
255212
			case NT_STATUS_ACCESS_DENIED:
255212
				toks_dprintf(STDERR_FILENO,
255212
					"%s: the abort operataion timed (access denied) [0x%x].\n",
255212
					toks_log_basename(argv[0]),status);
255212
				break;
255212
255212
			default:
255212
				toks_dprintf(STDERR_FILENO,
255212
					"%s: the abort operataion failed ",
255212
					"(check the system's documentation) [0x%x].",
255212
					toks_log_basename(argv[0]),status);
255212
		}
255212
	}
255212
618937
	return (dctx->cctx->drvflags & TOKS_DRIVER_MODE_SERVER)
618937
		? NT_STATUS_SERVICE_NOTIFICATION
618937
		: toks_exit(dctx,ret);
8b5736
}