sftp-server.exe first code drop that works

sftp-server.exe code modified to work in Windows as NoMachine never
finished it to work. I/O handling to work as a subsystem and
openssh7.1p1 sshbuf_new() buffer system code had to be used. sshd_config
file need location of sftp subsystem to be specified.
This commit is contained in:
quamrulmina 2015-09-30 20:26:32 -05:00
parent df2ea3875e
commit 5b06ebbbb5
4 changed files with 115 additions and 153 deletions

View File

@ -93,6 +93,7 @@ static char pw_gecos[UNLEN + 1] = {'\0'};
static char pw_username[UNLEN + 1] = {'\0'}; static char pw_username[UNLEN + 1] = {'\0'};
static char pw_passwd[UNLEN + 1] = {'\0'}; static char pw_passwd[UNLEN + 1] = {'\0'};
static wchar_t pw_homedir[MAX_PATH] = {L'\0'}; static wchar_t pw_homedir[MAX_PATH] = {L'\0'};
static char pw_homedir_ascii[MAX_PATH] = {'\0'};
static char pw_password[MAX_PATH] = {'\0'}; static char pw_password[MAX_PATH] = {'\0'};
static char pw_shellpath[MAX_PATH] = {'\0'}; static char pw_shellpath[MAX_PATH] = {'\0'};
@ -226,7 +227,7 @@ struct passwd *getpwuid(uid_t uid)
pw.pw_passwd = pw_password; pw.pw_passwd = pw_password;
pw.pw_gecos = pw_gecos; pw.pw_gecos = pw_gecos;
pw.pw_shell = pw_shellpath; pw.pw_shell = pw_shellpath;
pw.pw_dir = pw_homedir; pw.pw_dir = pw_homedir_ascii;
/* /*
* Get the current user's name. * Get the current user's name.
@ -275,19 +276,31 @@ struct passwd *getpwuid(uid_t uid)
debug3("getpwuid: homedir [%ls]", homedir_w); debug3("getpwuid: homedir [%ls]", homedir_w);
wcsncpy(pw_homedir, homedir_w, sizeof(pw_homedir)); //wcsncpy(pw_homedir, homedir_w, sizeof(pw_homedir));
// convert to ascii from widechar(unicode)
int rc = WideCharToMultiByte( CP_UTF8, // UTF8/ANSI Code Page
0, // No special handling of unmapped chars
homedir_w, // wide-character string to be converted
-1, // Unicode src str len, -1 means calc it
pw_homedir_ascii,
sizeof(pw_homedir_ascii),
NULL, NULL ); // Unrepresented char replacement - Use Default
free(homedir_w); free(homedir_w);
if ( rc == 0 ) {
debug3("Could not convert homedirectory [%ls]from unicode to utf8", homedir_w);
}
/* /*
* Point to the username static variable. * Point to the username static variable.
*/ */
pw.pw_name = pw_username; //pw.pw_name = pw_username;
pw.pw_passwd = pw_passwd; //pw.pw_passwd = pw_passwd;
pw.pw_gecos = pw_gecos; //pw.pw_gecos = pw_gecos;
pw.pw_shell = pw_shellpath; //pw.pw_shell = pw_shellpath;
pw.pw_dir = pw_homedir; //pw.pw_dir = pw_homedir;
return &pw; return &pw;
} }

View File

@ -112,7 +112,8 @@ AuthorizedKeysFile .ssh/authorized_keys
#Banner none #Banner none
# override default of no subsystems # override default of no subsystems
Subsystem sftp /usr/libexec/sftp-server #Subsystem sftp /usr/libexec/sftp-server
Subsystem sftp /win32openssh/bin/sftp-server.exe
# Example of overriding settings on a per-user basis # Example of overriding settings on a per-user basis
#Match User anoncvs #Match User anoncvs

View File

