mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-22 13:34:43 +02:00
Source snapshot from Powershell/openssh-portable:latestw_all
This commit is contained in:
parent
e404237322
commit
c8b8c4b82a
@ -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 */
|
||||
|
@ -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
12
auth2.c
@ -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 */
|
||||
|
24
authfd.c
24
authfd.c
@ -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;
|
||||
|
10
authfd.h
10
authfd.h
@ -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 */
|
||||
|
33
channels.c
33
channels.c
@ -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. */
|
||||
|
@ -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,
|
||||
|
@ -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.");
|
||||
|
48
compat.c
48
compat.c
@ -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')
|
||||
|
60
configure.ac
60
configure.ac
@ -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"
|
||||
|
@ -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}"
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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."
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
@ -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
|
||||
|
@ -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" />
|
||||
|
@ -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" />
|
||||
|
@ -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" />
|
||||
|
@ -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.
@ -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" />
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
}
|
@ -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 */
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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, ®_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, ®_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
@ -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)
|
||||
|
@ -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;
|
||||
}
|
@ -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
@ -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,
|
||||
"as,
|
||||
&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,
|
||||
"as,
|
||||
&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;
|
||||
}
|
||||
}
|
@ -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))
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
|
59
contrib/win32/win32compat/utf.c
Normal file
59
contrib/win32/win32compat/utf.c
Normal 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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
21
kex.c
@ -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
31
match.c
@ -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;
|
||||
}
|
||||
|
||||
|
3
match.h
3
match.h
@ -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
6
misc.c
@ -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] == ':'))
|
||||
|
@ -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
7
mux.c
@ -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:
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
70
packet.c
70
packet.c
@ -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;
|
||||
}
|
||||
|
9
packet.h
9
packet.h
@ -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 *);
|
||||
|
99
readconf.c
99
readconf.c
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
161
regress/pesterTests/SSHDConfig.tests.ps1
Normal file
161
regress/pesterTests/SSHDConfig.tests.ps1
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
127
regress/pesterTests/SSHD_Config
Normal file
127
regress/pesterTests/SSHD_Config
Normal 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*
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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 *);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
23
servconf.c
23
servconf.c
@ -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)
|
||||
|
36
serverloop.c
36
serverloop.c
@ -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
289
session.c
@ -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, ®_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, ®_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, ®_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
9
sftp.c
@ -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,
|
||||
|
@ -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, ",");
|
||||
}
|
||||
|
28
ssh_config.5
28
ssh_config.5
@ -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,
|
||||
|
@ -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
6
sshd.8
@ -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
29
sshd.c
@ -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());
|
||||
|
@ -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.
|
||||
|
35
sshpty.c
35
sshpty.c
@ -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
|
||||
|
5
sshtty.c
5
sshtty.c
@ -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
3
utf8.c
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user