From 7cb73e9c5c3014d9abcd6000d9ba17c17a797b3f Mon Sep 17 00:00:00 2001
From: Alex Wilson
Date: Wed, 6 Sep 2023 16:43:25 +1000
Subject: [PATCH] Assignment 2 base patch
sys/dev/vkeyvar.h | 48 +++
usr.sbin/vkeyadm/Makefile | 14 +
usr.sbin/vkeyadm/misc.c | 90 ++++++
usr.sbin/vkeyadm/vkeyadm.c | 609 +++++++++++++++++++++++++++++++++++++
4 files changed, 761 insertions(+)
create mode 100644 sys/dev/vkeyvar.h
create mode 100644 usr.sbin/vkeyadm/Makefile
create mode 100644 usr.sbin/vkeyadm/misc.c
create mode 100644 usr.sbin/vkeyadm/vkeyadm.c
diff –git a/sys/dev/vkeyvar.h b/sys/dev/vkeyvar.h
new file mode 100644
index 000000000..53f1aa7ac
— /dev/null
+++ b/sys/dev/vkeyvar.h
@@ -0,0 +1,48 @@
+ * Copyright 2023, The University of Queensland
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#if !defined(_DEV_VKEYVAR_H_)
+#define _DEV_VKEYVAR_H_
+#include
+#include
+#include
+#include
+struct vkey_info_arg {
+ uint32_t vkey_major;
+ uint32_t vkey_minor;
+#define VKEYIOC_GET_INFO _IOR(‘z’, 0, struct vkey_info_arg)
+struct vkey_cmd_arg {
+ /* inputs */
+#define VKEY_FLAG_TRUNC_OK (1<<0)
+ uint vkey_flags;
+ uint8_t vkey_cmd;
+ struct iovec vkey_in[4];
+ /* outputs */
+ uint8_t vkey_reply;
+ size_t vkey_rlen;
+ /* input + output */
+ struct iovec vkey_out[4];
+#define VKEYIOC_CMD _IOWR('z', 1, struct vkey_cmd_arg)
+#endif /* !_DEV_VKEYVAR_H_ */
diff --git a/usr.sbin/vkeyadm/Makefile b/usr.sbin/vkeyadm/Makefile
new file mode 100644
index 000000000..c15467323
--- /dev/null
+++ b/usr.sbin/vkeyadm/Makefile
@@ -0,0 +1,14 @@
+PROG= vkeyadm
+SRCS= vkeyadm.c \
+ sshbuf.c sshbuf-getput-basic.c sshbuf-io.c sshbuf-misc.c \
+ atomicio.c misc.c log.c match.c xmalloc.c addrmatch.c addr.c \
+ fatal.c ssherr.c
+.PATH: ${.CURDIR}/../../usr.bin/ssh
+CFLAGS+= -I${.CURDIR}/../../usr.bin/ssh
+CFLAGS+= -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wunused-variable -Werror
+.include
diff –git a/usr.sbin/vkeyadm/misc.c b/usr.sbin/vkeyadm/misc.c
new file mode 100644
index 000000000..f0617e5dc
— /dev/null
+++ b/usr.sbin/vkeyadm/misc.c
@@ -0,0 +1,90 @@
+/* $OpenBSD: misc.c,v 1.181 2023/03/03 02:37:58 dtucker Exp $ */
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ * Copyright (c) 2005-2020 Damien Miller. All rights reserved.
+ * Copyright (c) 2004 Henning Brauer
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * This has been cut down to just the subset of functions needed by the
+ * sshbuf_* files used in vkeyadm.
+ * If we use the stock misc.c, we end up with references to lots of other parts
+ * of the SSH code we don’t need.
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include “xmalloc.h”
+#include “misc.h”
+#include “log.h”
+#include “ssh.h”
+#include “sshbuf.h”
+#include “ssherr.h”
+lowercase(char *s)
+ for (; *s; s++)
+ *s = tolower((u_char)*s);
+ssh_signal(int signum, sshsig_t handler)
+ struct sigaction sa, osa;
+ /* mask all other signals while in handler */
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = handler;
+ sigfillset(&sa.sa_mask);
+ if (signum != SIGALRM)
+ sa.sa_flags = SA_RESTART;
+ if (sigaction(signum, &sa, &osa) == -1) {
+ debug3(“sigaction(%s): %s”, strsignal(signum), strerror(errno));
+ return SIG_ERR;
+ return osa.sa_handler;
diff –git a/usr.sbin/vkeyadm/vkeyadm.c b/usr.sbin/vkeyadm/vkeyadm.c
new file mode 100644
index 000000000..bda3d758d
— /dev/null
+++ b/usr.sbin/vkeyadm/vkeyadm.c
@@ -0,0 +1,609 @@
+ * Copyright 2023, The University of Queensland
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * Simple test tool for vkey(4)
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include “sshbuf.h”
+#include “authfd.h”
+#include “log.h”
+#define VKEY_MAX_MSG 16384
+#define VKEY_DEVFMT “/dev/vkey%u”
+#define VKEY_MAXDEV 8
+static int cmd_list(int argc, char *argv[]);
+static int cmd_mknod(int argc, char *argv[]);
+static int cmd_sign(int fd, int argc, char *argv[]);
+static int cmd_randbytes(int fd, int argc, char *argv[]);
+static int cmd_delay(int fd, int argc, char *argv[]);
+static const char *msg_type_str(uint8_t v);
+static __dead void
+usage(void)
+ extern char *__progname;
+ fprintf(stderr, “usage: %s [-v] list\n”, __progname);
+ fprintf(stderr, ” – lists all vkey devices and keys\n”);
+ fprintf(stderr, ” %s [-v] mknod\n”, __progname);
+ fprintf(stderr, ” – creates device nodes\n”);
+ fprintf(stderr, ” %s [-d DEV] [-v] sign [-k IDX] [-c COMMENT] ”
+ “[FILE]\n”, __progname);
+ fprintf(stderr, ” – signs some data using a key\n”);
+ fprintf(stderr, ” %s [-d DEV] [-v] randbytes [-b BYTES]\n”,
+ __progname);
+ fprintf(stderr, ” – generates random bytes\n”);
+ fprintf(stderr, ” %s [-d DEV] [-v] delay [-t MSEC]\n”,
+ __progname);
+ fprintf(stderr, ” – sends a command that does a sleep before ”
+ “replying\n”);
+ exit(1);
+static int verbose = 0;
+static char devpath[PATH_MAX];
+main(int argc, char *argv[])
+ const char *subcmd;
+ struct vkey_info_arg info;
+ const char *errstr;
+ snprintf(devpath, sizeof(devpath), VKEY_DEVFMT, 0);
+ while ((ch = getopt(argc, argv, “vd:”)) != -1) {
+ switch (ch) {
+ case ‘v’:
+ ++verbose;
+ break;
+ case ‘d’:
+ if (optarg[0] == ‘/’) {
+ strlcpy(devpath, optarg, sizeof(devpath));
+ } else if (isdigit(optarg[0])) {
+ i = strtonum(optarg, 0, VKEY_MAXDEV, &errstr);
+ if (errstr != NULL) {
+ warnx(“-d arg starts with a number ”
+ “but is %s”, errstr);
+ usage();
+ snprintf(devpath, sizeof(devpath), VKEY_DEVFMT,
+ i);
+ } else {
+ strlcpy(devpath, “/dev/”, sizeof(devpath));
+ strlcat(devpath, optarg, sizeof(devpath));
+ break;
+ default:
+ usage();
+ if (optind >= argc) {
+ warnx(“subcmd required”);
+ usage();
+ argc -= optind;
+ argv += optind;
+ subcmd = argv[0];
+ optreset = 1;
+ optind = 0;
+ if (strcmp(subcmd, “list”) == 0) {
+ return (cmd_list(argc, argv));
+ } else if (strcmp(subcmd, “mknod”) == 0) {
+ return (cmd_mknod(argc, argv));
+ fd = open(devpath, O_RDWR);
+ if (fd < 0)
+ err(1, "open");
+ if (ioctl(fd, VKEYIOC_GET_INFO, &info))
+ err(1, "ioctl(VKEYIOC_GET_INFO)");
+ if (verbose) {
+ fprintf(stderr, "%s: vkey v%u.%d\n", devpath,
+ info.vkey_major, info.vkey_minor);
+ if (strcmp(subcmd, "sign") == 0) {
+ return (cmd_sign(fd, argc, argv));
+ } else if (strcmp(subcmd, "randbytes") == 0) {
+ return (cmd_randbytes(fd, argc, argv));
+ } else if (strcmp(subcmd, "delay") == 0) {
+ return (cmd_delay(fd, argc, argv));
+ warnx("unknown subcmd: '%s'", subcmd);
+ usage();
+ return (0);
+cleanup_exit(int i)
+ _exit(i);
+static int
+do_ioctl_cmd(int fd, struct vkey_cmd_arg *cmd, struct sshbuf *inbuf,
+ struct sshbuf *outbuf)
+ size_t adjust;
+ if (inbuf != NULL) {
+ cmd->vkey_in[0].iov_len = sshbuf_len(inbuf);
+ cmd->vkey_in[0].iov_base = (void *)sshbuf_ptr(inbuf);
+ if (outbuf != NULL) {
+ rc = sshbuf_reserve(outbuf, VKEY_MAX_MSG,
+ (u_char **)&cmd->vkey_out[0].iov_base);
+ if (rc != 0)
+ fatal_fr(rc, “sshbuf_reserve”);
+ cmd->vkey_out[0].iov_len = VKEY_MAX_MSG;
+ if ((rc = ioctl(fd, VKEYIOC_CMD, cmd)))
+ return (rc);
+ adjust = VKEY_MAX_MSG – cmd->vkey_rlen;
+ if (outbuf != NULL && adjust != 0) {
+ if ((rc = sshbuf_consume_end(outbuf, adjust)))
+ fatal_fr(rc, “sshbuf_consume”);
+ return (0);
+static int
+cmd_mknod(int argc, char *argv[])
+ if (argc > 1) {
+ warnx(“no extra arguments to mknod”);
+ usage();
+ for (i = 0; i < VKEY_MAXDEV; ++i) {
+ snprintf(devpath, sizeof(devpath), VKEY_DEVFMT, i);
+ if (verbose)
+ fprintf(stderr, "%s\n", devpath);
+ if (mknod(devpath, S_IFCHR | 0666, makedev(101, i))) {
+ switch (errno) {
+ case EEXIST:
+ continue;
+ default:
+ warn("mknod(%s)", devpath);
+ return (0);
+static int
+cmd_list(int argc, char *argv[])
+ struct sshbuf *buf, *sbuf;
+ uint i, j;
+ struct vkey_info_arg info;
+ struct vkey_cmd_arg cmd;
+ uint32_t count;
+ char *ktype, *comment;
+ size_t len;
+ if (argc > 1) {
+ warnx(“no extra arguments to list”);
+ usage();
+ buf = sshbuf_new();
+ sbuf = sshbuf_new();
+ for (i = 0; i < VKEY_MAXDEV; ++i) {
+ snprintf(devpath, sizeof(devpath), VKEY_DEVFMT, i);
+ fd = open(devpath, O_RDWR);
+ if (fd < 0) {
+ switch (errno) {
+ case ENXIO:
+ if (verbose)
+ warn("open(%s)", devpath);
+ continue;
+ default:
+ warn("open(%s)", devpath);
+ continue;
+ if (ioctl(fd, VKEYIOC_GET_INFO, &info)) {
+ warn("ioctl(%s, VKEYIOC_GET_INFO)", devpath);
+ continue;
+ if (verbose) {
+ fprintf(stderr, "%s: vkey v%u.%u\n", devpath,
+ info.vkey_major, info.vkey_minor);
+ bzero(&cmd, sizeof(cmd));
+ cmd.vkey_cmd = SSH2_AGENTC_REQUEST_IDENTITIES;
+ if ((rc = do_ioctl_cmd(fd, &cmd, NULL, buf))) {
+ warn("ioctl(%s, VKEYIOC_CMD)", devpath);
+ continue;
+ if (cmd.vkey_reply != SSH2_AGENT_IDENTITIES_ANSWER) {
+ warnx("%s: replied with msg type %d (%s)", devpath,
+ cmd.vkey_reply, msg_type_str(cmd.vkey_reply));
+ continue;
+ if ((rc = sshbuf_get_u32(buf, &count)))
+ fatal_fr(rc, "sshbuf_get_u32");
+ fprintf(stderr, "%s: has %d keys\n", devpath, count);
+ for (j = 0; j < count; ++j) {
+ sshbuf_reset(sbuf);
+ if ((rc = sshbuf_get_stringb(buf, sbuf)))
+ fatal_fr(rc, "sshbuf_get_stringb");
+ if ((rc = sshbuf_get_cstring(sbuf, &ktype, &len)))
+ fatal_fr(rc, "sshbuf_get_cstring");
+ if ((rc = sshbuf_get_cstring(buf, &comment, &len)))
+ fatal_fr(rc, "sshbuf_get_cstring");
+ fprintf(stderr, " key %u: type = %s, comment = %s\n",
+ j, ktype, comment);
+ free(ktype);
+ free(comment);
+ return (0);
+static int
+cmd_sign(int fd, int argc, char *argv[])
+ const char *findcmt = NULL;
+ int kidx = -1;
+ const char *errstr;
+ const char *fname = NULL;
+ int sfd;
+ struct vkey_cmd_arg cmd;
+ struct sshbuf *buf, *ibuf, *kbuf, *tbuf;
+ uint32_t count;
+ size_t len;
+ char *ktype, *comment;
+ int found;
+ char *b64;
+ while ((ch = getopt(argc, argv, "k:c:")) != -1) {
+ switch (ch) {
+ case 'k':
+ kidx = strtonum(optarg, 0, UINT32_MAX, &errstr);
+ if (errstr != NULL) {
+ warnx("-k arg must be a number but is %s",
+ errstr);
+ usage();
+ break;
+ case 'c':
+ findcmt = optarg;
+ break;
+ default:
+ usage();
+ argc -= optind;
+ argv += optind;
+ if (argc == 1) {
+ fname = argv[0];
+ sfd = open(fname, O_RDONLY);
+ if (sfd < 0)
+ err(1, "open(%s)", fname);
+ } else if (argc > 1) {
+ warnx(“too many arguments to sign”);
+ usage();
+ } else {
+ sfd = STDIN_FILENO;
+ buf = sshbuf_new();
+ kbuf = sshbuf_new();
+ ibuf = sshbuf_new();
+ bzero(&cmd, sizeof(cmd));
+ cmd.vkey_cmd = SSH2_AGENTC_REQUEST_IDENTITIES;
+ if ((rc = do_ioctl_cmd(fd, &cmd, NULL, buf))) {
+ err(1, “ioctl(%s, VKEYIOC_CMD)”, devpath);
+ if (cmd.vkey_reply != SSH2_AGENT_IDENTITIES_ANSWER) {
+ errx(1, “%s: replied with msg type %d (%s)”, devpath,
+ cmd.vkey_reply, msg_type_str(cmd.vkey_reply));
+ if ((rc = sshbuf_get_u32(buf, &count)))
+ fatal_fr(rc, “sshbuf_get_u32”);
+ found = 0;
+ for (i = 0; i < count; ++i) {
+ sshbuf_reset(kbuf);
+ if ((rc = sshbuf_get_stringb(buf, kbuf)))
+ fatal_fr(rc, "sshbuf_get_stringb");
+ tbuf = sshbuf_fromb(kbuf);
+ if ((rc = sshbuf_get_cstring(tbuf, &ktype, &len)))
+ fatal_fr(rc, "sshbuf_get_cstring");
+ sshbuf_free(tbuf);
+ if ((rc = sshbuf_get_cstring(buf, &comment, &len)))
+ fatal_fr(rc, "sshbuf_get_cstring");
+ if (kidx > -1) {
+ if ((uint)kidx == i) {
+ found = 1;
+ break;
+ } else if (findcmt != NULL) {
+ if (strstr(comment, findcmt) != NULL) {
+ found = 1;
+ break;
+ } else {
+ /* user gave no filters: use first key */
+ found = 1;
+ break;
+ free(ktype);
+ free(comment);
+ if (!found)
+ errx(1, “%s: failed to find key”, devpath);
+ if (verbose) {
+ fprintf(stderr, “%s: using key %u (type = %s, comment = %s)\n”,
+ devpath, i, ktype, comment);
+ sshbuf_reset(buf);
+ if ((rc = sshbuf_read(sfd, buf, VKEY_MAX_MSG, &len)))
+ fatal_fr(rc, “sshbuf_read”);
+ } while (len == VKEY_MAX_MSG);
+ if ((rc = sshbuf_put_stringb(ibuf, kbuf)))
+ fatal_fr(rc, “sshbuf_put_stringb”);
+ if ((rc = sshbuf_put_stringb(ibuf, buf)))
+ fatal_fr(rc, “sshbuf_put_stringb”);
+ if ((rc = sshbuf_put_u32(ibuf, 0)))
+ fatal_fr(rc, “sshbuf_put_u32”);
+ if (verbose) {
+ fprintf(stderr, “sending cmd with %zu byte body\n”,
+ sshbuf_len(ibuf));
+ bzero(&cmd, sizeof(cmd));
+ cmd.vkey_cmd = SSH2_AGENTC_SIGN_REQUEST;
+ sshbuf_reset(buf);
+ if ((rc = do_ioctl_cmd(fd, &cmd, ibuf, buf))) {
+ err(1, “ioctl(%s, VKEYIOC_CMD)”, devpath);
+ if (cmd.vkey_reply != SSH2_AGENT_SIGN_RESPONSE) {
+ errx(1, “%s: replied with msg type %d (%s)”, devpath,
+ cmd.vkey_reply, msg_type_str(cmd.vkey_reply));
+ sshbuf_reset(kbuf);
+ if ((rc = sshbuf_get_stringb(buf, kbuf)))
+ fatal_fr(rc, “sshbuf_get_stringb”);
+ b64 = sshbuf_dtob64_string(kbuf, 0);
+ fprintf(stdout, “%s\n”, b64);
+ return (0);
+static int
+cmd_randbytes(int fd, int argc, char *argv[])
+ struct sshbuf *buf, *obuf;
+ uint32_t bytes = 16;
+ char *b64;
+ const char *errstr;
+ struct vkey_cmd_arg cmd;
+ while ((ch = getopt(argc, argv, “b:”)) != -1) {
+ switch (ch) {
+ case ‘b’:
+ bytes = strtonum(optarg, 1, UINT32_MAX, &errstr);
+ if (errstr != NULL) {
+ warnx(“-b arg must be a number but is %s”,
+ errstr);
+ usage();
+ break;
+ default:
+ usage();
+ argc -= optind;
+ argv += optind;
+ if (argc > 0) {
+ warnx(“too many arguments to randbytes”);
+ usage();
+ buf = sshbuf_new();
+ obuf = sshbuf_new();
+ if ((rc = sshbuf_put_cstring(buf,
+ fatal_fr(rc, “sshbuf_put_cstring”);
+ if ((rc = sshbuf_put_u32(buf, bytes)))
+ fatal_fr(rc, “sshbuf_put_u32”);
+ bzero(&cmd, sizeof(cmd));
+ cmd.vkey_cmd = SSH_AGENTC_EXTENSION;
+ if ((rc = do_ioctl_cmd(fd, &cmd, buf, obuf))) {
+ err(1, “ioctl(%s, VKEYIOC_CMD)”, devpath);
+ if (cmd.vkey_reply != SSH_AGENT_SUCCESS) {
+ errx(1, “%s: replied with msg type %d (%s)”, devpath,
+ cmd.vkey_reply, msg_type_str(cmd.vkey_reply));
+ b64 = sshbuf_dtob64_string(obuf, 0);
+ fprintf(stdout, “%s\n”, b64);
+ return (0);
+static int
+cmd_delay(int fd, int argc, char *argv[])
+ struct sshbuf *buf;
+ uint32_t msec = 1000;
+ const char *errstr;
+ struct vkey_cmd_arg cmd;
+ while ((ch = getopt(argc, argv, “t:”)) != -1) {
+ switch (ch) {
+ case ‘b’:
+ msec = strtonum(optarg, 1, UINT32_MAX, &errstr);
+ if (errstr != NULL) {
+ warnx(“-t arg must be a number but is %s”,
+ errstr);
+ usage();
+ break;
+ default:
+ usage();
+ argc -= optind;
+ argv += optind;
+ if (argc > 0) {
+ warnx(“too many arguments to delay”);
+ usage();
+ buf = sshbuf_new();
+ if ((rc = sshbuf_put_cstring(buf,
+ fatal_fr(rc, “sshbuf_put_cstring”);
+ if ((rc = sshbuf_put_u32(buf, msec)))
+ fatal_fr(rc, “sshbuf_put_u32”);
+ bzero(&cmd, sizeof(cmd));
+ cmd.vkey_cmd = SSH_AGENTC_EXTENSION;
+ if ((rc = do_ioctl_cmd(fd, &cmd, buf, NULL))) {
+ err(1, “ioctl(%s, VKEYIOC_CMD)”, devpath);
+ if (cmd.vkey_reply != SSH_AGENT_SUCCESS) {
+ errx(1, “%s: replied with msg type %d (%s)”, devpath,
+ cmd.vkey_reply, msg_type_str(cmd.vkey_reply));
+ return (0);
+static const char *
+msg_type_str(uint8_t v)
+ switch (v) {
+ case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
+ return (“SSH_AGENTC_REQUEST_RSA_IDENTITIES”);
+ case SSH_AGENT_RSA_IDENTITIES_ANSWER:
+ return (“SSH_AGENT_RSA_IDENTITIES_ANSWER”);
+ case SSH_AGENTC_RSA_CHALLENGE:
+ return (“SSH_AGENTC_RSA_CHALLENGE”);
+ case SSH_AGENT_RSA_RESPONSE:
+ return (“SSH_AGENT_RSA_RESPONSE”);
+ case SSH_AGENT_FAILURE:
+ return (“SSH_AGENT_FAILURE”);
+ case SSH_AGENT_SUCCESS:
+ return (“SSH_AGENT_SUCCESS”);
+ case SSH_AGENTC_ADD_RSA_IDENTITY:
+ return (“SSH_AGENTC_ADD_RSA_IDENTITY”);
+ case SSH_AGENTC_REMOVE_RSA_IDENTITY:
+ return (“SSH_AGENTC_REMOVE_RSA_IDENTITY”);
+ case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
+ return (“SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES”);
+ case SSH2_AGENTC_REQUEST_IDENTITIES:
+ return (“SSH2_AGENTC_REQUEST_IDENTITIES”);
+ case SSH2_AGENT_IDENTITIES_ANSWER:
+ return (“SSH2_AGENT_IDENTITIES_ANSWER”);
+ case SSH2_AGENTC_SIGN_REQUEST:
+ return (“SSH2_AGENTC_SIGN_REQUEST”);
+ case SSH2_AGENT_SIGN_RESPONSE:
+ return (“SSH2_AGENT_SIGN_RESPONSE”);
+ case SSH2_AGENTC_ADD_IDENTITY:
+ return (“SSH2_AGENTC_ADD_IDENTITY”);
+ case SSH2_AGENTC_REMOVE_IDENTITY:
+ return (“SSH2_AGENTC_REMOVE_IDENTITY”);
+ case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
+ return (“SSH2_AGENTC_REMOVE_ALL_IDENTITIES”);
+ case SSH_AGENTC_ADD_SMARTCARD_KEY:
+ return (“SSH_AGENTC_ADD_SMARTCARD_KEY”);
+ case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
+ return (“SSH_AGENTC_REMOVE_SMARTCARD_KEY”);
+ case SSH_AGENTC_LOCK:
+ return (“SSH_AGENTC_LOCK”);
+ case SSH_AGENTC_UNLOCK:
+ return (“SSH_AGENTC_UNLOCK”);
+ case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
+ return (“SSH_AGENTC_ADD_RSA_ID_CONSTRAINED”);
+ case SSH2_AGENTC_ADD_ID_CONSTRAINED:
+ return (“SSH2_AGENTC_ADD_ID_CONSTRAINED”);
+ case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
+ return (“SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED”);
+ case SSH_AGENTC_EXTENSION:
+ return (“SSH_AGENTC_EXTENSION”);
+ case SSH2_AGENT_FAILURE:
+ return (“SSH2_AGENT_FAILURE”);
+ case SSH_COM_AGENT2_FAILURE:
+ return (“SSH_COM_AGENT2_FAILURE”);
+ default:
+ return (“???”);