Source snapshot from Powershell/openssh-portable:latestw_all

This commit is contained in:
Manoj Ampalam 2017-02-15 22:47:07 -08:00
parent e404237322
commit c8b8c4b82a
92 changed files with 6091 additions and 5747 deletions

View File

@ -54,6 +54,7 @@
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
#include "authfd.h"
extern Buffer loginmsg;
extern ServerOptions options;
@ -225,38 +226,36 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
#elif defined(WINDOWS)
/*
* Authenticate on Windows - Pass creds to ssh-agent and retrieve token
* Authenticate on Windows - Pass credentials to ssh-agent and retrieve token
* upon succesful authentication
*/
extern int auth_sock;
int sys_auth_passwd(Authctxt *authctxt, const char *password)
{
u_char *blob = NULL;
size_t blen = 0;
DWORD token = 0;
struct sshbuf *msg = NULL;
int r;
msg = sshbuf_new();
if (!msg)
return 0;
if (sshbuf_put_u8(msg, 100) != 0 ||
sshbuf_put_cstring(msg, "password") != 0 ||
sshbuf_put_cstring(msg, authctxt->user) != 0 ||
sshbuf_put_cstring(msg, password) != 0 ||
ssh_request_reply(auth_sock, msg, msg) != 0 ||
sshbuf_get_u32(msg, &token) != 0) {
debug("auth agent did not authorize client %s", authctxt->pw->pw_name);
return 0;
fatal("%s: out of memory", __func__);
if (sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE) != 0 ||
sshbuf_put_cstring(msg, PASSWD_AUTH_REQUEST) != 0 ||
sshbuf_put_cstring(msg, authctxt->pw->pw_name) != 0 ||
sshbuf_put_cstring(msg, password) != 0 ||
ssh_request_reply(auth_sock, msg, msg) != 0 ||
sshbuf_get_u32(msg, &token) != 0) {
debug("auth agent did not authorize client %s", authctxt->user);
r = 0;
goto done;
}
if (blob)
free(blob);
authctxt->methoddata = (void*)(INT_PTR)token;
r = 1;
done:
if (msg)
sshbuf_free(msg);
authctxt->methoddata = (void*)(INT_PTR)token;
return 1;
return r;
}
#endif /* WINDOWS */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.61 2016/12/30 22:08:02 djm Exp $ */
/* $OpenBSD: auth2-pubkey.c,v 1.62 2017/01/30 01:03:00 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -68,6 +68,7 @@
#include "ssherr.h"
#include "channels.h" /* XXX for session.h */
#include "session.h" /* XXX for child_set_env(); refactor? */
#include "authfd.h"
/* import */
extern ServerOptions options;
@ -189,21 +190,21 @@ userauth_pubkey(Authctxt *authctxt)
while (1) {
msg = sshbuf_new();
if (!msg)
break;
if ((r = sshbuf_put_u8(msg, 100)) != 0 ||
(r = sshbuf_put_cstring(msg, "pubkey")) != 0 ||
(r = sshkey_to_blob(key, &blob, &blen)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_cstring(msg, authctxt->pw->pw_name)) != 0 ||
(r = sshbuf_put_string(msg, sig, slen)) != 0 ||
(r = sshbuf_put_string(msg, buffer_ptr(&b), buffer_len(&b))) != 0 ||
(r = ssh_request_reply(auth_sock, msg, msg)) != 0 ||
(r = sshbuf_get_u32(msg, &token)) != 0) {
debug("auth agent did not authorize client %s", authctxt->pw->pw_name);
fatal("%s: out of memory", __func__);
if ((r = sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE)) != 0 ||
(r = sshbuf_put_cstring(msg, PUBKEY_AUTH_REQUEST)) != 0 ||
(r = sshkey_to_blob(key, &blob, &blen)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_cstring(msg, authctxt->pw->pw_name)) != 0 ||
(r = sshbuf_put_string(msg, sig, slen)) != 0 ||
(r = sshbuf_put_string(msg, buffer_ptr(&b), buffer_len(&b))) != 0 ||
(r = ssh_request_reply(auth_sock, msg, msg)) != 0 ||
(r = sshbuf_get_u32(msg, &token)) != 0) {
debug("auth agent did not authorize client %s", authctxt->user);
break;
}
debug3("auth agent authenticated %s", authctxt->pw->pw_name);
debug3("auth agent authenticated %s", authctxt->user);
break;
}
@ -620,9 +621,12 @@ process_principals(FILE *f, char *file, struct passwd *pw,
{
char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
u_long linenum = 0;
u_int i;
u_int i, found_principal = 0;
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
/* Always consume entire input */
if (found_principal)
continue;
/* Skip leading whitespace. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
@ -655,11 +659,12 @@ process_principals(FILE *f, char *file, struct passwd *pw,
if (auth_parse_options(pw, line_opts,
file, linenum) != 1)
continue;
return 1;
found_principal = 1;
continue;
}
}
}
return 0;
return found_principal;
}
static int
@ -827,6 +832,9 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
char *cp, *key_options = NULL, *fp = NULL;
const char *reason = NULL;
/* Always consume entrire file */
if (found_key)
continue;
if (found != NULL)
key_free(found);
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
@ -913,7 +921,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
file, linenum, key_type(found), fp);
free(fp);
found_key = 1;
break;
continue;
}
}
if (found != NULL)

