Source snapshot from Powershell/openssh-portable:latestw_all

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

View File

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

View File

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

12
auth2.c
View File

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

View File

@ -97,35 +97,39 @@ ssh_get_authentication_socket(int *fdp)
#ifdef WINDOWS #ifdef WINDOWS
/* Auth socket in Windows is a static-named pipe listener in ssh-agent */ /* 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; HKEY agent_root = 0;
DWORD agent_pid = 0, tmp_size = 4, pipe_server_pid = 0xff; DWORD agent_pid = 0, tmp_size = 4, pipe_server_pid = 0xff;
DWORD connection_attempts = 0;
HANDLE h; 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) { 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); RegCloseKey(agent_root);
} }
do { do {
h = CreateFileW(SSH_AGENT_PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, h = CreateFileW(SSH_AGENT_PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (h != INVALID_HANDLE_VALUE || GetLastError() != ERROR_PIPE_BUSY) if (h != INVALID_HANDLE_VALUE || GetLastError() != ERROR_PIPE_BUSY ||
++connection_attempts > 10)
break; break;
Sleep(100); Sleep(100);
} while(1); } while(1);
if (h == INVALID_HANDLE_VALUE) { 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; return SSH_ERR_AGENT_NOT_PRESENT;
} }
/* /*
* ensure that connected server pid matches published pid. this provides service side * ensure that connected server pid matches published pid.
* auth and prevents mitm * 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"); debug("agent pid mismatch");
CloseHandle(h); CloseHandle(h);
return SSH_ERR_AGENT_COMMUNICATION; return SSH_ERR_AGENT_COMMUNICATION;

View File

@ -89,4 +89,14 @@ int ssh_agent_sign(int sock, struct sshkey *key,
#define SSH_AGENT_RSA_SHA2_256 0x02 #define SSH_AGENT_RSA_SHA2_256 0x02
#define SSH_AGENT_RSA_SHA2_512 0x04 #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 */ #endif /* AUTHFD_H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.c,v 1.356 2016/10/18 17:32:54 dtucker Exp $ */ /* $OpenBSD: channels.c,v 1.357 2017/02/01 02:59:09 dtucker Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * 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(); packet_check_eom();
c = channel_connect_to_port(host, host_port, c = channel_connect_to_port(host, host_port,
"connected socket", originator_string); "connected socket", originator_string, NULL, NULL);
free(originator_string); free(originator_string);
free(host); free(host);
if (c == NULL) { if (c == NULL) {
@ -4028,9 +4028,13 @@ channel_connect_ctx_free(struct channel_connect *cctx)
memset(cctx, 0, sizeof(*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 * 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; struct addrinfo hints;
int gaierr; int gaierr;
@ -4071,7 +4075,12 @@ connect_to(const char *name, int port, char *ctype, char *rname)
hints.ai_family = IPv4or6; hints.ai_family = IPv4or6;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port); 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, error("connect_to %.100s: unknown host (%s)", name,
ssh_gai_strerror(gaierr)); ssh_gai_strerror(gaierr));
return NULL; return NULL;
@ -4094,6 +4103,13 @@ connect_to(const char *name, int port, char *ctype, char *rname)
return c; 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 * returns either the newly connected channel or the downstream channel
* that needs to deal with this connection. * 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. */ /* Check if connecting to that port is permitted and connect. */
Channel * 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; 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) { if (!permit || !permit_adm) {
logit("Received request to connect to host %.100s port %d, " logit("Received request to connect to host %.100s port %d, "
"but the request was denied.", host, port); "but the request was denied.", host, port);
if (reason != NULL)
*reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
return NULL; 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. */ /* Check if connecting to that path is permitted and connect. */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.120 2016/10/18 17:32:54 dtucker Exp $ */ /* $OpenBSD: channels.h,v 1.121 2017/02/01 02:59:09 dtucker Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * 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_permitted_opens(void);
void channel_clear_adm_permitted_opens(void); void channel_clear_adm_permitted_opens(void);
void channel_print_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_to_path(const char *, char *, char *);
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
Channel *channel_connect_by_listen_address(const char *, u_short, Channel *channel_connect_by_listen_address(const char *, u_short,

View File

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

View File

@ -1,4 +1,4 @@
/* $OpenBSD: compat.c,v 1.99 2016/05/24 02:31:57 dtucker Exp $ */ /* $OpenBSD: compat.c,v 1.100 2017/02/03 23:01:19 djm Exp $ */
/* /*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
* *
@ -37,6 +37,7 @@
#include "compat.h" #include "compat.h"
#include "log.h" #include "log.h"
#include "match.h" #include "match.h"
#include "kex.h"
int compat13 = 0; int compat13 = 0;
int compat20 = 0; int compat20 = 0;
@ -250,42 +251,14 @@ proto_spec(const char *spec)
return ret; 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 * char *
compat_cipher_proposal(char *cipher_prop) compat_cipher_proposal(char *cipher_prop)
{ {
if (!(datafellows & SSH_BUG_BIGENDIANAES)) if (!(datafellows & SSH_BUG_BIGENDIANAES))
return cipher_prop; return cipher_prop;
debug2("%s: original cipher proposal: %s", __func__, 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); debug2("%s: compat cipher proposal: %s", __func__, cipher_prop);
if (*cipher_prop == '\0') if (*cipher_prop == '\0')
fatal("No supported ciphers found"); fatal("No supported ciphers found");
@ -298,7 +271,8 @@ compat_pkalg_proposal(char *pkalg_prop)
if (!(datafellows & SSH_BUG_RSASIGMD5)) if (!(datafellows & SSH_BUG_RSASIGMD5))
return pkalg_prop; return pkalg_prop;
debug2("%s: original public key proposal: %s", __func__, 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); debug2("%s: compat public key proposal: %s", __func__, pkalg_prop);
if (*pkalg_prop == '\0') if (*pkalg_prop == '\0')
fatal("No supported PK algorithms found"); fatal("No supported PK algorithms found");
@ -312,10 +286,14 @@ compat_kex_proposal(char *p)
return p; return p;
debug2("%s: original KEX proposal: %s", __func__, p); debug2("%s: original KEX proposal: %s", __func__, p);
if ((datafellows & SSH_BUG_CURVE25519PAD) != 0) 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) { if ((datafellows & SSH_OLD_DHGEX) != 0) {
p = filter_proposal(p, "diffie-hellman-group-exchange-sha256"); if ((p = match_filter_list(p,
p = filter_proposal(p, "diffie-hellman-group-exchange-sha1"); "diffie-hellman-group-exchange-sha256,"
"diffie-hellman-group-exchange-sha1")) == NULL)
fatal("match_filter_list failed");
} }
debug2("%s: compat KEX proposal: %s", __func__, p); debug2("%s: compat KEX proposal: %s", __func__, p);
if (*p == '\0') if (*p == '\0')

View File

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

View File

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

View File

@ -3,7 +3,6 @@ Import-Module $PSScriptRoot\build.psm1 -Force -DisableNameChecking
$repoRoot = Get-RepositoryRoot $repoRoot = Get-RepositoryRoot
$script:logFile = join-path $repoRoot.FullName "appveyor.log" $script:logFile = join-path $repoRoot.FullName "appveyor.log"
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log" $script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
$testfailed = $false
<# <#
Called by Write-BuildMsg to write to the build log, if it exists. Called by Write-BuildMsg to write to the build log, if it exists.
@ -234,13 +233,20 @@ function Download-PSCoreMSI
.SYNOPSIS .SYNOPSIS
This function installs the tools required by our tests This function installs the tools required by our tests
1) Pester for running the 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 function Install-TestDependencies
{ {
[CmdletBinding()] [CmdletBinding()]
param () 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 $isModuleAvailable = Get-Module 'Pester' -ListAvailable
if (-not ($isModuleAvailable)) if (-not ($isModuleAvailable))
{ {
@ -360,18 +366,18 @@ function Build-Win32OpenSSHPackage
$folderName = $NativeHostArch $folderName = $NativeHostArch
if($NativeHostArch -ieq 'x86') if($NativeHostArch -ieq 'x86')
{ {
$folderName = "Win32" $folderName = "Win32"
} }
} }
else else
{ {
if($platform -ieq "AMD64") if($platform -ieq "AMD64")
{ {
$folderName = "x64" $folderName = "x64"
} }
else else
{ {
$folderName = "Win32" $folderName = "Win32"
} }
} }
@ -430,7 +436,7 @@ function Build-Win32OpenSSHPackage
} }
Add-Type -assemblyname System.IO.Compression.FileSystem 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" $sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Include *.ps1,*.psm1 -Force -ErrorAction Stop Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Include *.ps1,*.psm1, sshd_config -Force -ErrorAction Stop
#copy all unit tests.
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration" $sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Exclude ssh-agent.exe, sshd.exe -Force -ErrorAction Stop Copy-Item -Path "$sourceDir\unittest-*" -Destination $OpenSSHTestDir -Force -ErrorAction Stop
#restart the service to use the test copy of sshd_config
Restart-Service sshd
$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
} }
@ -691,7 +669,7 @@ function Run-OpenSSHUnitTest
Remove-Item -Path $unitTestOutputFile -Force -ErrorAction SilentlyContinue 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 $testfailed = $false
if ($unitTestFiles -ne $null) if ($unitTestFiles -ne $null)
{ {

View File

@ -152,17 +152,6 @@ function Start-SSHBootstrap
{ {
Write-BuildMsg -AsInfo -Message "Chocolatey not present. Installing chocolatey." -Silent:$silent 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 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 # Add git\cmd to the path
@ -231,7 +220,7 @@ function Start-SSHBootstrap
# Install Windows 8.1 SDK # Install Windows 8.1 SDK
$packageName = "windows-sdk-8.1" $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)) if (-not (Test-Path -Path $sdkPath))
{ {
@ -264,7 +253,7 @@ function Start-SSHBootstrap
Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent
if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false) if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false)
{ {
Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at" + $script:vcPath Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at$script:vcPath, which means some required develop kits are missing on the machine."
} }
} }

View File

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

View File

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

View File

@ -38,7 +38,10 @@ cd $scriptdir
cmd.exe /c $ntrights cmd.exe /c $ntrights
Pop-Location 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" $rights = [System.Security.AccessControl.FileSystemRights]"Read, Write"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($account, $rights, "ContainerInherit,ObjectInherit", "None", "Allow") $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($account, $rights, "ContainerInherit,ObjectInherit", "None", "Allow")
$acl = Get-Acl -Path $logsdir $acl = Get-Acl -Path $logsdir

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -28,10 +28,11 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "w32fd.h"
#include <errno.h> #include <errno.h>
#include "w32fd.h"
#include "signal_internal.h" #include "signal_internal.h"
#include "inc\signal.h" #include "inc\signal.h"
#undef signal #undef signal
#undef raise #undef raise
#undef SIGINT #undef SIGINT
@ -48,30 +49,27 @@
/* pending signals to be processed */ /* pending signals to be processed */
sigset_t pending_signals; sigset_t pending_signals;
/* signal handler table*/ /* signal handler table*/
sighandler_t sig_handlers[W32_SIGMAX]; sighandler_t sig_handlers[W32_SIGMAX];
extern struct _children children;
static VOID CALLBACK static VOID CALLBACK
sigint_APCProc( sigint_APCProc(_In_ ULONG_PTR dwParam)
_In_ ULONG_PTR dwParam {
) {
debug3("SIGINT APCProc()"); debug3("SIGINT APCProc()");
sigaddset(&pending_signals, W32_SIGINT); sigaddset(&pending_signals, W32_SIGINT);
} }
static VOID CALLBACK static VOID CALLBACK
sigterm_APCProc( sigterm_APCProc(_In_ ULONG_PTR dwParam)
_In_ ULONG_PTR dwParam {
) {
debug3("SIGTERM APCProc()"); debug3("SIGTERM APCProc()");
sigaddset(&pending_signals, W32_SIGTERM); sigaddset(&pending_signals, W32_SIGTERM);
} }
static VOID CALLBACK static VOID CALLBACK
sigtstp_APCProc( sigtstp_APCProc(_In_ ULONG_PTR dwParam)
_In_ ULONG_PTR dwParam {
) {
debug3("SIGTSTP APCProc()"); debug3("SIGTSTP APCProc()");
sigaddset(&pending_signals, W32_SIGTSTP); sigaddset(&pending_signals, W32_SIGTSTP);
} }
@ -100,48 +98,50 @@ native_sig_handler(DWORD dwCtrlType)
} }
static VOID CALLBACK static VOID CALLBACK
sigwinch_APCProc( sigwinch_APCProc(_In_ ULONG_PTR dwParam)
_In_ ULONG_PTR dwParam {
) {
debug3("SIGTERM APCProc()"); debug3("SIGTERM APCProc()");
sigaddset(&pending_signals, W32_SIGWINCH); sigaddset(&pending_signals, W32_SIGWINCH);
} }
void void
queue_terminal_window_change_event() { queue_terminal_window_change_event()
{
QueueUserAPC(sigwinch_APCProc, main_thread, (ULONG_PTR)NULL); QueueUserAPC(sigwinch_APCProc, main_thread, (ULONG_PTR)NULL);
} }
void void
sw_init_signal_handler_table() { sw_init_signal_handler_table()
int i; {
SetConsoleCtrlHandler(native_sig_handler, TRUE); SetConsoleCtrlHandler(native_sig_handler, TRUE);
sigemptyset(&pending_signals); sigemptyset(&pending_signals);
/* this automatically sets all to W32_SIG_DFL (0)*/ /* this automatically sets all to W32_SIG_DFL (0)*/
memset(sig_handlers, 0, sizeof(sig_handlers)); 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 sighandler_t
w32_signal(int signum, sighandler_t handler) { w32_signal(int signum, sighandler_t handler)
{
sighandler_t prev; sighandler_t prev;
debug2("signal() sig:%d, handler:%p", signum, handler); debug2("signal() sig:%d, handler:%p", signum, handler);
if (signum >= W32_SIGMAX) { if (signum >= W32_SIGMAX) {
errno = EINVAL; errno = EINVAL;
return W32_SIG_ERR; return W32_SIG_ERR;
} }
prev = sig_handlers[signum]; prev = sig_handlers[signum];
sig_handlers[signum] = handler; sig_handlers[signum] = handler;
return prev; return prev;
} }
int int
w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) { w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
/* this is only used by sshd to block SIGCHLD while doing waitpid() */ /* 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*/ /* our implementation of waidpid() is never interrupted, so no need to implement this for now*/
debug3("sigprocmask() how:%d"); debug3("sigprocmask() how:%d");
@ -150,8 +150,9 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
int int
w32_raise(int sig) { w32_raise(int sig)
{
debug("raise sig:%d", sig); debug("raise sig:%d", sig);
if (sig == W32_SIGSEGV) if (sig == W32_SIGSEGV)
return raise(SIGSEGV); /* raise native exception handler*/ return raise(SIGSEGV); /* raise native exception handler*/
@ -170,7 +171,7 @@ w32_raise(int sig) {
/* if set to ignore, nothing to do */ /* if set to ignore, nothing to do */
if (sig_handlers[sig] == W32_SIG_IGN) if (sig_handlers[sig] == W32_SIG_IGN)
return 0; return 0;
/* execute any default handlers */ /* execute any default handlers */
switch (sig) { switch (sig) {
case W32_SIGCHLD: case W32_SIGCHLD:
@ -184,8 +185,9 @@ w32_raise(int sig) {
} }
/* processes pending signals, return -1 and errno=EINTR if any are processed*/ /* processes pending signals, return -1 and errno=EINTR if any are processed*/
static int static int
sw_process_pending_signals() { sw_process_pending_signals()
{
sigset_t pending_tmp = pending_signals; sigset_t pending_tmp = pending_signals;
BOOL sig_int = FALSE; /* has any signal actually interrupted */ BOOL sig_int = FALSE; /* has any signal actually interrupted */
@ -195,7 +197,7 @@ sw_process_pending_signals() {
/* check for expected signals*/ /* check for expected signals*/
for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++) for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++)
sigdelset(&pending_tmp, exp[i]); sigdelset(&pending_tmp, exp[i]);
if (pending_tmp) { if (pending_tmp) {
/* unexpected signals queued up */ /* unexpected signals queued up */
debug("process_signals() - ERROR unexpected signals in queue: %d", pending_tmp); debug("process_signals() - ERROR unexpected signals in queue: %d", pending_tmp);
errno = ENOTSUP; errno = ENOTSUP;
@ -219,7 +221,7 @@ sw_process_pending_signals() {
sigdelset(&pending_tmp, exp[i]); sigdelset(&pending_tmp, exp[i]);
} }
} }
/* by now all pending signals should have been taken care of*/ /* by now all pending signals should have been taken care of*/
if (pending_tmp) if (pending_tmp)
@ -235,17 +237,17 @@ sw_process_pending_signals() {
} }
/* /*
* Main wait routine used by all blocking calls. * Main wait routine used by all blocking calls.
* It wakes up on * It wakes up on
* - any signals (errno = EINTR ) * - any signals (errno = EINTR )
* - any of the supplied events set * - any of the supplied events set
* - any APCs caused by IO completions * - any APCs caused by IO completions
* - time out * - time out
* - Returns 0 on IO completion and timeout, -1 on rest * - 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 * to execute any scheduled APCs
*/ */
int int
wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds) wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
{ {
HANDLE all_events[MAXIMUM_WAIT_OBJECTS]; 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); debug3("wait() on %d events and %d children", num_events, live_children);
/* TODO - implement signal catching and handling */ /* TODO - implement signal catching and handling */
if (num_all_events) { if (num_all_events) {
DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE, DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE, milli_seconds, TRUE);
milli_seconds, TRUE);
if ((ret >= WAIT_OBJECT_0) && (ret <= WAIT_OBJECT_0 + num_all_events - 1)) { if ((ret >= WAIT_OBJECT_0) && (ret <= WAIT_OBJECT_0 + num_all_events - 1)) {
//woken up by event signalled /* woken up by event signalled
/* is this due to a child process going down*/ * is this due to a child process going down
*/
if (live_children && ((ret - WAIT_OBJECT_0) < live_children)) { if (live_children && ((ret - WAIT_OBJECT_0) < live_children)) {
sigaddset(&pending_signals, W32_SIGCHLD); sigaddset(&pending_signals, W32_SIGCHLD);
sw_child_to_zombie(ret - WAIT_OBJECT_0); 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*/ /* APC processed due to IO or signal*/
} } else if (ret == WAIT_TIMEOUT) {
else if (ret == WAIT_TIMEOUT) {
/* timed out */ /* timed out */
return 0; return 0;
} } else { /* some other error*/
/* some other error*/
else {
errno = EOTHER; errno = EOTHER;
debug("ERROR: unxpected wait end: %d", ret); debug("ERROR: unxpected wait end: %d", ret);
return -1; return -1;
} }
} } else {
else {
DWORD ret = SleepEx(milli_seconds, TRUE); DWORD ret = SleepEx(milli_seconds, TRUE);
if (ret == WAIT_IO_COMPLETION) { if (ret == WAIT_IO_COMPLETION) {
/* APC processed due to IO or signal*/ /* APC processed due to IO or signal*/
} } else if (ret == 0) {
else if (ret == 0) {
/* timed out */ /* timed out */
return 0; return 0;
} } else { /* some other error */
else { //some other error
errno = EOTHER; errno = EOTHER;
debug("ERROR: unxpected SleepEx error: %d", ret); debug("ERROR: unxpected SleepEx error: %d", ret);
return -1; return -1;
} }
} }
if (pending_signals) { if (pending_signals)
return sw_process_pending_signals(); return sw_process_pending_signals();
}
return 0; return 0;
} }
int int
sw_initialize() { sw_initialize()
{
memset(&children, 0, sizeof(children)); memset(&children, 0, sizeof(children));
sw_init_signal_handler_table(); sw_init_signal_handler_table();
if (sw_init_timer() != 0) if (sw_init_timer() != 0)

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -1,7 +1,33 @@
/* /*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com> * Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
* *
* Definitions for Win32 wrapper functions with POSIX like signatures * 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 #pragma once
@ -17,7 +43,7 @@ enum w32_io_type {
}; };
enum w32_io_sock_state { enum w32_io_sock_state {
SOCK_INITIALIZED = 0, SOCK_INITIALIZED = 0,
SOCK_LISTENING = 1, /*listen called on socket*/ SOCK_LISTENING = 1, /*listen called on socket*/
SOCK_ACCEPTED = 2, /*socket returned from accept()*/ SOCK_ACCEPTED = 2, /*socket returned from accept()*/
SOCK_CONNECTING = 3, /*connect called on socket, connect is in progress*/ 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 * to Win32 Handle
*/ */
struct w32_io { struct w32_io {
OVERLAPPED read_overlapped; OVERLAPPED read_overlapped;
OVERLAPPED write_overlapped; OVERLAPPED write_overlapped;
struct { struct {
/*internal read buffer*/ char *buf; /*internal read buffer*/
char *buf;
DWORD buf_size; DWORD buf_size;
/*bytes in internal buffer remaining to be read by application*/ DWORD remaining; /*bytes in internal buffer remaining to be read by application*/
DWORD remaining; DWORD completed; /*bytes in internal buffer already read by application*/
/*bytes in internal buffer already read by application*/
DWORD completed;
BOOL pending; /*waiting on a read operation to complete*/ BOOL pending; /*waiting on a read operation to complete*/
DWORD error; /*error reported on async read or accept completion*/ DWORD error; /*error reported on async read or accept completion*/
}read_details; }read_details;
struct { struct {
/*internal write buffer*/ char *buf; /*internal write buffer*/
char *buf;
DWORD buf_size; DWORD buf_size;
/*bytes in internal buffer remaining to be written to network*/ DWORD remaining; /*bytes in internal buffer remaining to be written to network*/
DWORD remaining; DWORD completed; /*bytes in internal buffer already written to network*/
/*bytes in internal buffer already written to network*/
DWORD completed;
BOOL pending; /*waiting on a write operation to complete*/ BOOL pending; /*waiting on a write operation to complete*/
DWORD error; /*error reported on async write or connect completion*/ DWORD error; /*error reported on async write or connect completion*/
}write_details; }write_details;
/*index at which this object is stored in fd_table*/ /*index at which this object is stored in fd_table*/
int table_index; int table_index;
enum w32_io_type type; /*hanldle type*/ enum w32_io_type type; /*hanldle type*/
DWORD fd_flags; /*fd flags from POSIX*/ DWORD fd_flags; /*fd flags from POSIX*/
DWORD fd_status_flags; /*fd status flags from POSIX*/ DWORD fd_status_flags; /*fd status flags from POSIX*/
/*underlying w32 handle*/ /*underlying w32 handle*/
union { union {
SOCKET sock; 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); 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_socket(int domain, int type, int protocol);
struct w32_io* socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen); 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, int socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval, int optlen);
const char* optval, int optlen); int socketio_getsockopt(struct w32_io* pio, int level, int optname, 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_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen);
int socketio_getpeername(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); 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 */ /* If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
/* #define O_EXCL 0x400 */ /* #define O_EXCL 0x400 */
/* #define O_BINARY 0x8000 //Gives raw data (while O_TEXT normalises line endings */ /* #define O_BINARY 0x8000 //Gives raw data (while O_TEXT normalises line endings */
// open modes /* open modes */
#ifndef S_IRUSR #ifndef S_IRUSR
#define S_IRUSR 00400 //user has read permission #define S_IRUSR 00400 /* user has read permission */
#endif // ! S_IRUSR #endif /* ! S_IRUSR */
#ifndef S_IWUSR #ifndef S_IWUSR
#define S_IWUSR 00200 //user has write permission #define S_IWUSR 00200 /* user has write permission */
#endif #endif
#ifndef S_IRGRP #ifndef S_IRGRP
#define S_IRGRP 00040 //group has read permission #define S_IRGRP 00040 /* group has read permission */
#endif #endif
#ifndef S_IROTH #ifndef S_IROTH
#define S_IROTH 00004 //others have read permission #define S_IROTH 00004 /* others have read permission */
#endif #endif

View File

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

View File

@ -1,19 +1,43 @@
// win32_dirent.c /*
// directory entry functions in Windows platform like Ubix/Linux * Copyright (c) 2016 Microsoft Corp.
// opendir(), readdir(), closedir(). * 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 <windows.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include "inc\utf.h"
#include "inc\utf.h"
#include "inc\dirent.h" #include "inc\dirent.h"
#include "inc\libgen.h" #include "inc\libgen.h"
#include "misc_internal.h" #include "misc_internal.h"
struct DIR_ { struct DIR_ {
intptr_t hFile; intptr_t hFile;
struct _wfinddata_t c_file; struct _wfinddata_t c_file;
@ -22,7 +46,8 @@ struct DIR_ {
/* Open a directory stream on NAME. /* Open a directory stream on NAME.
Return a DIR stream on the directory, or NULL if it could not be opened. */ 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; struct _wfinddata_t c_file;
intptr_t hFile; intptr_t hFile;
@ -30,17 +55,17 @@ DIR * opendir(const char *name)
wchar_t searchstr[PATH_MAX]; wchar_t searchstr[PATH_MAX];
wchar_t* wname = NULL; wchar_t* wname = NULL;
int needed; int needed;
if ((wname = utf8_to_utf16(sanitized_path(name))) == NULL) { if ((wname = utf8_to_utf16(sanitized_path(name))) == NULL) {
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }
// add *.* for Windows _findfirst() search pattern /* add *.* for Windows _findfirst() search pattern */
swprintf_s(searchstr, PATH_MAX, L"%s\\*.*", wname); swprintf_s(searchstr, PATH_MAX, L"%s\\*.*", wname);
free(wname); free(wname);
if ((hFile = _wfindfirst(searchstr, &c_file)) == -1L) if ((hFile = _wfindfirst(searchstr, &c_file)) == -1L)
return NULL; /* errno is set by _wfindfirst */ return NULL; /* errno is set by _wfindfirst */
else { else {
if ((pdir = malloc(sizeof(DIR))) == NULL) { if ((pdir = malloc(sizeof(DIR))) == NULL) {
@ -48,34 +73,36 @@ DIR * opendir(const char *name)
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }
memset(pdir, 0, sizeof(DIR)); memset(pdir, 0, sizeof(DIR));
pdir->hFile = hFile; pdir->hFile = hFile;
memcpy(&pdir->c_file, &c_file, sizeof(c_file)); memcpy(&pdir->c_file, &c_file, sizeof(c_file));
pdir->first = 1; pdir->first = 1;
return pdir ; return pdir;
} }
} }
/* Close the directory stream DIRP. /* Close the directory stream DIRP.
Return 0 if successful, -1 if not. */ Return 0 if successful, -1 if not. */
int closedir(DIR *dirp) int
closedir(DIR *dirp)
{ {
if ( dirp && (dirp->hFile) ) { if (dirp && (dirp->hFile)) {
_findclose( dirp->hFile ); _findclose(dirp->hFile);
dirp->hFile = 0; dirp->hFile = 0;
free (dirp); free(dirp);
} }
return 0; return 0;
} }
/* Read a directory entry from DIRP. /* Read a directory entry from DIRP.
Return a pointer to a `struct dirent' describing the entry, Return a pointer to a `struct dirent' describing the entry,
or NULL for EOF or error. The storage returned may be overwritten or NULL for EOF or error. The storage returned may be overwritten
by a later readdir call on the same DIR stream. */ by a later readdir call on the same DIR stream. */
struct dirent *readdir(void *avp) struct dirent *
readdir(void *avp)
{ {
static struct dirent pdirentry; static struct dirent pdirentry;
struct _wfinddata_t c_file; struct _wfinddata_t c_file;
@ -86,11 +113,10 @@ struct dirent *readdir(void *avp)
if (dirp->first) { if (dirp->first) {
memcpy(&c_file, &dirp->c_file, sizeof(c_file)); memcpy(&c_file, &dirp->c_file, sizeof(c_file));
dirp->first = 0; dirp->first = 0;
} } else if (_wfindnext(dirp->hFile, &c_file) != 0)
else if (_wfindnext(dirp->hFile, &c_file) != 0)
return NULL; 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; continue;
if ((tmp = utf16_to_utf8(c_file.name)) == NULL) { 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); strncpy(pdirentry.d_name, tmp, strlen(tmp) + 1);
free(tmp); free(tmp);
pdirentry.d_ino = 1; // a fictious one like UNIX to say it is nonzero pdirentry.d_ino = 1; /* a fictious one like UNIX to say it is nonzero */
return &pdirentry ; return &pdirentry;
} }
} }
// return last part of a path. The last path being a filename. /* return last part of a path. The last path being a filename */
char *basename(char *path) char *
basename(char *path)
{ {
char *pdest; char *pdest;
@ -115,10 +142,10 @@ char *basename(char *path)
return "."; return ".";
pdest = strrchr(path, '/'); pdest = strrchr(path, '/');
if (pdest) if (pdest)
return (pdest+1); return (pdest + 1);
pdest = strrchr(path, '\\'); pdest = strrchr(path, '\\');
if (pdest) if (pdest)
return (pdest+1); return (pdest + 1);
return path; // path does not have a slash return path; /* path does not have a slash */
} }

View File

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

View File

@ -33,6 +33,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#ifdef WINDOWS
#include <lm.h>
#endif
#include "xmalloc.h" #include "xmalloc.h"
#include "groupaccess.h" #include "groupaccess.h"
@ -49,6 +52,82 @@ static char **groups_byname;
int int
ga_init(const char *user, gid_t base) 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; gid_t *groups_bygid;
int i, j; int i, j;
struct group *gr; struct group *gr;
@ -70,7 +149,9 @@ ga_init(const char *user, gid_t base)
if ((gr = getgrgid(groups_bygid[i])) != NULL) if ((gr = getgrgid(groups_bygid[i])) != NULL)
groups_byname[j++] = xstrdup(gr->gr_name); groups_byname[j++] = xstrdup(gr->gr_name);
free(groups_bygid); free(groups_bygid);
#endif /* !WINDOWS */
return (ngroups = j); return (ngroups = j);
} }
/* /*

21
kex.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.c,v 1.127 2016/10/10 19:28:48 markus Exp $ */ /* $OpenBSD: kex.c,v 1.128 2017/02/03 23:01:19 djm Exp $ */
/* /*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * 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 * Assemble a list of algorithms from a default list and a string from a
* configuration file. The user-provided string may begin with '+' to * 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 int
kex_assemble_names(const char *def, char **list) kex_assemble_names(const char *def, char **list)
@ -222,14 +223,18 @@ kex_assemble_names(const char *def, char **list)
*list = strdup(def); *list = strdup(def);
return 0; return 0;
} }
if (**list != '+') { if (**list == '+') {
return 0; 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; return 0;
} }

31
match.c
View File

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

View File

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

6
misc.c
View File

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

View File

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

7
mux.c
View File

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

View File

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

View File

@ -211,7 +211,11 @@ tcsendbreak(int fd, int duration)
} }
#endif /* HAVE_TCSENDBREAK */ #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 mysig_t
mysignal(int sig, mysig_t act) mysignal(int sig, mysig_t act)
{ {

View File

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

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.243 2016/10/11 21:47:45 djm Exp $ */ /* $OpenBSD: packet.c,v 1.245 2017/02/03 23:03:33 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * 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; 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 int
ssh_packet_stop_discard(struct ssh *ssh) 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 */ /* Time-based rekeying */
if (state->rekey_interval != 0 && if (state->rekey_interval != 0 &&
state->rekey_time + state->rekey_interval <= monotime()) (int64_t)state->rekey_time + state->rekey_interval <= monotime())
return 1; return 1;
/* Always rekey when MAX_PACKETS sent in either direction */ /* 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)); 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. * Pretty-print connection-terminating errors and exit.
*/ */
void void
sshpkt_fatal(struct ssh *ssh, const char *tag, int r) 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) { switch (r) {
case SSH_ERR_CONN_CLOSED: case SSH_ERR_CONN_CLOSED:
logdie("Connection closed by %.200s port %d", logdie("Connection closed by %s", remote_id);
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
case SSH_ERR_CONN_TIMEOUT: case SSH_ERR_CONN_TIMEOUT:
logdie("Connection %s %.200s port %d timed out", logdie("Connection %s %s timed out",
ssh->state->server_side ? "from" : "to", ssh->state->server_side ? "from" : "to", remote_id);
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
case SSH_ERR_DISCONNECTED: case SSH_ERR_DISCONNECTED:
logdie("Disconnected from %.200s port %d", logdie("Disconnected from %s", remote_id);
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
case SSH_ERR_SYSTEM_ERROR: case SSH_ERR_SYSTEM_ERROR:
if (errno == ECONNRESET) if (errno == ECONNRESET)
logdie("Connection reset by %.200s port %d", logdie("Connection reset by %s", remote_id);
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
/* FALLTHROUGH */ /* FALLTHROUGH */
case SSH_ERR_NO_CIPHER_ALG_MATCH: case SSH_ERR_NO_CIPHER_ALG_MATCH:
case SSH_ERR_NO_MAC_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_KEX_ALG_MATCH:
case SSH_ERR_NO_HOSTKEY_ALG_MATCH: case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
if (ssh && ssh->kex && ssh->kex->failed_choice) { if (ssh && ssh->kex && ssh->kex->failed_choice) {
logdie("Unable to negotiate with %.200s port %d: %s. " logdie("Unable to negotiate with %s: %s. "
"Their offer: %s", ssh_remote_ipaddr(ssh), "Their offer: %s", remote_id, ssh_err(r),
ssh_remote_port(ssh), ssh_err(r),
ssh->kex->failed_choice); ssh->kex->failed_choice);
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
default: default:
logdie("%s%sConnection %s %.200s port %d: %s", logdie("%s%sConnection %s %s: %s",
tag != NULL ? tag : "", tag != NULL ? ": " : "", tag != NULL ? tag : "", tag != NULL ? ": " : "",
ssh->state->server_side ? "from" : "to", 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 void
ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...) ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
{ {
char buf[1024]; char buf[1024], remote_id[512];
va_list args; va_list args;
static int disconnecting = 0; static int disconnecting = 0;
int r; 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 * Format the message. Note that the caller must make sure the
* message is of limited size. * message is of limited size.
*/ */
fmt_connection_id(ssh, remote_id, sizeof(remote_id));
va_start(args, fmt); va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args); vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args); va_end(args);
/* Display the error locally */ /* 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 * Send the disconnect message to the other side, and wait
@ -2396,10 +2424,10 @@ ssh_packet_send_ignore(struct ssh *ssh, int nbytes)
} }
void 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, debug3("rekey after %llu bytes, %u seconds", (unsigned long long)bytes,
(int)seconds); (unsigned int)seconds);
ssh->state->rekey_limit = bytes; ssh->state->rekey_limit = bytes;
ssh->state->rekey_interval = seconds; ssh->state->rekey_interval = seconds;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -75,9 +75,11 @@ Class Machine
[string] $localAdminUserName = "localadmin" [string] $localAdminUserName = "localadmin"
[string] $localAdminPassword = "Bull_dog1" [string] $localAdminPassword = "Bull_dog1"
[string] $localAdminAuthorizedKeyPath [string] $localAdminAuthorizedKeyPath
[string] $sshdConfigFile = (join-path $PSScriptRoot "sshd_config")
[string] $backupFileName = (join-path $PSScriptRoot "sshd_backup")
[System.Security.SecureString] $password [System.Security.SecureString] $password
$preLatfpSetting $preLatfpSetting
$localUserprofilePath [string] $localUserprofilePath
#Members on client role #Members on client role
[string []] $clientPrivateKeyPaths [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) { [void] SetupServerRemoting([Protocol] $protocol) {
if ($this.Platform -eq [PlatformType]::Windows) 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) { [void] AddAdminUser($UserName, $password) {
if ( $this.Platform -eq [PlatformType]::Windows ) { if ( $this.Platform -eq [PlatformType]::Windows ) {
$a = Get-LocalUser -Name $UserName -ErrorAction Ignore $a = Get-LocalUser -Name $UserName -ErrorAction Ignore
@ -253,8 +346,7 @@ Class Machine
Add-LocalGroupMember -SID s-1-5-32-544 -Member $a Add-LocalGroupMember -SID s-1-5-32-544 -Member $a
} }
} else { } else {
#Todo add local user and add it to administrators group on linux #Todo add local user and add it to a administrators on linux
#Todo: get $localUserprofilePath
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tests.c,v 1.3 2016/09/21 17:03:54 djm Exp $ */ /* $OpenBSD: tests.c,v 1.4 2017/02/03 23:01:42 djm Exp $ */
/* /*
* Regress test for matching functions * 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); */ /* XXX negated ASSERT_INT_EQ(addr_match_list("127.0.0.1", "!127.0.0.2,10.0.0.1"), 1); */
TEST_DONE(); 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 * XXX TODO
* int match_host_and_ip(const char *, const char *, const char *); * int match_host_and_ip(const char *, const char *, const char *);

View File

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

View File

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

View File

@ -101,7 +101,6 @@ sshkey_file_tests(void)
sshkey_free(k1); sshkey_free(k1);
#endif #endif
#ifdef WITH_OPENSSL
TEST_START("parse RSA from private"); TEST_START("parse RSA from private");
buf = load_file("rsa_1"); buf = load_file("rsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); 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); ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
sshkey_free(k2); sshkey_free(k2);
TEST_DONE(); TEST_DONE();
TEST_START("parse RSA from new-format w/ passphrase"); TEST_START("parse RSA from new-format w/ passphrase");
buf = load_file("rsa_n_pw"); buf = load_file("rsa_n_pw");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
@ -146,7 +145,7 @@ sshkey_file_tests(void)
ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
sshkey_free(k2); sshkey_free(k2);
TEST_DONE(); TEST_DONE();
TEST_START("load RSA from public"); TEST_START("load RSA from public");
ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
NULL), 0); NULL), 0);
@ -283,7 +282,6 @@ sshkey_file_tests(void)
TEST_DONE(); TEST_DONE();
sshkey_free(k1); sshkey_free(k1);
#endif
#ifdef OPENSSL_HAS_ECC #ifdef OPENSSL_HAS_ECC
TEST_START("parse ECDSA from private"); TEST_START("parse ECDSA from private");

View File

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

View File

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

View File

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

View File

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

View File

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

289
session.c
View File

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

9
sftp.c
View File

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

View File

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

View File

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

View File

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

6
sshd.8
View File

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

29
sshd.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.480 2016/12/09 03:04:29 djm Exp $ */ /* $OpenBSD: sshd.c,v 1.482 2017/02/06 09:22:51 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * 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; u_int i;
int remote_major, remote_minor; int remote_major, remote_minor;
char *s, *newline = "\n"; char *s;
char buf[256]; /* Must not be larger than remote_version. */ char buf[256]; /* Must not be larger than remote_version. */
char remote_version[256]; /* Must be at least as big as buf. */ 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, PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
*options.version_addendum == '\0' ? "" : " ", *options.version_addendum == '\0' ? "" : " ",
options.version_addendum, newline); options.version_addendum);
/* Send our protocol version identification. */ /* Send our protocol version identification. */
if (atomicio(vwrite, sock_out, server_version_string, if (atomicio(vwrite, sock_out, server_version_string,
@ -1087,7 +1087,8 @@ server_listen(void)
#ifdef WINDOWS #ifdef WINDOWS
/* disable inheritance on listener socket */ /* disable inheritance on listener socket */
if (fcntl(listen_sock, F_SETFD, FD_CLOEXEC) != 0) { 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); close(listen_sock);
continue; 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* 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) if (path_utf8 == NULL)
fatal("Failed to alloc memory"); 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 || 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 || SetEnvironmentVariable("SSHD_STARTUPSOC", fd_handle) == FALSE
|| fcntl(startup_p[0], F_SETFD, FD_CLOEXEC) == -1) { || 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(*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]); close(startup_p[1]);
continue; continue;
} }
@ -2261,7 +2268,7 @@ do_ssh2_kex(void)
if (options.rekey_limit || options.rekey_interval) if (options.rekey_limit || options.rekey_interval)
packet_set_rekey_limits(options.rekey_limit, packet_set_rekey_limits(options.rekey_limit,
(time_t)options.rekey_interval); options.rekey_interval);
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
list_hostkey_types()); list_hostkey_types());

View File

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

View File

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

View File

@ -57,7 +57,10 @@ int ConUnInit(void);
struct termios term_settings; 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 * struct termios *
get_saved_tio(void) { get_saved_tio(void) {

3
utf8.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: utf8.c,v 1.3 2016/05/30 12:57:21 schwarze Exp $ */ /* $OpenBSD: utf8.c,v 1.4 2017/02/02 10:54:25 jsg Exp $ */
/* /*
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org> * 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; sz = strlen(src) + 1;
if ((dst = malloc(sz)) == NULL) { if ((dst = malloc(sz)) == NULL) {
free(src); free(src);
ret = -1;
goto fail; goto fail;
} }