@ -746,12 +746,12 @@ process_open(u_int32_t id)
char *name; char *name;
int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
#ifdef WIN32_FIXME // #ifdef WIN32_FIXME
name = buffer_get_string_local8_from_utf8(&iqueue, NULL); // name = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else //#else
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 )
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif /* WIN32_FIXME */ //#endif /* WIN32_FIXME */
if ((r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ if ((r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
(r = decode_attrib(iqueue, &a)) != 0) (r = decode_attrib(iqueue, &a)) != 0)
@ -900,7 +900,8 @@ process_do_stat(u_int32_t id, int do_lstat)
#ifdef WIN32_FIXME #ifdef WIN32_FIXME
name = buffer_get_string_local8_from_utf8(&iqueue, NULL); if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (realpathWin32(name, resolvedname)) if (realpathWin32(name, resolvedname))
{ {
@ -923,7 +924,7 @@ process_do_stat(u_int32_t id, int do_lstat)
debug3("request %u: %sstat", id, do_lstat ? "l" : ""); debug3("request %u: %sstat", id, do_lstat ? "l" : "");
verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
r = do_lstat ? lstat(name, &st) : stat(name, &st); r = do_lstat ? lstat(name, &st) : stat(name, &st);
#endif /* WIN32_FIXME */ #endif /* WIN32_FIXME */
if (r < 0) { if (r < 0) {
status = errno_to_portable(errno); status = errno_to_portable(errno);
} else { } else {
@ -993,12 +994,8 @@ process_setstat(u_int32_t id)
char *name; char *name;
int r, status = SSH2_FX_OK; int r, status = SSH2_FX_OK;
#ifdef WIN32_FIXME
name = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 )
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
if ((r = decode_attrib(iqueue, &a)) != 0) if ((r = decode_attrib(iqueue, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
@ -1119,13 +1116,8 @@ process_opendir(u_int32_t id)
char *path; char *path;
int r, handle, status = SSH2_FX_FAILURE; int r, handle, status = SSH2_FX_FAILURE;
#ifdef WIN32_FIXME
path = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
debug3("request %u: opendir", id); debug3("request %u: opendir", id);
@ -1225,13 +1217,9 @@ process_remove(u_int32_t id)
{ {
char *name; char *name;
int r, status = SSH2_FX_FAILURE; int r, status = SSH2_FX_FAILURE;
#ifdef WIN32_FIXME
name = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
debug3("request %u: remove", id); debug3("request %u: remove", id);
logit("remove name \"%s\"", name); logit("remove name \"%s\"", name);
@ -1248,12 +1236,8 @@ process_mkdir(u_int32_t id)
char *name; char *name;
int r, mode, status = SSH2_FX_FAILURE; int r, mode, status = SSH2_FX_FAILURE;
#ifdef WIN32_FIXME
name = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 )
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
if ((r = decode_attrib(iqueue, &a)) != 0) if ((r = decode_attrib(iqueue, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
@ -1274,14 +1258,8 @@ process_rmdir(u_int32_t id)
char *name; char *name;
int r, status; int r, status;
#ifdef WIN32_FIXME
name = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
debug3("request %u: rmdir", id); debug3("request %u: rmdir", id);
logit("rmdir name \"%s\"", name); logit("rmdir name \"%s\"", name);
@ -1297,12 +1275,12 @@ process_realpath(u_int32_t id)
char resolvedname[PATH_MAX]; char resolvedname[PATH_MAX];
char *path; char *path;
int r; int r;
#ifdef WIN32_FIXME //#ifdef WIN32_FIXME
path = buffer_get_string_local8_from_utf8(&iqueue, NULL); //path = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else //#else
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif //#endif
@ -1330,16 +1308,10 @@ process_rename(u_int32_t id)
int r, status; int r, status;
struct stat sb; struct stat sb;
#ifdef WIN32_FIXME
oldpath = buffer_get_string_local8_from_utf8(&iqueue, NULL);
newpath = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
debug3("request %u: rename", id); debug3("request %u: rename", id);
logit("rename old \"%s\" new \"%s\"", oldpath, newpath); logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
@ -1496,16 +1468,10 @@ process_extended_posix_rename(u_int32_t id)
char *oldpath, *newpath; char *oldpath, *newpath;
int r, status; int r, status;
#ifdef WIN32_FIXME
oldpath = buffer_get_string_local8_from_utf8(&iqueue, NULL);
newpath = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
debug3("request %u: posix-rename", id); debug3("request %u: posix-rename", id);
logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
@ -1653,13 +1619,8 @@ process_extended_statvfs(u_int32_t id)
int r; int r;
#ifdef WIN32_FIXME
path = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
debug3("request %u: statvfs", id); debug3("request %u: statvfs", id);
logit("statvfs \"%s\"", path); logit("statvfs \"%s\"", path);
@ -1706,15 +1667,9 @@ process_extended_hardlink(u_int32_t id)
char *oldpath, *newpath; char *oldpath, *newpath;
int r, status; int r, status;
#ifdef WIN32_FIXME
oldpath = buffer_get_string_local8_from_utf8(&iqueue, NULL);
newpath = buffer_get_string_local8_from_utf8(&iqueue, NULL);
#else
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
debug3("request %u: hardlink", id); debug3("request %u: hardlink", id);
@ -1876,6 +1831,17 @@ sftp_server_usage(void)
exit(1); exit(1);
} }
#ifdef WIN32_FIXME
DWORD select_in_handle( HANDLE in_handle)
{
DWORD bytesavail = 0 ;
//rc = WaitForSingleObject (in_handle, 0);
PeekNamedPipe(in_handle, NULL,0, NULL, &bytesavail, NULL );
return bytesavail;
}
#endif
int int
sftp_server_main(int argc, char **argv, struct passwd *user_pw) sftp_server_main(int argc, char **argv, struct passwd *user_pw)
{ {
@ -1934,8 +1900,9 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
__progname = ssh_get_progname(argv[0]); __progname = ssh_get_progname(argv[0]);
log_init(__progname, log_level, log_facility, log_stderr); log_init(__progname, log_level, log_facility, log_stderr);
#endif
pw = pwcopy(user_pw); pw = pwcopy(user_pw);
#endif
while (!skipargs && (ch = getopt(argc, argv, while (!skipargs && (ch = getopt(argc, argv,
"d:f:l:P:p:Q:u:cehR")) != -1) { "d:f:l:P:p:Q:u:cehR")) != -1) {
@ -2039,10 +2006,16 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
out = STDOUT_FILENO; out = STDOUT_FILENO;
#ifdef WIN32_FIXME #ifdef WIN32_FIXME
in = GetStdHandle(STD_INPUT_HANDLE); //in = GetStdHandle(STD_INPUT_HANDLE);
out = GetStdHandle(STD_OUTPUT_HANDLE); //out = GetStdHandle(STD_OUTPUT_HANDLE);
setmode(in, O_BINARY); //setmode(in, O_BINARY);
setmode(out, O_BINARY); //setmode(out, O_BINARY);
in = STDIN_FILENO;
out = STDOUT_FILENO;
_setmode(in,O_BINARY); // avoid CrLf translations of text mode
_setmode(out,O_BINARY); // avoid CrLf translation
HANDLE in_handle = (HANDLE) _get_osfhandle (in);
#else #else
#ifdef HAVE_CYGWIN #ifdef HAVE_CYGWIN
setmode(in, O_BINARY); setmode(in, O_BINARY);
@ -2061,8 +2034,8 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
if ((oqueue = sshbuf_new()) == NULL) if ((oqueue = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__); fatal("%s: sshbuf_new failed", __func__);
#ifdef WIN32_FIXME #ifdef WIN32_FIXME
rset = (fd_set *)xmalloc(sizeof(fd_set)); //rset = (fd_set *)xmalloc(sizeof(fd_set));
wset = (fd_set *)xmalloc(sizeof(fd_set)); //wset = (fd_set *)xmalloc(sizeof(fd_set));
#else #else
set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
rset = xmalloc(set_size); rset = xmalloc(set_size);
@ -2078,16 +2051,10 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
} }
for (;;) { for (;;) {
#ifdef WIN32_FIXME #ifndef WIN32_FIXME
FD_ZERO(rset);
FD_ZERO(wset);
#else
memset(rset, 0, set_size); memset(rset, 0, set_size);
memset(wset, 0, set_size); memset(wset, 0, set_size);
#endif
/* /*
* Ensure that we can read a full buffer and handle * Ensure that we can read a full buffer and handle
@ -2101,83 +2068,64 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
else if (r != SSH_ERR_NO_BUFFER_SPACE) else if (r != SSH_ERR_NO_BUFFER_SPACE)
fatal("%s: sshbuf_check_reserve failed: %s", fatal("%s: sshbuf_check_reserve failed: %s",
__func__, ssh_err(r)); __func__, ssh_err(r));
#endif
#ifdef WIN32_FIXME #ifdef WIN32_FIXME
/* int select_read = 0;
* FIXME: Change to wrapper to save compatibility if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
* with non-socket handles. (r = sshbuf_check_reserve(oqueue,
*/ SFTP_MAX_MSG_LENGTH)) == 0)
select_read = 1;
olen = buffer_len(&oqueue); else if (r != SSH_ERR_NO_BUFFER_SPACE)
fatal("%s: sshbuf_check_reserve failed: %s",
__func__, ssh_err(r));
if (olen > 0)
{ /* send oqueue to stdout */
FD_SET(out, wset); olen = sshbuf_len(oqueue);
}
if (select(max+1, rset, wset, NULL, NULL) < 0) if (olen > 0) {
{ len = _write(out, sshbuf_ptr(oqueue), olen);
if (errno == EINTR) if (len < 0) {
continue; error("write: %s", strerror(errno));
sftp_server_cleanup_exit(1);
} else if ((r = sshbuf_consume(oqueue, len)) != 0) {
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
}
error("select: %s", strerror(errno)); /* copy stdin to iqueue */
if ( select_read ) {
sftp_server_cleanup_exit(2); if ( select_in_handle(in_handle) || ( sshbuf_len(iqueue) <= 0)) {
} len = _read(in, buf, sizeof buf);
if (len == 0) {
debug("read eof");
sftp_server_cleanup_exit(0);
} else if (len < 0) {
error("read: %s", strerror(errno));
sftp_server_cleanup_exit(1);
} else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
}
}
/* copy stdin to iqueue */
if (FD_ISSET(in, rset)) /*
{ * Process requests from client if we can fit the results
len = recv(in, buf, sizeof buf, 0); * into the output buffer, otherwise stop processing input
* and let the output queue drain.
if (len == 0) */
{ r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH);
debug("read eof"); if (r == 0)
process();
sftp_server_cleanup_exit(0); else if (r != SSH_ERR_NO_BUFFER_SPACE)
} fatal("%s: sshbuf_check_reserve: %s",
else if (len < 0) __func__, ssh_err(r));
{ }
error("read: %s", strerror(errno));
sftp_server_cleanup_exit(1);
}
else
{
buffer_append(&iqueue, buf, len);
}
}
/* send oqueue to stdout */
if (FD_ISSET(out, wset))
{
len = send(out, buffer_ptr(&oqueue), olen, 0);
if (len < 0)
{
error("write: %s", strerror(errno));
sftp_server_cleanup_exit(1);
}
else
{
buffer_consume(&oqueue, len);
}
}
/*
* Process requests from client if we can fit the results
* into the output buffer, otherwise stop processing input
* and let the output queue drain.
*/
if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
{
process();
}
}
#else /* WIN32_FIXME */ #else /* WIN32_FIXME */
olen = sshbuf_len(oqueue); olen = sshbuf_len(oqueue);

View File

@ -2,5 +2,5 @@
#define SSH_VERSION "OpenSSH_7.1" #define SSH_VERSION "OpenSSH_7.1"
#define SSH_PORTABLE "p1 Microsoft Pragma Win32 port Sep 21 2015" #define SSH_PORTABLE "p1 Microsoft Pragma Win32 port Sep 30 2015"
#define SSH_RELEASE SSH_VERSION SSH_PORTABLE #define SSH_RELEASE SSH_VERSION SSH_PORTABLE