Simplified code around getting file type and enabled password mode for passphrase collection, Ctrl+c while entering passphrase now works

This commit is contained in:
Manoj Ampalam 2016-03-15 13:22:14 -07:00
parent 238c80b33d
commit defe8ce39f
6 changed files with 162 additions and 105 deletions

View File

@ -145,6 +145,7 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\socketio.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\fileio.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\termio.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />

View File

@ -136,9 +136,7 @@ fileio_pipe(struct w32_io* pio[2]) {
memset(pio_write, 0, sizeof(struct w32_io));
pio_read->handle = read_handle;
pio_read->internal.state = PIPE_READ_END;
pio_write->handle = write_handle;
pio_write->internal.state = PIPE_WRITE_END;
pio[0] = pio_read;
pio[1] = pio_write;
@ -281,7 +279,6 @@ fileio_open(const char *pathname, int flags, int mode) {
return pio;
}
VOID CALLBACK ReadCompletionRoutine(
_In_ DWORD dwErrorCode,
_In_ DWORD dwNumberOfBytesTransfered,
@ -301,8 +298,8 @@ VOID CALLBACK ReadCompletionRoutine(
/* initiate an async read */
int
fileio_ReadFileEx(struct w32_io* pio) {
HANDLE h = pio->handle;
debug2("ReadFileEx io:%p", pio);
if (pio->read_details.buf == NULL){
pio->read_details.buf = malloc(READ_BUFFER_SIZE);
if (!pio->read_details.buf) {
@ -313,11 +310,7 @@ fileio_ReadFileEx(struct w32_io* pio) {
pio->read_details.buf_size = READ_BUFFER_SIZE;
}
/* get underlying handle for standard io */
if (pio->type == STD_IO_FD)
h = GetStdHandle(pio->std_handle);
if (ReadFileEx(h, pio->read_details.buf, pio->read_details.buf_size,
if (ReadFileEx(WINHANDLE(pio), pio->read_details.buf, pio->read_details.buf_size,
&pio->read_overlapped, &ReadCompletionRoutine))
pio->read_details.pending = TRUE;
else {
@ -335,11 +328,6 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
int bytes_copied;
debug3("read - io:%p remaining:%d", pio, pio->read_details.remaining);
if ((pio->type == PIPE_FD) && (pio->internal.state == PIPE_WRITE_END)) {
debug("read - ERROR: called on write end of pipe, io:%p", pio);
errno = EBADF;
return -1;
}
/* if read is pending */
if (pio->read_details.pending) {
@ -357,7 +345,8 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
if (fileio_is_io_available(pio, TRUE) == FALSE) {
if (-1 == fileio_ReadFileEx(pio)) {
if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) {
if ((FILETYPE(pio) == FILE_TYPE_PIPE)
&& (errno == ERROR_NEGATIVE_SEEK)) {
/* write end of the pipe closed */
debug2("read - no more data, io:%p", pio);
errno = 0;
@ -433,14 +422,8 @@ VOID CALLBACK WriteCompletionRoutine(
int
fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
int bytes_copied;
HANDLE h = pio->handle;
debug2("write - io:%p", pio);
if ((pio->type == PIPE_FD) && (pio->internal.state == PIPE_READ_END)) {
debug("write - ERROR: write called on a read end of pipe, io:%p", pio);
errno = EBADF;
return -1;
}
if (pio->write_details.pending) {
if (w32_io_is_blocking(pio))
@ -478,11 +461,7 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
bytes_copied = min(max, pio->write_details.buf_size);
memcpy(pio->write_details.buf, buf, bytes_copied);
/* get underlying handle for standard io */
if (pio->type == STD_IO_FD)
h = GetStdHandle(pio->std_handle);
if (WriteFileEx(h, pio->write_details.buf, bytes_copied,
if (WriteFileEx(WINHANDLE(pio), pio->write_details.buf, bytes_copied,
&pio->write_overlapped, &WriteCompletionRoutine)) {
pio->write_details.pending = TRUE;
pio->write_details.remaining = bytes_copied;
@ -507,8 +486,8 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
}
else {
errno = errno_from_Win32LastError();
/* read end of the pipe closed */
if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) {
/* read end of the pipe closed ? */
if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_NEGATIVE_SEEK)) {
debug("write - ERROR:read end of the pipe closed, io:%p", pio);
errno = EPIPE;
}
@ -551,17 +530,6 @@ fileio_lseek(struct w32_io* pio, long offset, int origin) {
return 0;
}
/* isatty() implementation */
int
fileio_isatty(struct w32_io* pio) {
if (GetFileType(pio->handle) == FILE_TYPE_CHAR)
return 1;
else {
errno = EINVAL;
return 0;
}
}
/* fdopen implementation */
FILE*
fileio_fdopen(struct w32_io* pio, const char *mode) {
@ -617,12 +585,14 @@ fileio_on_select(struct w32_io* pio, BOOL rd) {
int
fileio_close(struct w32_io* pio) {
debug2("fileclose - pio:%p", pio);
CancelIo(pio->handle);
CancelIo(WINHANDLE(pio));
//let queued APCs (if any) drain
SleepEx(0, TRUE);
if (pio->type != STD_IO_FD) {//STD handles are never explicitly closed
CloseHandle(pio->handle);
CloseHandle(WINHANDLE(pio));
if (pio->read_details.buf)
free(pio->read_details.buf);

View File

@ -0,0 +1,62 @@
#include "w32fd.h"
#include "inc/defs.h"
/* Win7 - Read Term Support - START*/
int
fileio_initiateReadTerm_Win7(struct w32_io* pio) {
if (pio->read_details.pending || w32_io_is_io_available(pio, TRUE)) {
debug("Win7 term read - ERROR - called in wrong state");
errno = EINVAL;
return -1;
}
return 0;
}
/* Win7 - Read Term Support - END*/
int
termio_on_select(struct w32_io* pio, BOOL rd) {
return fileio_on_select(pio, rd);
}
int
termio_read(struct w32_io* pio, void *dst, unsigned int max) {
return fileio_read(pio, dst, max);
}
int
termio_write(struct w32_io* pio, const void *buf, unsigned int max) {
//{
// /* assert that io is in blocking mode */
// if (w32_io_is_blocking(pio) == FALSE) {
// debug("write - ERROR, nonblocking write to term is not supported");
// errno = ENOTSUP;
// return -1;
// }
// pio->write_details.remaining = bytes_copied;
// if (!WriteFile(h, buf, bytes_copied, &pio->write_details.completed, NULL))
// pio->write_details.error = GetLastError();
// else if (bytes_copied != pio->write_details.completed)
// pio->write_details.error = ERROR_INTERNAL_ERROR;
// if (pio->write_details.error != 0) {
// debug("write - ERROR writing to term %d", pio->write_details.error);
// errno = errno_from_Win32Error(pio->write_details.error);
// return -1;
// }
// else {
// pio->write_details.completed = 0;
// return bytes_copied;
// }
//}
return fileio_write(pio, buf, max);
}
int termio_close(struct w32_io* pio) {
return fileio_close(pio);
}

View File

@ -152,8 +152,13 @@ w32_io_on_select(struct w32_io* pio, BOOL rd)
{
if ((pio->type == SOCK_FD))
return socketio_on_select(pio, rd);
else
return fileio_on_select(pio, rd);
else
switch (FILETYPE(pio)) {
case FILE_TYPE_CHAR:
return termio_on_select(pio, rd);
default:
return fileio_on_select(pio, rd);
}
}
#define CHECK_FD(fd) do { \
@ -284,6 +289,7 @@ int
w32_send(int fd, const void *buf, size_t len, int flags) {
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_send(fd_table.w32_ios[fd], buf, len, flags);
}
@ -324,8 +330,8 @@ w32_pipe(int *pfds) {
if (-1 == fileio_pipe(pio))
return -1;
pio[0]->type = PIPE_FD;
pio[1]->type = PIPE_FD;
pio[0]->type = NONSOCK_FD;
pio[1]->type = NONSOCK_FD;
fd_table_set(pio[0], read_index);
fd_table_set(pio[1], write_index);
pfds[0] = read_index;
@ -348,7 +354,7 @@ w32_open(const char *pathname, int flags, ...) {
if (pio == NULL)
return -1;
pio->type = FILE_FD;
pio->type = NONSOCK_FD;
fd_table_set(pio, min_index);
debug("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index);
debug3("open - path:%s", pathname);
@ -358,17 +364,31 @@ w32_open(const char *pathname, int flags, ...) {
int
w32_read(int fd, void *dst, unsigned int max) {
CHECK_FD(fd);
if (fd_table.w32_ios[fd]->type == SOCK_FD)
return socketio_recv(fd_table.w32_ios[fd], dst, max, 0);
return fileio_read(fd_table.w32_ios[fd], dst, max);
else
switch (FILETYPE(fd_table.w32_ios[fd])) {
case FILE_TYPE_CHAR:
return termio_read(fd_table.w32_ios[fd], dst, max);
default:
return fileio_read(fd_table.w32_ios[fd], dst, max);
}
}
int
w32_write(int fd, const void *buf, unsigned int max) {
CHECK_FD(fd);
if (fd_table.w32_ios[fd]->type == SOCK_FD)
return socketio_send(fd_table.w32_ios[fd], buf, max, 0);
return fileio_write(fd_table.w32_ios[fd], buf, max);
else
switch (FILETYPE(fd_table.w32_ios[fd])) {
case FILE_TYPE_CHAR:
return termio_write(fd_table.w32_ios[fd], buf, max);
default:
return fileio_write(fd_table.w32_ios[fd], buf, max);
}
}
int
@ -395,11 +415,20 @@ w32_mkdir(const char *pathname, unsigned short mode) {
int
w32_isatty(int fd) {
struct w32_io* pio;
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
errno = EBADF;
return 0;
}
return fileio_isatty(fd_table.w32_ios[fd]);
pio = fd_table.w32_ios[fd];
if (FILETYPE(pio) == FILE_TYPE_CHAR)
return 1;
else {
errno = EINVAL;
return 0;
}
}
FILE*
@ -423,10 +452,16 @@ w32_close(int fd) {
debug("close - io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd,
pio->table_index);
fd_table_clear(pio->table_index);
if ((pio->type == SOCK_FD))
if (pio->type == SOCK_FD)
return socketio_close(pio);
else
return fileio_close(pio);
switch (FILETYPE(pio)) {
case FILE_TYPE_CHAR:
return termio_close(pio);
default:
return fileio_close(pio);
}
}
int
@ -690,7 +725,7 @@ w32_dup(int oldfd) {
memset(pio, 0, sizeof(struct w32_io));
pio->handle = target;
pio->type = FILE_FD;
pio->type = NONSOCK_FD;
fd_table_set(pio, min_index);
return min_index;
}
@ -746,7 +781,7 @@ int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock) {
}
memset(pio, 0, sizeof(struct w32_io));
pio->type = is_sock? SOCK_FD : FILE_FD;
pio->type = is_sock? SOCK_FD : NONSOCK_FD;
pio->handle = h;
fd_table_set(pio, min_index);
return min_index;

View File

@ -13,9 +13,8 @@
enum w32_io_type {
UNKNOWN_FD = 0,
SOCK_FD = 1, /*maps a socket fd*/
FILE_FD = 2, /*maps a file fd*/
PIPE_FD = 3, /*maps a pipe fd*/
STD_IO_FD = 5 /*maps a std fd*/
NONSOCK_FD = 2, /*maps a file fd, pipe fd or a tty fd*/
STD_IO_FD = 5 /*maps a std fd - ex. STDIN_FILE*/
};
enum w32_io_sock_state {
@ -26,11 +25,6 @@ enum w32_io_sock_state {
SOCK_CONNECTED = 4 /*connect completed on socket*/
};
enum w32_io_pipe_state {
PIPE_READ_END = 1, /*read end of a pipe()*/
PIPE_WRITE_END = 2 /*write end of a pipe()*/
};
/*
* This sturcture encapsulates the state info needed to map a File Descriptor
* to Win32 Handle
@ -81,6 +75,9 @@ struct w32_io {
}internal;
};
#define WINHANDLE(pio) (((pio)->type == STD_IO_FD)? GetStdHandle((pio)->std_handle):(pio)->handle)
#define FILETYPE(pio) (GetFileType(WINHANDLE(pio)))
BOOL w32_io_is_blocking(struct w32_io*);
BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd);
int wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds);
@ -118,9 +115,14 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max);
int fileio_fstat(struct w32_io* pio, struct _stat64 *buf);
int fileio_stat(const char *path, struct _stat64 *buf);
long fileio_lseek(struct w32_io* pio, long offset, int origin);
int fileio_isatty(struct w32_io* pio);
FILE* fileio_fdopen(struct w32_io* pio, const char *mode);
/* terminal io specific versions */
int termio_on_select(struct w32_io* pio, BOOL rd);
int termio_read(struct w32_io* pio, void *dst, unsigned int max);
int termio_write(struct w32_io* pio, const void *buf, unsigned int max);
int termio_close(struct w32_io* pio);
/* signal related APIs*/
void signalio_initialize();
//int signalio_add_child(HANDLE child);

View File

@ -334,57 +334,44 @@ read_passphrase(const char *prompt, int flags)
/*
* Show prompt for user.
*/
HANDLE c_in = CreateFileA("CONIN$", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
HANDLE c_out = CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
int tmp;
int originalMode, tmpMode;
_cputs(prompt);
GetConsoleMode(c_in, &originalMode);
SetConsoleMode(c_in, ENABLE_LINE_INPUT);
//SetConsoleMode(c_in, (originalMode & ~(ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT)));
len = retr = 0;
int bufsize = sizeof(buf);
GetConsoleMode(c_in, &tmpMode);
while (_kbhit())
_getch();
WriteFile(c_out, prompt, strlen(prompt), &tmp, NULL);
// write(STDOUT_FILENO, prompt, strlen(prompt));
ReadFile(c_in, buf, 1024, &tmp, NULL);
buf[tmp - 2] = '\0';
SetConsoleMode(c_in, originalMode);
CloseHandle(c_in);
CloseHandle(c_out);
while ( len < bufsize ) {
// len = retr = 0;
// int bufsize = sizeof(buf);
//while (_kbhit())
// _getch();
//while ( len < bufsize ) {
// buf[len] = (unsigned char) _getch() ;
buf[len] = (unsigned char) _getch() ;
// if ( buf[len] == '\r' ) {
// if (_kbhit() )
// _getch(); // read linefeed if its there
// break;
// }
// else if ( buf[len] == '\n' ) {
// break;
// }
// else if ( buf[len] == '\b' ) { // backspace
// if (len > 0 )
// len--; // overwrite last character
// }
// else {
if ( buf[len] == '\r' ) {
if (_kbhit() )
_getch(); // read linefeed if its there
break;
}
else if ( buf[len] == '\n' ) {
break;
}
else if ( buf[len] == '\b' ) { // backspace
if (len > 0 )
len--; // overwrite last character
}
else if (buf[len] == '\003') {
/* exit on Ctrl+C */
fatal("");
}
else {
// //_putch( (int) '*' ); // show a star in place of what is typed
// len++; // keep reading in the loop
// }
//}
//_putch( (int) '*' ); // show a star in place of what is typed
len++; // keep reading in the loop
}
}
//buf[len] = '\0' ; // get rid of the cr/lf
//write(STDOUT_FILENO,"\n", strlen("\n")); // show a newline as we do not echo password or the line
buf[len] = '\0' ; // get rid of the cr/lf
_cputs("\n"); // show a newline as we do not echo password or the line
ret = xstrdup(buf);