#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
+#include <errno.h>
#include <termios.h>
#include <unistd.h>
{
}
-void timer_change_notify(long next)
+void timer_change_notify(unsigned long next)
{
}
-int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
- char *keystr, char *fingerprint,
+/*
+ * Wrapper around Unix read(2), suitable for use on a file descriptor
+ * that's been set into nonblocking mode. Handles EAGAIN/EWOULDBLOCK
+ * by means of doing a one-fd select and then trying again; all other
+ * errors (including errors from select) are returned to the caller.
+ */
+static int block_and_read(int fd, void *buf, size_t len)
+{
+ int ret;
+
+ while ((ret = read(fd, buf, len)) < 0 && (
+#ifdef EAGAIN
+ (errno == EAGAIN) ||
+#endif
+#ifdef EWOULDBLOCK
+ (errno == EWOULDBLOCK) ||
+#endif
+ 0)) {
+
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ ret = select(fd+1, &rfds, NULL, NULL, NULL);
+ assert(ret != 0);
+ if (ret < 0)
+ return ret;
+ assert(FD_ISSET(fd, &rfds));
+ }
+
+ return ret;
+}
+
+int verify_ssh_host_key(void *frontend, char *host, int port,
+ const char *keytype, char *keystr, char *fingerprint,
void (*callback)(void *ctx, int result), void *ctx)
{
int ret;
newmode.c_lflag |= ECHO | ISIG | ICANON;
tcsetattr(0, TCSANOW, &newmode);
line[0] = '\0';
- if (read(0, line, sizeof(line) - 1) <= 0)
+ if (block_and_read(0, line, sizeof(line) - 1) <= 0)
/* handled below */;
tcsetattr(0, TCSANOW, &oldmode);
}
newmode.c_lflag |= ECHO | ISIG | ICANON;
tcsetattr(0, TCSANOW, &newmode);
line[0] = '\0';
- if (read(0, line, sizeof(line) - 1) <= 0)
+ if (block_and_read(0, line, sizeof(line) - 1) <= 0)
+ /* handled below */;
+ tcsetattr(0, TCSANOW, &oldmode);
+ }
+
+ if (line[0] == 'y' || line[0] == 'Y') {
+ postmsg(&cf);
+ return 1;
+ } else {
+ fprintf(stderr, abandoned);
+ postmsg(&cf);
+ return 0;
+ }
+}
+
+int askhk(void *frontend, const char *algname, const char *betteralgs,
+ void (*callback)(void *ctx, int result), void *ctx)
+{
+ static const char msg[] =
+ "The first host key type we have stored for this server\n"
+ "is %s, which is below the configured warning threshold.\n"
+ "The server also provides the following types of host key\n"
+ "above the threshold, which we do not have stored:\n"
+ "%s\n"
+ "Continue with connection? (y/n) ";
+ static const char msg_batch[] =
+ "The first host key type we have stored for this server\n"
+ "is %s, which is below the configured warning threshold.\n"
+ "The server also provides the following types of host key\n"
+ "above the threshold, which we do not have stored:\n"
+ "%s\n"
+ "Connection abandoned.\n";
+ static const char abandoned[] = "Connection abandoned.\n";
+
+ char line[32];
+ struct termios cf;
+
+ premsg(&cf);
+ if (console_batch_mode) {
+ fprintf(stderr, msg_batch, algname, betteralgs);
+ return 0;
+ }
+
+ fprintf(stderr, msg, algname, betteralgs);
+ fflush(stderr);
+
+ {
+ struct termios oldmode, newmode;
+ tcgetattr(0, &oldmode);
+ newmode = oldmode;
+ newmode.c_lflag |= ECHO | ISIG | ICANON;
+ tcsetattr(0, TCSANOW, &newmode);
+ line[0] = '\0';
+ if (block_and_read(0, line, sizeof(line) - 1) <= 0)
/* handled below */;
tcsetattr(0, TCSANOW, &oldmode);
}
newmode.c_lflag |= ECHO | ISIG | ICANON;
tcsetattr(0, TCSANOW, &newmode);
line[0] = '\0';
- if (read(0, line, sizeof(line) - 1) <= 0)
+ if (block_and_read(0, line, sizeof(line) - 1) <= 0)
/* handled below */;
tcsetattr(0, TCSANOW, &oldmode);
}
void logevent(void *frontend, const char *string)
{
struct termios cf;
- premsg(&cf);
+ if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE))
+ premsg(&cf);
if (console_logctx)
log_eventlog(console_logctx, string);
- postmsg(&cf);
+ if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE))
+ postmsg(&cf);
}
/*
fflush(outfp);
}
-int console_get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
+int console_get_userpass_input(prompts_t *p, const unsigned char *in,
+ int inlen)
{
size_t curr_prompt;
FILE *outfp = NULL;