#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libssh/priv.h>
static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
char *tmp;
char *ptr = NULL;
int ok = 0;
tmp = calloc(1, len);
if (tmp == NULL) {
return 0;
}
while (!ok) {
if (buf[0] != '\0') {
fprintf(stdout, "%s[%s] ", prompt, buf);
} else {
fprintf(stdout, "%s", prompt);
}
fflush(stdout);
if (fgets(tmp, len, stdin) == NULL) {
free(tmp);
return 0;
}
if ((ptr = strchr(tmp, '\n'))) {
*ptr = '\0';
}
fprintf(stdout, "\n");
if (*tmp) {
strncpy(buf, tmp, len);
}
if (verify) {
char *key_string;
key_string = calloc(1, len);
if (key_string == NULL) {
break;
}
fprintf(stdout, "\nVerifying, please re-enter. %s", prompt);
fflush(stdout);
if (! fgets(key_string, len, stdin)) {
explicit_bzero(key_string, len);
SAFE_FREE(key_string);
clearerr(stdin);
continue;
}
if ((ptr = strchr(key_string, '\n'))) {
*ptr = '\0';
}
fprintf(stdout, "\n");
if (strcmp(buf, key_string)) {
printf("\n\07\07Mismatch - try again\n");
explicit_bzero(key_string, len);
SAFE_FREE(key_string);
fflush(stdout);
continue;
}
explicit_bzero(key_string, len);
SAFE_FREE(key_string);
}
ok = 1;
}
explicit_bzero(tmp, len);
free(tmp);
return ok;
}
#ifdef _WIN32
#include <windows.h>
int ssh_getpass(const char *prompt,
char *buf,
size_t len,
int echo,
int verify) {
HANDLE h;
DWORD mode = 0;
int ok;
if (prompt == NULL || buf == NULL || len < 2) {
return -1;
}
h = GetStdHandle(STD_INPUT_HANDLE);
if (!GetConsoleMode(h, &mode)) {
return -1;
}
if (!echo) {
if (!SetConsoleMode(h, mode & ~ENABLE_ECHO_INPUT)) {
return -1;
}
}
ok = ssh_gets(prompt, buf, len, verify);
SetConsoleMode(h, mode);
if (!ok) {
explicit_bzero(buf, len);
return -1;
}
buf[len - 1] = '\0';
return 0;
}
#else
#include <fcntl.h>
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
int ssh_getpass(const char *prompt,
char *buf,
size_t len,
int echo,
int verify) {
struct termios attr;
struct termios old_attr;
int ok = 0;
int fd = -1;
if (prompt == NULL || buf == NULL || len < 2) {
return -1;
}
if (isatty(STDIN_FILENO)) {
ZERO_STRUCT(attr);
ZERO_STRUCT(old_attr);
if (tcgetattr(STDIN_FILENO, &attr) < 0) {
perror("tcgetattr");
return -1;
}
memcpy(&old_attr, &attr, sizeof(attr));
if((fd = fcntl(0, F_GETFL, 0)) < 0) {
perror("fcntl");
return -1;
}
if (!echo) {
attr.c_lflag &= ~(ECHO);
}
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) < 0) {
perror("tcsetattr");
return -1;
}
}
if (fd & O_NDELAY) {
ok = fcntl(0, F_SETFL, fd & ~O_NDELAY);
if (ok < 0) {
perror("fcntl");
return -1;
}
}
ok = ssh_gets(prompt, buf, len, verify);
if (isatty(STDIN_FILENO)) {
tcsetattr(STDIN_FILENO, TCSANOW, &old_attr);
}
if (fd & O_NDELAY) {
ok = fcntl(0, F_SETFL, fd);
if (ok < 0) {
perror("fcntl");
return -1;
}
}
if (!ok) {
explicit_bzero(buf, len);
return -1;
}
buf[len - 1] = '\0';
return 0;
}
#endif