12
auth2.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2.c,v 1.136 2016/05/02 08:49:03 djm Exp $ */
/* $OpenBSD: auth2.c,v 1.137 2017/02/03 23:05:57 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -212,6 +212,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
static int
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
struct ssh *ssh = active_state; /* XXX */
Authctxt *authctxt = ctxt;
Authmethod *m = NULL;
char *user, *service, *method, *style = NULL;
@ -235,9 +236,10 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
authctxt->user = xstrdup(user);
if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
debug2("input_userauth_request: setting up authctxt for %s", user);
debug2("%s: setting up authctxt for %s",
__func__, user);
} else {
logit("input_userauth_request: invalid user %s", user);
/* Invalid user, fake password information */
authctxt->pw = fakepw();
#ifdef SSH_AUDIT_EVENTS
PRIVSEP(audit_event(SSH_INVALID_USER));
@ -247,6 +249,8 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
if (options.use_pam)
PRIVSEP(start_pam(authctxt));
#endif
ssh_packet_set_log_preamble(ssh, "%suser %s",
authctxt->valid ? "authenticating " : "invalid ", user);
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
authctxt->service = xstrdup(service);
@ -292,6 +296,7 @@ void
userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
const char *submethod)
{
struct ssh *ssh = active_state; /* XXX */
char *methods;
int partial = 0;
@ -353,6 +358,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
packet_write_wait();
/* now we can break out */
authctxt->success = 1;
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
} else {
/* Allow initial try of "none" auth without failure penalty */

View File

@ -97,35 +97,39 @@ ssh_get_authentication_socket(int *fdp)
#ifdef WINDOWS
/* Auth socket in Windows is a static-named pipe listener in ssh-agent */
{
#define SSH_AGENT_REG_ROOT L"SOFTWARE\\SSH\\Agent"
#define SSH_AGENT_PIPE_NAME L"\\\\.\\pipe\\ssh-agent"
HKEY agent_root = 0;
DWORD agent_pid = 0, tmp_size = 4, pipe_server_pid = 0xff;
DWORD connection_attempts = 0;
HANDLE h;
RegOpenKeyExW(HKEY_LOCAL_MACHINE, SSH_AGENT_REG_ROOT, 0, KEY_QUERY_VALUE, &agent_root);
RegOpenKeyExW(HKEY_LOCAL_MACHINE, SSH_AGENT_REG_ROOT,
0, KEY_QUERY_VALUE, &agent_root);
if (agent_root) {
RegQueryValueEx(agent_root, "ProcessId", 0, NULL, (LPBYTE)&agent_pid, &tmp_size);
RegQueryValueEx(agent_root, "ProcessId", 0,
NULL, (LPBYTE)&agent_pid, &tmp_size);
RegCloseKey(agent_root);
}
do {
h = CreateFileW(SSH_AGENT_PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (h != INVALID_HANDLE_VALUE || GetLastError() != ERROR_PIPE_BUSY)
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (h != INVALID_HANDLE_VALUE || GetLastError() != ERROR_PIPE_BUSY ||
++connection_attempts > 10)
break;
Sleep(100);
} while(1);
if (h == INVALID_HANDLE_VALUE) {
debug("ssh_get_authentication_socket - CreateFileW failed error %d", GetLastError());
debug("ssh_get_authentication_socket - CreateFileW failed error %d",
GetLastError());
return SSH_ERR_AGENT_NOT_PRESENT;
}
/*
* ensure that connected server pid matches published pid. this provides service side
* auth and prevents mitm
* ensure that connected server pid matches published pid.
* this provides service side auth and prevents mitm
*/
if (!GetNamedPipeServerProcessId(h, &pipe_server_pid) || (agent_pid != pipe_server_pid)) {
if (!GetNamedPipeServerProcessId(h, &pipe_server_pid) ||
(agent_pid != pipe_server_pid)) {
debug("agent pid mismatch");
CloseHandle(h);
return SSH_ERR_AGENT_COMMUNICATION;

View File

@ -89,4 +89,14 @@ int ssh_agent_sign(int sock, struct sshkey *key,
#define SSH_AGENT_RSA_SHA2_256 0x02
#define SSH_AGENT_RSA_SHA2_512 0x04
/*
* Following are used in Windows implementation
* ssh-agent in Windows also serves user authentication
*/
#define SSH_AGENT_AUTHENTICATE 200
#define PUBKEY_AUTH_REQUEST "pubkey"
#define PASSWD_AUTH_REQUEST "password"
#define SSH_AGENT_REG_ROOT L"SOFTWARE\\SSH\\Agent"
#define SSH_AGENT_PIPE_NAME L"\\\\.\\pipe\\ssh-agent"
#endif /* AUTHFD_H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.c,v 1.356 2016/10/18 17:32:54 dtucker Exp $ */
/* $OpenBSD: channels.c,v 1.357 2017/02/01 02:59:09 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -3067,7 +3067,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
}
packet_check_eom();
c = channel_connect_to_port(host, host_port,
"connected socket", originator_string);
"connected socket", originator_string, NULL, NULL);
free(originator_string);
free(host);
if (c == NULL) {
@ -4028,9 +4028,13 @@ channel_connect_ctx_free(struct channel_connect *cctx)
memset(cctx, 0, sizeof(*cctx));
}
/* Return CONNECTING channel to remote host:port or local socket path */
/*
* Return CONNECTING channel to remote host:port or local socket path,
* passing back the failure reason if appropriate.
*/
static Channel *
connect_to(const char *name, int port, char *ctype, char *rname)
connect_to_reason(const char *name, int port, char *ctype, char *rname,
int *reason, const char **errmsg)
{
struct addrinfo hints;
int gaierr;
@ -4071,7 +4075,12 @@ connect_to(const char *name, int port, char *ctype, char *rname)
hints.ai_family = IPv4or6;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) {
if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop))
!= 0) {
if (errmsg != NULL)
*errmsg = ssh_gai_strerror(gaierr);
if (reason != NULL)
*reason = SSH2_OPEN_CONNECT_FAILED;
error("connect_to %.100s: unknown host (%s)", name,
ssh_gai_strerror(gaierr));
return NULL;
@ -4094,6 +4103,13 @@ connect_to(const char *name, int port, char *ctype, char *rname)
return c;
}
/* Return CONNECTING channel to remote host:port or local socket path */
static Channel *
connect_to(const char *name, int port, char *ctype, char *rname)
{
return connect_to_reason(name, port, ctype, rname, NULL, NULL);
}
/*
* returns either the newly connected channel or the downstream channel
* that needs to deal with this connection.
@ -4138,7 +4154,8 @@ channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
/* Check if connecting to that port is permitted and connect. */
Channel *
channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname)
channel_connect_to_port(const char *host, u_short port, char *ctype,
char *rname, int *reason, const char **errmsg)
{
int i, permit, permit_adm = 1;
@ -4163,9 +4180,11 @@ channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname
if (!permit || !permit_adm) {
logit("Received request to connect to host %.100s port %d, "
"but the request was denied.", host, port);
if (reason != NULL)
*reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
return NULL;
}
return connect_to(host, port, ctype, rname);
return connect_to_reason(host, port, ctype, rname, reason, errmsg);
}
/* Check if connecting to that path is permitted and connect. */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.120 2016/10/18 17:32:54 dtucker Exp $ */
/* $OpenBSD: channels.h,v 1.121 2017/02/01 02:59:09 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -275,7 +275,8 @@ void channel_update_permitted_opens(int, int);
void channel_clear_permitted_opens(void);
void channel_clear_adm_permitted_opens(void);
void channel_print_adm_permitted_opens(void);
Channel *channel_connect_to_port(const char *, u_short, char *, char *);
Channel *channel_connect_to_port(const char *, u_short, char *, char *, int *,
const char **);
Channel *channel_connect_to_path(const char *, char *, char *);
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
Channel *channel_connect_by_listen_address(const char *, u_short,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.289 2016/09/30 09:19:13 markus Exp $ */
/* $OpenBSD: clientloop.c,v 1.290 2017/01/29 21:35:23 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -991,7 +991,7 @@ process_cmdline(void)
CHANNEL_CANCEL_PORT_STATIC,
&options.fwd_opts) > 0;
if (!ok) {
logit("Unkown port forwarding.");
logit("Unknown port forwarding.");
goto out;
}
logit("Canceled forwarding.");

View File

@ -1,4 +1,4 @@
/* $OpenBSD: compat.c,v 1.99 2016/05/24 02:31:57 dtucker Exp $ */
/* $OpenBSD: compat.c,v 1.100 2017/02/03 23:01:19 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@ -37,6 +37,7 @@
#include "compat.h"
#include "log.h"
#include "match.h"
#include "kex.h"
int compat13 = 0;
int compat20 = 0;
@ -250,42 +251,14 @@ proto_spec(const char *spec)
return ret;
}
/*
* Filters a proposal string, excluding any algorithm matching the 'filter'
* pattern list.
*/
static char *
filter_proposal(char *proposal, const char *filter)
{
Buffer b;
char *orig_prop, *fix_prop;
char *cp, *tmp;
buffer_init(&b);
tmp = orig_prop = xstrdup(proposal);
while ((cp = strsep(&tmp, ",")) != NULL) {
if (match_pattern_list(cp, filter, 0) != 1) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, cp, strlen(cp));
} else
debug2("Compat: skipping algorithm \"%s\"", cp);
}
buffer_append(&b, "\0", 1);
fix_prop = xstrdup((char *)buffer_ptr(&b));
buffer_free(&b);
free(orig_prop);
return fix_prop;
}
char *
compat_cipher_proposal(char *cipher_prop)
{
if (!(datafellows & SSH_BUG_BIGENDIANAES))
return cipher_prop;
debug2("%s: original cipher proposal: %s", __func__, cipher_prop);
cipher_prop = filter_proposal(cipher_prop, "aes*");
if ((cipher_prop = match_filter_list(cipher_prop, "aes*")) == NULL)
fatal("match_filter_list failed");
debug2("%s: compat cipher proposal: %s", __func__, cipher_prop);
if (*cipher_prop == '\0')
fatal("No supported ciphers found");
@ -298,7 +271,8 @@ compat_pkalg_proposal(char *pkalg_prop)
if (!(datafellows & SSH_BUG_RSASIGMD5))
return pkalg_prop;
debug2("%s: original public key proposal: %s", __func__, pkalg_prop);
pkalg_prop = filter_proposal(pkalg_prop, "ssh-rsa");
if ((pkalg_prop = match_filter_list(pkalg_prop, "ssh-rsa")) == NULL)
fatal("match_filter_list failed");
debug2("%s: compat public key proposal: %s", __func__, pkalg_prop);
if (*pkalg_prop == '\0')
fatal("No supported PK algorithms found");
@ -312,10 +286,14 @@ compat_kex_proposal(char *p)
return p;
debug2("%s: original KEX proposal: %s", __func__, p);
if ((datafellows & SSH_BUG_CURVE25519PAD) != 0)
p = filter_proposal(p, "curve25519-sha256@libssh.org");
if ((p = match_filter_list(p,
"curve25519-sha256@libssh.org")) == NULL)
fatal("match_filter_list failed");
if ((datafellows & SSH_OLD_DHGEX) != 0) {
p = filter_proposal(p, "diffie-hellman-group-exchange-sha256");
p = filter_proposal(p, "diffie-hellman-group-exchange-sha1");
if ((p = match_filter_list(p,
"diffie-hellman-group-exchange-sha256,"
"diffie-hellman-group-exchange-sha1")) == NULL)
fatal("match_filter_list failed");
}
debug2("%s: compat KEX proposal: %s", __func__, p);
if (*p == '\0')

View File

@ -740,6 +740,9 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
use_pie=auto
check_for_libcrypt_later=1
check_for_openpty_ctty_bug=1
dnl Target SUSv3/POSIX.1-2001 plus BSD specifics.
dnl _DEFAULT_SOURCE is the new name for _BSD_SOURCE
CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE"
AC_DEFINE([PAM_TTY_KLUDGE], [1],
[Work around problematic Linux PAM modules handling of PAM_TTY])
AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"],
@ -1471,36 +1474,47 @@ AC_ARG_WITH([skey],
LDNS_MSG="no"
AC_ARG_WITH(ldns,
[ --with-ldns[[=PATH]] Use ldns for DNSSEC support (optionally in PATH)],
[
if test "x$withval" != "xno" ; then
[
ldns=""
if test "x$withval" = "xyes" ; then
AC_PATH_TOOL([LDNSCONFIG], [ldns-config], [no])
if test "x$PKGCONFIG" = "xno"; then
CPPFLAGS="$CPPFLAGS -I${withval}/include"
LDFLAGS="$LDFLAGS -L${withval}/lib"
LIBS="-lldns $LIBS"
ldns=yes
else
LIBS="$LIBS `$LDNSCONFIG --libs`"
CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`"
fi
elif test "x$withval" != "xno" ; then
CPPFLAGS="$CPPFLAGS -I${withval}/include"
LDFLAGS="$LDFLAGS -L${withval}/lib"
LIBS="-lldns $LIBS"
ldns=yes
fi
if test "x$withval" != "xyes" ; then
CPPFLAGS="$CPPFLAGS -I${withval}/include"
LDFLAGS="$LDFLAGS -L${withval}/lib"
fi
AC_DEFINE(HAVE_LDNS, 1, [Define if you want ldns support])
LIBS="-lldns $LIBS"
LDNS_MSG="yes"
AC_MSG_CHECKING([for ldns support])
AC_LINK_IFELSE(
[AC_LANG_SOURCE([[
# Verify that it works.
if test "x$ldns" = "xyes" ; then
AC_DEFINE(HAVE_LDNS, 1, [Define if you want ldns support])
LDNS_MSG="yes"
AC_MSG_CHECKING([for ldns support])
AC_LINK_IFELSE(
[AC_LANG_SOURCE([[
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ldns/ldns.h>
int main() { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); }
]])
],
[AC_MSG_RESULT(yes)],
]])
],
[AC_MSG_RESULT(yes)],
[
AC_MSG_RESULT(no)
AC_MSG_ERROR([** Incomplete or missing ldns libraries.])
])
fi
]
)
fi
])
# Check whether user wants libedit support
LIBEDIT_MSG="no"
@ -1771,11 +1785,8 @@ AC_CHECK_FUNCS([ \
warn \
])
dnl Wide character support. Linux man page says it needs _XOPEN_SOURCE.
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -D_XOPEN_SOURCE"
dnl Wide character support.
AC_CHECK_FUNCS([mblen mbtowc nl_langinfo wcwidth])
CFLAGS="$saved_CFLAGS"
TEST_SSH_UTF8=${TEST_SSH_UTF8:=yes}
AC_MSG_CHECKING([for utf8 locale support])
@ -5083,6 +5094,7 @@ echo " Smartcard support: $SCARD_MSG"
echo " S/KEY support: $SKEY_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " libldns support: $LDNS_MSG"
echo " Solaris process contract support: $SPC_MSG"
echo " Solaris project support: $SP_MSG"
echo " Solaris privilege support: $SPP_MSG"

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh", "ssh.vcxproj", "{74E69D5E-A1EF-46EA-9173-19A412774104}"
ProjectSection(ProjectDependencies) = postProject
@ -68,6 +68,7 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-shellhost", "ssh-shellhost.vcxproj", "{C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}"
ProjectSection(ProjectDependencies) = postProject
{8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
{DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-agent", "ssh-agent.vcxproj", "{F6644EC5-D6B6-42A1-828C-75E2977470E0}"

View File

@ -3,7 +3,6 @@ Import-Module $PSScriptRoot\build.psm1 -Force -DisableNameChecking
$repoRoot = Get-RepositoryRoot
$script:logFile = join-path $repoRoot.FullName "appveyor.log"
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
$testfailed = $false
<#
Called by Write-BuildMsg to write to the build log, if it exists.
@ -241,6 +240,13 @@ function Install-TestDependencies
[CmdletBinding()]
param ()
# Install chocolatey
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
{
Write-Log -Message "Chocolatey not present. Installing chocolatey."
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:logFile
}
$isModuleAvailable = Get-Module 'Pester' -ListAvailable
if (-not ($isModuleAvailable))
{
@ -495,42 +501,14 @@ function Deploy-OpenSSHTests
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
#copy all pester tests
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Include *.ps1,*.psm1 -Force -ErrorAction Stop
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Include *.ps1,*.psm1, sshd_config -Force -ErrorAction Stop
#copy all unit tests.
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Exclude ssh-agent.exe, sshd.exe -Force -ErrorAction Stop
$sshdConfigFile = "$OpenSSHTestDir\sshd_config"
if (-not (Test-Path -Path $sshdConfigFile -PathType Leaf))
{
Write-BuildMessage "Installation dependencies: $OpenSSHTestDir\sshd_config is missing in the folder" -Category Error
throw "$OpenSSHTestDir\sshd_config is missing in the folder"
}
if ($env:DebugMode)
{
$strToReplace = "#LogLevel INFO"
(Get-Content $sshdConfigFile).Replace($strToReplace,"LogLevel Debug3") | Set-Content $sshdConfigFile
}
if(-not ($env:psPath))
{
$psCorePath = GetLocalPSCorePath
Set-BuildVariable -Name psPath -Value $psCorePath
}
$strToReplace = "Subsystem sftp sftp-server.exe"
if($env:psPath)
{
$strNewsubSystem = @"
Subsystem sftp sftp-server.exe
Subsystem powershell $env:psPath
"@
}
(Get-Content $sshdConfigFile).Replace($strToReplace, $strNewsubSystem) | Set-Content $sshdConfigFile
Copy-Item -Path "$sourceDir\unittest-*" -Destination $OpenSSHTestDir -Force -ErrorAction Stop
#restart the service to use the test copy of sshd_config
Restart-Service sshd
}
@ -691,7 +669,7 @@ function Run-OpenSSHUnitTest
Remove-Item -Path $unitTestOutputFile -Force -ErrorAction SilentlyContinue
}
$unitTestFiles = Get-ChildItem -Path "$testRoot\unittest*.exe" -Exclude unittest-kex.exe
$unitTestFiles = Get-ChildItem -Path "$testRoot\unittest*.exe" -Exclude unittest-kex.exe,unittest-hostkeys.exe
$testfailed = $false
if ($unitTestFiles -ne $null)
{

View File

@ -152,17 +152,6 @@ function Start-SSHBootstrap
{
Write-BuildMsg -AsInfo -Message "Chocolatey not present. Installing chocolatey." -Silent:$silent
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:BuildLogFile
if (-not ($machinePath.ToLower().Contains($chocolateyPath.ToLower())))
{
Write-BuildMsg -AsVerbose -Message "Adding $chocolateyPath to Path environment variable" -Silent:$silent
$newMachineEnvironmentPath += ";$chocolateyPath"
$env:Path += ";$chocolateyPath"
}
else
{
Write-BuildMsg -AsVerbose -Message "$chocolateyPath already present in Path environment variable" -Silent:$silent
}
}
# Add git\cmd to the path
@ -231,7 +220,7 @@ function Start-SSHBootstrap
# Install Windows 8.1 SDK
$packageName = "windows-sdk-8.1"
$sdkPath = "C:\Program Files (x86)\Windows Kits\8.1\bin\x86\register_app.vbs"
$sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs"
if (-not (Test-Path -Path $sdkPath))
{
@ -264,7 +253,7 @@ function Start-SSHBootstrap
Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent
if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false)
{
Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at" + $script:vcPath
Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at$script:vcPath, which means some required develop kits are missing on the machine."
}
}

View File

@ -1673,19 +1673,18 @@
#define HAVE_DECL_HOWMANY 0
#define HAVE_STRTOULL 1
#define HAVE_USLEEP 1
#define HAVE_EVP_RIPEMD160 1
#if defined ( WIN32 )
#define __func__ __FUNCTION__
#endif
/* Windows specific macro added to workaround mysignal implementaion in bsd-misc.c */
#define HAVE_MYSIGNAL 1
#define PATH_MAX MAX_PATH
//#define IN_LOOPBACKNET INADDR_LOOPBACK
#define S_IFIFO 0x1000
//#define SHUT_RDWR 2
//#define SHUT_WR 1
//#define SHUT_RD 0
#define HAVE_EXPLICIT_BZERO

View File

@ -201,4 +201,7 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<Target Name="BeforeClean">
<Delete Files="$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h" />
</Target>
</Project>

View File

@ -38,7 +38,10 @@ cd $scriptdir
cmd.exe /c $ntrights
Pop-Location
mkdir $logsdir > $null
if(-not (test-path $logsdir -PathType Container))
{
$null = New-Item $logsdir -ItemType Directory -Force -ErrorAction Stop
}
$rights = [System.Security.AccessControl.FileSystemRights]"Read, Write"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($account, $rights, "ContainerInherit,ObjectInherit", "None", "Allow")
$acl = Get-Acl -Path $logsdir

View File

@ -202,6 +202,7 @@
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\ssh-pubkey\ssh-pubkeydefs.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\agent-request.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\agent.h" />
<ClInclude Include="$(OpenSSH-Src-Path)groupaccess.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(OpenSSH-Src-Path)\auth.c" />
@ -212,8 +213,9 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\agentconfig.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\connection.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\keyagent-request.c" />
<ClCompile Include="..\..\..\auth-options.c" />
<ClCompile Include="..\..\..\auth2-pubkey.c" />
<ClCompile Include="$(OpenSSH-Src-Path)auth-options.c" />
<ClCompile Include="$(OpenSSH-Src-Path)auth2-pubkey.c" />
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />

View File

@ -21,6 +21,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\shell-host.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />
@ -113,7 +114,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>openbsd_compat.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
@ -133,7 +134,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>openbsd_compat.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
@ -156,7 +157,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>openbsd_compat.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<FullProgramDatabaseFile>true</FullProgramDatabaseFile>
<StripPrivateSymbols>No</StripPrivateSymbols>
@ -181,9 +182,10 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>openbsd_compat.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<FullProgramDatabaseFile>true</FullProgramDatabaseFile>
<StripPrivateSymbols>No</StripPrivateSymbols>
<AdditionalLibraryDirectories>$(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -248,6 +248,7 @@
<ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c" />
<ClCompile Include="$(OpenSSH-Src-Path)sshpty.c" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c" />
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />

View File

@ -150,6 +150,9 @@
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc">

Binary file not shown.

View File

@ -159,6 +159,7 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\console.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tncon.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />

View File

@ -18,6 +18,7 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\console.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tncon.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -32,9 +32,10 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <io.h>
#include "w32fd.h"
#include <errno.h>
#include <stddef.h>
#include "w32fd.h"
#include "inc\utf.h"
#include "misc_internal.h"
@ -44,6 +45,14 @@
#define WRITE_BUFFER_SIZE 100*1024
#define errno_from_Win32LastError() errno_from_Win32Error(GetLastError())
struct createFile_flags {
DWORD dwDesiredAccess;
DWORD dwShareMode;
SECURITY_ATTRIBUTES securityAttributes;
DWORD dwCreationDisposition;
DWORD dwFlagsAndAttributes;
};
int termio_initiate_read(struct w32_io* pio);
int termio_initiate_write(struct w32_io* pio, DWORD num_bytes);
@ -73,7 +82,8 @@ static int pipe_counter = 0;
* to it. These handles are associated with read end and write end of the pipe
*/
int
fileio_pipe(struct w32_io* pio[2]) {
fileio_pipe(struct w32_io* pio[2])
{
HANDLE read_handle = INVALID_HANDLE_VALUE, write_handle = INVALID_HANDLE_VALUE;
struct w32_io *pio_read = NULL, *pio_write = NULL;
char pipe_name[PATH_MAX];
@ -158,18 +168,10 @@ error:
return -1;
}
struct createFile_flags {
DWORD dwDesiredAccess;
DWORD dwShareMode;
SECURITY_ATTRIBUTES securityAttributes;
DWORD dwCreationDisposition;
DWORD dwFlagsAndAttributes;
};
/* maps open() file modes and flags to ones needed by CreateFile */
static int
createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags)
{
/* check flags */
int rwflags = flags & 0x3;
int c_s_flags = flags & 0xfffffff0;
@ -185,8 +187,7 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
}
/*only following create and status flags currently supported*/
if (c_s_flags & ~(O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC
| O_EXCL | O_BINARY)) {
if (c_s_flags & ~(O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC | O_EXCL | O_BINARY)) {
debug("open - ERROR: Unsupported flags: %d", flags);
errno = ENOTSUP;
return -1;
@ -240,11 +241,12 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
/* open() implementation. Uses CreateFile to open file, console, device, etc */
struct w32_io*
fileio_open(const char *path_utf8, int flags, int mode) {
fileio_open(const char *path_utf8, int flags, int mode)
{
struct w32_io* pio = NULL;
struct createFile_flags cf_flags;
HANDLE handle;
wchar_t *path_utf16 = NULL;
wchar_t *path_utf16 = NULL;
debug2("open - pathname:%s, flags:%d, mode:%d", path_utf8, flags, mode);
/* check input params*/
@ -254,11 +256,11 @@ struct w32_io*
return NULL;
}
if ((path_utf16 = utf8_to_utf16(path_utf8)) == NULL) {
errno = ENOMEM;
debug("utf8_to_utf16 failed - ERROR:%d", GetLastError());
return NULL;
}
if ((path_utf16 = utf8_to_utf16(path_utf8)) == NULL) {
errno = ENOMEM;
debug("utf8_to_utf16 failed for file:%s error:%d", path_utf8, GetLastError());
return NULL;
}
if (createFile_flags_setup(flags, mode, &cf_flags) == -1)
return NULL;
@ -269,17 +271,17 @@ struct w32_io*
if (handle == INVALID_HANDLE_VALUE) {
errno = errno_from_Win32LastError();
debug("open - CreateFile ERROR:%d", GetLastError());
free(path_utf16);
debug("failed to open file:%s error:%d", path_utf8, GetLastError());
free(path_utf16);
return NULL;
}
free(path_utf16);
free(path_utf16);
pio = (struct w32_io*)malloc(sizeof(struct w32_io));
if (pio == NULL) {
CloseHandle(handle);
errno = ENOMEM;
debug("open - ERROR:%d", errno);
debug("fileio_open(), failed to allocate memory error:%d", errno);
return NULL;
}
@ -292,13 +294,10 @@ struct w32_io*
return pio;
}
VOID CALLBACK ReadCompletionRoutine(
_In_ DWORD dwErrorCode,
_In_ DWORD dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped
) {
struct w32_io* pio =
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
VOID CALLBACK
ReadCompletionRoutine(_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped)
{
struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
debug2("ReadCB pio:%p, pending_state:%d, error:%d, received:%d",
pio, pio->read_details.pending, dwErrorCode, dwNumberOfBytesTransfered);
pio->read_details.error = dwErrorCode;
@ -311,7 +310,8 @@ VOID CALLBACK ReadCompletionRoutine(
/* initiate an async read */
/* TODO: make this a void func, store error in context */
int
fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested) {
fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested)
{
debug2("ReadFileEx io:%p", pio);
if (pio->read_details.buf == NULL) {
@ -342,11 +342,11 @@ fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested) {
/* read() implementation */
int
fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
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 read is pending */
if (pio->read_details.pending) {
if (w32_io_is_blocking(pio)) {
@ -426,11 +426,11 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
return bytes_copied;
}
VOID CALLBACK WriteCompletionRoutine(
_In_ DWORD dwErrorCode,
_In_ DWORD dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped
) {
VOID CALLBACK
WriteCompletionRoutine(_In_ DWORD dwErrorCode,
_In_ DWORD dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped)
{
struct w32_io* pio =
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
debug2("WriteCB - pio:%p, pending_state:%d, error:%d, transferred:%d of remaining: %d",
@ -450,21 +450,18 @@ VOID CALLBACK WriteCompletionRoutine(
/* write() implementation */
int
fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
{
int bytes_copied;
debug2("write - io:%p", pio);
if (pio->write_details.pending) {
if (w32_io_is_blocking(pio))
{
if (w32_io_is_blocking(pio)) {
debug2("write - io pending, blocking call made, io:%p", pio);
while (pio->write_details.pending) {
while (pio->write_details.pending)
if (wait_for_any_event(NULL, 0, INFINITE) == -1)
return -1;
}
}
else {
} else {
errno = EAGAIN;
debug2("write - IO is already pending, io:%p", pio);
return -1;
@ -502,14 +499,12 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
}
else
return -1;
}
else {
} else {
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;
}
else {
} else {
errno = errno_from_Win32LastError();
/* read end of the pipe closed ? */
if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_BROKEN_PIPE)) {
@ -531,6 +526,7 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
}
}
}
/* execute APC to give a chance for write to complete */
SleepEx(0, TRUE);
@ -548,8 +544,8 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
/* fstat() implemetation */
int
fileio_fstat(struct w32_io* pio, struct _stat64 *buf) {
fileio_fstat(struct w32_io* pio, struct _stat64 *buf)
{
int fd = _open_osfhandle((intptr_t)pio->handle, 0);
debug2("fstat - pio:%p", pio);
if (fd == -1) {
@ -561,12 +557,23 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf) {
}
int
fileio_stat(const char *path, struct _stat64 *buf) {
fileio_stat(const char *path, struct _stat64 *buf)
{
wchar_t wpath[PATH_MAX];
wchar_t* wtmp = NULL;
struct w32_io* pio;
if ((wtmp = utf8_to_utf16(path)) == NULL)
fatal("failed to covert input arguments");
/* If we doesn't have sufficient permissions then _wstat4() is returning
* file not found so added fileio_open() which will set the errorno correctly (access denied)
*/
if (NULL == (pio = fileio_open(path, O_RDONLY, 0)))
return -1;
fileio_close(pio);
wcscpy(&wpath[0], wtmp);
free(wtmp);
@ -574,7 +581,8 @@ fileio_stat(const char *path, struct _stat64 *buf) {
}
long
fileio_lseek(struct w32_io* pio, long offset, int origin) {
fileio_lseek(struct w32_io* pio, long offset, int origin)
{
debug2("lseek - pio:%p", pio);
if (origin != SEEK_SET) {
debug("lseek - ERROR, origin is not supported %d", origin);
@ -589,13 +597,12 @@ fileio_lseek(struct w32_io* pio, long offset, int origin) {
/* fdopen implementation */
FILE*
fileio_fdopen(struct w32_io* pio, const char *mode) {
fileio_fdopen(struct w32_io* pio, const char *mode)
{
int fd_flags = 0;
debug2("fdopen - io:%p", pio);
/* logic below doesn't work with overlapped file HANDLES */
if (mode[1] == '\0') {
switch (*mode) {
case 'r':
@ -611,8 +618,7 @@ fileio_fdopen(struct w32_io* pio, const char *mode) {
debug("fdopen - ERROR unsupported mode %s", mode);
return NULL;
}
}
else {
} else {
errno = ENOTSUP;
debug("fdopen - ERROR unsupported mode %s", mode);
return NULL;
@ -630,8 +636,8 @@ fileio_fdopen(struct w32_io* pio, const char *mode) {
}
void
fileio_on_select(struct w32_io* pio, BOOL rd) {
fileio_on_select(struct w32_io* pio, BOOL rd)
{
if (!rd)
return;
@ -643,8 +649,7 @@ fileio_on_select(struct w32_io* pio, BOOL rd) {
errno = 0;
return;
}
}
else {
} else {
if (fileio_ReadFileEx(pio, INT_MAX) != 0) {
pio->read_details.error = errno;
errno = 0;
@ -653,16 +658,15 @@ fileio_on_select(struct w32_io* pio, BOOL rd) {
}
}
int
fileio_close(struct w32_io* pio) {
fileio_close(struct w32_io* pio)
{
debug2("fileclose - pio:%p", pio);
CancelIo(WINHANDLE(pio));
//let queued APCs (if any) drain
/* let queued APCs (if any) drain */
SleepEx(0, TRUE);
if (pio->type != STD_IO_FD) {//STD handles are never explicitly closed
if (pio->type != STD_IO_FD) { /* STD handles are never explicitly closed */
CloseHandle(WINHANDLE(pio));
if (pio->read_details.buf)
@ -677,14 +681,14 @@ fileio_close(struct w32_io* pio) {
}
BOOL
fileio_is_io_available(struct w32_io* pio, BOOL rd) {
fileio_is_io_available(struct w32_io* pio, BOOL rd)
{
if (rd) {
if (pio->read_details.remaining || pio->read_details.error)
return TRUE;
else
return FALSE;
}
else { //write
} else { /* write */
return (pio->write_details.pending == FALSE) ? TRUE : FALSE;
}
}

View File

@ -13,13 +13,14 @@
#include "sys\types.h"
struct passwd {
char *pw_name; /* user's login name */
char *pw_passwd; /* password? */
char *pw_name; /* user's login name */
char *pw_passwd; /* password? */
char *pw_gecos; /* ??? */
uid_t pw_uid; /* numerical user ID */
gid_t pw_gid; /* numerical group ID */
char *pw_dir; /* initial working directory */
char *pw_shell; /* path to shell */
char *pw_sid; /* sid of user */
};
/*start - declarations not applicable in Windows */

View File

@ -52,8 +52,10 @@ typedef int sigset_t;
#define W32_SIG_IGN ((sighandler_t)1)
sighandler_t w32_signal(int signum, sighandler_t handler);
#define signal(a,b) w32_signal((a), (b))
#define mysignal(a,b) w32_signal((a), (b))
//#define signal(a,b) w32_signal((a), (b))
//#define mysignal(a,b) w32_signal((a), (b))
sighandler_t mysignal(int signum, sighandler_t handler);
int w32_raise(int sig);
#define raise(a) w32_raise(a)

File diff suppressed because it is too large Load Diff

View File

@ -31,23 +31,28 @@
#include "inc\sys\types.h"
/* uuidswap.c defs */
void temporarily_use_uid(struct passwd *pw){
return;
void
temporarily_use_uid(struct passwd *pw)
{
return;
}
void
permanently_drop_suid(uid_t uid) {
return;
permanently_drop_suid(uid_t uid)
{
return;
}
void
restore_uid(void) {
return;
restore_uid(void)
{
return;
}
void
permanently_set_uid(struct passwd *pw) {
return;
permanently_set_uid(struct passwd *pw)
{
return;
}
@ -56,74 +61,63 @@ int muxserver_sock = -1;
typedef struct Channel Channel;
unsigned int muxclient_command = 0;
void
muxserver_listen(void){
return;
muxserver_listen(void)
{
return;
}
void
mux_exit_message(Channel *c, int exitval) {
return;
mux_exit_message(Channel *c, int exitval)
{
return;
}
void
mux_tty_alloc_failed(Channel *c) {
return;
mux_tty_alloc_failed(Channel *c)
{
return;
}
void
muxclient(const char *path) {
return;
}
int
innetgr(const char *netgroup, const char *host,
const char *user, const char *domain) {
return -1;
}
/* groupaccess.c*/
int
ga_init(const char *user, gid_t base) {
return -1;
muxclient(const char *path)
{
return;
}
int
ga_match(char * const *groups, int n) {
return -1;
innetgr(const char *netgroup, const char *host, const char *user, const char *domain)
{
return -1;
}
int
ga_match_pattern_list(const char *group_pattern) {
return -1;
chroot(const char *path)
{
return -1;
}
void
ga_free(void) {
return;
int
initgroups(const char *user, gid_t group)
{
return -1;
}
int chroot(const char *path) {
return -1;
}
int initgroups(const char *user, gid_t group) {
return -1;
}
/* sshd.c */
int
setgroups(gid_t group, char* name) {
return 0;
setgroups(gid_t group, char* name)
{
return 0;
}
int
setsid(void) {
return 0;
}
int startup_handler(void) {
setsid(void)
{
return 0;
}
int
startup_handler(void)
{
return 0;
}

View File

@ -36,6 +36,7 @@
#include <DsGetDC.h>
#define SECURITY_WIN32
#include <security.h>
#include "inc\pwd.h"
#include "inc\grp.h"
#include "inc\utf.h"
@ -45,237 +46,279 @@ static struct passwd pw;
static char* pw_shellpath = NULL;
#define SHELL_HOST "\\ssh-shellhost.exe"
int
initialize_pw() {
if (pw_shellpath == NULL) {
if ((pw_shellpath = malloc(strlen(w32_programdir()) + strlen(SHELL_HOST) + 1)) == NULL)
fatal("initialize_pw - out of memory");
else {
char* head = pw_shellpath;
memcpy(head, w32_programdir(), strlen(w32_programdir()));
head += strlen(w32_programdir());
memcpy(head, SHELL_HOST, strlen(SHELL_HOST));
head += strlen(SHELL_HOST);
*head = '\0';
}
}
if (pw.pw_shell != pw_shellpath) {
memset(&pw, 0, sizeof(pw));
pw.pw_shell = pw_shellpath;
pw.pw_passwd = "\0";
/* pw_uid = 0 for root on Unix and SSH code has specific restrictions for root
* that are not applicable in Windows */
pw.pw_uid = 1;
}
return 0;
initialize_pw()
{
if (pw_shellpath == NULL) {
if ((pw_shellpath = malloc(strlen(w32_programdir()) + strlen(SHELL_HOST) + 1)) == NULL)
fatal("initialize_pw - out of memory");
else {
char* head = pw_shellpath;
memcpy(head, w32_programdir(), strlen(w32_programdir()));
head += strlen(w32_programdir());
memcpy(head, SHELL_HOST, strlen(SHELL_HOST));
head += strlen(SHELL_HOST);
*head = '\0';
}
}
if (pw.pw_shell != pw_shellpath) {
memset(&pw, 0, sizeof(pw));
pw.pw_shell = pw_shellpath;
pw.pw_passwd = "\0";
/* pw_uid = 0 for root on Unix and SSH code has specific restrictions for root
* that are not applicable in Windows */
pw.pw_uid = 1;
}
return 0;
}
void
reset_pw() {
initialize_pw();
if (pw.pw_name)
free(pw.pw_name);
if (pw.pw_dir)
free(pw.pw_dir);
reset_pw()
{
initialize_pw();
if (pw.pw_name)
free(pw.pw_name);
if (pw.pw_dir)
free(pw.pw_dir);
if (pw.pw_sid)
free(pw.pw_sid);
pw.pw_name = NULL;
pw.pw_dir = NULL;
pw.pw_sid = NULL;
}
static struct passwd*
get_passwd(const char *user_utf8, LPWSTR user_sid) {
struct passwd *ret = NULL;
wchar_t *user_utf16 = NULL, *uname_utf16, *udom_utf16, *tmp;
char *uname_utf8 = NULL, *pw_home_utf8 = NULL;
LPBYTE user_info = NULL;
LPWSTR user_sid_local = NULL;
wchar_t reg_path[PATH_MAX], profile_home[PATH_MAX];
HKEY reg_key = 0;
int tmp_len = PATH_MAX;
PDOMAIN_CONTROLLER_INFOW pdc = NULL;
get_passwd(const char *user_utf8, LPWSTR user_sid)
{
struct passwd *ret = NULL;
wchar_t *user_utf16 = NULL, *uname_utf16, *udom_utf16, *tmp;
char *uname_utf8 = NULL, *uname_upn = NULL, *udom_utf8 = NULL, *pw_home_utf8 = NULL, *user_sid_utf8 = NULL;
LPBYTE user_info = NULL;
LPWSTR user_sid_local = NULL;
wchar_t reg_path[PATH_MAX], profile_home[PATH_MAX];
HKEY reg_key = 0;
int tmp_len = PATH_MAX;
PDOMAIN_CONTROLLER_INFOW pdc = NULL;
DWORD dsStatus, uname_upn_len = 0;;
errno = 0;
errno = 0;
reset_pw();
if ((user_utf16 = utf8_to_utf16(user_utf8)) == NULL) {
errno = ENOMEM;
goto done;
}
reset_pw();
/*find domain part if any*/
if ((tmp = wcschr(user_utf16, L'\\')) != NULL) {
udom_utf16 = user_utf16;
uname_utf16 = tmp + 1;
*tmp = L'\0';
if ((user_utf16 = utf8_to_utf16(user_utf8) ) == NULL) {
errno = ENOMEM;
goto done;
}
} else if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
udom_utf16 = tmp + 1;
uname_utf16 = user_utf16;
*tmp = L'\0';
} else {
uname_utf16 = user_utf16;
udom_utf16 = NULL;
}
/*find domain part if any*/
if ((tmp = wcschr(user_utf16, L'\\')) != NULL) {
udom_utf16 = user_utf16;
uname_utf16 = tmp + 1;
*tmp = L'\0';
if (user_sid == NULL) {
NET_API_STATUS status;
if ((status = NetUserGetInfo(udom_utf16, uname_utf16, 23, &user_info)) != NERR_Success) {
debug("NetUserGetInfo() failed with error: %d for user: %ls and domain: %ls \n", status, uname_utf16, udom_utf16);
}
else if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
udom_utf16 = tmp + 1;
uname_utf16 = user_utf16;
*tmp = L'\0';
}
else {
uname_utf16 = user_utf16;
udom_utf16 = NULL;
}
if ((dsStatus = DsGetDcNameW(NULL, udom_utf16, NULL, NULL, DS_DIRECTORY_SERVICE_PREFERRED, &pdc)) != ERROR_SUCCESS) {
error("DsGetDcNameW() failed with error: %d \n", dsStatus);
errno = ENOENT;
goto done;
}
if (user_sid == NULL) {
NET_API_STATUS status;
if ((status = NetUserGetInfo(udom_utf16, uname_utf16, 23, &user_info)) != NERR_Success) {
debug("NetUserGetInfo() failed with error: %d \n", status);
if ((status = NetUserGetInfo(pdc->DomainControllerName, uname_utf16, 23, &user_info)) != NERR_Success) {
debug("NetUserGetInfo() with domainController: %ls failed with error: %d \n", pdc->DomainControllerName, status);
errno = ENOENT;
goto done;
}
}
DWORD dsStatus;
if ((dsStatus = DsGetDcNameW(NULL, udom_utf16, NULL, NULL, DS_DIRECTORY_SERVICE_PREFERRED, &pdc)) == ERROR_SUCCESS) {
if ((status = NetUserGetInfo(pdc->DomainControllerName, uname_utf16, 23, &user_info)) != NERR_Success) {
debug("NetUserGetInfo() with domainController failed with error: %d \n", status);
if (ConvertSidToStringSidW(((LPUSER_INFO_23)user_info)->usri23_user_sid, &user_sid_local) == FALSE) {
debug("NetUserGetInfo() Succeded but ConvertSidToStringSidW() failed with error: %d\n", GetLastError());
errno = ENOENT;
goto done;
}
if (ConvertSidToStringSidW(((LPUSER_INFO_23)user_info)->usri23_user_sid, &user_sid_local) == FALSE) {
error("ConvertSidToStringSidW() failed with error: %d\n", GetLastError());
user_sid = user_sid_local;
}
errno = ENOMEM; //??
goto done;
}
}
} else {
error("DsGetDcNameW() failed with error: %d \n", dsStatus);
errno = ENOMEM; //??
goto done;
}
} else {
if (ConvertSidToStringSidW(((LPUSER_INFO_23)user_info)->usri23_user_sid, &user_sid_local) == FALSE) {
error("NetUserGetInfo() Succeded but ConvertSidToStringSidW() failed with error: %d\n", GetLastError());
errno = ENOMEM; //??
goto done;
}
}
/* if one of below fails, set profile path to Windows directory */
if (swprintf(reg_path, PATH_MAX, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", user_sid) == PATH_MAX ||
RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &reg_key) != 0 ||
RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)profile_home, &tmp_len) != 0)
GetWindowsDirectoryW(profile_home, PATH_MAX);
user_sid = user_sid_local;
}
if ((uname_utf8 = utf16_to_utf8(uname_utf16)) == NULL ||
(udom_utf16 && (udom_utf8 = utf16_to_utf8(udom_utf16)) == NULL) ||
(pw_home_utf8 = utf16_to_utf8(profile_home)) == NULL ||
(user_sid_utf8 = utf16_to_utf8(user_sid)) == NULL) {
errno = ENOMEM;
goto done;
}
if (swprintf(reg_path, PATH_MAX, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", user_sid) == PATH_MAX ||
RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &reg_key) != 0 ||
RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)profile_home, &tmp_len) != 0)
GetWindowsDirectoryW(profile_home, PATH_MAX);
uname_upn_len = strlen(uname_utf8) + 1;
if (udom_utf8)
uname_upn_len += strlen(udom_utf8) + 1;
if ((uname_utf8 = _strdup(user_utf8)) == NULL ||
(pw_home_utf8 = utf16_to_utf8(profile_home)) == NULL) {
errno = ENOMEM;
goto done;
}
if ((uname_upn = malloc(uname_upn_len)) == NULL) {
errno = ENOMEM;
goto done;
}
memcpy(uname_upn, uname_utf8, strlen(uname_utf8) + 1);
if (udom_utf8) {
/* TODO - get domain FQDN */
uname_upn[strlen(uname_utf8)] = '@';
memcpy(uname_upn + strlen(uname_utf8) + 1, udom_utf8, strlen(udom_utf8) + 1);
}
pw.pw_name = uname_upn;
uname_upn = NULL;
pw.pw_dir = pw_home_utf8;
pw_home_utf8 = NULL;
pw.pw_sid = user_sid_utf8;
user_sid_utf8 = NULL;
ret = &pw;
pw.pw_name = uname_utf8;
uname_utf8 = NULL;
pw.pw_dir = pw_home_utf8;
pw_home_utf8 = NULL;
ret = &pw;
done:
if (user_utf16)
free(user_utf16);
if (uname_utf8)
free(uname_utf8);
if (pw_home_utf8)
free(pw_home_utf8);
if (user_info)
NetApiBufferFree(user_info);
if (user_sid_local)
LocalFree(user_sid_local);
if (reg_key)
RegCloseKey(reg_key);
if (pdc)
NetApiBufferFree(pdc);
return ret;
if (user_utf16)
free(user_utf16);
if (uname_utf8)
free(uname_utf8);
if (uname_upn)
free(uname_upn);
if (udom_utf8)
free(udom_utf8);
if (pw_home_utf8)
free(pw_home_utf8);
if (user_sid_utf8)
free(user_sid_utf8);
if (user_info)
NetApiBufferFree(user_info);
if (user_sid_local)
LocalFree(user_sid_local);
if (reg_key)
RegCloseKey(reg_key);
if (pdc)
NetApiBufferFree(pdc);
return ret;
}
struct passwd*
w32_getpwnam(const char *user_utf8) {
return get_passwd(user_utf8, NULL);
w32_getpwnam(const char *user_utf8)
{
return get_passwd(user_utf8, NULL);
}
struct passwd*
w32_getpwuid(uid_t uid) {
wchar_t* wuser = NULL;
char* user_utf8 = NULL;
ULONG needed = 0;
struct passwd *ret = NULL;
HANDLE token = 0;
DWORD info_len = 0;
TOKEN_USER* info = NULL;
LPWSTR user_sid = NULL;
w32_getpwuid(uid_t uid)
{
wchar_t* wuser = NULL;
char* user_utf8 = NULL;
ULONG needed = 0;
struct passwd *ret = NULL;
HANDLE token = 0;
DWORD info_len = 0;
TOKEN_USER* info = NULL;
LPWSTR user_sid = NULL;
errno = 0;
errno = 0;
if (GetUserNameExW(NameSamCompatible, NULL, &needed) != 0 ||
(wuser = malloc(needed * sizeof(wchar_t))) == NULL ||
GetUserNameExW(NameSamCompatible, wuser, &needed) == 0 ||
(user_utf8 = utf16_to_utf8(wuser)) == NULL ||
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == FALSE ||
GetTokenInformation(token, TokenUser, NULL, 0, &info_len) == TRUE ||
(info = (TOKEN_USER*)malloc(info_len)) == NULL ||
GetTokenInformation(token, TokenUser, info, info_len, &info_len) == FALSE ||
ConvertSidToStringSidW(info->User.Sid, &user_sid) == FALSE){
errno = ENOMEM;
goto done;
}
ret = get_passwd(user_utf8, user_sid);
if (GetUserNameExW(NameSamCompatible, NULL, &needed) != 0 ||
(wuser = malloc(needed * sizeof(wchar_t))) == NULL ||
GetUserNameExW(NameSamCompatible, wuser, &needed) == 0 ||
(user_utf8 = utf16_to_utf8(wuser)) == NULL ||
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == FALSE ||
GetTokenInformation(token, TokenUser, NULL, 0, &info_len) == TRUE ||
(info = (TOKEN_USER*)malloc(info_len)) == NULL ||
GetTokenInformation(token, TokenUser, info, info_len, &info_len) == FALSE ||
ConvertSidToStringSidW(info->User.Sid, &user_sid) == FALSE) {
errno = ENOMEM;
goto done;
}
ret = get_passwd(user_utf8, user_sid);
done:
if (wuser)
free(wuser);
if (user_utf8)
free(user_utf8);
if (token)
CloseHandle(token);
if (info)
free(info);
if (user_sid)
LocalFree(user_sid);
return ret;
if (wuser)
free(wuser);
if (user_utf8)
free(user_utf8);
if (token)
CloseHandle(token);
if (info)
free(info);
if (user_sid)
LocalFree(user_sid);
return ret;
}
char *group_from_gid(gid_t gid, int nogroup) {
char *
group_from_gid(gid_t gid, int nogroup)
{
return "-";
}
char *user_from_uid(uid_t uid, int nouser) {
char *
user_from_uid(uid_t uid, int nouser)
{
return "-";
}
uid_t
getuid(void) {
getuid(void)
{
return 0;
}
gid_t
getgid(void) {
getgid(void)
{
return 0;
}
uid_t
geteuid(void) {
geteuid(void)
{
return 0;
}
gid_t
getegid(void) {
getegid(void)
{
return 0;
}
int
setuid(uid_t uid) {
setuid(uid_t uid)
{
return 0;
}
int
setgid(gid_t gid) {
setgid(gid_t gid)
{
return 0;
}
int
seteuid(uid_t uid) {
seteuid(uid_t uid)
{
return 0;
}
int
setegid(gid_t gid) {
setegid(gid_t gid)
{
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -28,10 +28,11 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "w32fd.h"
#include <errno.h>
#include "w32fd.h"
#include "signal_internal.h"
#include "inc\signal.h"
#undef signal
#undef raise
#undef SIGINT
@ -48,30 +49,27 @@
/* pending signals to be processed */
sigset_t pending_signals;
/* signal handler table*/
sighandler_t sig_handlers[W32_SIGMAX];
extern struct _children children;
static VOID CALLBACK
sigint_APCProc(
_In_ ULONG_PTR dwParam
) {
sigint_APCProc(_In_ ULONG_PTR dwParam)
{
debug3("SIGINT APCProc()");
sigaddset(&pending_signals, W32_SIGINT);
}
static VOID CALLBACK
sigterm_APCProc(
_In_ ULONG_PTR dwParam
) {
sigterm_APCProc(_In_ ULONG_PTR dwParam)
{
debug3("SIGTERM APCProc()");
sigaddset(&pending_signals, W32_SIGTERM);
}
static VOID CALLBACK
sigtstp_APCProc(
_In_ ULONG_PTR dwParam
) {
sigtstp_APCProc(_In_ ULONG_PTR dwParam)
{
debug3("SIGTSTP APCProc()");
sigaddset(&pending_signals, W32_SIGTSTP);
}
@ -100,35 +98,36 @@ native_sig_handler(DWORD dwCtrlType)
}
static VOID CALLBACK
sigwinch_APCProc(
_In_ ULONG_PTR dwParam
) {
sigwinch_APCProc(_In_ ULONG_PTR dwParam)
{
debug3("SIGTERM APCProc()");
sigaddset(&pending_signals, W32_SIGWINCH);
}
void
queue_terminal_window_change_event() {
queue_terminal_window_change_event()
{
QueueUserAPC(sigwinch_APCProc, main_thread, (ULONG_PTR)NULL);
}
void
sw_init_signal_handler_table() {
int i;
sw_init_signal_handler_table()
{
SetConsoleCtrlHandler(native_sig_handler, TRUE);
sigemptyset(&pending_signals);
/* this automatically sets all to W32_SIG_DFL (0)*/
memset(sig_handlers, 0, sizeof(sig_handlers));
}
extern struct _children children;
sighandler_t
mysignal(int signum, sighandler_t handler) {
return w32_signal(signum, handler);
}
sighandler_t
w32_signal(int signum, sighandler_t handler) {
w32_signal(int signum, sighandler_t handler)
{
sighandler_t prev;
debug2("signal() sig:%d, handler:%p", signum, handler);
if (signum >= W32_SIGMAX) {
errno = EINVAL;
@ -141,7 +140,8 @@ w32_signal(int signum, sighandler_t handler) {
}
int
w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
/* this is only used by sshd to block SIGCHLD while doing waitpid() */
/* our implementation of waidpid() is never interrupted, so no need to implement this for now*/
debug3("sigprocmask() how:%d");
@ -151,7 +151,8 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
int
w32_raise(int sig) {
w32_raise(int sig)
{
debug("raise sig:%d", sig);
if (sig == W32_SIGSEGV)
return raise(SIGSEGV); /* raise native exception handler*/
@ -185,7 +186,8 @@ w32_raise(int sig) {
/* processes pending signals, return -1 and errno=EINTR if any are processed*/
static int
sw_process_pending_signals() {
sw_process_pending_signals()
{
sigset_t pending_tmp = pending_signals;
BOOL sig_int = FALSE; /* has any signal actually interrupted */
@ -266,55 +268,49 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
debug3("wait() on %d events and %d children", num_events, live_children);
/* TODO - implement signal catching and handling */
if (num_all_events) {
DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE,
milli_seconds, TRUE);
DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE, milli_seconds, TRUE);
if ((ret >= WAIT_OBJECT_0) && (ret <= WAIT_OBJECT_0 + num_all_events - 1)) {
//woken up by event signalled
/* is this due to a child process going down*/
/* woken up by event signalled
* is this due to a child process going down
*/
if (live_children && ((ret - WAIT_OBJECT_0) < live_children)) {
sigaddset(&pending_signals, W32_SIGCHLD);
sw_child_to_zombie(ret - WAIT_OBJECT_0);
}
}
else if (ret == WAIT_IO_COMPLETION) {
} else if (ret == WAIT_IO_COMPLETION) {
/* APC processed due to IO or signal*/
}
else if (ret == WAIT_TIMEOUT) {
} else if (ret == WAIT_TIMEOUT) {
/* timed out */
return 0;
}
/* some other error*/
else {
} else { /* some other error*/
errno = EOTHER;
debug("ERROR: unxpected wait end: %d", ret);
return -1;
}
}
else {
} else {
DWORD ret = SleepEx(milli_seconds, TRUE);
if (ret == WAIT_IO_COMPLETION) {
/* APC processed due to IO or signal*/
}
else if (ret == 0) {
} else if (ret == 0) {
/* timed out */
return 0;
}
else { //some other error
} else { /* some other error */
errno = EOTHER;
debug("ERROR: unxpected SleepEx error: %d", ret);
return -1;
}
}
if (pending_signals) {
if (pending_signals)
return sw_process_pending_signals();
}
return 0;
}
int
sw_initialize() {
sw_initialize()
{
memset(&children, 0, sizeof(children));
sw_init_signal_handler_table();
if (sw_init_timer() != 0)

View File

@ -35,16 +35,16 @@ struct _timer_info timer_info;
extern sigset_t pending_signals;
static VOID CALLBACK
sigalrm_APC(
_In_opt_ LPVOID lpArgToCompletionRoutine,
_In_ DWORD dwTimerLowValue,
_In_ DWORD dwTimerHighValue
) {
sigalrm_APC(_In_opt_ LPVOID lpArgToCompletionRoutine,
_In_ DWORD dwTimerLowValue,
_In_ DWORD dwTimerHighValue)
{
sigaddset(&pending_signals, W32_SIGALRM);
}
unsigned int
w32_alarm(unsigned int sec) {
w32_alarm(unsigned int sec)
{
LARGE_INTEGER due;
ULONGLONG sec_passed;
int ret = 0;
@ -59,7 +59,7 @@ w32_alarm(unsigned int sec) {
return 0;
}
due.QuadPart = -10000000LL; //1 sec in 100 nanosec intervals
due.QuadPart = -10000000LL; /* 1 sec in 100 nanosec intervals */
due.QuadPart *= sec;
/* this call resets the timer if it is already active */
if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) {
@ -75,16 +75,19 @@ w32_alarm(unsigned int sec) {
}
timer_info.ticks_at_start = GetTickCount64();
timer_info.run_time_sec = sec;
return ret;
}
int
sw_init_timer() {
sw_init_timer()
{
memset(&timer_info, 0, sizeof(timer_info));
timer_info.timer = CreateWaitableTimer(NULL, TRUE, NULL);
if (timer_info.timer == NULL) {
errno = ENOMEM;
return -1;
}
return 0;
}

View File

@ -34,7 +34,8 @@
struct _children children;
int
register_child(HANDLE child, DWORD pid) {
register_child(HANDLE child, DWORD pid)
{
DWORD first_zombie_index;
debug("Register child %p pid %d, %d zombies of %d", child, pid,
@ -43,6 +44,7 @@ register_child(HANDLE child, DWORD pid) {
errno = ENOMEM;
return -1;
}
if (children.num_zombies) {
first_zombie_index = children.num_children - children.num_zombies;
children.handles[children.num_children] = children.handles[first_zombie_index];
@ -50,26 +52,23 @@ register_child(HANDLE child, DWORD pid) {
children.handles[first_zombie_index] = child;
children.process_id[first_zombie_index] = pid;
}
else {
} else {
children.handles[children.num_children] = child;
children.process_id[children.num_children] = pid;
}
children.num_children++;
return 0;
}
int
sw_remove_child_at_index(DWORD index) {
sw_remove_child_at_index(DWORD index)
{
DWORD last_non_zombie;
debug("Unregister child at index %d, %d zombies of %d", index,
children.num_zombies, children.num_children);
if ((index >= children.num_children)
|| (children.num_children == 0)) {
if ((index >= children.num_children) || (children.num_children == 0)) {
errno = EINVAL;
return -1;
}
@ -78,15 +77,13 @@ sw_remove_child_at_index(DWORD index) {
if (children.num_zombies == 0) {
children.handles[index] = children.handles[children.num_children - 1];
children.process_id[index] = children.process_id[children.num_children - 1];
}
else {
} else {
/* if its a zombie */
if (index >= (children.num_children - children.num_zombies)) {
children.handles[index] = children.handles[children.num_children - 1];
children.process_id[index] = children.process_id[children.num_children - 1];
children.num_zombies--;
}
else {
} else {
last_non_zombie = children.num_children - children.num_zombies - 1;
children.handles[index] = children.handles[last_non_zombie];
children.process_id[index] = children.process_id[last_non_zombie];
@ -101,7 +98,8 @@ sw_remove_child_at_index(DWORD index) {
}
int
sw_child_to_zombie(DWORD index) {
sw_child_to_zombie(DWORD index)
{
DWORD last_non_zombie, zombie_pid;
HANDLE zombie_handle;
@ -114,7 +112,6 @@ sw_child_to_zombie(DWORD index) {
}
last_non_zombie = children.num_children - children.num_zombies - 1;
if (last_non_zombie != index) {
/* swap */
zombie_pid = children.process_id[index];
@ -129,7 +126,8 @@ sw_child_to_zombie(DWORD index) {
}
int
w32_kill(int pid, int sig) {
w32_kill(int pid, int sig)
{
int child_index, i;
if (pid == GetCurrentProcessId())
return w32_raise(sig);
@ -148,7 +146,9 @@ w32_kill(int pid, int sig) {
}
int waitpid(int pid, int *status, int options) {
int
waitpid(int pid, int *status, int options)
{
DWORD index, ret, ret_id, exit_code, timeout = 0;
HANDLE process = NULL;
@ -230,20 +230,19 @@ int waitpid(int pid, int *status, int options) {
if (status)
*status = exit_code;
return ret_id;
}
else if (ret == WAIT_TIMEOUT) {
} else if (ret == WAIT_TIMEOUT) {
/* TODO - assert that WNOHANG was specified*/
return 0;
}
DebugBreak();//fatal
DebugBreak(); /* fatal */
return -1;
}
void
sw_cleanup_child_zombies() {
sw_cleanup_child_zombies()
{
int pid = 1;
while (pid > 0) {
while (pid > 0)
pid = waitpid(-1, NULL, WNOHANG);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -38,352 +38,329 @@
#include "agent.h"
#include "agent-request.h"
#include "key.h"
#include "inc\utf.h"
static void
InitLsaString(LSA_STRING *lsa_string, const char *str)
{
if (str == NULL)
memset(lsa_string, 0, sizeof(LSA_STRING));
else {
lsa_string->Buffer = (char *)str;
lsa_string->Length = strlen(str);
lsa_string->MaximumLength = lsa_string->Length + 1;
}
if (str == NULL)
memset(lsa_string, 0, sizeof(LSA_STRING));
else {
lsa_string->Buffer = (char *)str;
lsa_string->Length = strlen(str);
lsa_string->MaximumLength = lsa_string->Length + 1;
}
}
static void
EnablePrivilege(const char *privName, int enabled)
{
TOKEN_PRIVILEGES tp;
HANDLE hProcToken = NULL;
LUID luid;
TOKEN_PRIVILEGES tp;
HANDLE hProcToken = NULL;
LUID luid;
int exitCode = 1;
int exitCode = 1;
if (LookupPrivilegeValueA(NULL, privName, &luid) == FALSE ||
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcToken) == FALSE)
goto done;
if (LookupPrivilegeValueA(NULL, privName, &luid) == FALSE ||
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcToken) == FALSE)
goto done;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = enabled ? SE_PRIVILEGE_ENABLED : 0;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = enabled ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hProcToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
AdjustTokenPrivileges(hProcToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
done:
if (hProcToken)
CloseHandle(hProcToken);
if (hProcToken)
CloseHandle(hProcToken);
return;
return;
}
void
LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
PROFILEINFOW profileInfo;
profileInfo.dwFlags = PI_NOUI;
profileInfo.lpProfilePath = NULL;
profileInfo.lpUserName = user;
profileInfo.lpDefaultPath = NULL;
profileInfo.lpServerName = domain;
profileInfo.lpPolicyPath = NULL;
profileInfo.hProfile = NULL;
profileInfo.dwSize = sizeof(profileInfo);
EnablePrivilege("SeBackupPrivilege", 1);
EnablePrivilege("SeRestorePrivilege", 1);
if (LoadUserProfileW(con->auth_token, &profileInfo) == FALSE)
debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError());
else
con->hProfile = profileInfo.hProfile;
EnablePrivilege("SeBackupPrivilege", 0);
EnablePrivilege("SeRestorePrivilege", 0);
PROFILEINFOW profileInfo;
profileInfo.dwFlags = PI_NOUI;
profileInfo.lpProfilePath = NULL;
profileInfo.lpUserName = user;
profileInfo.lpDefaultPath = NULL;
profileInfo.lpServerName = domain;
profileInfo.lpPolicyPath = NULL;
profileInfo.hProfile = NULL;
profileInfo.dwSize = sizeof(profileInfo);
EnablePrivilege("SeBackupPrivilege", 1);
EnablePrivilege("SeRestorePrivilege", 1);
if (LoadUserProfileW(con->auth_token, &profileInfo) == FALSE)
debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError());
else
con->hProfile = profileInfo.hProfile;
EnablePrivilege("SeBackupPrivilege", 0);
EnablePrivilege("SeRestorePrivilege", 0);
}
#define MAX_USER_LEN 256
#define MAX_USER_LEN 64
/* https://technet.microsoft.com/en-us/library/active-directory-maximum-limits-scalability(v=ws.10).aspx */
#define MAX_FQDN_LEN 64
#define MAX_PW_LEN 64
static HANDLE
generate_user_token(wchar_t* user) {
HANDLE lsa_handle = 0, token = 0;
LSA_OPERATIONAL_MODE mode;
ULONG auth_package_id;
NTSTATUS ret, subStatus;
void * logon_info = NULL;
size_t logon_info_size;
LSA_STRING logon_process_name, auth_package_name, originName;
TOKEN_SOURCE sourceContext;
PKERB_INTERACTIVE_PROFILE pProfile = NULL;
LUID logonId;
QUOTA_LIMITS quotas;
DWORD cbProfile;
BOOL domain_user;
wchar_t user_copy[MAX_USER_LEN];
generate_user_token(wchar_t* user_cpn) {
HANDLE lsa_handle = 0, token = 0;
LSA_OPERATIONAL_MODE mode;
ULONG auth_package_id;
NTSTATUS ret, subStatus;
void * logon_info = NULL;
size_t logon_info_size;
LSA_STRING logon_process_name, auth_package_name, originName;
TOKEN_SOURCE sourceContext;
PKERB_INTERACTIVE_PROFILE pProfile = NULL;
LUID logonId;
QUOTA_LIMITS quotas;
DWORD cbProfile;
BOOL domain_user;
/* prep user name - TODO: implment an accurate check if user is domain account*/
if (wcsnlen(user, MAX_USER_LEN) == MAX_USER_LEN) {
debug("user length is not supported");
goto done;
}
domain_user = wcschr(user_cpn, L'@')? TRUE : FALSE;
if (wcschr(user, L'\\') != NULL) {
wchar_t *un = NULL, *dn = NULL;
DWORD un_len = 0, dn_len = 0;
dn = user;
dn_len = wcschr(user, L'\\') - user;
un = wcschr(user, L'\\') + 1;
un_len = wcsnlen(user, MAX_USER_LEN) - dn_len - 1;
if (dn_len == 0 || un_len == 0) {
debug("cannot get user token - bad user name");
goto done;
}
memcpy(user_copy, un, un_len * sizeof(wchar_t));
user_copy[un_len] = L'@';
memcpy(user_copy + un_len + 1, dn, dn_len * sizeof(wchar_t));
user_copy[dn_len + 1 + un_len] = L'\0';
user = user_copy;
}
InitLsaString(&logon_process_name, "ssh-agent");
if (domain_user)
InitLsaString(&auth_package_name, MICROSOFT_KERBEROS_NAME_A);
else
InitLsaString(&auth_package_name, "SSH-LSA");
domain_user = (wcschr(user, L'@') != NULL) ? TRUE : FALSE;
InitLsaString(&originName, "sshd");
if (ret = LsaRegisterLogonProcess(&logon_process_name, &lsa_handle, &mode) != STATUS_SUCCESS)
goto done;
InitLsaString(&logon_process_name, "ssh-agent");
if (domain_user)
InitLsaString(&auth_package_name, MICROSOFT_KERBEROS_NAME_A);
else
InitLsaString(&auth_package_name, "SSH-LSA");
if (ret = LsaLookupAuthenticationPackage(lsa_handle, &auth_package_name, &auth_package_id) != STATUS_SUCCESS)
goto done;
InitLsaString(&originName, "sshd");
if (ret = LsaRegisterLogonProcess(&logon_process_name, &lsa_handle, &mode) != STATUS_SUCCESS)
goto done;
if (domain_user) {
KERB_S4U_LOGON *s4u_logon;
logon_info_size = sizeof(KERB_S4U_LOGON);
logon_info_size += (wcslen(user_cpn) * 2 + 2);
logon_info = malloc(logon_info_size);
if (logon_info == NULL)
goto done;
s4u_logon = (KERB_S4U_LOGON*)logon_info;
s4u_logon->MessageType = KerbS4ULogon;
s4u_logon->Flags = 0;
s4u_logon->ClientUpn.Length = wcslen(user_cpn) * 2;
s4u_logon->ClientUpn.MaximumLength = s4u_logon->ClientUpn.Length;
s4u_logon->ClientUpn.Buffer = (WCHAR*)(s4u_logon + 1);
memcpy(s4u_logon->ClientUpn.Buffer, user_cpn, s4u_logon->ClientUpn.Length + 2);
s4u_logon->ClientRealm.Length = 0;
s4u_logon->ClientRealm.MaximumLength = 0;
s4u_logon->ClientRealm.Buffer = 0;
} else {
logon_info_size = (wcslen(user_cpn) + 1)*sizeof(wchar_t);
logon_info = malloc(logon_info_size);
if (logon_info == NULL)
goto done;
memcpy(logon_info, user_cpn, logon_info_size);
}
if (ret = LsaLookupAuthenticationPackage(lsa_handle, &auth_package_name, &auth_package_id) != STATUS_SUCCESS)
goto done;
memcpy(sourceContext.SourceName,"sshagent", sizeof(sourceContext.SourceName));
if (domain_user) {
KERB_S4U_LOGON *s4u_logon;
logon_info_size = sizeof(KERB_S4U_LOGON);
logon_info_size += (wcslen(user) * 2 + 2);
logon_info = malloc(logon_info_size);
if (logon_info == NULL)
goto done;
s4u_logon = (KERB_S4U_LOGON*)logon_info;
s4u_logon->MessageType = KerbS4ULogon;
s4u_logon->Flags = 0;
s4u_logon->ClientUpn.Length = wcslen(user) * 2;
s4u_logon->ClientUpn.MaximumLength = s4u_logon->ClientUpn.Length;
s4u_logon->ClientUpn.Buffer = (WCHAR*)(s4u_logon + 1);
memcpy(s4u_logon->ClientUpn.Buffer, user, s4u_logon->ClientUpn.Length + 2);
s4u_logon->ClientRealm.Length = 0;
s4u_logon->ClientRealm.MaximumLength = 0;
s4u_logon->ClientRealm.Buffer = 0;
}
else {
logon_info_size = (wcslen(user) + 1)*sizeof(wchar_t);
logon_info = malloc(logon_info_size);
if (logon_info == NULL)
goto done;
memcpy(logon_info, user, logon_info_size);
}
if (AllocateLocallyUniqueId(&sourceContext.SourceIdentifier) != TRUE)
goto done;
memcpy(sourceContext.SourceName,"sshagent", sizeof(sourceContext.SourceName));
if (AllocateLocallyUniqueId(&sourceContext.SourceIdentifier) != TRUE)
goto done;
if (ret = LsaLogonUser(lsa_handle,
&originName,
Network,
auth_package_id,
logon_info,
logon_info_size,
NULL,
&sourceContext,
(PVOID*)&pProfile,
&cbProfile,
&logonId,
&token,
&quotas,
&subStatus) != STATUS_SUCCESS) {
debug("LsaLogonUser failed %d", ret);
goto done;
}
debug3("LsaLogonUser succeeded");
if (ret = LsaLogonUser(lsa_handle,
&originName,
Network,
auth_package_id,
logon_info,
logon_info_size,
NULL,
&sourceContext,
(PVOID*)&pProfile,
&cbProfile,
&logonId,
&token,
&quotas,
&subStatus) != STATUS_SUCCESS) {
debug("LsaLogonUser failed %d", ret);
goto done;
}
debug3("LsaLogonUser succeeded");
done:
if (lsa_handle)
LsaDeregisterLogonProcess(lsa_handle);
if (logon_info)
free(logon_info);
if (pProfile)
LsaFreeReturnBuffer(pProfile);
if (lsa_handle)
LsaDeregisterLogonProcess(lsa_handle);
if (logon_info)
free(logon_info);
if (pProfile)
LsaFreeReturnBuffer(pProfile);
return token;
return token;
}
#define PUBKEY_AUTH_REQUEST "pubkey"
#define PASSWD_AUTH_REQUEST "password"
#define MAX_USER_NAME_LEN 256
#define MAX_PW_LEN 128
/* TODO - SecureZeroMemory password */
int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
char *user = NULL, *pwd = NULL;
wchar_t userW_buf[MAX_USER_NAME_LEN], pwdW_buf[MAX_PW_LEN];
wchar_t *userW = userW_buf, *domW = NULL, *pwdW = pwdW_buf, *tmp;
size_t user_len = 0, pwd_len = 0, dom_len = 0;
int r = -1;
HANDLE token = 0, dup_token, client_proc = 0;
ULONG client_pid;
char *user = NULL, *domain = NULL, *pwd = NULL;
size_t user_len, pwd_len;
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *pwd_utf16 = NULL, *tmp;
int r = -1;
HANDLE token = 0, dup_token, client_proc = 0;
ULONG client_pid;
if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
sshbuf_get_cstring(request, &pwd, &pwd_len) != 0 ||
user_len == 0 ||
pwd_len == 0 ){
debug("bad password auth request");
goto done;
}
if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
sshbuf_get_cstring(request, &pwd, &pwd_len) != 0 ||
user_len == 0 ||
pwd_len == 0 ||
user_len > MAX_USER_LEN + MAX_FQDN_LEN ||
pwd_len > MAX_PW_LEN) {
debug("bad password auth request");
goto done;
}
userW[0] = L'\0';
if (MultiByteToWideChar(CP_UTF8, 0, user, user_len + 1, userW, MAX_USER_NAME_LEN) == 0 ||
MultiByteToWideChar(CP_UTF8, 0, pwd, pwd_len + 1, pwdW, MAX_PW_LEN) == 0) {
debug("unable to convert user (%s) or password to UTF-16", user);
goto done;
}
if ((user_utf16 = utf8_to_utf16(user)) == NULL ||
(pwd_utf16 = utf8_to_utf16(pwd)) == NULL) {
debug("out of memory");
goto done;
}
if ((tmp = wcschr(userW, L'\\')) != NULL) {
domW = userW;
userW = tmp + 1;
*tmp = L'\0';
if ((tmp = wcschr(user_utf16, L'@') ) != NULL ) {
udom_utf16 = tmp + 1;
*tmp = L'\0';
}
}
else if ((tmp = wcschr(userW, L'@')) != NULL) {
domW = tmp + 1;
*tmp = L'\0';
}
if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
debug("failed to logon user: %ls domain: %ls", user_utf16, udom_utf16);
goto done;
}
if (LogonUserW(userW, domW, pwdW, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
debug("failed to logon user");
goto done;
}
if ((FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) ||
((client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
(FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
(sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)) {
debug("failed to duplicate user token");
goto done;
}
if ((FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) ||
((client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
(FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
(sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)) {
debug("failed to duplicate user token");
goto done;
}
con->auth_token = token;
LoadProfile(con, userW, domW);
r = 0;
con->auth_token = token;
LoadProfile(con, user_utf16, udom_utf16);
r = 0;
done:
/* TODO Fix this hacky protocol*/
if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
r = 0;
/* TODO Fix this hacky protocol*/
if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
r = 0;
if (user)
free(user);
if (pwd)
free(pwd);
if (client_proc)
CloseHandle(client_proc);
if (user)
free(user);
if (pwd)
free(pwd);
if (user_utf16)
free(user_utf16);
if (pwd_utf16)
free(pwd_utf16);
if (client_proc)
CloseHandle(client_proc);
return r;
return r;
}
int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
int r = -1;
char *key_blob, *user, *sig, *blob;
size_t key_blob_len, user_len, sig_len, blob_len;
struct sshkey *key = NULL;
HANDLE token = NULL, dup_token = NULL, client_proc = NULL;
wchar_t wuser[MAX_USER_NAME_LEN];
PWSTR wuser_home = NULL;
ULONG client_pid;
int r = -1;
char *key_blob, *user, *sig, *blob;
size_t key_blob_len, user_len, sig_len, blob_len;
struct sshkey *key = NULL;
HANDLE token = NULL, restricted_token = NULL, dup_token = NULL, client_proc = NULL;
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *tmp;
PWSTR wuser_home = NULL;
ULONG client_pid;
LUID_AND_ATTRIBUTES priv_to_delete[1];
user = NULL;
if (sshbuf_get_string_direct(request, &key_blob, &key_blob_len) != 0 ||
sshbuf_get_cstring(request, &user, &user_len) != 0 ||
sshbuf_get_string_direct(request, &sig, &sig_len) != 0 ||
sshbuf_get_string_direct(request, &blob, &blob_len) != 0 ||
sshkey_from_blob(key_blob, key_blob_len, &key) != 0) {
debug("invalid pubkey auth request");
goto done;
}
user = NULL;
if (sshbuf_get_string_direct(request, &key_blob, &key_blob_len) != 0 ||
sshbuf_get_cstring(request, &user, &user_len) != 0 ||
user_len > MAX_USER_LEN ||
sshbuf_get_string_direct(request, &sig, &sig_len) != 0 ||
sshbuf_get_string_direct(request, &blob, &blob_len) != 0 ||
sshkey_from_blob(key_blob, key_blob_len, &key) != 0) {
debug("invalid pubkey auth request");
goto done;
}
wuser[0] = L'\0';
if (MultiByteToWideChar(CP_UTF8, 0, user, user_len + 1, wuser, MAX_USER_NAME_LEN) == 0 ||
(token = generate_user_token(wuser)) == 0) {
debug("unable to generate token for user %ls", wuser);
goto done;
}
if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
debug("out of memory");
goto done;
}
con->auth_token = token;
if ((token = generate_user_token(user_utf16)) == 0) {
debug("unable to generate token for user %ls", user_utf16);
goto done;
}
if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, token, &wuser_home) != S_OK ||
pubkey_allowed(key, wuser, wuser_home) != 1) {
debug("unable to verify public key for user %ls (profile:%ls)", wuser, wuser_home);
goto done;
}
/* for key based auth, remove SeTakeOwnershipPrivilege */
if (LookupPrivilegeValueW(NULL, L"SeTakeOwnershipPrivilege", &priv_to_delete[0].Luid) == FALSE ||
CreateRestrictedToken(token, 0, 0, NULL, 1, priv_to_delete, 0, NULL, &restricted_token) == FALSE) {
debug("unable to remove SeTakeOwnershipPrivilege privilege");
goto done;
}
if (key_verify(key, sig, sig_len, blob, blob_len) != 1) {
debug("signature verification failed");
goto done;
}
if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, restricted_token, &wuser_home) != S_OK ||
pubkey_allowed(key, user_utf16, wuser_home) != 1) {
debug("unable to verify public key for user %ls (profile:%ls)", user_utf16, wuser_home);
goto done;
}
if ((FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) ||
( (client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
(FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
(sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0) ) {
debug("failed to authorize user");
goto done;
}
if (key_verify(key, sig, sig_len, blob, blob_len) != 1) {
debug("signature verification failed");
goto done;
}
{
wchar_t *tmp, *userW, *domW;
userW = wuser;
domW = NULL;
if ((tmp = wcschr(userW, L'\\')) != NULL) {
domW = userW;
userW = tmp + 1;
*tmp = L'\0';
if ((FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) ||
( (client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
(FALSE == DuplicateHandle(GetCurrentProcess(), restricted_token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
(sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)) {
debug("failed to authorize user");
goto done;
}
}
else if ((tmp = wcschr(userW, L'@')) != NULL) {
domW = tmp + 1;
*tmp = L'\0';
}
LoadProfile(con, userW, domW);
}
con->auth_token = restricted_token;
restricted_token = NULL;
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
udom_utf16 = tmp + 1;
*tmp = L'\0';
}
LoadProfile(con, user_utf16, udom_utf16);
r = 0;
r = 0;
done:
/* TODO Fix this hacky protocol*/
if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
r = 0;
/* TODO Fix this hacky protocol*/
if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
r = 0;
if (user)
free(user);
if (key)
sshkey_free(key);
if (wuser_home)
CoTaskMemFree(wuser_home);
if (client_proc)
CloseHandle(client_proc);
return r;
if (user)
free(user);
if (user_utf16)
free(user_utf16);
if (key)
sshkey_free(key);
if (wuser_home)
CoTaskMemFree(wuser_home);
if (client_proc)
CloseHandle(client_proc);
if (token)
CloseHandle(token);
return r;
}
int process_authagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
char *opn;
size_t opn_len;
if (sshbuf_get_string_direct(request, &opn, &opn_len) != 0) {
debug("invalid auth request");
return -1;
}
if (opn_len == strlen(PUBKEY_AUTH_REQUEST) && memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0)
return process_pubkeyauth_request(request, response, con);
else if (opn_len == strlen(PASSWD_AUTH_REQUEST) && memcmp(opn, PASSWD_AUTH_REQUEST, opn_len) == 0)
return process_passwordauth_request(request, response, con);
else {
debug("unknown auth request: %s", opn);
return -1;
}
char *opn;
size_t opn_len;
if (sshbuf_get_string_direct(request, &opn, &opn_len) != 0) {
debug("invalid auth request");
return -1;
}
if (memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0)
return process_pubkeyauth_request(request, response, con);
else if (memcmp(opn, PASSWD_AUTH_REQUEST, opn_len) == 0)
return process_passwordauth_request(request, response, con);
else {
debug("unknown auth request: %s", opn);
return -1;
}
}

View File

@ -167,9 +167,6 @@ done:
return r;
}
/* TODO - move this to common header*/
#define SSH_AGENT_AUTHENTICATE 100
static int
process_request(struct agent_connection* con) {
int r = -1;
@ -179,7 +176,7 @@ process_request(struct agent_connection* con) {
if ((con->client_process = get_con_client_type(con->connection)) == -1)
goto done;
//Sleep(30 * 1000);
request = sshbuf_from(con->io_buf.buf, con->io_buf.num_bytes);
response = sshbuf_new();
if ((request == NULL) || (response == NULL))

View File

@ -1,3 +1,40 @@
/*
* Author: Manoj Ampalam <manojamp@microsoft.com>
* read() and write() on tty using worker threads to handle
* synchronous Windows Console IO
*
* Author: Ray Hayes <ray.hayes@microsoft.com>
* TTY/PTY support added by capturing all terminal input events
*
* Author: Balu <bagajjal@microsoft.com>
* Misc fixes and code cleanup
*
* Copyright (c) 2017 Microsoft Corp.
* All rights reserved
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <Windows.h>
#include "w32fd.h"
#include "tncon.h"
@ -12,12 +49,12 @@ struct io_status {
DWORD transferred;
DWORD error;
};
static struct io_status read_status, write_status;
static VOID CALLBACK ReadAPCProc(
_In_ ULONG_PTR dwParam
) {
/* APC that gets queued on main thread when a sync Read completes on worker thread */
static VOID CALLBACK
ReadAPCProc(_In_ ULONG_PTR dwParam)
{
struct w32_io* pio = (struct w32_io*)dwParam;
debug3("TermRead CB - io:%p, bytes: %d, pending: %d, error: %d", pio, read_status.transferred,
pio->read_details.pending, read_status.error);
@ -30,39 +67,37 @@ static VOID CALLBACK ReadAPCProc(
pio->read_overlapped.hEvent = 0;
}
static DWORD WINAPI ReadConsoleThread(
_In_ LPVOID lpParameter
) {
int nBytesReturned = 0;
/* Read worker thread */
static DWORD WINAPI
ReadConsoleThread(_In_ LPVOID lpParameter)
{
int nBytesReturned = 0;
struct w32_io* pio = (struct w32_io*)lpParameter;
struct w32_io* pio = (struct w32_io*)lpParameter;
debug3("TermRead thread, io:%p", pio);
memset(&read_status, 0, sizeof(read_status));
while (nBytesReturned == 0) {
nBytesReturned = ReadConsoleForTermEmul(WINHANDLE(pio),
pio->read_details.buf, pio->read_details.buf_size);
}
read_status.transferred = nBytesReturned;
if (0 == QueueUserAPC(ReadAPCProc, main_thread, (ULONG_PTR)pio)) {
debug("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
pio->read_details.pending = FALSE;
pio->read_details.error = GetLastError();
DebugBreak();
}
debug3("TermRead thread, io:%p", pio);
memset(&read_status, 0, sizeof(read_status));
while (nBytesReturned == 0) {
nBytesReturned = ReadConsoleForTermEmul(WINHANDLE(pio),
pio->read_details.buf, pio->read_details.buf_size);
}
read_status.transferred = nBytesReturned;
if (0 == QueueUserAPC(ReadAPCProc, main_thread, (ULONG_PTR)pio)) {
debug("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
pio->read_details.pending = FALSE;
pio->read_details.error = GetLastError();
DebugBreak();
}
return 0;
return 0;
}
/* Initiates read on tty */
int
termio_initiate_read(struct w32_io* pio) {
termio_initiate_read(struct w32_io* pio)
{
HANDLE read_thread;
debug3("TermRead initiate io:%p", pio);
if (pio->read_details.buf_size == 0) {
pio->read_details.buf = malloc(TERM_IO_BUF_SIZE);
if (pio->read_details.buf == NULL) {
@ -72,7 +107,7 @@ termio_initiate_read(struct w32_io* pio) {
pio->read_details.buf_size = TERM_IO_BUF_SIZE;
}
read_thread = CreateThread(NULL, 0, ReadConsoleThread, pio, 0, NULL);
read_thread = CreateThread(NULL, 0, ReadConsoleThread, pio, 0, NULL);
if (read_thread == NULL) {
errno = errno_from_Win32Error(GetLastError());
debug("TermRead initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
@ -84,15 +119,16 @@ termio_initiate_read(struct w32_io* pio) {
return 0;
}
static VOID CALLBACK WriteAPCProc(
_In_ ULONG_PTR dwParam
) {
/* APC that gets queued on main thread when a sync Write completes on worker thread */
static VOID CALLBACK
WriteAPCProc(_In_ ULONG_PTR dwParam)
{
struct w32_io* pio = (struct w32_io*)dwParam;
debug3("TermWrite CB - io:%p, bytes: %d, pending: %d, error: %d", pio, write_status.transferred,
pio->write_details.pending, write_status.error);
pio->write_details.error = write_status.error;
pio->write_details.remaining -= write_status.transferred;
/*TODO- assert that reamining is 0 by now*/
/* TODO- assert that reamining is 0 by now */
pio->write_details.completed = 0;
pio->write_details.pending = FALSE;
WaitForSingleObject(pio->write_overlapped.hEvent, INFINITE);
@ -100,28 +136,29 @@ static VOID CALLBACK WriteAPCProc(
pio->write_overlapped.hEvent = 0;
}
static DWORD WINAPI WriteThread(
_In_ LPVOID lpParameter
) {
/* Write worker thread */
static DWORD WINAPI
WriteThread(_In_ LPVOID lpParameter)
{
struct w32_io* pio = (struct w32_io*)lpParameter;
char *respbuf = NULL;
size_t resplen = 0;
DWORD dwSavedAttributes = ENABLE_PROCESSED_INPUT;
char *respbuf = NULL;
size_t resplen = 0;
DWORD dwSavedAttributes = ENABLE_PROCESSED_INPUT;
debug3("TermWrite thread, io:%p", pio);
if (in_raw_mode == 0) {
if (in_raw_mode == 0) {
/* convert stream to utf16 and dump on console */
pio->write_details.buf[write_status.to_transfer] = '\0';
wchar_t* t = utf8_to_utf16(pio->write_details.buf);
WriteConsoleW(WINHANDLE(pio), t, wcslen(t), 0, 0);
free(t);
write_status.transferred = write_status.to_transfer;
} else {
/* console mode */
telProcessNetwork(pio->write_details.buf, write_status.to_transfer, &respbuf, &resplen);
/*TODO - respbuf is not null in some cases, this needs to be returned back via read stream*/
write_status.transferred = write_status.to_transfer;
}
} else {
/* console mode */
telProcessNetwork(pio->write_details.buf, write_status.to_transfer, &respbuf, &resplen);
/* TODO - respbuf is not null in some cases, this needs to be returned back via read stream */
write_status.transferred = write_status.to_transfer;
}
if (0 == QueueUserAPC(WriteAPCProc, main_thread, (ULONG_PTR)pio)) {
debug("TermWrite thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
@ -132,10 +169,11 @@ static DWORD WINAPI WriteThread(
return 0;
}
/* Initiates write on tty */
int
termio_initiate_write(struct w32_io* pio, DWORD num_bytes) {
termio_initiate_write(struct w32_io* pio, DWORD num_bytes)
{
HANDLE write_thread;
debug3("TermWrite initiate io:%p", pio);
memset(&write_status, 0, sizeof(write_status));
write_status.to_transfer = num_bytes;
@ -151,28 +189,27 @@ termio_initiate_write(struct w32_io* pio, DWORD num_bytes) {
return 0;
}
int termio_close(struct w32_io* pio) {
/* tty close */
int
termio_close(struct w32_io* pio)
{
debug2("termio_close - pio:%p", pio);
HANDLE h;
CancelIoEx(WINHANDLE(pio), NULL);
/* If io is pending, let write worker threads exit. The read thread is blocked so terminate it.*/
if (pio->read_details.pending)
TerminateThread(pio->read_overlapped.hEvent, 0);
if (pio->read_details.pending)
TerminateThread(pio->read_overlapped.hEvent, 0);
if (pio->write_details.pending)
WaitForSingleObject(pio->write_overlapped.hEvent, INFINITE);
/* drain queued APCs */
SleepEx(0, TRUE);
if (pio->type != STD_IO_FD) {//STD handles are never explicitly closed
if (pio->type != STD_IO_FD) {
/* STD handles are never explicitly closed */
CloseHandle(WINHANDLE(pio));
if (pio->read_details.buf)
free(pio->read_details.buf);
if (pio->write_details.buf)
free(pio->write_details.buf);
free(pio);
}
return 0;

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,11 @@
/*
* Author: Microsoft Corp.
*
* Copyright (c) 2015 Microsoft Corp.
* Copyright (c) 2017 Microsoft Corp.
* All rights reserved
*
* Microsoft openssh win32 port
* This file is responsible for terminal emulation related network calls to
* invoke ANSI parsing engine.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -27,61 +28,52 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* tnnet.c
*
* Contains terminal emulation related network calls to invoke ANSI parsing engine
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <windows.h>
#include "ansiprsr.h"
#define dwBuffer 4096
// Server will always be returning a sequence of ANSI control characters which the client
// protocol can either passthru directly to the console or transform based on an output terminal
// type. We're not using termcap so we're only supporting the ANSI (vt100) sequences that
// are hardcoded in the server and will be transformed to Windows Console commands.
size_t telProcessNetwork(char *buf, size_t len, unsigned char **respbuf, size_t *resplen)
/*
* Server will always be returning a sequence of ANSI control characters which the client
* protocol can either passthru directly to the console or transform based on an output terminal
* type. We're not using termcap so we're only supporting the ANSI (vt100) sequences that
* are hardcoded in the server and will be transformed to Windows Console commands.
*/
size_t
telProcessNetwork(char *buf, size_t len, unsigned char **respbuf, size_t *resplen)
{
unsigned char szBuffer[dwBuffer + 8];
unsigned char* pszNewHead = NULL;
unsigned char* pszHead = NULL;
unsigned char* pszTail = NULL;
unsigned char* pszHead = NULL;
unsigned char* pszTail = NULL;
if (len == 0)
return len;
if (len == 0)
return len;
// Transform a single carriage return into a single linefeed before
// continuing.
/* Transform a single carriage return into a single linefeed before continuing */
if ((len == 1) && (buf[0] == 13))
buf[0] = 10;
pszTail = (unsigned char *)buf;
pszHead = (unsigned char *)buf;
pszTail += len;
pszNewHead = pszHead;
// Loop through the network buffer transforming characters as necessary.
// The buffer will be empty after the transformation
// process since the buffer will contain only commands that are handled by the console API.
/*
* Loop through the network buffer transforming characters as necessary.
* The buffer will be empty after the transformation
* process since the buffer will contain only commands that are handled by the console API.
*/
do {
pszHead = pszNewHead;
pszNewHead = ParseBuffer(pszHead, pszTail, respbuf, resplen);
} while ((pszNewHead != pszHead) && (pszNewHead < pszTail) && (resplen == NULL || (resplen != NULL && *resplen == 0)));
len = 0;
len = 0;
return len;
}

View File

@ -0,0 +1,59 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Copyright(c) 2016 Microsoft Corp.
* All rights reserved
*
* UTF8 <--> UTF16 conversion routines
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <Windows.h>
#include "inc\utf.h"
wchar_t *
utf8_to_utf16(const char *utf8)
{
int needed = 0;
wchar_t* utf16 = NULL;
if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 ||
(utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0)
return NULL;
return utf16;
}
char *
utf16_to_utf8(const wchar_t* utf16)
{
int needed = 0;
char* utf8 = NULL;
if ((needed = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL)) == 0 ||
(utf8 = malloc(needed)) == NULL ||
WideCharToMultiByte(CP_UTF8, 0, utf16, -1, utf8, needed, NULL, NULL) == 0)
return NULL;
return utf8;
}

View File

@ -67,7 +67,8 @@ void fd_table_set(struct w32_io* pio, int index);
/* initializes mapping table*/
static int
fd_table_initialize() {
fd_table_initialize()
{
memset(&fd_table, 0, sizeof(fd_table));
memset(&w32_io_stdin, 0, sizeof(w32_io_stdin));
w32_io_stdin.std_handle = STD_INPUT_HANDLE;
@ -86,7 +87,8 @@ fd_table_initialize() {
/* get a free slot in mapping table with least index*/
static int
fd_table_get_min_index() {
fd_table_get_min_index()
{
int min_index = 0;
unsigned char* bitmap = fd_table.occupied.bitmap;
unsigned char tmp;
@ -102,9 +104,7 @@ fd_table_get_min_index() {
}
tmp = *bitmap;
while (tmp & 0x80)
{
while (tmp & 0x80) {
tmp <<= 1;
min_index++;
}
@ -114,7 +114,8 @@ fd_table_get_min_index() {
/* maps pio to fd (specified by index)*/
static void
fd_table_set(struct w32_io* pio, int index) {
fd_table_set(struct w32_io* pio, int index)
{
fd_table.w32_ios[index] = pio;
pio->table_index = index;
assert(pio->type != UNKNOWN_FD);
@ -131,19 +132,20 @@ fd_table_clear(int index)
}
void
w32posix_initialize() {
if ((fd_table_initialize() != 0)
|| (socketio_initialize() != 0))
w32posix_initialize()
{
if ((fd_table_initialize() != 0) || (socketio_initialize() != 0))
DebugBreak();
main_thread = OpenThread(THREAD_SET_CONTEXT | SYNCHRONIZE, FALSE, GetCurrentThreadId());
if ((main_thread == NULL) || (sw_initialize() != 0) || w32_programdir() == NULL) {
DebugBreak();
fatal("failed to initialize w32posix wrapper");
}
if ((main_thread == NULL) || (sw_initialize() != 0) || w32_programdir() == NULL) {
DebugBreak();
fatal("failed to initialize w32posix wrapper");
}
}
void
w32posix_done() {
w32posix_done()
{
socketio_done();
}
@ -159,7 +161,8 @@ w32_io_is_blocking(struct w32_io* pio)
* as it decides on what fds can be set.
*/
BOOL
w32_io_is_io_available(struct w32_io* pio, BOOL rd) {
w32_io_is_io_available(struct w32_io* pio, BOOL rd)
{
if (pio->type == SOCK_FD)
return socketio_is_io_available(pio, rd);
else
@ -195,7 +198,8 @@ w32_io_on_select(struct w32_io* pio, BOOL rd)
} while (0)
int
w32_socket(int domain, int type, int protocol) {
w32_socket(int domain, int type, int protocol)
{
int min_index = fd_table_get_min_index();
struct w32_io* pio = NULL;
@ -216,7 +220,6 @@ w32_socket(int domain, int type, int protocol) {
int
w32_accept(int fd, struct sockaddr* addr, int* addrlen)
{
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
int min_index = fd_table_get_min_index();
@ -236,72 +239,72 @@ w32_accept(int fd, struct sockaddr* addr, int* addrlen)
}
int
w32_setsockopt(int fd, int level, int optname, const void* optval, int optlen) {
w32_setsockopt(int fd, int level, int optname, const void* optval, int optlen)
{
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_setsockopt(fd_table.w32_ios[fd], level, optname, (const char*)optval, optlen);
}
int
w32_getsockopt(int fd, int level, int optname, void* optval, int* optlen) {
w32_getsockopt(int fd, int level, int optname, void* optval, int* optlen)
{
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_getsockopt(fd_table.w32_ios[fd], level, optname, (char*)optval, optlen);
}
int
w32_getsockname(int fd, struct sockaddr* name, int* namelen) {
w32_getsockname(int fd, struct sockaddr* name, int* namelen)
{
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_getsockname(fd_table.w32_ios[fd], name, namelen);
}
int
w32_getpeername(int fd, struct sockaddr* name, int* namelen) {
w32_getpeername(int fd, struct sockaddr* name, int* namelen)
{
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_getpeername(fd_table.w32_ios[fd], name, namelen);
}
int
w32_listen(int fd, int backlog) {
w32_listen(int fd, int backlog)
{
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_listen(fd_table.w32_ios[fd], backlog);
}
int
w32_bind(int fd, const struct sockaddr *name, int namelen) {
w32_bind(int fd, const struct sockaddr *name, int namelen)
{
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_bind(fd_table.w32_ios[fd], name, namelen);
}
int
w32_connect(int fd, const struct sockaddr* name, int namelen) {
w32_connect(int fd, const struct sockaddr* name, int namelen)
{
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_connect(fd_table.w32_ios[fd], name, namelen);
}
int
w32_recv(int fd, void *buf, size_t len, int flags) {
w32_recv(int fd, void *buf, size_t len, int flags)
{
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_recv(fd_table.w32_ios[fd], buf, len, flags);
}
int
w32_send(int fd, const void *buf, size_t len, int flags) {
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);
@ -309,7 +312,8 @@ w32_send(int fd, const void *buf, size_t len, int flags) {
int
w32_shutdown(int fd, int how) {
w32_shutdown(int fd, int how)
{
debug2("shutdown - fd:%d how:%d", fd, how);
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
@ -317,15 +321,17 @@ w32_shutdown(int fd, int how) {
}
int
w32_socketpair(int domain, int type, int protocol, int sv[2]) {
errno = ENOTSUP;
w32_socketpair(int domain, int type, int protocol, int sv[2])
{
errno = ENOTSUP;
debug("socketpair - ERROR not supported");
return -1;
}
int
w32_pipe(int *pfds) {
w32_pipe(int *pfds)
{
int read_index, write_index;
struct w32_io* pio[2];
@ -351,12 +357,14 @@ w32_pipe(int *pfds) {
pfds[0] = read_index;
pfds[1] = write_index;
debug("pipe - r-h:%d,io:%p,fd:%d w-h:%d,io:%p,fd:%d",
pio[0]->handle, pio[0], read_index, pio[1]->handle, pio[1], write_index);
pio[0]->handle, pio[0], read_index, pio[1]->handle, pio[1], write_index);
return 0;
}
int
w32_open(const char *pathname, int flags, ...) {
w32_open(const char *pathname, int flags, ...)
{
int min_index = fd_table_get_min_index();
struct w32_io* pio;
@ -376,9 +384,9 @@ w32_open(const char *pathname, int flags, ...) {
}
int
w32_read(int fd, void *dst, size_t max) {
w32_read(int fd, void *dst, size_t max)
{
CHECK_FD(fd);
if (fd_table.w32_ios[fd]->type == SOCK_FD)
return socketio_recv(fd_table.w32_ios[fd], dst, max, 0);
@ -386,7 +394,8 @@ w32_read(int fd, void *dst, size_t max) {
}
int
w32_write(int fd, const void *buf, unsigned int max) {
w32_write(int fd, const void *buf, unsigned int max)
{
CHECK_FD(fd);
if (fd_table.w32_ios[fd]->type == SOCK_FD)
@ -395,37 +404,39 @@ w32_write(int fd, const void *buf, unsigned int max) {
return fileio_write(fd_table.w32_ios[fd], buf, max);
}
int w32_writev(int fd, const struct iovec *iov, int iovcnt) {
int written = 0;
int i = 0;
int
w32_writev(int fd, const struct iovec *iov, int iovcnt)
{
int written = 0;
int i = 0;
CHECK_FD(fd);
CHECK_FD(fd);
for (i = 0; i < iovcnt; i++) {
int ret = w32_write(fd, iov[i].iov_base, iov[i].iov_len);
if (ret > 0)
written += ret;
}
for (i = 0; i < iovcnt; i++) {
int ret = w32_write(fd, iov[i].iov_base, iov[i].iov_len);
if (ret > 0) {
written += ret;
}
}
return written;
return written;
}
int
w32_fstat(int fd, struct w32_stat *buf) {
w32_fstat(int fd, struct w32_stat *buf)
{
CHECK_FD(fd);
return fileio_fstat(fd_table.w32_ios[fd], (struct _stat64*)buf);
}
long
w32_lseek(int fd, long offset, int origin) {
w32_lseek(int fd, long offset, int origin)
{
CHECK_FD(fd);
return fileio_lseek(fd_table.w32_ios[fd], offset, origin);
}
int
w32_isatty(int fd) {
w32_isatty(int fd)
{
struct w32_io* pio;
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
errno = EBADF;
@ -433,7 +444,6 @@ w32_isatty(int fd) {
}
pio = fd_table.w32_ios[fd];
if (FILETYPE(pio) == FILE_TYPE_CHAR)
return 1;
else {
@ -443,7 +453,8 @@ w32_isatty(int fd) {
}
FILE*
w32_fdopen(int fd, const char *mode) {
w32_fdopen(int fd, const char *mode)
{
errno = 0;
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
errno = EBADF;
@ -454,13 +465,13 @@ w32_fdopen(int fd, const char *mode) {
}
int
w32_close(int fd) {
w32_close(int fd)
{
struct w32_io* pio;
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
errno = EBADF;
return -1;
}
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
errno = EBADF;
return -1;
}
pio = fd_table.w32_ios[fd];
@ -480,7 +491,8 @@ w32_close(int fd) {
}
static int
w32_io_process_fd_flags(struct w32_io* pio, int flags) {
w32_io_process_fd_flags(struct w32_io* pio, int flags)
{
DWORD shi_flags;
if (flags & ~FD_CLOEXEC) {
debug("fcntl - ERROR unsupported flags %d, io:%p", flags, pio);
@ -502,42 +514,43 @@ w32_io_process_fd_flags(struct w32_io* pio, int flags) {
}
int
w32_fcntl(int fd, int cmd, ... /* arg */) {
w32_fcntl(int fd, int cmd, ... /* arg */)
{
va_list valist;
va_start(valist, cmd);
int ret = 0;
int ret = 0;
CHECK_FD(fd);
switch (cmd) {
case F_GETFL:
ret = fd_table.w32_ios[fd]->fd_status_flags;
break;
break;
case F_SETFL:
fd_table.w32_ios[fd]->fd_status_flags = va_arg(valist, int);
ret = 0;
break;
break;
case F_GETFD:
ret = fd_table.w32_ios[fd]->fd_flags;
break;
break;
case F_SETFD:
ret = w32_io_process_fd_flags(fd_table.w32_ios[fd], va_arg(valist, int));
break;
ret = w32_io_process_fd_flags(fd_table.w32_ios[fd], va_arg(valist, int));
break;
default:
errno = EINVAL;
debug("fcntl - ERROR not supported cmd:%d", cmd);
ret = -1;
break;
}
break;
}
va_end(valist);
return ret;
va_end(valist);
return ret;
}
#define SELECT_EVENT_LIMIT 32
int
w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* exceptfds,
const struct timeval *timeout) {
w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* exceptfds, const struct timeval *timeout)
{
ULONGLONG ticks_start = GetTickCount64(), ticks_spent;
w32_fd_set read_ready_fds, write_ready_fds;
HANDLE events[SELECT_EVENT_LIMIT];
@ -566,12 +579,12 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
}
/* TODO - see if this needs to be supported */
//if (exceptfds) {
// errno = EOPNOTSUPP;
// debug("select - ERROR: exceptfds not supported");
// DebugBreak();
// return -1;
//}
/* if (exceptfds) {
errno = EOPNOTSUPP;
debug("select - ERROR: exceptfds not supported");
DebugBreak();
return -1;
} */
if (readfds) {
for (i = 0; i < fds; i++)
@ -602,11 +615,10 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
* that select needs to listen on
*/
for (int i = 0; i < fds; i++) {
if (readfds && FD_ISSET(i, readfds)) {
w32_io_on_select(fd_table.w32_ios[i], TRUE);
if ((fd_table.w32_ios[i]->type == SOCK_FD)
&& (fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) {
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
(fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) {
if (num_events == SELECT_EVENT_LIMIT) {
debug("select - ERROR: max #events breach");
errno = ENOMEM;
@ -618,8 +630,8 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
if (writefds && FD_ISSET(i, writefds)) {
w32_io_on_select(fd_table.w32_ios[i], FALSE);
if ((fd_table.w32_ios[i]->type == SOCK_FD)
&& (fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) {
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
(fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) {
if (num_events == SELECT_EVENT_LIMIT) {
debug("select - ERROR: max #events reached for select");
errno = ENOMEM;
@ -636,7 +648,6 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
/* see if any io is ready */
for (i = 0; i < fds; i++) {
if (readfds && FD_ISSET(i, readfds)) {
if (w32_io_is_io_available(fd_table.w32_ios[i], TRUE)) {
FD_SET(i, &read_ready_fds);
@ -677,7 +688,6 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
/* check on fd status */
out_ready_fds = 0;
for (int i = 0; i < fds; i++) {
if (readfds && FD_ISSET(i, readfds)) {
if (w32_io_is_io_available(fd_table.w32_ios[i], TRUE)) {
FD_SET(i, &read_ready_fds);
@ -695,7 +705,6 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
if (out_ready_fds == 0)
debug3("select - wait ended without any IO completion, looping again");
}
/* clear out fds that are not ready yet */
@ -709,8 +718,8 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
if (FD_ISSET(i, writefds)) {
if (FD_ISSET(i, &write_ready_fds)) {
/* for connect() completed sockets finish WSA connect process*/
if ((fd_table.w32_ios[i]->type == SOCK_FD)
&& ((fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)))
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
((fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)))
if (socketio_finish_connect(fd_table.w32_ios[i]) != 0) {
/* finalizeing connect failed - recored error */
/* error gets picked up later recv and/or send*/
@ -730,7 +739,8 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
}
int
w32_dup(int oldfd) {
w32_dup(int oldfd)
{
int min_index;
struct w32_io* pio;
HANDLE src, target;
@ -773,7 +783,8 @@ w32_dup(int oldfd) {
}
int
w32_dup2(int oldfd, int newfd) {
w32_dup2(int oldfd, int newfd)
{
CHECK_FD(oldfd);
errno = EOPNOTSUPP;
debug("dup2 - ERROR: not implemented yet");
@ -781,14 +792,17 @@ w32_dup2(int oldfd, int newfd) {
}
HANDLE
w32_fd_to_handle(int fd) {
w32_fd_to_handle(int fd)
{
HANDLE h = fd_table.w32_ios[fd]->handle;
if (fd <= STDERR_FILENO)
h = GetStdHandle(fd_table.w32_ios[fd]->std_handle);
return h;
}
int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock) {
int
w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock)
{
int min_index = fd_table_get_min_index();
struct w32_io* pio;
@ -803,7 +817,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 : NONSOCK_FD;
pio->type = is_sock ? SOCK_FD : NONSOCK_FD;
pio->handle = h;
fd_table_set(pio, min_index);
return min_index;
@ -811,20 +825,23 @@ int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock) {
int
w32_ftruncate(int fd, off_t length) {
CHECK_FD(fd);
w32_ftruncate(int fd, off_t length)
{
LARGE_INTEGER new_postion;
CHECK_FD(fd);
if (!SetFilePointer(w32_fd_to_handle(fd), length, 0, FILE_BEGIN))
return -1;
if (!SetEndOfFile(w32_fd_to_handle(fd)))
return -1;
new_postion.QuadPart = length;
if (!SetFilePointerEx(w32_fd_to_handle(fd), new_postion, 0, FILE_BEGIN))
return -1;
if (!SetEndOfFile(w32_fd_to_handle(fd)))
return -1;
return 0;
return 0;
}
int
w32_fsync(int fd) {
CHECK_FD(fd);
return FlushFileBuffers(w32_fd_to_handle(fd));
w32_fsync(int fd)
{
CHECK_FD(fd);
return FlushFileBuffers(w32_fd_to_handle(fd));
}

View File

@ -1,7 +1,33 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Definitions for Win32 wrapper functions with POSIX like signatures
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Definitions for Win32 wrapper functions with POSIX like signatures
*
* Copyright (c) 2015 Microsoft Corp.
* All rights reserved
*
* Microsoft openssh win32 port
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
@ -32,24 +58,18 @@ struct w32_io {
OVERLAPPED read_overlapped;
OVERLAPPED write_overlapped;
struct {
/*internal read buffer*/
char *buf;
char *buf; /*internal read buffer*/
DWORD buf_size;
/*bytes in internal buffer remaining to be read by application*/
DWORD remaining;
/*bytes in internal buffer already read by application*/
DWORD completed;
DWORD remaining; /*bytes in internal buffer remaining to be read by application*/
DWORD completed; /*bytes in internal buffer already read by application*/
BOOL pending; /*waiting on a read operation to complete*/
DWORD error; /*error reported on async read or accept completion*/
}read_details;
struct {
/*internal write buffer*/
char *buf;
char *buf; /*internal write buffer*/
DWORD buf_size;
/*bytes in internal buffer remaining to be written to network*/
DWORD remaining;
/*bytes in internal buffer already written to network*/
DWORD completed;
DWORD remaining; /*bytes in internal buffer remaining to be written to network*/
DWORD completed; /*bytes in internal buffer already written to network*/
BOOL pending; /*waiting on a write operation to complete*/
DWORD error; /*error reported on async write or connect completion*/
}write_details;
@ -89,10 +109,8 @@ BOOL socketio_is_io_available(struct w32_io* pio, BOOL rd);
void socketio_on_select(struct w32_io* pio, BOOL rd);
struct w32_io* socketio_socket(int domain, int type, int protocol);
struct w32_io* socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen);
int socketio_setsockopt(struct w32_io* pio, int level, int optname,
const char* optval, int optlen);
int socketio_getsockopt(struct w32_io* pio, int level, int optname,
char* optval, int* optlen);
int socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval, int optlen);
int socketio_getsockopt(struct w32_io* pio, int level, int optname, char* optval, int* optlen);
int socketio_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen);
int socketio_getpeername(struct w32_io* pio, struct sockaddr* name, int* namelen);
int socketio_listen(struct w32_io* pio, int backlog);
@ -145,16 +163,16 @@ int termio_close(struct w32_io* pio);
/* If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
/* #define O_EXCL 0x400 */
/* #define O_BINARY 0x8000 //Gives raw data (while O_TEXT normalises line endings */
// open modes
/* open modes */
#ifndef S_IRUSR
#define S_IRUSR 00400 //user has read permission
#endif // ! S_IRUSR
#define S_IRUSR 00400 /* user has read permission */
#endif /* ! S_IRUSR */
#ifndef S_IWUSR
#define S_IWUSR 00200 //user has write permission
#define S_IWUSR 00200 /* user has write permission */
#endif
#ifndef S_IRGRP
#define S_IRGRP 00040 //group has read permission
#define S_IRGRP 00040 /* group has read permission */
#endif
#ifndef S_IROTH
#define S_IROTH 00004 //others have read permission
#define S_IROTH 00004 /* others have read permission */
#endif

View File

@ -27,11 +27,11 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <Windows.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "inc\syslog.h"
#include "misc_internal.h"
@ -39,14 +39,15 @@
static int logfd = -1;
void
openlog(char *ident, unsigned int option, int facility) {
openlog(char *ident, unsigned int option, int facility)
{
if (logfd != -1 || ident == NULL)
return;
wchar_t path[PATH_MAX], log_file[PATH_MAX + 12];
if (GetModuleFileNameW(NULL, path, PATH_MAX) == 0)
return;
path[PATH_MAX - 1] = '\0';
/* split path root and module */
@ -64,20 +65,20 @@ openlog(char *ident, unsigned int option, int facility) {
memcpy(p, L"log\0", 8);
}
logfd = _wopen(log_file, O_WRONLY | O_CREAT | O_APPEND,
S_IREAD | S_IWRITE);
logfd = _wopen(log_file, O_WRONLY | O_CREAT | O_APPEND, S_IREAD | S_IWRITE);
if (logfd != -1)
SetHandleInformation((HANDLE)_get_osfhandle(logfd),
HANDLE_FLAG_INHERIT, 0);
SetHandleInformation((HANDLE)_get_osfhandle(logfd), HANDLE_FLAG_INHERIT, 0);
}
void
closelog(void) {
closelog(void)
{
/*NOOP*/
}
void
syslog(int priority, const char *format, const char *formatBuffer) {
syslog(int priority, const char *format, const char *formatBuffer)
{
char msgbufTimestamp[MSGBUFSIZ];
SYSTEMTIME st;

View File

@ -1,19 +1,43 @@
// win32_dirent.c
// directory entry functions in Windows platform like Ubix/Linux
// opendir(), readdir(), closedir().
/*
* Copyright (c) 2016 Microsoft Corp.
* All rights reserved
*
* directory entry functions in Windows platform like Ubix/Linux
* opendir(), readdir(), closedir().
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "inc\utf.h"
#include "inc\utf.h"
#include "inc\dirent.h"
#include "inc\libgen.h"
#include "misc_internal.h"
struct DIR_ {
intptr_t hFile;
struct _wfinddata_t c_file;
@ -22,7 +46,8 @@ struct DIR_ {
/* Open a directory stream on NAME.
Return a DIR stream on the directory, or NULL if it could not be opened. */
DIR * opendir(const char *name)
DIR *
opendir(const char *name)
{
struct _wfinddata_t c_file;
intptr_t hFile;
@ -36,7 +61,7 @@ DIR * opendir(const char *name)
return NULL;
}
// add *.* for Windows _findfirst() search pattern
/* add *.* for Windows _findfirst() search pattern */
swprintf_s(searchstr, PATH_MAX, L"%s\\*.*", wname);
free(wname);
@ -54,28 +79,30 @@ DIR * opendir(const char *name)
memcpy(&pdir->c_file, &c_file, sizeof(c_file));
pdir->first = 1;
return pdir ;
return pdir;
}
}
/* Close the directory stream DIRP.
Return 0 if successful, -1 if not. */
int closedir(DIR *dirp)
int
closedir(DIR *dirp)
{
if ( dirp && (dirp->hFile) ) {
_findclose( dirp->hFile );
dirp->hFile = 0;
free (dirp);
}
if (dirp && (dirp->hFile)) {
_findclose(dirp->hFile);
dirp->hFile = 0;
free(dirp);
}
return 0;
return 0;
}
/* Read a directory entry from DIRP.
Return a pointer to a `struct dirent' describing the entry,
or NULL for EOF or error. The storage returned may be overwritten
by a later readdir call on the same DIR stream. */
struct dirent *readdir(void *avp)
struct dirent *
readdir(void *avp)
{
static struct dirent pdirentry;
struct _wfinddata_t c_file;
@ -86,11 +113,10 @@ struct dirent *readdir(void *avp)
if (dirp->first) {
memcpy(&c_file, &dirp->c_file, sizeof(c_file));
dirp->first = 0;
}
else if (_wfindnext(dirp->hFile, &c_file) != 0)
} else if (_wfindnext(dirp->hFile, &c_file) != 0)
return NULL;
if (wcscmp(c_file.name, L".") == 0 || wcscmp(c_file.name, L"..") == 0 )
if (wcscmp(c_file.name, L".") == 0 || wcscmp(c_file.name, L"..") == 0)
continue;
if ((tmp = utf16_to_utf8(c_file.name)) == NULL) {
@ -101,13 +127,14 @@ struct dirent *readdir(void *avp)
strncpy(pdirentry.d_name, tmp, strlen(tmp) + 1);
free(tmp);
pdirentry.d_ino = 1; // a fictious one like UNIX to say it is nonzero
return &pdirentry ;
}
pdirentry.d_ino = 1; /* a fictious one like UNIX to say it is nonzero */
return &pdirentry;
}
}
// return last part of a path. The last path being a filename.
char *basename(char *path)
/* return last part of a path. The last path being a filename */
char *
basename(char *path)
{
char *pdest;
@ -115,10 +142,10 @@ char *basename(char *path)
return ".";
pdest = strrchr(path, '/');
if (pdest)
return (pdest+1);
return (pdest + 1);
pdest = strrchr(path, '\\');
if (pdest)
return (pdest+1);
return (pdest + 1);
return path; // path does not have a slash
return path; /* path does not have a slash */
}

View File

@ -32,33 +32,38 @@
#include "inc\zlib.h"
int
deflateEnd(z_streamp strm) {
deflateEnd(z_streamp strm)
{
return Z_DATA_ERROR;
}
int
inflateEnd(z_streamp strm) {
inflateEnd(z_streamp strm)
{
return Z_DATA_ERROR;
}
int
deflateInit(z_streamp strm, int level) {
deflateInit(z_streamp strm, int level)
{
return Z_DATA_ERROR;
}
int
inflateInit(z_streamp strm) {
inflateInit(z_streamp strm)
{
return Z_DATA_ERROR;
}
int
deflate(z_streamp strm, int flush) {
deflate(z_streamp strm, int flush)
{
return Z_DATA_ERROR;
}
int
inflate(z_streamp strm, int flush) {
inflate(z_streamp strm, int flush)
{
return Z_DATA_ERROR;
}

View File

@ -33,6 +33,9 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#ifdef WINDOWS
#include <lm.h>
#endif
#include "xmalloc.h"
#include "groupaccess.h"
@ -49,6 +52,82 @@ static char **groups_byname;
int
ga_init(const char *user, gid_t base)
{
#ifdef WINDOWS
DWORD i = 0, j = 0;
LPLOCALGROUP_USERS_INFO_0 local_groups_info = NULL, tmp_groups_info;
wchar_t *user_utf16 = NULL, *full_name_utf16 = NULL, *udom_utf16 = NULL, *tmp;
char *group_utf8 = NULL;
DWORD entries_read = 0, total_entries = 0, full_name_len = 0, index = 0;
NET_API_STATUS nStatus;
if (ngroups > 0)
ga_free();
user_utf16 = utf8_to_utf16(user);
if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
errno = ENOMEM;
goto done;
}
full_name_len = wcslen(user_utf16) + 1;
if ((full_name_utf16 = malloc(full_name_len * sizeof(wchar_t))) == NULL) {
errno = ENOMEM;
goto done;
}
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
udom_utf16 = tmp + 1;
*tmp = L'\0';
index = wcslen(udom_utf16) + 1;
wmemcpy(full_name_utf16, udom_utf16, index);
full_name_utf16[wcslen(udom_utf16)] = L'\\';
}
wmemcpy(full_name_utf16 + index, user_utf16, wcslen(user_utf16) + 1);
nStatus = NetUserGetLocalGroups(NULL,
full_name_utf16,
0,
LG_INCLUDE_INDIRECT,
(LPBYTE *)&local_groups_info,
MAX_PREFERRED_LENGTH,
&entries_read,
&total_entries);
if (NERR_Success != nStatus) {
error("NetUserGetLocalGroups() failed with error: %u",
nStatus);
errno = ENOENT;
goto done;
}
if (entries_read != total_entries) {
error("NetUserGetLocalGroups(): entries_read (%u) is not equal to "
"total_entries (%u) for user %.100s", entries_read, total_entries, user);
errno = ENOENT;
goto done;
}
if ((tmp_groups_info = local_groups_info) != NULL) {
groups_byname = xcalloc(entries_read, sizeof(*groups_byname));
for (i = 0, j = 0; i < total_entries; i++)
{
if ((group_utf8 = utf16_to_utf8(tmp_groups_info->lgrui0_name)) == NULL) {
errno = ENOMEM;
goto done;
}
groups_byname[j++] = group_utf8;
tmp_groups_info++;
}
}
done:
if(user_utf16 != NULL)
free(user_utf16);
if(full_name_utf16 != NULL)
free(full_name_utf16);
if (local_groups_info != NULL)
NetApiBufferFree(local_groups_info);
#else /* !WINDOWS */
gid_t *groups_bygid;
int i, j;
struct group *gr;
@ -70,7 +149,9 @@ ga_init(const char *user, gid_t base)
if ((gr = getgrgid(groups_bygid[i])) != NULL)
groups_byname[j++] = xstrdup(gr->gr_name);
free(groups_bygid);
#endif /* !WINDOWS */
return (ngroups = j);
}
/*

21
kex.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.c,v 1.127 2016/10/10 19:28:48 markus Exp $ */
/* $OpenBSD: kex.c,v 1.128 2017/02/03 23:01:19 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@ -211,7 +211,8 @@ kex_names_cat(const char *a, const char *b)
/*
* Assemble a list of algorithms from a default list and a string from a
* configuration file. The user-provided string may begin with '+' to
* indicate that it should be appended to the default.
* indicate that it should be appended to the default or '-' that the
* specified names should be removed.
*/
int
kex_assemble_names(const char *def, char **list)
@ -222,14 +223,18 @@ kex_assemble_names(const char *def, char **list)
*list = strdup(def);
return 0;
}
if (**list != '+') {
return 0;
if (**list == '+') {
if ((ret = kex_names_cat(def, *list + 1)) == NULL)
return SSH_ERR_ALLOC_FAIL;
free(*list);
*list = ret;
} else if (**list == '-') {
if ((ret = match_filter_list(def, *list + 1)) == NULL)
return SSH_ERR_ALLOC_FAIL;
free(*list);
*list = ret;
}
if ((ret = kex_names_cat(def, *list + 1)) == NULL)
return SSH_ERR_ALLOC_FAIL;
free(*list);
*list = ret;
return 0;
}

31
match.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: match.c,v 1.33 2016/11/06 05:46:37 djm Exp $ */
/* $OpenBSD: match.c,v 1.34 2017/02/03 23:01:19 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -284,3 +284,32 @@ match_list(const char *client, const char *server, u_int *next)
free(s);
return NULL;
}
/*
* Filters a comma-separated list of strings, excluding any entry matching
* the 'filter' pattern list. Caller must free returned string.
*/
char *
match_filter_list(const char *proposal, const char *filter)
{
size_t len = strlen(proposal) + 1;
char *fix_prop = malloc(len);
char *orig_prop = strdup(proposal);
char *cp, *tmp;
if (fix_prop == NULL || orig_prop == NULL)
return NULL;
tmp = orig_prop;
*fix_prop = '\0';
while ((cp = strsep(&tmp, ",")) != NULL) {
if (match_pattern_list(cp, filter, 0) != 1) {
if (*fix_prop != '\0')
strlcat(fix_prop, ",", len);
strlcat(fix_prop, cp, len);
}
}
free(orig_prop);
return fix_prop;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: match.h,v 1.16 2015/05/04 06:10:48 djm Exp $ */
/* $OpenBSD: match.h,v 1.17 2017/02/03 23:01:19 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -20,6 +20,7 @@ int match_hostname(const char *, const char *);
int match_host_and_ip(const char *, const char *, const char *);
int match_user(const char *, const char *, const char *, const char *);
char *match_list(const char *, const char *, u_int *);
char *match_filter_list(const char *, const char *);
/* addrmatch.c */
int addr_match_list(const char *, const char *);

6
misc.c
View File

@ -225,6 +225,10 @@ pwcopy(struct passwd *pw)
#endif
copy->pw_dir = xstrdup(pw->pw_dir);
copy->pw_shell = xstrdup(pw->pw_shell);
#ifdef WINDOWS
copy->pw_sid = xstrdup(pw->pw_sid);
#endif /* WINDOWS */
return copy;
}
@ -439,7 +443,7 @@ colon(char *cp)
#ifdef WINDOWS
/*
* Account for Windows file names in the form x: or /x:
* Note: This may conflict with potential single charecter targets
* Note: This may conflict with potential single character targets
*/
if ((*cp != '\0' && cp[1] == ':') ||
(cp[0] == '/' && cp[1] != '\0' && cp[2] == ':'))

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.166 2016/09/28 16:33:06 djm Exp $ */
/* $OpenBSD: monitor.c,v 1.167 2017/02/03 23:05:57 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -283,6 +283,7 @@ monitor_permit_authentications(int permit)
void
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
{
struct ssh *ssh = active_state; /* XXX */
struct mon_table *ent;
int authenticated = 0, partial = 0;
@ -356,6 +357,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
debug("%s: %s has been authenticated by privileged process",
__func__, authctxt->user);
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
mm_get_keystate(pmonitor);
@ -695,6 +697,7 @@ mm_answer_sign(int sock, Buffer *m)
int
mm_answer_pwnamallow(int sock, Buffer *m)
{
struct ssh *ssh = active_state; /* XXX */
char *username;
struct passwd *pwent;
int allowed = 0;
@ -739,6 +742,8 @@ mm_answer_pwnamallow(int sock, Buffer *m)
buffer_put_cstring(m, pwent->pw_shell);
out:
ssh_packet_set_log_preamble(ssh, "%suser %s",
authctxt->valid ? "authenticating" : "invalid ", authctxt->user);
buffer_put_string(m, &options, sizeof(options));
#define M_CP_STROPT(x) do { \

7
mux.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: mux.c,v 1.63 2016/10/19 23:21:56 dtucker Exp $ */
/* $OpenBSD: mux.c,v 1.64 2017/01/21 11:32:04 guenther Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@ -2161,7 +2161,6 @@ int
muxclient(const char *path)
{
struct sockaddr_un addr;
socklen_t sun_len;
int sock;
u_int pid;
@ -2185,8 +2184,6 @@ muxclient(const char *path)
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
sun_len = offsetof(struct sockaddr_un, sun_path) +
strlen(path) + 1;
if (strlcpy(addr.sun_path, path,
sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
@ -2196,7 +2193,7 @@ muxclient(const char *path)
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
fatal("%s socket(): %s", __func__, strerror(errno));
if (connect(sock, (struct sockaddr *)&addr, sun_len) == -1) {
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
switch (muxclient_command) {
case SSHMUX_COMMAND_OPEN:
case SSHMUX_COMMAND_STDIO_FWD:

View File

@ -83,10 +83,11 @@ _rs_init(u_char *buf, size_t n)
static void
getrnd(u_char *s, size_t len) {
HCRYPTPROV hProvider;
if (CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT) == FALSE ||
CryptGenRandom(hProvider, len, s) == FALSE ||
CryptReleaseContext(hProvider, 0) == FALSE)
DebugBreak();
if (CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT) == FALSE ||
CryptGenRandom(hProvider, len, s) == FALSE ||
CryptReleaseContext(hProvider, 0) == FALSE)
fatal("%s Crypto error: %d", __func__, GetLastError());
}
#else /* !WINDOWS */

View File

@ -211,7 +211,11 @@ tcsendbreak(int fd, int duration)
}
#endif /* HAVE_TCSENDBREAK */
#ifdef HAVE_SIGACTION /* Moved out of function definition */
/*
* This is not a BSD routine. Why is this here?
* Macro added to override this implementation for Windows
*/
#ifndef HAVE_MYSIGNAL
mysig_t
mysignal(int sig, mysig_t act)
{

View File

@ -95,12 +95,10 @@ int unsetenv(const char *);
#endif
/* wrapper for signal interface */
#ifdef HAVE_SIGACTION
typedef void (*mysig_t)(int);
mysig_t mysignal(int sig, mysig_t act);
#define signal(a,b) mysignal(a,b)
#endif
#ifndef HAVE_ISBLANK
int isblank(int);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.243 2016/10/11 21:47:45 djm Exp $ */
/* $OpenBSD: packet.c,v 1.245 2017/02/03 23:03:33 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -352,6 +352,25 @@ ssh_packet_get_mux(struct ssh *ssh)
return ssh->state->mux;
}
int
ssh_packet_set_log_preamble(struct ssh *ssh, const char *fmt, ...)
{
va_list args;
int r;
free(ssh->log_preamble);
if (fmt == NULL)
ssh->log_preamble = NULL;
else {
va_start(args, fmt);
r = vasprintf(&ssh->log_preamble, fmt, args);
va_end(args);
if (r < 0 || ssh->log_preamble == NULL)
return SSH_ERR_ALLOC_FAIL;
}
return 0;
}
int
ssh_packet_stop_discard(struct ssh *ssh)
{
@ -1049,7 +1068,7 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
/* Time-based rekeying */
if (state->rekey_interval != 0 &&
state->rekey_time + state->rekey_interval <= monotime())
(int64_t)state->rekey_time + state->rekey_interval <= monotime())
return 1;
/* Always rekey when MAX_PACKETS sent in either direction */
@ -2074,27 +2093,36 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
fatal("%s: %s", __func__, ssh_err(r));
}
static void
fmt_connection_id(struct ssh *ssh, char *s, size_t l)
{
snprintf(s, l, "%.200s%s%s port %d",
ssh->log_preamble ? ssh->log_preamble : "",
ssh->log_preamble ? " " : "",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
}
/*
* Pretty-print connection-terminating errors and exit.
*/
void
sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
{
char remote_id[512];
fmt_connection_id(ssh, remote_id, sizeof(remote_id));
switch (r) {
case SSH_ERR_CONN_CLOSED:
logdie("Connection closed by %.200s port %d",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
logdie("Connection closed by %s", remote_id);
case SSH_ERR_CONN_TIMEOUT:
logdie("Connection %s %.200s port %d timed out",
ssh->state->server_side ? "from" : "to",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
logdie("Connection %s %s timed out",
ssh->state->server_side ? "from" : "to", remote_id);
case SSH_ERR_DISCONNECTED:
logdie("Disconnected from %.200s port %d",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
logdie("Disconnected from %s", remote_id);
case SSH_ERR_SYSTEM_ERROR:
if (errno == ECONNRESET)
logdie("Connection reset by %.200s port %d",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
logdie("Connection reset by %s", remote_id);
/* FALLTHROUGH */
case SSH_ERR_NO_CIPHER_ALG_MATCH:
case SSH_ERR_NO_MAC_ALG_MATCH:
@ -2102,17 +2130,16 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
case SSH_ERR_NO_KEX_ALG_MATCH:
case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
if (ssh && ssh->kex && ssh->kex->failed_choice) {
logdie("Unable to negotiate with %.200s port %d: %s. "
"Their offer: %s", ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh), ssh_err(r),
logdie("Unable to negotiate with %s: %s. "
"Their offer: %s", remote_id, ssh_err(r),
ssh->kex->failed_choice);
}
/* FALLTHROUGH */
default:
logdie("%s%sConnection %s %.200s port %d: %s",
logdie("%s%sConnection %s %s: %s",
tag != NULL ? tag : "", tag != NULL ? ": " : "",
ssh->state->server_side ? "from" : "to",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), ssh_err(r));
remote_id, ssh_err(r));
}
}
@ -2125,7 +2152,7 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
void
ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
{
char buf[1024];
char buf[1024], remote_id[512];
va_list args;
static int disconnecting = 0;
int r;
@ -2138,12 +2165,13 @@ ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
* Format the message. Note that the caller must make sure the
* message is of limited size.
*/
fmt_connection_id(ssh, remote_id, sizeof(remote_id));
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
/* Display the error locally */
logit("Disconnecting: %.100s", buf);
logit("Disconnecting %s: %.100s", remote_id, buf);
/*
* Send the disconnect message to the other side, and wait
@ -2396,10 +2424,10 @@ ssh_packet_send_ignore(struct ssh *ssh, int nbytes)
}
void
ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, time_t seconds)
ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds)
{
debug3("rekey after %llu bytes, %d seconds", (unsigned long long)bytes,
(int)seconds);
debug3("rekey after %llu bytes, %u seconds", (unsigned long long)bytes,
(unsigned int)seconds);
ssh->state->rekey_limit = bytes;
ssh->state->rekey_interval = seconds;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.h,v 1.74 2016/10/11 21:47:45 djm Exp $ */
/* $OpenBSD: packet.h,v 1.76 2017/02/03 23:03:33 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -62,6 +62,9 @@ struct ssh {
char *local_ipaddr;
int local_port;
/* Optional preamble for log messages (e.g. username) */
char *log_preamble;
/* Dispatcher table */
dispatch_fn *dispatch[DISPATCH_MAX];
/* number of packets to ignore in the dispatcher */
@ -104,6 +107,8 @@ void ssh_packet_set_server(struct ssh *);
void ssh_packet_set_authenticated(struct ssh *);
void ssh_packet_set_mux(struct ssh *);
int ssh_packet_get_mux(struct ssh *);
int ssh_packet_set_log_preamble(struct ssh *, const char *, ...)
__attribute__((format(printf, 2, 3)));
int ssh_packet_log_type(u_char);
@ -154,7 +159,7 @@ int ssh_remote_port(struct ssh *);
const char *ssh_local_ipaddr(struct ssh *);
int ssh_local_port(struct ssh *);
void ssh_packet_set_rekey_limits(struct ssh *, u_int64_t, time_t);
void ssh_packet_set_rekey_limits(struct ssh *, u_int64_t, u_int32_t);
time_t ssh_packet_get_rekey_timeout(struct ssh *);
void *ssh_packet_get_input(struct ssh *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.262 2016/10/25 04:08:13 jsg Exp $ */
/* $OpenBSD: readconf.c,v 1.268 2017/02/03 23:01:19 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -93,7 +93,7 @@
Host books.com
RemoteForward 9999 shadows.cs.hut.fi:9999
Cipher 3des
Ciphers 3des-cbc
Host fascist.blob.com
Port 23123
@ -108,7 +108,7 @@
PublicKeyAuthentication no
Host *.su
Cipher none
Ciphers aes128-ctr
PasswordAuthentication no
Host vpn.fake.com
@ -180,6 +180,44 @@ static struct {
const char *name;
OpCodes opcode;
} keywords[] = {
/* Deprecated options */
{ "fallbacktorsh", oDeprecated },
{ "globalknownhostsfile2", oDeprecated },
{ "rhostsauthentication", oDeprecated },
{ "userknownhostsfile2", oDeprecated },
{ "useroaming", oDeprecated },
{ "usersh", oDeprecated },
/* Unsupported options */
{ "afstokenpassing", oUnsupported },
{ "kerberosauthentication", oUnsupported },
{ "kerberostgtpassing", oUnsupported },
/* Sometimes-unsupported options */
#if defined(GSSAPI)
{ "gssapiauthentication", oGssAuthentication },
{ "gssapidelegatecredentials", oGssDelegateCreds },
# else
{ "gssapiauthentication", oUnsupported },
{ "gssapidelegatecredentials", oUnsupported },
#endif
#ifdef ENABLE_PKCS11
{ "smartcarddevice", oPKCS11Provider },
{ "pkcs11provider", oPKCS11Provider },
# else
{ "smartcarddevice", oUnsupported },
{ "pkcs11provider", oUnsupported },
#endif
#ifdef WITH_SSH1
{ "rsaauthentication", oRSAAuthentication },
{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
{ "compressionlevel", oCompressionLevel },
# else
{ "rsaauthentication", oUnsupported },
{ "rhostsrsaauthentication", oUnsupported },
{ "compressionlevel", oUnsupported },
#endif
{ "forwardagent", oForwardAgent },
{ "forwardx11", oForwardX11 },
{ "forwardx11trusted", oForwardX11Trusted },
@ -188,30 +226,15 @@ static struct {
{ "xauthlocation", oXAuthLocation },
{ "gatewayports", oGatewayPorts },
{ "useprivilegedport", oUsePrivilegedPort },
{ "rhostsauthentication", oDeprecated },
{ "passwordauthentication", oPasswordAuthentication },
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
{ "kbdinteractivedevices", oKbdInteractiveDevices },
{ "rsaauthentication", oRSAAuthentication },
{ "pubkeyauthentication", oPubkeyAuthentication },
{ "dsaauthentication", oPubkeyAuthentication }, /* alias */
{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
{ "hostbasedauthentication", oHostbasedAuthentication },
{ "challengeresponseauthentication", oChallengeResponseAuthentication },
{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
{ "tisauthentication", oChallengeResponseAuthentication }, /* alias */
{ "kerberosauthentication", oUnsupported },
{ "kerberostgtpassing", oUnsupported },
{ "afstokenpassing", oUnsupported },
#if defined(GSSAPI)
{ "gssapiauthentication", oGssAuthentication },
{ "gssapidelegatecredentials", oGssDelegateCreds },
#else
{ "gssapiauthentication", oUnsupported },
{ "gssapidelegatecredentials", oUnsupported },
#endif
{ "fallbacktorsh", oDeprecated },
{ "usersh", oDeprecated },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* obsolete */
{ "identitiesonly", oIdentitiesOnly },
@ -233,15 +256,12 @@ static struct {
{ "match", oMatch },
{ "escapechar", oEscapeChar },
{ "globalknownhostsfile", oGlobalKnownHostsFile },
{ "globalknownhostsfile2", oDeprecated },
{ "userknownhostsfile", oUserKnownHostsFile },
{ "userknownhostsfile2", oDeprecated },
{ "connectionattempts", oConnectionAttempts },
{ "batchmode", oBatchMode },
{ "checkhostip", oCheckHostIP },
{ "stricthostkeychecking", oStrictHostKeyChecking },
{ "compression", oCompression },
{ "compressionlevel", oCompressionLevel },
{ "tcpkeepalive", oTCPKeepAlive },
{ "keepalive", oTCPKeepAlive }, /* obsolete */
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
@ -250,13 +270,6 @@ static struct {
{ "preferredauthentications", oPreferredAuthentications },
{ "hostkeyalgorithms", oHostKeyAlgorithms },
{ "bindaddress", oBindAddress },
#ifdef ENABLE_PKCS11
{ "smartcarddevice", oPKCS11Provider },
{ "pkcs11provider", oPKCS11Provider },
#else
{ "smartcarddevice", oUnsupported },
{ "pkcs11provider", oUnsupported },
#endif
{ "clearallforwardings", oClearAllForwardings },
{ "enablesshkeysign", oEnableSSHKeysign },
{ "verifyhostkeydns", oVerifyHostKeyDNS },
@ -277,7 +290,6 @@ static struct {
{ "localcommand", oLocalCommand },
{ "permitlocalcommand", oPermitLocalCommand },
{ "visualhostkey", oVisualHostKey },
{ "useroaming", oDeprecated },
{ "kexalgorithms", oKexAlgorithms },
{ "ipqos", oIPQoS },
{ "requesttty", oRequestTTY },
@ -835,11 +847,11 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
activep = &cmdline;
}
/* Strip trailing whitespace */
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
if ((len = strlen(line)) == 0)
return 0;
for (len--; len > 0; len--) {
if (strchr(WHITESPACE, line[len]) == NULL)
if (strchr(WHITESPACE "\f", line[len]) == NULL)
break;
line[len] = '\0';
}
@ -1187,7 +1199,7 @@ parse_int:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (!ciphers_valid(*arg == '+' ? arg + 1 : arg))
if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->ciphers == NULL)
@ -1198,7 +1210,7 @@ parse_int:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (!mac_valid(*arg == '+' ? arg + 1 : arg))
if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->macs == NULL)
@ -1210,7 +1222,8 @@ parse_int:
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if (!kex_names_valid(*arg == '+' ? arg + 1 : arg))
if (*arg != '-' &&
!kex_names_valid(*arg == '+' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->kex_algorithms == NULL)
@ -1224,7 +1237,8 @@ parse_keytypes:
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
if (*arg != '-' &&
!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
fatal("%s line %d: Bad key types '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *charptr == NULL)
@ -1507,6 +1521,11 @@ parse_keytypes:
flags | SSHCONF_CHECKPERM |
(oactive ? 0 : SSHCONF_NEVERMATCH),
activep, depth + 1);
if (r != 1 && errno != ENOENT) {
fatal("Can't open user config file "
"%.100s: %.100s", gl.gl_pathv[i],
strerror(errno));
}
/*
* don't let Match in includes clobber the
* containing file's Match state.
@ -2453,10 +2472,10 @@ dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
/* oDynamicForward */
for (i = 0; i < count; i++) {
fwd = &fwds[i];
if (code == oDynamicForward &&
if (code == oDynamicForward && fwd->connect_host != NULL &&
strcmp(fwd->connect_host, "socks") != 0)
continue;
if (code == oLocalForward &&
if (code == oLocalForward && fwd->connect_host != NULL &&
strcmp(fwd->connect_host, "socks") == 0)
continue;
printf("%s", lookup_opcode_name(code));
@ -2529,8 +2548,10 @@ dump_client_config(Options *o, const char *host)
dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
dump_cfg_fmtint(oRequestTTY, o->request_tty);
#ifdef WITH_RSA1
dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication);
dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication);
#endif
dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
@ -2542,7 +2563,9 @@ dump_client_config(Options *o, const char *host)
/* Integer options */
dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
#ifdef WITH_SSH1
dump_cfg_int(oCompressionLevel, o->compression_level);
#endif
dump_cfg_int(oConnectionAttempts, o->connection_attempts);
dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
@ -2562,7 +2585,9 @@ dump_client_config(Options *o, const char *host)
dump_cfg_string(oLocalCommand, o->local_command);
dump_cfg_string(oLogLevel, log_level_name(o->log_level));
dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
#ifdef ENABLE_PKCS11
dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
#endif
dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);

View File

@ -1,4 +1,4 @@
# $OpenBSD: agent-getpeereid.sh,v 1.7 2016/09/26 21:34:38 bluhm Exp $
# $OpenBSD: agent-getpeereid.sh,v 1.8 2017/01/06 02:51:16 djm Exp $
# Placed in the Public Domain.
tid="disallow agent attach from other uid"
@ -32,17 +32,17 @@ if [ $r -ne 0 ]; then
else
chmod 644 ${SSH_AUTH_SOCK}
ssh-add -l > /dev/null 2>&1
${SSHADD} -l > /dev/null 2>&1
r=$?
if [ $r -ne 1 ]; then
fail "ssh-add failed with $r != 1"
fi
if test -z "$sudo" ; then
# doas
${SUDO} -n -u ${UNPRIV} ssh-add -l 2>/dev/null
${SUDO} -n -u ${UNPRIV} ${SSHADD} -l 2>/dev/null
else
# sudo
< /dev/null ${SUDO} -S -u ${UNPRIV} ssh-add -l 2>/dev/null
< /dev/null ${SUDO} -S -u ${UNPRIV} ${SSHADD} -l 2>/dev/null
fi
r=$?
if [ $r -lt 2 ]; then

View File

@ -1,4 +1,4 @@
# $OpenBSD: forwarding.sh,v 1.16 2016/04/14 23:57:17 djm Exp $
# $OpenBSD: forwarding.sh,v 1.19 2017/01/30 05:22:14 djm Exp $
# Placed in the Public Domain.
tid="local and remote forwarding"
@ -11,7 +11,6 @@ base=33
last=$PORT
fwd=""
CTL=$OBJ/ctl-sock
rm -f $CTL
for j in 0 1 2; do
for i in 0 1 2; do
@ -29,7 +28,8 @@ for p in ${SSH_PROTOCOLS}; do
q=$p
fi
trace "start forwarding, fork to background"
${SSH} -$p -F $OBJ/ssh_config -f $fwd somehost sleep 10
rm -f $CTL
${SSH} -S $CTL -M -$p -F $OBJ/ssh_config -f $fwd somehost sleep 10
trace "transfer over forwarded channels and check result"
${SSH} -$q -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \
@ -37,7 +37,7 @@ for p in ${SSH_PROTOCOLS}; do
test -s ${COPY} || fail "failed copy of ${DATA}"
cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
sleep 10
${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost
done
for p in ${SSH_PROTOCOLS}; do
@ -52,7 +52,7 @@ for d in L R; do
-$d ${base}04:127.0.0.1:$PORT \
-oExitOnForwardFailure=yes somehost true
if [ $? != 0 ]; then
fail "connection failed, should not"
fatal "connection failed, should not"
else
# this one should fail
${SSH} -q -$p -F $OBJ/ssh_config \
@ -75,30 +75,32 @@ for p in ${SSH_PROTOCOLS}; do
${SSH} -$p -F $OBJ/ssh_config -oClearAllForwardings=yes somehost true
trace "clear local forward proto $p"
${SSH} -$p -f -F $OBJ/ssh_config -L ${base}01:127.0.0.1:$PORT \
rm -f $CTL
${SSH} -S $CTL -M -$p -f -F $OBJ/ssh_config -L ${base}01:127.0.0.1:$PORT \
-oClearAllForwardings=yes somehost sleep 10
if [ $? != 0 ]; then
fail "connection failed with cleared local forwarding"
else
# this one should fail
${SSH} -$p -F $OBJ/ssh_config -p ${base}01 true \
${SSH} -$p -F $OBJ/ssh_config -p ${base}01 somehost true \
>>$TEST_REGRESS_LOGFILE 2>&1 && \
fail "local forwarding not cleared"
fi
sleep 10
${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost
trace "clear remote forward proto $p"
${SSH} -$p -f -F $OBJ/ssh_config -R ${base}01:127.0.0.1:$PORT \
rm -f $CTL
${SSH} -S $CTL -M -$p -f -F $OBJ/ssh_config -R ${base}01:127.0.0.1:$PORT \
-oClearAllForwardings=yes somehost sleep 10
if [ $? != 0 ]; then
fail "connection failed with cleared remote forwarding"
else
# this one should fail
${SSH} -$p -F $OBJ/ssh_config -p ${base}01 true \
${SSH} -$p -F $OBJ/ssh_config -p ${base}01 somehost true \
>>$TEST_REGRESS_LOGFILE 2>&1 && \
fail "remote forwarding not cleared"
fi
sleep 10
${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost
done
for p in 2; do
@ -115,6 +117,7 @@ echo "LocalForward ${base}01 127.0.0.1:$PORT" >> $OBJ/ssh_config
echo "RemoteForward ${base}02 127.0.0.1:${base}01" >> $OBJ/ssh_config
for p in ${SSH_PROTOCOLS}; do
trace "config file: start forwarding, fork to background"
rm -f $CTL
${SSH} -S $CTL -M -$p -F $OBJ/ssh_config -f somehost sleep 10
trace "config file: transfer over forwarded channels and check result"
@ -123,21 +126,24 @@ for p in ${SSH_PROTOCOLS}; do
test -s ${COPY} || fail "failed copy of ${DATA}"
cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
${SSH} -S $CTL -O exit somehost
${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost
done
for p in 2; do
trace "transfer over chained unix domain socket forwards and check result"
rm -f $OBJ/unix-[123].fwd
${SSH} -f -F $OBJ/ssh_config -R${base}01:[$OBJ/unix-1.fwd] somehost sleep 10
${SSH} -f -F $OBJ/ssh_config -L[$OBJ/unix-1.fwd]:[$OBJ/unix-2.fwd] somehost sleep 10
${SSH} -f -F $OBJ/ssh_config -R[$OBJ/unix-2.fwd]:[$OBJ/unix-3.fwd] somehost sleep 10
${SSH} -f -F $OBJ/ssh_config -L[$OBJ/unix-3.fwd]:127.0.0.1:$PORT somehost sleep 10
rm -f $CTL $CTL.[123]
${SSH} -S $CTL -M -f -F $OBJ/ssh_config -R${base}01:[$OBJ/unix-1.fwd] somehost sleep 10
${SSH} -S $CTL.1 -M -f -F $OBJ/ssh_config -L[$OBJ/unix-1.fwd]:[$OBJ/unix-2.fwd] somehost sleep 10
${SSH} -S $CTL.2 -M -f -F $OBJ/ssh_config -R[$OBJ/unix-2.fwd]:[$OBJ/unix-3.fwd] somehost sleep 10
${SSH} -S $CTL.3 -M -f -F $OBJ/ssh_config -L[$OBJ/unix-3.fwd]:127.0.0.1:$PORT somehost sleep 10
${SSH} -F $OBJ/ssh_config -p${base}01 -o 'ConnectionAttempts=4' \
somehost cat ${DATA} > ${COPY}
test -s ${COPY} || fail "failed copy ${DATA}"
cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
#wait
sleep 10
${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost
${SSH} -F $OBJ/ssh_config -S $CTL.1 -O exit somehost
${SSH} -F $OBJ/ssh_config -S $CTL.2 -O exit somehost
${SSH} -F $OBJ/ssh_config -S $CTL.3 -O exit somehost
done

View File

@ -1,12 +1,10 @@
# $OpenBSD: integrity.sh,v 1.19 2016/11/25 02:56:49 dtucker Exp $
# $OpenBSD: integrity.sh,v 1.20 2017/01/06 02:26:10 dtucker Exp $
# Placed in the Public Domain.
tid="integrity"
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
# start at byte 2900 (i.e. after kex) and corrupt at different offsets
# XXX the test hangs if we modify the low bytes of the packet length
# XXX and ssh tries to read...
tries=10
startoffset=2900
macs=`${SSH} -Q mac`
@ -27,6 +25,7 @@ for m in $macs; do
elen=0
epad=0
emac=0
etmo=0
ecnt=0
skip=0
for off in `jot $tries $startoffset`; do

View File

@ -558,9 +558,8 @@ unix_connect(char *path)
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return (-1);
}
#ifndef WIN32_FIXME
(void)fcntl(s, F_SETFD, FD_CLOEXEC);
#endif
memset(&sun_sa, 0, sizeof(struct sockaddr_un));
sun_sa.sun_family = AF_UNIX;
@ -670,13 +669,12 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
socklen_t optlen;
int flags = 0, optval;
int ret;
#ifndef WIN32_FIXME
if (timeout != -1) {
flags = fcntl(s, F_GETFL, 0);
if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
err(1, "set non-blocking mode");
}
#endif
if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
pfd.fd = s;
@ -694,10 +692,10 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
} else
err(1, "poll failed");
}
#ifndef WIN32_FIXME
if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
err(1, "restoring flags");
#endif
return (ret);
}
@ -766,13 +764,6 @@ local_listen(char *host, char *port, struct addrinfo hints)
* readwrite()
* Loop that polls on the network file descriptor and stdin.
*/
#ifdef WIN32_FIXME
#define POLLNVAL 0x0020
#define POLLHUP 0x0010
#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */
#endif
void
readwrite(int net_fd)
{
@ -1222,9 +1213,7 @@ map_tos(char *s, int *val)
{ "af41", IPTOS_DSCP_AF41 },
{ "af42", IPTOS_DSCP_AF42 },
{ "af43", IPTOS_DSCP_AF43 },
#ifndef WIN32_FIXME
{ "critical", IPTOS_PREC_CRITIC_ECP },
#endif
{ "cs0", IPTOS_DSCP_CS0 },
{ "cs1", IPTOS_DSCP_CS1 },
{ "cs2", IPTOS_DSCP_CS2 },
@ -1234,13 +1223,9 @@ map_tos(char *s, int *val)
{ "cs6", IPTOS_DSCP_CS6 },
{ "cs7", IPTOS_DSCP_CS7 },
{ "ef", IPTOS_DSCP_EF },
#ifndef WIN32_FIXME
{ "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
#endif
{ "lowdelay", IPTOS_LOWDELAY },
#ifndef WIN32_FIXME
{ "netcontrol", IPTOS_PREC_NETCONTROL },
#endif
{ "reliability", IPTOS_RELIABILITY },
{ "throughput", IPTOS_THROUGHPUT },
{ NULL, -1 },
@ -1450,10 +1435,8 @@ getproxypass(const char *proxyuser, const char *proxyhost)
snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ",
proxyuser, proxyhost);
#ifndef WIN32_FIXME
if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL)
errx(1, "Unable to read proxy passphrase");
#endif
return (pw);
}

View File

@ -75,9 +75,11 @@ Class Machine
[string] $localAdminUserName = "localadmin"
[string] $localAdminPassword = "Bull_dog1"
[string] $localAdminAuthorizedKeyPath
[string] $sshdConfigFile = (join-path $PSScriptRoot "sshd_config")
[string] $backupFileName = (join-path $PSScriptRoot "sshd_backup")
[System.Security.SecureString] $password
$preLatfpSetting
$localUserprofilePath
[string] $localUserprofilePath
#Members on client role
[string []] $clientPrivateKeyPaths
@ -177,6 +179,47 @@ Class Machine
}
}
[void] SetupSingleSignon([string] $identifyFile) {
.\ssh-add.exe $identifyFile
}
[void] CleanupSingleSignon([string] $identifyFile) {
.\ssh-add.exe -d $identifyFile
}
[void] AddItemInSSHDConfig([string] $key, [string] $value) {
if ( $this.Platform -eq [PlatformType]::Windows ) {
Get-Content $this.sshdConfigFile | % {
if($_.StartsWith($key)) {
"#$_"
}
else {$_}
} | Set-Content $this.sshdConfigFile
Add-Content -Path $this.sshdConfigFile -Value "`r`n$key $value"
Restart-Service sshd
} else {
}
}
[void] BackupSSHDConfig() {
if ( $this.Platform -eq [PlatformType]::Windows ) {
if(Test-path $this.backupFileName) {
Remove-Item -Path $this.backupFileName -Force
}
Copy-Item $this.sshdConfigFile $this.backupFileName -Force
}
}
[void] RestoreSSHDConfig() {
if ( $this.Platform -eq [PlatformType]::Windows ) {
Copy-Item $this.backupFileName $this.sshdConfigFile -Force
Remove-Item -Path $this.backupFileName -Force
Restart-Service sshd
}
}
[void] SetupServerRemoting([Protocol] $protocol) {
if ($this.Platform -eq [PlatformType]::Windows)
{
@ -240,6 +283,56 @@ Class Machine
}
}
[void] AddLocalUser($UserName, $password) {
$a = Get-LocalUser -Name $UserName -ErrorAction Ignore
if ($a -eq $null)
{
$pass = ConvertTo-SecureString -String $this.localAdminPassword -AsPlainText -Force
$a = New-LocalUser -Name $UserName -Password $pass -AccountNeverExpires -PasswordNeverExpires -UserMayNotChangePassword
}
}
[void] AddLocalGroup($groupName) {
$g = Get-LocalGroup -Name $groupName -ErrorAction Ignore
if ($g -eq $null)
{
$g = New-LocalGroup -Name $groupName
}
}
[void] AddUserToLocalGroup($UserName, $password, $groupName) {
if ( $this.Platform -eq [PlatformType]::Windows ) {
$this.AddLocalUser($UserName, $password)
$this.AddLocalGroup($groupName)
if((Get-LocalGroupMember -Name $groupName -Member $UserName -ErrorAction Ignore ) -eq $null)
{
Add-LocalGroupMember -Name $groupName -Member $UserName
}
} else {
#Todo add local user and add it to a user group on linux
}
}
[void] RemoveUserFromLocalGroup($UserName, $groupName) {
if ( $this.Platform -eq [PlatformType]::Windows ) {
if((Get-LocalGroupMember -Name $groupName -Member $UserName -ErrorAction Ignore ) -eq $null)
{
Remove-LocalGroupMember -Name $groupName -Member $UserName
}
} else {
#Todo add local user and add it to a user group on linux
}
}
[void] ClenaupLocalGroup($groupName) {
$g = Get-LocalGroup -Name $groupName -ErrorAction Ignore
if ($g -eq $null)
{
$g | Remove-LocalGroup
}
}
[void] AddAdminUser($UserName, $password) {
if ( $this.Platform -eq [PlatformType]::Windows ) {
$a = Get-LocalUser -Name $UserName -ErrorAction Ignore
@ -253,8 +346,7 @@ Class Machine
Add-LocalGroupMember -SID s-1-5-32-544 -Member $a
}
} else {
#Todo add local user and add it to administrators group on linux
#Todo: get $localUserprofilePath
#Todo add local user and add it to a administrators on linux
}
}

View File

@ -66,11 +66,11 @@ Describe "Tests for scp command" -Tags "CI" {
Source = $sourceDir
Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationDir"
},
@{
<# @{
Title = 'copy from local dir to local dir'
Source = $sourceDir
Destination = $DestinationDir
},
},#>
@{
Title = 'copy from remote dir to local dir'
Source = "$($server.localAdminUserName)@$($server.MachineName):$sourceDir"

View File

@ -39,7 +39,8 @@ Describe "SFTP Testcases" -Tags "CI" {
options = '-i $identifyfile'
commands = "put $tempFilePath $serverDirectory
ls $serverDirectory"
expectedoutput = (join-path $serverdirectory $tempFileName).replace("\", "/")
expectedoutput = (join-path $serverdirectory $tempFileName)
},
@{
title = "get, ls for non-unicode file names"
@ -47,7 +48,7 @@ Describe "SFTP Testcases" -Tags "CI" {
options = '-i $identifyfile'
commands = "get $tempFilePath $clientDirectory
ls $clientDirectory"
expectedoutput = (join-path $clientDirectory $tempFileName).replace("\", "/")
expectedoutput = (join-path $clientDirectory $tempFileName)
},
@{
title = "mput, ls for non-unicode file names"
@ -55,7 +56,7 @@ Describe "SFTP Testcases" -Tags "CI" {
options = '-i $identifyfile'
commands = "mput $tempFilePath $serverDirectory
ls $serverDirectory"
expectedoutput = (join-path $serverdirectory $tempFileName).replace("\", "/")
expectedoutput = (join-path $serverdirectory $tempFileName)
},
@{
title = "mget, ls for non-unicode file names"
@ -63,7 +64,7 @@ Describe "SFTP Testcases" -Tags "CI" {
options = '-i $identifyfile'
commands = "mget $tempFilePath $clientDirectory
ls $clientDirectory"
expectedoutput = (join-path $clientDirectory $tempFileName).replace("\", "/")
expectedoutput = (join-path $clientDirectory $tempFileName)
},
@{
title = "mkdir, cd, pwd for non-unicode directory names"
@ -73,7 +74,7 @@ Describe "SFTP Testcases" -Tags "CI" {
mkdir server_test_dir
cd server_test_dir
pwd"
expectedoutput = (join-path $serverdirectory "server_test_dir").replace("\", "/")
expectedoutput = (join-path $serverdirectory "server_test_dir")
},
@{
Title = "lmkdir, lcd, lpwd for non-unicode directory names"
@ -91,7 +92,7 @@ Describe "SFTP Testcases" -Tags "CI" {
options = '-i $identifyfile'
commands = "put $tempUnicodeFilePath $serverDirectory
ls $serverDirectory"
expectedoutput = (join-path $serverdirectory $tempUnicodeFileName).replace("\", "/")
expectedoutput = (join-path $serverdirectory $tempUnicodeFileName)
},
@{
title = "get, ls for unicode file names"
@ -99,7 +100,7 @@ Describe "SFTP Testcases" -Tags "CI" {
options = '-i $identifyfile'
commands = "get $tempUnicodeFilePath $clientDirectory
ls $clientDirectory"
expectedoutput = (join-path $clientDirectory $tempUnicodeFileName).replace("\", "/")
expectedoutput = (join-path $clientDirectory $tempUnicodeFileName)
},
@{
title = "mput, ls for unicode file names"
@ -107,7 +108,7 @@ Describe "SFTP Testcases" -Tags "CI" {
options = '-i $identifyfile'
commands = "mput $tempUnicodeFilePath $serverDirectory
ls $serverDirectory"
expectedoutput = (join-path $serverdirectory $tempUnicodeFileName).replace("\", "/")
expectedoutput = (join-path $serverdirectory $tempUnicodeFileName)
},
@{
title = "mget, ls for unicode file names"
@ -115,7 +116,7 @@ Describe "SFTP Testcases" -Tags "CI" {
options = '-i $identifyfile'
commands = "mget $tempUnicodeFilePath $clientDirectory
ls $clientDirectory"
expectedoutput = (join-path $clientDirectory $tempUnicodeFileName).replace("\", "/")
expectedoutput = (join-path $clientDirectory $tempUnicodeFileName)
},
@{
title = "mkdir, cd, pwd for unicode directory names"
@ -125,7 +126,7 @@ Describe "SFTP Testcases" -Tags "CI" {
mkdir server_test_dir_язык
cd server_test_dir_язык
pwd"
expectedoutput = (join-path $serverdirectory "server_test_dir_язык").replace("\", "/")
expectedoutput = (join-path $serverdirectory "server_test_dir_язык")
},
@{
Title = "lmkdir, lcd, lpwd for unicode directory names"
@ -208,7 +209,7 @@ Describe "SFTP Testcases" -Tags "CI" {
#validate file content.
$($ExpectedOutput).split($expectedOutputDelimiter) | foreach {
$outputFilePath | Should Contain ([RegEx]::Escape($_))
Test-Path ($_) | Should be $true
}
}
@ -222,7 +223,7 @@ Describe "SFTP Testcases" -Tags "CI" {
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
$outputFilePath | Should Contain ([RegEx]::Escape((join-path $tmpDirectoryPath1 $tmpFileName1).replace("\", "/")))
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $true
$commands = "rm $tmpDirectoryPath1\*
ls $tmpDirectoryPath1
@ -231,7 +232,7 @@ Describe "SFTP Testcases" -Tags "CI" {
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
$outputFilePath | Should Not Contain ([RegEx]::Escape((join-path $tmpDirectoryPath1 $tmpFileName1).replace("\", "/")))
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $false
#rename file
Remove-Item $outputFilePath
@ -242,7 +243,7 @@ Describe "SFTP Testcases" -Tags "CI" {
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
$outputFilePath | Should Contain ([RegEx]::Escape((join-path $tmpDirectoryPath1 $tmpFileName2).replace("\", "/")))
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName2) | Should be $true
#rename directory
Remove-Item $outputFilePath
@ -252,7 +253,7 @@ Describe "SFTP Testcases" -Tags "CI" {
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
$outputFilePath | Should Contain ([RegEx]::Escape($tmpDirectoryPath2.replace("\", "/")))
Test-Path $tmpDirectoryPath2 | Should be $true
#rmdir (remove directory)
Remove-Item $outputFilePath
@ -261,7 +262,7 @@ Describe "SFTP Testcases" -Tags "CI" {
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
$outputFilePath | Should Not Contain ([RegEx]::Escape($tmpDirectoryPath2).replace("\", "/"))
Test-Path $tmpDirectoryPath2 | Should be $false
}
}
}

View File

@ -0,0 +1,161 @@
using module .\PlatformAbstractLayer.psm1
Describe "Tests of sshd_config" -Tags "CI" {
BeforeAll {
$fileName = "test.txt"
$filePath = Join-Path ${TestDrive} $fileName
[Machine] $client = [Machine]::new([MachineRole]::Client)
[Machine] $server = [Machine]::new([MachineRole]::Server)
$client.SetupClient($server)
$server.SetupServer($client)
}
AfterAll {
$client.CleanupClient()
$server.CleanupServer()
}
<#
Settings in the sshd_config:
DenyUsers denyuser1 denyu*2 denyuse?3,
AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
DenyGroups denygroup1 denygr*p2 deny?rou?3
AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
#>
Context "Tests of AllowGroups, AllowUsers, DenyUsers, DenyGroups" {
BeforeAll {
Remove-Item -Path $filePath -Force -ea silentlycontinue
$password = "Bull_dog1"
$allowUser1 = "allowuser1"
$allowUser2 = "allowuser2"
$allowUser3 = "allowuser3"
$allowUser4 = "allowuser4"
$denyUser1 = "denyuser1"
$denyUser2 = "denyuser2"
$denyUser3 = "denyuser3"
$localuser1 = "localuser1"
$localuser2 = "localuser2"
$localuser3 = "localuser3"
$allowGroup1 = "allowgroup1"
$allowGroup2 = "allowgroup2"
$allowGroup3 = "allowgroup3"
$denyGroup1 = "denygroup1"
$denyGroup2 = "denygroup2"
$denyGroup3 = "denygroup3"
$client.AddPasswordSetting($password)
}
AfterEach {
Remove-Item -Path $filePath -Force -ea ignore
}
AfterAll {
$client.CleanupPasswordSetting()
}
It 'User with full name in the list of AllowUsers' {
$server.AddUserToLocalGroup($allowUser1, $password, $allowGroup1)
$client.RunCmd(".\ssh $($allowUser1)@$($server.MachineName) hostname > $filePath")
Get-Content $filePath | Should be $server.MachineName
$server.RemoveUserFromLocalGroup($allowUser1, $allowGroup1)
}
It 'User with * wildcard' {
$server.AddUserToLocalGroup($allowUser2, $password, $allowGroup1)
$client.RunCmd(".\ssh $($allowUser2)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Be 0
Get-Content $filePath | Should be $server.MachineName
$server.RemoveUserFromLocalGroup($allowUser2, $allowGroup1)
}
It 'User with ? wildcard' {
$server.AddUserToLocalGroup($allowUser3, $password, $allowGroup1)
$client.RunCmd(".\ssh $($allowUser3)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Be 0
Get-Content $filePath | Should be $server.MachineName
$server.RemoveUserFromLocalGroup($allowUser3, $allowGroup1)
}
It 'User with full name in the list of AllowUsers but not in any AllowGroups' {
$server.AddLocalUser($allowUser4, $password)
$client.RunCmd(".\ssh $($allowUser4)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
}
It 'User with full name in the list of DenyUsers' {
$server.AddUserToLocalGroup($denyUser1, $password, $allowGroup1)
$client.RunCmd(".\ssh $($denyUser1)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($denyUser1, $allowGroup1)
}
It 'User with * wildcard in the list of DenyUsers' {
$server.AddUserToLocalGroup($denyUser2, $password, $allowGroup1)
$str = ".\ssh $($denyUser2)@$($server.MachineName) hostname > $filePath"
$client.RunCmd(".\ssh $($denyUser2)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($denyUser2, $allowGroup1)
}
It 'User with ? wildcard in the list of DenyUsers' {
$server.AddUserToLocalGroup($denyUser3, $password, $allowGroup1)
$client.RunCmd(".\ssh $($denyUser3)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($denyUser3, $allowGroup1)
}
It 'User is listed in the list of AllowUsers but also in a full name DenyGroups and AllowGroups' {
$server.AddUserToLocalGroup($localuser1, $password, $allowGroup1)
$server.AddUserToLocalGroup($localuser1, $password, $denyGroup1)
$client.RunCmd(".\ssh $($localuser1)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($localuser1, $allowGroup1)
$server.RemoveUserFromLocalGroup($localuser1, $denyGroup1)
}
It 'User is listed in the list of AllowUsers but also in a wildcard * DenyGroups' {
$server.AddUserToLocalGroup($localuser2, $password, $denyGroup2)
$client.RunCmd(".\ssh $($localuser2)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($localuser2, $denyGroup2)
}
It 'User is listed in the list of AllowUsers but also in a wildcard ? DenyGroups' {
$server.AddUserToLocalGroup($localuser3, $password, $denyGroup3)
$client.RunCmd(".\ssh $($localuser3)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($localuser3, $denyGroup3)
}
}
}

View File

@ -0,0 +1,127 @@
# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
# The default requires explicit activation of protocol 1
#Protocol 2
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024
# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
LogLevel DEBUG3
# Authentication:
#LoginGraceTime 2m
#PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
#RSAAuthentication yes
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM no
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#UsePrivilegeSeparation yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10
#PermitTunnel no
#ChrootDirectory none
# no default banner path
#Banner none
# override default of no subsystems
Subsystem sftp sftp-server.exe
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# ForceCommand cvs server
PubkeyAcceptedKeyTypes ssh-ed25519*
DenyUsers denyuser1 deny*2 denyuse?3,
AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
DenyGroups denygroup1 denygr*p2 deny?rou?3
AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*

View File

@ -26,10 +26,6 @@
#include <string.h>
#include <errno.h>
#ifdef WIN32_FIXME
void debug3(const char *fmt,...) {/*stub*/}
#endif
void
static void
usage(void)
{

View File

@ -61,6 +61,7 @@ check(struct hostkey_foreach_line *l, void *_ctx)
test_subtest_info("entry %zu/%zu, file line %ld",
ctx->i + 1, ctx->nexpected, l->linenum);
for (;;) {
ASSERT_SIZE_T_LT(ctx->i, ctx->nexpected);
expected = ctx->expected + ctx->i++;
@ -281,7 +282,6 @@ struct expected expected_full[] = {
NULL, /* filled at runtime */
"DSA #2",
} },
#ifdef OPENSSL_HAS_NISTP521
{ "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
10,
@ -295,7 +295,6 @@ struct expected expected_full[] = {
NULL, /* filled at runtime */
"ECDSA #2",
} },
#endif
{ "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
11,

View File

@ -145,12 +145,10 @@ do_kex_with_key(char *kex, int keytype, int bits)
sshbuf_free(state);
ASSERT_PTR_NE(server2->kex, NULL);
/* XXX we need to set the callbacks */
#ifdef WITH_OPENSSL
server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
#endif
#ifdef OPENSSL_HAS_ECC
server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
#endif
@ -195,9 +193,7 @@ kex_tests(void)
#ifdef OPENSSL_HAS_ECC
do_kex("ecdh-sha2-nistp256");
do_kex("ecdh-sha2-nistp384");
#ifdef OPENSSL_HAS_NISTP521
do_kex("ecdh-sha2-nistp521");
#endif
#endif
do_kex("diffie-hellman-group-exchange-sha256");
do_kex("diffie-hellman-group-exchange-sha1");

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tests.c,v 1.3 2016/09/21 17:03:54 djm Exp $ */
/* $OpenBSD: tests.c,v 1.4 2017/02/03 23:01:42 djm Exp $ */
/*
* Regress test for matching functions
*
@ -103,6 +103,25 @@ tests(void)
/* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.2,10.0.0.1"), 1); */
TEST_DONE();
#define CHECK_FILTER(string,filter,expected) \
do { \
char *result = match_filter_list((string), (filter)); \
ASSERT_STRING_EQ(result, expected); \
free(result); \
} while (0)
TEST_START("match_filter_list");
CHECK_FILTER("a,b,c", "", "a,b,c");
CHECK_FILTER("a,b,c", "a", "b,c");
CHECK_FILTER("a,b,c", "b", "a,c");
CHECK_FILTER("a,b,c", "c", "a,b");
CHECK_FILTER("a,b,c", "a,b", "c");
CHECK_FILTER("a,b,c", "a,c", "b");
CHECK_FILTER("a,b,c", "b,c", "a");
CHECK_FILTER("a,b,c", "a,b,c", "");
CHECK_FILTER("a,b,c", "b,c", "a");
CHECK_FILTER("", "a,b,c", "");
TEST_DONE();
/*
* XXX TODO
* int match_host_and_ip(const char *, const char *, const char *);

View File

@ -20,13 +20,9 @@ tests(void)
{
sshbuf_tests();
sshbuf_getput_basic_tests();
#ifdef WITH_OPENSSL
sshbuf_getput_crypto_tests();
#endif
sshbuf_misc_tests();
sshbuf_fuzz_tests();
#ifdef WITH_OPENSSL
sshbuf_getput_fuzz_tests();
#endif
sshbuf_fixed();
}

View File

@ -19,12 +19,10 @@
#include <string.h>
#include <unistd.h>
#ifdef WITH_OPENSSL
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/objects.h>
#endif
#ifdef OPENSSL_HAS_NISTP256
# include <openssl/ec.h>
#endif
@ -72,7 +70,6 @@ load_text_file(const char *name)
return ret;
}
#ifdef WITH_OPENSSL
BIGNUM *
load_bignum(const char *name)
{
@ -84,4 +81,4 @@ load_bignum(const char *name)
sshbuf_free(buf);
return ret;
}
#endif

View File

@ -101,7 +101,6 @@ sshkey_file_tests(void)
sshkey_free(k1);
#endif
#ifdef WITH_OPENSSL
TEST_START("parse RSA from private");
buf = load_file("rsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
@ -283,7 +282,6 @@ sshkey_file_tests(void)
TEST_DONE();
sshkey_free(k1);
#endif
#ifdef OPENSSL_HAS_ECC
TEST_START("parse ECDSA from private");

View File

@ -193,7 +193,6 @@ sshkey_tests(void)
sshkey_free(k1);
TEST_DONE();
#ifdef WITH_OPENSSL
TEST_START("new/free KEY_RSA1");
k1 = sshkey_new(KEY_RSA1);
ASSERT_PTR_NE(k1, NULL);
@ -222,7 +221,6 @@ sshkey_tests(void)
ASSERT_PTR_EQ(k1->dsa->priv_key, NULL);
sshkey_free(k1);
TEST_DONE();
#endif
#ifdef OPENSSL_HAS_ECC
TEST_START("new/free KEY_ECDSA");
@ -242,7 +240,6 @@ sshkey_tests(void)
sshkey_free(k1);
TEST_DONE();
#ifdef WITH_OPENSSL
TEST_START("new_private KEY_RSA");
k1 = sshkey_new_private(KEY_RSA);
ASSERT_PTR_NE(k1, NULL);
@ -311,7 +308,7 @@ sshkey_tests(void)
ASSERT_PTR_NE(kd->dsa->g, NULL);
ASSERT_PTR_NE(kd->dsa->priv_key, NULL);
TEST_DONE();
#endif
#ifdef OPENSSL_HAS_ECC
TEST_START("generate KEY_ECDSA");
ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &ke), 0);
@ -330,7 +327,6 @@ sshkey_tests(void)
ASSERT_PTR_NE(kf->ed25519_sk, NULL);
TEST_DONE();
#ifdef WITH_OPENSSL
TEST_START("demote KEY_RSA");
ASSERT_INT_EQ(sshkey_demote(kr, &k1), 0);
ASSERT_PTR_NE(k1, NULL);
@ -361,7 +357,6 @@ sshkey_tests(void)
ASSERT_INT_EQ(sshkey_equal(kd, k1), 1);
sshkey_free(k1);
TEST_DONE();
#endif
#ifdef OPENSSL_HAS_ECC
TEST_START("demote KEY_ECDSA");
@ -508,7 +503,6 @@ sshkey_tests(void)
sshkey_free(k2);
TEST_DONE();
#ifdef OPENSSL_HAS_ECC
TEST_START("sign and verify ECDSA");
k1 = get_private("ecdsa_1");
@ -518,6 +512,7 @@ sshkey_tests(void)
sshkey_free(k1);
sshkey_free(k2);
TEST_DONE();
#endif
TEST_START("sign and verify ED25519");
k1 = get_private("ed25519_1");
@ -542,5 +537,5 @@ sshkey_tests(void)
sshkey_free(k3);
sshbuf_free(b);
TEST_DONE();
#endif
}

View File

@ -18,10 +18,9 @@ void sshkey_fuzz_tests(void);
void
tests(void)
{
#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
ERR_load_CRYPTO_strings();
#endif
sshkey_tests();
sshkey_file_tests();
sshkey_fuzz_tests();

View File

@ -64,9 +64,8 @@ tests(void)
TEST_DONE();
return;
#endif
TEST_START("utf8_setlocale");
loc = setlocale(LC_CTYPE, "en_US.UTF-8");
loc = setlocale(LC_CTYPE, "en_US.UTF-8");
ASSERT_PTR_NE(loc, NULL);
TEST_DONE();

View File

@ -1,5 +1,5 @@
/* $OpenBSD: servconf.c,v 1.301 2016/11/30 03:00:05 djm Exp $ */
/* $OpenBSD: servconf.c,v 1.304 2017/02/03 23:01:19 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -270,7 +270,7 @@ fill_default_server_options(ServerOptions *options)
if (options->gss_cleanup_creds == -1)
options->gss_cleanup_creds = 1;
if (options->gss_strict_acceptor == -1)
options->gss_strict_acceptor = 0;
options->gss_strict_acceptor = 1;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
@ -971,6 +971,15 @@ process_server_config_line(ServerOptions *options, char *line,
long long val64;
const struct multistate *multistate_ptr;
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
if ((len = strlen(line)) == 0)
return 0;
for (len--; len > 0; len--) {
if (strchr(WHITESPACE "\f", line[len]) == NULL)
break;
line[len] = '\0';
}
cp = line;
if ((arg = strdelim(&cp)) == NULL)
return 0;
@ -1173,7 +1182,8 @@ process_server_config_line(ServerOptions *options, char *line,
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
if (*arg != '-' &&
!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
fatal("%s line %d: Bad key types '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *charptr == NULL)
@ -1432,7 +1442,7 @@ process_server_config_line(ServerOptions *options, char *line,
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (!ciphers_valid(*arg == '+' ? arg + 1 : arg))
if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->ciphers == NULL)
@ -1443,7 +1453,7 @@ process_server_config_line(ServerOptions *options, char *line,
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (!mac_valid(*arg == '+' ? arg + 1 : arg))
if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 mac spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->macs == NULL)
@ -1455,7 +1465,8 @@ process_server_config_line(ServerOptions *options, char *line,
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
if (!kex_names_valid(*arg == '+' ? arg + 1 : arg))
if (*arg != '-' &&
!kex_names_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->kex_algorithms == NULL)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: serverloop.c,v 1.189 2016/12/14 00:36:34 djm Exp $ */
/* $OpenBSD: serverloop.c,v 1.191 2017/02/01 02:59:09 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -430,7 +430,7 @@ server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
}
static Channel *
server_request_direct_tcpip(void)
server_request_direct_tcpip(int *reason, const char **errmsg)
{
Channel *c = NULL;
char *target, *originator;
@ -449,11 +449,13 @@ server_request_direct_tcpip(void)
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag && !options.disable_forwarding) {
c = channel_connect_to_port(target, target_port,
"direct-tcpip", "direct-tcpip");
"direct-tcpip", "direct-tcpip", reason, errmsg);
} else {
logit("refused local port forward: "
"originator %s port %d, target %s port %d",
originator, originator_port, target, target_port);
if (reason != NULL)
*reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
}
free(originator);
@ -468,6 +470,10 @@ server_request_direct_streamlocal(void)
Channel *c = NULL;
char *target, *originator;
u_short originator_port;
struct passwd *pw = the_authctxt->pw;
if (pw == NULL || !the_authctxt->valid)
fatal("server_input_global_request: no/invalid user");
target = packet_get_string(NULL);
originator = packet_get_string(NULL);
@ -480,7 +486,7 @@ server_request_direct_streamlocal(void)
/* XXX fine grained permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag && !options.disable_forwarding &&
use_privsep) {
(pw->pw_uid == 0 || use_privsep)) {
c = channel_connect_to_path(target,
"direct-streamlocal@openssh.com", "direct-streamlocal");
} else {
@ -577,7 +583,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
{
Channel *c = NULL;
char *ctype;
int rchan;
const char *errmsg = NULL;
int rchan, reason = SSH2_OPEN_CONNECT_FAILED;
u_int rmaxpack, rwindow, len;
ctype = packet_get_string(&len);
@ -591,7 +598,7 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
if (strcmp(ctype, "session") == 0) {
c = server_request_session();
} else if (strcmp(ctype, "direct-tcpip") == 0) {
c = server_request_direct_tcpip();
c = server_request_direct_tcpip(&reason, &errmsg);
} else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
c = server_request_direct_streamlocal();
} else if (strcmp(ctype, "tun@openssh.com") == 0) {
@ -614,9 +621,9 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
debug("server_input_channel_open: failure %s", ctype);
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(rchan);
packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
packet_put_int(reason);
if (!(datafellows & SSH_BUG_OPENFAILURE)) {
packet_put_cstring("open failed");
packet_put_cstring(errmsg ? errmsg : "open failed");
packet_put_cstring("");
}
packet_send();
@ -702,6 +709,10 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
int want_reply;
int r, success = 0, allocated_listen_port = 0;
struct sshbuf *resp = NULL;
struct passwd *pw = the_authctxt->pw;
if (pw == NULL || !the_authctxt->valid)
fatal("server_input_global_request: no/invalid user");
rtype = packet_get_string(NULL);
want_reply = packet_get_char();
@ -709,12 +720,8 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
/* -R style forwarding */
if (strcmp(rtype, "tcpip-forward") == 0) {
struct passwd *pw;
struct Forward fwd;
pw = the_authctxt->pw;
if (pw == NULL || !the_authctxt->valid)
fatal("server_input_global_request: no/invalid user");
memset(&fwd, 0, sizeof(fwd));
fwd.listen_host = packet_get_string(NULL);
fwd.listen_port = (u_short)packet_get_int();
@ -762,9 +769,10 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
/* check permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
|| no_port_forwarding_flag || options.disable_forwarding ||
!use_privsep) {
(pw->pw_uid != 0 && !use_privsep)) {
success = 0;
packet_send_debug("Server has disabled port forwarding.");
packet_send_debug("Server has disabled "
"streamlocal forwarding.");
} else {
/* Start listening on the socket */
success = channel_setup_remote_fwd_listener(

283
session.c
View File

@ -310,27 +310,106 @@ xauth_valid_string(const char *s)
} \
} while (0)
void setup_session_vars(Session* s)
#define UTF8_TO_UTF16_FATAL(o, i) do { \
if (o != NULL) free(o); \
if ((o = utf8_to_utf16(i)) == NULL) \
fatal("%s, out of memory", __func__); \
} while (0)
static void setup_session_user_vars(Session* s) /* set user environment variables from user profile */
{
wchar_t* pw_dir_w;
wchar_t* tmp;
char buf[128];
/* retrieve and set env variables. */
HKEY reg_key = 0;
HANDLE token = s->authctxt->methoddata;
wchar_t *path;
wchar_t name[256];
wchar_t *data = NULL, *data_expanded = NULL, *path_value = NULL, *to_apply;
DWORD type, name_chars = 256, data_chars = 0, data_expanded_chars = 0, required, i = 0;
LONG ret;
if (ImpersonateLoggedOnUser(token) == FALSE)
debug("Failed to impersonate user token, %d", GetLastError());
SET_USER_ENV(FOLDERID_LocalAppData, L"LOCALAPPDATA");
SET_USER_ENV(FOLDERID_Profile, L"USERPROFILE");
SET_USER_ENV(FOLDERID_RoamingAppData, L"APPDATA");
ret = RegOpenKeyExW(HKEY_CURRENT_USER, L"Environment", 0, KEY_QUERY_VALUE, &reg_key);
if (ret != ERROR_SUCCESS)
error("Error retrieving user environment variables. RegOpenKeyExW returned %d", ret);
else while (1) {
to_apply = NULL;
required = data_chars * 2;
name_chars = 256;
ret = RegEnumValueW(reg_key, i++, name, &name_chars, 0, &type, (LPBYTE)data, &required);
if (ret == ERROR_NO_MORE_ITEMS)
break;
else if (ret != ERROR_SUCCESS) {
error("Error retrieving user environment variables. RegEnumValueW returned %d", ret);
break;
}
else if (required > data_chars * 2) {
if (data != NULL)
free(data);
data = xmalloc(required);
data_chars = required/2;
i--;
continue;
}
if (type == REG_SZ)
to_apply = data;
else if (type == REG_EXPAND_SZ) {
required = ExpandEnvironmentStringsW(data, data_expanded, data_expanded_chars);
if (required > data_expanded_chars) {
if (data_expanded)
free(data_expanded);
data_expanded = xmalloc(required * 2);
data_expanded_chars = required;
ExpandEnvironmentStringsW(data, data_expanded, data_expanded_chars);
}
to_apply = data_expanded;
}
if (wcsicmp(name, L"PATH") == 0) {
if ((required = GetEnvironmentVariableW(L"PATH", NULL, 0)) != 0) {
/* "required" includes null term */
path_value = xmalloc((wcslen(to_apply) + 1 + required)*2);
GetEnvironmentVariableW(L"PATH", path_value, required);
path_value[required - 1] = L';';
memcpy(path_value + required, to_apply, (wcslen(to_apply) + 1) * 2);
to_apply = path_value;
}
}
if (to_apply)
SetEnvironmentVariableW(name, to_apply);
}
if (reg_key)
RegCloseKey(reg_key);
if (data)
free(data);
if (data_expanded)
free(data_expanded);
if (path_value)
free(path_value);
RevertToSelf();
}
static void setup_session_vars(Session* s) {
wchar_t *pw_dir_w = NULL, *tmp = NULL;
char buf[256];
wchar_t wbuf[256];
char* laddr;
struct ssh *ssh = active_state; /* XXX */
if ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL)
fatal("%s: out of memory");
if ((tmp = utf8_to_utf16(s->pw->pw_name)) == NULL)
fatal("%s, out of memory");
UTF8_TO_UTF16_FATAL(pw_dir_w, s->pw->pw_dir);
UTF8_TO_UTF16_FATAL(tmp, s->pw->pw_name);
SetEnvironmentVariableW(L"USERNAME", tmp);
free(tmp);
if (s->display)
SetEnvironmentVariableA("DISPLAY", s->display);
if (s->display) {
UTF8_TO_UTF16_FATAL(tmp, s->display);
SetEnvironmentVariableW(L"DISPLAY", tmp);
}
SetEnvironmentVariableW(L"HOMEPATH", pw_dir_w);
SetEnvironmentVariableW(L"USERPROFILE", pw_dir_w);
@ -343,111 +422,31 @@ void setup_session_vars(Session* s)
snprintf(buf, sizeof buf, "%.50s %d %d",
ssh->remote_ipaddr, ssh->remote_port, ssh->local_port);
SetEnvironmentVariableA("SSH_CLIENT", buf);
laddr = get_local_ipaddr(packet_get_connection_in());
snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
ssh->remote_ipaddr, ssh->remote_port, laddr, ssh->local_port);
free(laddr);
SetEnvironmentVariableA("SSH_CONNECTION", buf);
if (original_command)
SetEnvironmentVariableA("SSH_ORIGINAL_COMMAND", original_command);
if (original_command) {
UTF8_TO_UTF16_FATAL(tmp, original_command);
SetEnvironmentVariableW(L"SSH_ORIGINAL_COMMAND", tmp);
}
if ((s->term) && (s->term[0]))
SetEnvironmentVariable("TERM", s->term);
SetEnvironmentVariableA("TERM", s->term);
if (!s->is_subsystem) {
snprintf(buf, sizeof buf, "%s@%s $P$G", s->pw->pw_name, getenv("COMPUTERNAME"));
SetEnvironmentVariableA("PROMPT", buf);
}
/*set user environment variables*/
{
UCHAR InfoBuffer[1000];
PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;
DWORD dwInfoBufferSize, tmp_len;
LPWSTR sid_str = NULL;
wchar_t reg_path[MAX_PATH];
HKEY reg_key = 0;
HANDLE token = s->authctxt->methoddata;
tmp_len = MAX_PATH;
if (GetTokenInformation(token, TokenUser, InfoBuffer,
1000, &dwInfoBufferSize) == FALSE ||
ConvertSidToStringSidW(pTokenUser->User.Sid, &sid_str) == FALSE ||
swprintf(reg_path, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", sid_str) == MAX_PATH ||
RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &reg_key) != 0 ||
RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)pw_dir_w, &tmp_len) != 0) {
/* one of the above failed */
debug("cannot retirve profile path - perhaps user profile is not created yet");
}
if (sid_str)
LocalFree(sid_str);
if (reg_key)
RegCloseKey(reg_key);
/* retrieve and set env variables. */
{
#define MAX_VALUE_LEN 1000
#define MAX_DATA_LEN 2000
#define MAX_EXPANDED_DATA_LEN 5000
/* TODO - Get away with fixed limits and dynamically allocate required memory, cleanup this logic*/
wchar_t *path;
wchar_t value_name[MAX_VALUE_LEN];
wchar_t value_data[MAX_DATA_LEN], value_data_expanded[MAX_EXPANDED_DATA_LEN], *to_apply;
DWORD value_type, name_len, data_len;
int i;
LONG ret;
if (ImpersonateLoggedOnUser(token) == FALSE)
debug("Failed to impersonate user token, %d", GetLastError());
SET_USER_ENV(FOLDERID_LocalAppData, L"LOCALAPPDATA");
SET_USER_ENV(FOLDERID_Profile, L"USERPROFILE");
SET_USER_ENV(FOLDERID_RoamingAppData, L"APPDATA");
reg_key = 0;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Environment", 0, KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS) {
i = 0;
while (1) {
name_len = MAX_VALUE_LEN * 2;
data_len = MAX_DATA_LEN * 2;
to_apply = NULL;
if (RegEnumValueW(reg_key, i++, value_name, &name_len, 0, &value_type, (LPBYTE)&value_data, &data_len) != ERROR_SUCCESS)
break;
if (value_type == REG_SZ)
to_apply = value_data;
else if (value_type == REG_EXPAND_SZ) {
ExpandEnvironmentStringsW(value_data, value_data_expanded, MAX_EXPANDED_DATA_LEN);
to_apply = value_data_expanded;
}
if (wcsicmp(value_name, L"PATH") == 0) {
DWORD size;
if ((size = GetEnvironmentVariableW(L"PATH", NULL, 0)) != ERROR_ENVVAR_NOT_FOUND) {
memcpy(value_data_expanded + size, to_apply, (wcslen(to_apply) + 1) * 2);
GetEnvironmentVariableW(L"PATH", value_data_expanded, MAX_EXPANDED_DATA_LEN);
value_data_expanded[size - 1] = L';';
to_apply = value_data_expanded;
}
}
if (to_apply)
SetEnvironmentVariableW(value_name, to_apply);
}
RegCloseKey(reg_key);
}
RevertToSelf();
}
UTF8_TO_UTF16_FATAL(tmp, s->pw->pw_name);
_snwprintf(wbuf, sizeof(wbuf)/2, L"%ls@%ls $P$G", tmp, _wgetenv(L"COMPUTERNAME"));
SetEnvironmentVariableW(L"PROMPT", wbuf);
}
setup_session_user_vars(s);
free(pw_dir_w);
free(tmp);
}
char* w32_programdir();
@ -459,7 +458,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
wchar_t *exec_command_w = NULL, *pw_dir_w;
if (s->is_subsystem >= SUBSYSTEM_INT_SFTP_ERROR) {
error("sub system not supported, exiting\n");
error("sub system not supported, exiting");
fflush(NULL);
exit(1);
}
@ -469,7 +468,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
fatal("%s: cannot create pipe: %.100s", __func__, strerror(errno));
if ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL)
fatal("%s: out of memory");
fatal("%s: out of memory", __func__);
set_nonblock(pipein[0]);
@ -494,62 +493,62 @@ int do_exec_windows(Session *s, const char *command, int pty) {
else {/*relative*/
exec_command = malloc(strlen(progdir) + 1 + strlen(command));
if (exec_command == NULL)
fatal("%s, out of memory");
fatal("%s, out of memory", __func__);
memcpy(exec_command, progdir, strlen(progdir));
exec_command[strlen(progdir)] = '\\';
memcpy(exec_command + strlen(progdir) + 1, command, strlen(command) + 1);
}
} else {
/*
* contruct %programdir%\ssh-shellhost.exe <-nopty> base64encoded(command)
* command is base64 encoded to preserve original special charecters like '"'
* else they will get lost in CreateProcess translation
*/
char *shell_host = pty ? "ssh-shellhost.exe " : "ssh-shellhost.exe -nopty ", *c;
exec_command = malloc(strlen(progdir) + 1 + strlen(shell_host) + (command ? strlen(command) : 0) + 1);
char *command_b64 = NULL;
size_t command_b64_len = 0;
if (command) {
/* accomodate bas64 encoding bloat and null terminator */
command_b64_len = ((strlen(command) + 2) / 3) * 4 + 1;
if ((command_b64 = malloc(command_b64_len)) == NULL ||
b64_ntop(command, strlen(command), command_b64, command_b64_len) == -1)
fatal("%s, error encoding session command");
}
exec_command = malloc(strlen(progdir) + 1 + strlen(shell_host) + (command_b64 ? strlen(command_b64): 0) + 1);
if (exec_command == NULL)
fatal("%s, out of memory");
fatal("%s, out of memory", __func__);
c = exec_command;
memcpy(c, progdir, strlen(progdir));
c += strlen(progdir);
*c++ = '\\';
memcpy(c, shell_host, strlen(shell_host));
c += strlen(shell_host);
if (command) {
memcpy(c, command, strlen(command));
c += strlen(command);
if (command_b64) {
memcpy(c, command_b64, strlen(command_b64));
c += strlen(command_b64);
}
*c = '\0';
}
/* setup Environment varibles */
setup_session_vars(s);
extern int debug_flag;
/* start the process */
{
PROCESS_INFORMATION pi;
STARTUPINFOW si;
BOOL b;
HANDLE hToken = INVALID_HANDLE_VALUE;
/*
* Assign sockets to StartupInfo
*/
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpReserved = 0;
si.lpTitle = NULL; /* NULL means use exe name as title */
si.dwX = 0;
si.dwY = 0;
si.dwXSize = 5;
si.dwYSize = 5;
si.dwXCountChars = s->col;
si.dwYCountChars = s->row;
si.dwFillAttribute = 0;
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS;
si.wShowWindow = 0; // FALSE ;
si.cbReserved2 = 0;
si.lpReserved2 = 0;
si.hStdInput = (HANDLE)w32_fd_to_handle(pipein[0]);
si.hStdOutput = (HANDLE)w32_fd_to_handle(pipeout[1]);
@ -559,29 +558,20 @@ int do_exec_windows(Session *s, const char *command, int pty) {
hToken = s->authctxt->methoddata;
debug("Executing command: %s", exec_command);
UTF8_TO_UTF16_FATAL(exec_command_w, exec_command);
/* Create the child process */
exec_command_w = utf8_to_utf16(exec_command);
/* in debug mode launch using sshd.exe user context */
if (debug_flag)
b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE,
DETACHED_PROCESS, NULL, pw_dir_w,
&si, &pi);
else
else /* launch as client user context */
b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE,
DETACHED_PROCESS , NULL, pw_dir_w,
&si, &pi);
if (!b)
{
debug("ERROR. Cannot create process (%u).\n", GetLastError());
free(pw_dir_w);
free(exec_command_w);
CloseHandle(hToken);
exit(1);
}
fatal("ERROR. Cannot create process (%u).\n", GetLastError());
else if (pty) { /*attach to shell console */
FreeConsole();
if (!debug_flag)
@ -610,6 +600,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
s->pid = pi.dwProcessId;
register_child(pi.hProcess, pi.dwProcessId);
}
/*
* Set interactive/non-interactive mode.
*/
@ -625,16 +616,14 @@ int do_exec_windows(Session *s, const char *command, int pty) {
* Enter the interactive session. Note: server_loop must be able to
* handle the case that fdin and fdout are the same.
*/
if (s->ttyfd == -1)
session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 0);
else
session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 1); // tty interactive session
session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 1); /* tty interactive session */
free(pw_dir_w);
free(exec_command_w);
return 0;
}
int
@ -2389,9 +2378,9 @@ static int
session_env_req(Session *s)
{
char *name, *val;
u_int name_len, val_len, i;
u_int name_chars, val_len, i;
name = packet_get_cstring(&name_len);
name = packet_get_cstring(&name_chars);
val = packet_get_cstring(&val_len);
packet_check_eom();

9
sftp.c
View File

@ -2216,8 +2216,10 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
setvbuf(stdout, NULL, _IOLBF, 2);
/* We do this only in interactive mode as we are unable to read files with UTF8 BOM */
if(interactive)
if (interactive) {
setvbuf(infile, NULL, _IOLBF, 2);
_setmode(_fileno(stdin), O_U16TEXT); /* prepare for Unicode input */
}
#else /* !WINDOWS */
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(infile, NULL, _IOLBF, 0);
@ -2449,11 +2451,6 @@ main(int argc, char **argv)
addargs(&args, "-oClearAllForwardings yes");
ll = SYSLOG_LEVEL_INFO;
#ifdef WINDOWS
/* prepare for Unicode input */
_setmode(_fileno(stdin), O_U16TEXT);
#endif
infile = stdin;
while ((ch = getopt(argc, argv,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keyscan.c,v 1.106 2016/05/02 10:26:04 djm Exp $ */
/* $OpenBSD: ssh-keyscan.c,v 1.107 2017/01/06 03:41:58 djm Exp $ */
/*
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
@ -752,10 +752,13 @@ main(int argc, char **argv)
tname = strtok(optarg, ",");
while (tname) {
int type = sshkey_type_from_name(tname);
switch (type) {
#ifdef WITH_SSH1
case KEY_RSA1:
get_keytypes |= KT_RSA1;
break;
#endif
case KEY_DSA:
get_keytypes |= KT_DSA;
break;
@ -769,7 +772,8 @@ main(int argc, char **argv)
get_keytypes |= KT_ED25519;
break;
case KEY_UNSPEC:
fatal("unknown key type %s", tname);
default:
fatal("Unknown key type \"%s\"", tname);
}
tname = strtok(NULL, ",");
}

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh_config.5,v 1.240 2016/10/15 19:56:25 jmc Exp $
.Dd $Mdocdate: October 15 2016 $
.\" $OpenBSD: ssh_config.5,v 1.241 2017/02/03 23:01:19 djm Exp $
.Dd $Mdocdate: February 3 2017 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@ -415,6 +415,10 @@ If the specified value begins with a
.Sq +
character, then the specified ciphers will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
from the default set instead of replacing them.
.Pp
The supported ciphers are:
.Bd -literal -offset indent
@ -784,6 +788,10 @@ Alternately if the specified value begins with a
.Sq +
character, then the specified key types will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
@ -807,6 +815,10 @@ Alternately if the specified value begins with a
.Sq +
character, then the specified key types will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
@ -1027,6 +1039,10 @@ Alternately if the specified value begins with a
.Sq +
character, then the specified methods will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified methods (including wildcards) will be removed
from the default set instead of replacing them.
The default is:
.Bd -literal -offset indent
curve25519-sha256,curve25519-sha256@libssh.org,
@ -1102,6 +1118,10 @@ If the specified value begins with a
.Sq +
character, then the specified algorithms will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
from the default set instead of replacing them.
.Pp
The algorithms that contain
.Qq -etm
@ -1264,6 +1284,10 @@ Alternately if the specified value begins with a
.Sq +
character, then the key types after it will be appended to the default
instead of replacing it.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect2.c,v 1.251 2016/12/04 23:54:02 djm Exp $ */
/* $OpenBSD: sshconnect2.c,v 1.254 2017/02/03 02:56:00 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@ -198,8 +198,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
}
if (options.rekey_limit || options.rekey_interval)
packet_set_rekey_limits((u_int32_t)options.rekey_limit,
(time_t)options.rekey_interval);
packet_set_rekey_limits(options.rekey_limit,
options.rekey_interval);
/* start key exchange */
if ((r = kex_setup(active_state, myproposal)) != 0)
@ -939,14 +939,14 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
Authctxt *authctxt = ctxt;
char *info, *lang, *password = NULL, *retype = NULL;
char prompt[150];
const char *host = options.host_key_alias ? options.host_key_alias :
authctxt->host;
const char *host;
debug2("input_userauth_passwd_changereq");
if (authctxt == NULL)
fatal("input_userauth_passwd_changereq: "
"no authentication context");
host = options.host_key_alias ? options.host_key_alias : authctxt->host;
info = packet_get_string(NULL);
lang = packet_get_string(NULL);
@ -1641,7 +1641,7 @@ ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp,
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* send # of sock, data to be signed */
if ((r = sshbuf_put_u32(b, sock) != 0) ||
if ((r = sshbuf_put_u32(b, sock)) != 0 ||
(r = sshbuf_put_string(b, data, datalen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (ssh_msg_send(to[1], version, b) == -1)

6
sshd.8
View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: sshd.8,v 1.287 2016/11/30 02:57:40 djm Exp $
.Dd $Mdocdate: November 30 2016 $
.\" $OpenBSD: sshd.8,v 1.288 2017/01/30 23:27:39 dtucker Exp $
.Dd $Mdocdate: January 30 2017 $
.Dt SSHD 8
.Os
.Sh NAME
@ -631,7 +631,7 @@ and
files contain host public keys for all known hosts.
The global file should
be prepared by the administrator (optional), and the per-user file is
maintained automatically: whenever the user connects from an unknown host,
maintained automatically: whenever the user connects to an unknown host,
its key is added to the per-user file.
.Pp
Each line in these files contains the following fields: markers (optional),

29
sshd.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.480 2016/12/09 03:04:29 djm Exp $ */
/* $OpenBSD: sshd.c,v 1.482 2017/02/06 09:22:51 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -375,14 +375,14 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out)
{
u_int i;
int remote_major, remote_minor;
char *s, *newline = "\n";
char *s;
char buf[256]; /* Must not be larger than remote_version. */
char remote_version[256]; /* Must be at least as big as buf. */
xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s",
xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n",
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
*options.version_addendum == '\0' ? "" : " ",
options.version_addendum, newline);
options.version_addendum);
/* Send our protocol version identification. */
if (atomicio(vwrite, sock_out, server_version_string,
@ -1087,7 +1087,8 @@ server_listen(void)
#ifdef WINDOWS
/* disable inheritance on listener socket */
if (fcntl(listen_sock, F_SETFD, FD_CLOEXEC) != 0) {
error("F_SETFD FD_CLOEXEC on listener socket %d failed with %d", listen_sock, errno);
error("F_SETFD FD_CLOEXEC on socket %d error %d",
listen_sock, errno);
close(listen_sock);
continue;
}
@ -1297,19 +1298,25 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
*/
{
char* path_utf8 = utf16_to_utf8(GetCommandLineW());
char fd_handle[30]; /* large enough to hold pointer value in hex */
/* large enough to hold pointer value in hex */
char fd_handle[30];
if (path_utf8 == NULL)
fatal("Failed to alloc memory");
if (snprintf(fd_handle, sizeof(fd_handle), "%p", w32_fd_to_handle(*newsock)) == -1
if (snprintf(fd_handle, sizeof(fd_handle), "%p",
w32_fd_to_handle(*newsock)) == -1
|| SetEnvironmentVariable("SSHD_REMSOC", fd_handle) == FALSE
|| snprintf(fd_handle, sizeof(fd_handle), "%p", w32_fd_to_handle(startup_p[1])) == -1
|| snprintf(fd_handle, sizeof(fd_handle), "%p",
w32_fd_to_handle(startup_p[1])) == -1
|| SetEnvironmentVariable("SSHD_STARTUPSOC", fd_handle) == FALSE
|| fcntl(startup_p[0], F_SETFD, FD_CLOEXEC) == -1) {
error("unable to set the right environment for child, closing connection ");
error("unable to set environment for child");
close(*newsock);
/* close child end of startup pipe. parent end will automatically be cleaned up on next iteration*/
/*
* close child end of startup pipe. parent end will
* automatically be cleaned up on next iteration
*/
close(startup_p[1]);
continue;
}
@ -2261,7 +2268,7 @@ do_ssh2_kex(void)
if (options.rekey_limit || options.rekey_interval)
packet_set_rekey_limits(options.rekey_limit,
(time_t)options.rekey_interval);
options.rekey_interval);
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
list_hostkey_types());

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: sshd_config.5,v 1.239 2016/11/30 03:00:05 djm Exp $
.Dd $Mdocdate: November 30 2016 $
.\" $OpenBSD: sshd_config.5,v 1.242 2017/02/03 23:01:19 djm Exp $
.Dd $Mdocdate: February 3 2017 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@ -437,6 +437,10 @@ If the specified value begins with a
.Sq +
character, then the specified ciphers will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
from the default set instead of replacing them.
.Pp
The supported ciphers are:
.Pp
@ -649,6 +653,10 @@ Alternately if the specified value begins with a
.Sq +
character, then the specified key types will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
@ -843,6 +851,10 @@ Alternately if the specified value begins with a
.Sq +
character, then the specified methods will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified methods (including wildcards) will be removed
from the default set instead of replacing them.
The supported algorithms are:
.Pp
.Bl -item -compact -offset indent
@ -933,6 +945,10 @@ If the specified value begins with a
.Sq +
character, then the specified algorithms will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
from the default set instead of replacing them.
.Pp
The algorithms that contain
.Qq -etm
@ -1280,6 +1296,10 @@ Alternately if the specified value begins with a
.Sq +
character, then the specified key types will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
@ -1644,13 +1664,13 @@ The username.
.El
.Pp
.Cm AuthorizedKeysCommand
accepts the tokens %%, %f, %h, %t, and %u.
accepts the tokens %%, %f, %h, %k, %t, and %u.
.Pp
.Cm AuthorizedKeysFile
accepts the tokens %%, %h, and %u.
.Pp
.Cm AuthorizedPrincipalsCommand
accepts the tokens %%, %F, %f, %K, %k, %h, %i, %s, %T, %t, and %u.
accepts the tokens %%, %F, %f, %h, %i, %K, %k, %s, %T, %t, and %u.
.Pp
.Cm AuthorizedPrincipalsFile
accepts the tokens %%, %h, and %u.

View File

@ -55,45 +55,46 @@
#ifdef WINDOWS
/*
* Windows versions of pty_*. Some of them are NO-OPs and should go away when
* pty logic is refactored and abstracted out
* Windows versions of pty_*. Some of them are NO-OPs and should go
* away when pty logic is refactored and abstracted out
*
*/
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
{
/*
* Simple console screen implementation in Win32 to give a Unix like pty for interactive sessions
*/
*ttyfd = 0;
*ptyfd = 0;
strlcpy(namebuf, "console", namebuflen);
return 1;
/*
* Simple console screen implementation in Win32 to give a
* Unix like pty for interactive sessions
*/
*ttyfd = 0;
*ptyfd = 0;
strlcpy(namebuf, "console", namebuflen);
return 1;
}
void
pty_release(const char *tty) {
/* NO-OP */
/* NO-OP */
}
void
pty_make_controlling_tty(int *ttyfd, const char *tty) {
/* NO-OP */
/* NO-OP */
}
void
pty_change_window_size(int ptyfd, u_int row, u_int col,
u_int xpixel, u_int ypixel) {
COORD coord;
coord.X = col;
coord.Y = 9999;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
u_int xpixel, u_int ypixel) {
COORD coord;
coord.X = col;
coord.Y = 9999;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void
pty_setowner(struct passwd *pw, const char *tty) {
/* NO-OP */
/* NO-OP */
}
void

View File

@ -57,7 +57,10 @@ int ConUnInit(void);
struct termios term_settings;
/* TODO - clean this up for Windows, ConInit should return previous terminal settings that need to be stored in term_settings*/
/*
* TODO - clean this up for Windows, ConInit should return previous terminal
* settings that need to be stored in term_settings
*/
struct termios *
get_saved_tio(void) {

3
utf8.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: utf8.c,v 1.3 2016/05/30 12:57:21 schwarze Exp $ */
/* $OpenBSD: utf8.c,v 1.4 2017/02/02 10:54:25 jsg Exp $ */
/*
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
*
@ -122,6 +122,7 @@ vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap)
sz = strlen(src) + 1;
if ((dst = malloc(sz)) == NULL) {
free(src);
ret = -1;
goto fail;
}