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.
@ -234,13 +233,20 @@ function Download-PSCoreMSI
.SYNOPSIS
This function installs the tools required by our tests
1) Pester for running the tests
2) sysinternals required by the tests on windows.
2) sysinternals required by the tests on windows.
#>
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))
{
@ -360,18 +366,18 @@ function Build-Win32OpenSSHPackage
$folderName = $NativeHostArch
if($NativeHostArch -ieq 'x86')
{
$folderName = "Win32"
$folderName = "Win32"
}
}
else
{
if($platform -ieq "AMD64")
{
$folderName = "x64"
$folderName = "x64"
}
else
{
$folderName = "Win32"
$folderName = "Win32"
}
}
@ -430,7 +436,7 @@ function Build-Win32OpenSSHPackage
}
Add-Type -assemblyname System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory($OpenSSHDir, $package)
[System.IO.Compression.ZipFile]::CreateFromDirectory($OpenSSHDir, $package)
}
<#
@ -494,43 +500,15 @@ function Deploy-OpenSSHTests
}
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
[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
$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\*" -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\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;
@ -204,7 +205,7 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
switch (rwflags) {
case O_RDONLY:
cf_flags->dwDesiredAccess = GENERIC_READ;
cf_flags->dwShareMode = FILE_SHARE_READ;
cf_flags->dwShareMode = FILE_SHARE_READ;
break;
case O_WRONLY:
cf_flags->dwDesiredAccess = GENERIC_WRITE;
@ -226,7 +227,7 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
cf_flags->dwCreationDisposition = CREATE_NEW;
else
cf_flags->dwCreationDisposition = CREATE_ALWAYS;
}
}
if (c_s_flags & O_APPEND)
cf_flags->dwDesiredAccess = FILE_APPEND_DATA;
@ -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,12 +256,12 @@ 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_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;
if ((uname_utf8 = _strdup(user_utf8)) == NULL ||
(pw_home_utf8 = utf16_to_utf8(profile_home)) == NULL) {
errno = ENOMEM;
goto done;
}
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;
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);
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);
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
) {
static VOID CALLBACK
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,48 +98,50 @@ 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;
void
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) {
sighandler_t
w32_signal(int signum, sighandler_t handler)
{
sighandler_t prev;
debug2("signal() sig:%d, handler:%p", signum, handler);
if (signum >= W32_SIGMAX) {
errno = EINVAL;
return W32_SIG_ERR;
}
prev = sig_handlers[signum];
prev = sig_handlers[signum];
sig_handlers[signum] = handler;
return prev;
}
int
w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
int
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");
@ -150,8 +150,9 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
int
w32_raise(int sig) {
int
w32_raise(int sig)
{
debug("raise sig:%d", sig);
if (sig == W32_SIGSEGV)
return raise(SIGSEGV); /* raise native exception handler*/
@ -170,7 +171,7 @@ w32_raise(int sig) {
/* if set to ignore, nothing to do */
if (sig_handlers[sig] == W32_SIG_IGN)
return 0;
/* execute any default handlers */
switch (sig) {
case W32_SIGCHLD:
@ -184,8 +185,9 @@ w32_raise(int sig) {
}
/* processes pending signals, return -1 and errno=EINTR if any are processed*/
static int
sw_process_pending_signals() {
static int
sw_process_pending_signals()
{
sigset_t pending_tmp = pending_signals;
BOOL sig_int = FALSE; /* has any signal actually interrupted */
@ -195,7 +197,7 @@ sw_process_pending_signals() {
/* check for expected signals*/
for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++)
sigdelset(&pending_tmp, exp[i]);
if (pending_tmp) {
if (pending_tmp) {
/* unexpected signals queued up */
debug("process_signals() - ERROR unexpected signals in queue: %d", pending_tmp);
errno = ENOTSUP;
@ -219,7 +221,7 @@ sw_process_pending_signals() {
sigdelset(&pending_tmp, exp[i]);
}
}
/* by now all pending signals should have been taken care of*/
if (pending_tmp)
@ -235,17 +237,17 @@ sw_process_pending_signals() {
}
/*
* Main wait routine used by all blocking calls.
* It wakes up on
* Main wait routine used by all blocking calls.
* It wakes up on
* - any signals (errno = EINTR )
* - any of the supplied events set
* - any APCs caused by IO completions
* - time out
* - any of the supplied events set
* - any APCs caused by IO completions
* - time out
* - Returns 0 on IO completion and timeout, -1 on rest
* if milli_seconds is 0, this function returns 0, its called with 0
* if milli_seconds is 0, this function returns 0, its called with 0
* to execute any scheduled APCs
*/
int
int
wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
{
HANDLE all_events[MAXIMUM_WAIT_OBJECTS];
@ -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;
@ -214,7 +214,7 @@ int waitpid(int pid, int *status, int options) {
sw_remove_child_at_index(children.num_children - 1);
return ret_id;
}
/* all children are alive. wait for one of them to exit */
timeout = INFINITE;
if (options & WNOHANG)
@ -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
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);
return;
if (hProcToken)
CloseHandle(hProcToken);
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
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];
/* 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;
}
#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
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;
}
domain_user = (wcschr(user, L'@') != NULL) ? TRUE : FALSE;
static HANDLE
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;
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_cpn, L'@')? 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) * 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 (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_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 (AllocateLocallyUniqueId(&sourceContext.SourceIdentifier) != TRUE)
goto done;
memcpy(sourceContext.SourceName,"sshagent", sizeof(sourceContext.SourceName));
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 (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");
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 ((tmp = wcschr(userW, L'\\')) != NULL) {
domW = userW;
userW = tmp + 1;
*tmp = L'\0';
if ((user_utf16 = utf8_to_utf16(user)) == NULL ||
(pwd_utf16 = utf8_to_utf16(pwd)) == NULL) {
debug("out of memory");
goto done;
}
}
else if ((tmp = wcschr(userW, L'@')) != NULL) {
domW = tmp + 1;
*tmp = L'\0';
}
if ((tmp = wcschr(user_utf16, L'@') ) != NULL ) {
udom_utf16 = tmp + 1;
*tmp = L'\0';
}
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 (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;
}
con->auth_token = token;
LoadProfile(con, userW, domW);
r = 0;
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, 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;
if (user)
free(user);
if (pwd)
free(pwd);
if (client_proc)
CloseHandle(client_proc);
/* TODO Fix this hacky protocol*/
if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
r = 0;
return r;
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;
}
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 (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 (key_verify(key, sig, sig_len, blob, blob_len) != 1) {
debug("signature verification failed");
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;
}
{
wchar_t *tmp, *userW, *domW;
userW = wuser;
domW = NULL;
if ((tmp = wcschr(userW, L'\\')) != NULL) {
domW = userW;
userW = tmp + 1;
*tmp = L'\0';
if (key_verify(key, sig, sig_len, blob, blob_len) != 1) {
debug("signature verification failed");
goto done;
}
}
else if ((tmp = wcschr(userW, L'@')) != NULL) {
domW = tmp + 1;
*tmp = L'\0';
}
LoadProfile(con, userW, domW);
}
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;
}
r = 0;
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;
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;
}
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;
}
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
@ -171,7 +174,7 @@ w32_io_on_select(struct w32_io* pio, BOOL rd)
{
if ((pio->type == SOCK_FD))
socketio_on_select(pio, rd);
else
else
fileio_on_select(pio, rd);
}
@ -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];
@ -350,13 +356,15 @@ w32_pipe(int *pfds) {
fd_table_set(pio[1], write_index);
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);
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);
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,64 +384,66 @@ 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);
return fileio_read(fd_table.w32_ios[fd], dst, 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)
return socketio_send(fd_table.w32_ios[fd], buf, max, 0);
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) {
long
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;
return 0;
}
pio = fd_table.w32_ios[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);
@ -491,7 +503,7 @@ w32_io_process_fd_flags(struct w32_io* pio, int flags) {
shi_flags = (flags & FD_CLOEXEC) ? 0 : HANDLE_FLAG_INHERIT;
if (SetHandleInformation(WINHANDLE(pio), HANDLE_FLAG_INHERIT, shi_flags) == FALSE) {
debug("fcntl - SetHandleInformation failed %d, io:%p",
debug("fcntl - SetHandleInformation failed %d, io:%p",
GetLastError(), pio);
errno = EOTHER;
return -1;
@ -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;
ret = fd_table.w32_ios[fd]->fd_flags;
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);
@ -693,9 +703,8 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
}
}
if (out_ready_fds == 0)
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,28 +817,31 @@ 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;
}
int
w32_ftruncate(int fd, off_t length) {
CHECK_FD(fd);
int
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));
int
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
@ -17,7 +43,7 @@ enum w32_io_type {
};
enum w32_io_sock_state {
SOCK_INITIALIZED = 0,
SOCK_INITIALIZED = 0,
SOCK_LISTENING = 1, /*listen called on socket*/
SOCK_ACCEPTED = 2, /*socket returned from accept()*/
SOCK_CONNECTING = 3, /*connect called on socket, connect is in progress*/
@ -25,41 +51,35 @@ enum w32_io_sock_state {
};
/*
* This structure encapsulates the state info needed to map a File Descriptor
* This structure encapsulates the state info needed to map a File Descriptor
* to Win32 Handle
*/
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;
/*index at which this object is stored in fd_table*/
int table_index;
int table_index;
enum w32_io_type type; /*hanldle type*/
DWORD fd_flags; /*fd flags from POSIX*/
DWORD fd_status_flags; /*fd status flags from POSIX*/
/*underlying w32 handle*/
union {
SOCKET sock;
@ -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) {
void
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;
@ -30,17 +55,17 @@ DIR * opendir(const char *name)
wchar_t searchstr[PATH_MAX];
wchar_t* wname = NULL;
int needed;
if ((wname = utf8_to_utf16(sanitized_path(name))) == NULL) {
errno = ENOMEM;
return NULL;
}
// add *.* for Windows _findfirst() search pattern
/* add *.* for Windows _findfirst() search pattern */
swprintf_s(searchstr, PATH_MAX, L"%s\\*.*", wname);
free(wname);
if ((hFile = _wfindfirst(searchstr, &c_file)) == -1L)
if ((hFile = _wfindfirst(searchstr, &c_file)) == -1L)
return NULL; /* errno is set by _wfindfirst */
else {
if ((pdir = malloc(sizeof(DIR))) == NULL) {
@ -48,34 +73,36 @@ DIR * opendir(const char *name)
errno = ENOMEM;
return NULL;
}
memset(pdir, 0, sizeof(DIR));
pdir->hFile = hFile;
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 path; // path does not have a slash
return (pdest + 1);
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);
@ -136,7 +135,7 @@ sshkey_file_tests(void)
ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
sshkey_free(k2);
TEST_DONE();
TEST_START("parse RSA from new-format w/ passphrase");
buf = load_file("rsa_n_pw");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
@ -146,7 +145,7 @@ sshkey_file_tests(void)
ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
sshkey_free(k2);
TEST_DONE();
TEST_START("load RSA from public");
ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
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");
TEST_START("utf8_setlocale");
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(

289
session.c
View File

@ -308,29 +308,108 @@ xauth_valid_string(const char *s)
SetEnvironmentVariableW(evn_variable, path); \
CoTaskMemFree(path); \
} \
} while (0)
} 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,63 +493,63 @@ 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]);
si.hStdError = (HANDLE)w32_fd_to_handle(pipeerr[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);
/* Create the child process */
exec_command_w = utf8_to_utf16(exec_command);
UTF8_TO_UTF16_FATAL(exec_command_w, 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;
}