mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-27 07:54:50 +02:00
Source snapshot from Powershell/openssh-portable:latestw_all
This commit is contained in:
parent
c1680168e4
commit
25a4ae6a3c
@ -19,3 +19,5 @@ fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits
|
|||||||
ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags
|
ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags
|
||||||
b92c93266d8234d493857bb822260dacf4366157 moduli-gen.sh tweak
|
b92c93266d8234d493857bb822260dacf4366157 moduli-gen.sh tweak
|
||||||
b25bf747544265b39af74fe0716dc8d9f5b63b95 Updated moduli
|
b25bf747544265b39af74fe0716dc8d9f5b63b95 Updated moduli
|
||||||
|
1bd41cba06a7752de4df304305a8153ebfb6b0ac rsa.[ch] already removed
|
||||||
|
e39b3902fe1d6c4a7ba6a3c58e072219f3c1e604 Makefile changes
|
||||||
|
@ -81,7 +81,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
|
|||||||
cipher-ctr.o cleanup.o \
|
cipher-ctr.o cleanup.o \
|
||||||
compat.o crc32.o fatal.o hostfile.o \
|
compat.o crc32.o fatal.o hostfile.o \
|
||||||
log.o match.o moduli.o nchan.o packet.o opacket.o \
|
log.o match.o moduli.o nchan.o packet.o opacket.o \
|
||||||
readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
|
readpass.o ttymodes.o xmalloc.o addrmatch.o \
|
||||||
atomicio.o key.o dispatch.o mac.o uidswap.o uuencode.o misc.o utf8.o \
|
atomicio.o key.o dispatch.o mac.o uidswap.o uuencode.o misc.o utf8.o \
|
||||||
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
|
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
|
||||||
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
|
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
|
||||||
@ -92,7 +92,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
|
|||||||
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
|
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
|
||||||
kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
|
kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
|
||||||
kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
|
kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
|
||||||
platform-pledge.o platform-tracing.o
|
platform-pledge.o platform-tracing.o platform-misc.o
|
||||||
|
|
||||||
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
||||||
sshconnect.o sshconnect2.o mux.o
|
sshconnect.o sshconnect2.o mux.o
|
||||||
|
8
README
8
README
@ -30,7 +30,8 @@ The PAM support is now more functional than the popular packages of
|
|||||||
commercial ssh-1.2.x. It checks "account" and "session" modules for
|
commercial ssh-1.2.x. It checks "account" and "session" modules for
|
||||||
all logins, not just when using password authentication.
|
all logins, not just when using password authentication.
|
||||||
|
|
||||||
OpenSSH depends on Zlib[3], OpenSSL[4] and optionally PAM[5].
|
OpenSSH depends on Zlib[3], OpenSSL[4], and optionally PAM[5] and
|
||||||
|
libedit[6]
|
||||||
|
|
||||||
There is now several mailing lists for this port of OpenSSH. Please
|
There is now several mailing lists for this port of OpenSSH. Please
|
||||||
refer to https://www.openssh.com/list.html for details on how to join.
|
refer to https://www.openssh.com/list.html for details on how to join.
|
||||||
@ -38,7 +39,7 @@ refer to https://www.openssh.com/list.html for details on how to join.
|
|||||||
Please send bug reports and patches to the mailing list
|
Please send bug reports and patches to the mailing list
|
||||||
openssh-unix-dev@mindrot.org. The list is open to posting by unsubscribed
|
openssh-unix-dev@mindrot.org. The list is open to posting by unsubscribed
|
||||||
users. Code contribution are welcomed, but please follow the OpenBSD
|
users. Code contribution are welcomed, but please follow the OpenBSD
|
||||||
style guidelines[6].
|
style guidelines[7].
|
||||||
|
|
||||||
Please refer to the INSTALL document for information on how to install
|
Please refer to the INSTALL document for information on how to install
|
||||||
OpenSSH on your system.
|
OpenSSH on your system.
|
||||||
@ -61,4 +62,5 @@ References -
|
|||||||
[5] http://www.openpam.org
|
[5] http://www.openpam.org
|
||||||
http://www.kernel.org/pub/linux/libs/pam/
|
http://www.kernel.org/pub/linux/libs/pam/
|
||||||
(PAM also is standard on Solaris and HP-UX 11)
|
(PAM also is standard on Solaris and HP-UX 11)
|
||||||
[6] http://man.openbsd.org/style.9
|
[6] http://thrysoee.dk/editline/ (portable version)
|
||||||
|
[7] http://man.openbsd.org/style.9
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: 0.0.19.0.{build}
|
version: 0.0.20.0.{build}
|
||||||
image: Visual Studio 2015
|
image: Visual Studio 2015
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
|
26
auth-pam.c
26
auth-pam.c
@ -926,6 +926,27 @@ finish_pam(void)
|
|||||||
sshpam_cleanup();
|
sshpam_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
expose_authinfo(const char *caller)
|
||||||
|
{
|
||||||
|
char *auth_info;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expose authentication information to PAM.
|
||||||
|
* The enviornment variable is versioned. Please increment the
|
||||||
|
* version suffix if the format of session_info changes.
|
||||||
|
*/
|
||||||
|
if (sshpam_authctxt->session_info == NULL)
|
||||||
|
auth_info = xstrdup("");
|
||||||
|
else if ((auth_info = sshbuf_dup_string(
|
||||||
|
sshpam_authctxt->session_info)) == NULL)
|
||||||
|
fatal("%s: sshbuf_dup_string failed", __func__);
|
||||||
|
|
||||||
|
debug2("%s: auth information in SSH_AUTH_INFO_0", caller);
|
||||||
|
do_pam_putenv("SSH_AUTH_INFO_0", auth_info);
|
||||||
|
free(auth_info);
|
||||||
|
}
|
||||||
|
|
||||||
u_int
|
u_int
|
||||||
do_pam_account(void)
|
do_pam_account(void)
|
||||||
{
|
{
|
||||||
@ -933,6 +954,8 @@ do_pam_account(void)
|
|||||||
if (sshpam_account_status != -1)
|
if (sshpam_account_status != -1)
|
||||||
return (sshpam_account_status);
|
return (sshpam_account_status);
|
||||||
|
|
||||||
|
expose_authinfo(__func__);
|
||||||
|
|
||||||
sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
|
sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
|
||||||
debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
|
debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
|
||||||
pam_strerror(sshpam_handle, sshpam_err));
|
pam_strerror(sshpam_handle, sshpam_err));
|
||||||
@ -1057,6 +1080,9 @@ void
|
|||||||
do_pam_session(void)
|
do_pam_session(void)
|
||||||
{
|
{
|
||||||
debug3("PAM: opening session");
|
debug3("PAM: opening session");
|
||||||
|
|
||||||
|
expose_authinfo(__func__);
|
||||||
|
|
||||||
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
|
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
|
||||||
(const void *)&store_conv);
|
(const void *)&store_conv);
|
||||||
if (sshpam_err != PAM_SUCCESS)
|
if (sshpam_err != PAM_SUCCESS)
|
||||||
|
99
auth.c
99
auth.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: auth.c,v 1.122 2017/06/24 06:34:38 djm Exp $ */
|
/* $OpenBSD: auth.c,v 1.123 2017/08/18 05:36:45 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -43,9 +43,6 @@
|
|||||||
#ifdef USE_SHADOW
|
#ifdef USE_SHADOW
|
||||||
#include <shadow.h>
|
#include <shadow.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBGEN_H
|
|
||||||
#include <libgen.h>
|
|
||||||
#endif
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -508,98 +505,6 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
|
|||||||
return host_status;
|
return host_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Check a given path for security. This is defined as all components
|
|
||||||
* of the path to the file must be owned by either the owner of
|
|
||||||
* of the file or root and no directories must be group or world writable.
|
|
||||||
*
|
|
||||||
* XXX Should any specific check be done for sym links ?
|
|
||||||
*
|
|
||||||
* Takes a file name, its stat information (preferably from fstat() to
|
|
||||||
* avoid races), the uid of the expected owner, their home directory and an
|
|
||||||
* error buffer plus max size as arguments.
|
|
||||||
*
|
|
||||||
* Returns 0 on success and -1 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
|
|
||||||
uid_t uid, char *err, size_t errlen)
|
|
||||||
{
|
|
||||||
char buf[PATH_MAX], homedir[PATH_MAX];
|
|
||||||
char *cp;
|
|
||||||
int comparehome = 0;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (realpath(name, buf) == NULL) {
|
|
||||||
snprintf(err, errlen, "realpath %s failed: %s", name,
|
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
|
|
||||||
comparehome = 1;
|
|
||||||
|
|
||||||
if (!S_ISREG(stp->st_mode)) {
|
|
||||||
snprintf(err, errlen, "%s is not a regular file", buf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
|
|
||||||
(stp->st_mode & 022) != 0) {
|
|
||||||
snprintf(err, errlen, "bad ownership or modes for file %s",
|
|
||||||
buf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for each component of the canonical path, walking upwards */
|
|
||||||
for (;;) {
|
|
||||||
if ((cp = dirname(buf)) == NULL) {
|
|
||||||
snprintf(err, errlen, "dirname() failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
strlcpy(buf, cp, sizeof(buf));
|
|
||||||
|
|
||||||
if (stat(buf, &st) < 0 ||
|
|
||||||
(!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
|
|
||||||
(st.st_mode & 022) != 0) {
|
|
||||||
snprintf(err, errlen,
|
|
||||||
"bad ownership or modes for directory %s", buf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If are past the homedir then we can stop */
|
|
||||||
if (comparehome && strcmp(homedir, buf) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dirname should always complete with a "/" path,
|
|
||||||
* but we can be paranoid and check for "." too
|
|
||||||
*/
|
|
||||||
if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Version of secure_path() that accepts an open file descriptor to
|
|
||||||
* avoid races.
|
|
||||||
*
|
|
||||||
* Returns 0 on success and -1 on failure
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
secure_filename(FILE *f, const char *file, struct passwd *pw,
|
|
||||||
char *err, size_t errlen)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
/* check the open file to avoid races */
|
|
||||||
if (fstat(fileno(f), &st) < 0) {
|
|
||||||
snprintf(err, errlen, "cannot stat file %s: %s",
|
|
||||||
file, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FILE *
|
static FILE *
|
||||||
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
|
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
|
||||||
int log_missing, char *file_type)
|
int log_missing, char *file_type)
|
||||||
@ -646,7 +551,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (strict_modes &&
|
if (strict_modes &&
|
||||||
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
|
safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
logit("Authentication refused: %s", line);
|
logit("Authentication refused: %s", line);
|
||||||
auth_debug_add("Ignored %s: %s", file_type, line);
|
auth_debug_add("Ignored %s: %s", file_type, line);
|
||||||
|
6
auth.h
6
auth.h
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: auth.h,v 1.92 2017/06/24 06:34:38 djm Exp $ */
|
/* $OpenBSD: auth.h,v 1.93 2017/08/18 05:36:45 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
@ -149,10 +149,6 @@ void auth2_record_info(Authctxt *authctxt, const char *, ...)
|
|||||||
__attribute__((__nonnull__ (2)));
|
__attribute__((__nonnull__ (2)));
|
||||||
void auth2_update_session_info(Authctxt *, const char *, const char *);
|
void auth2_update_session_info(Authctxt *, const char *, const char *);
|
||||||
|
|
||||||
struct stat;
|
|
||||||
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
|
|
||||||
char *, size_t);
|
|
||||||
|
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
|
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
|
||||||
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
|
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
|
||||||
|
308
auth2-pubkey.c
308
auth2-pubkey.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: auth2-pubkey.c,v 1.68 2017/06/24 06:34:38 djm Exp $ */
|
/* $OpenBSD: auth2-pubkey.c,v 1.70 2017/08/18 05:48:04 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -249,293 +248,6 @@ done:
|
|||||||
return authenticated;
|
return authenticated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Splits 's' into an argument vector. Handles quoted string and basic
|
|
||||||
* escape characters (\\, \", \'). Caller must free the argument vector
|
|
||||||
* and its members.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
split_argv(const char *s, int *argcp, char ***argvp)
|
|
||||||
{
|
|
||||||
int r = SSH_ERR_INTERNAL_ERROR;
|
|
||||||
int argc = 0, quote, i, j;
|
|
||||||
char *arg, **argv = xcalloc(1, sizeof(*argv));
|
|
||||||
|
|
||||||
*argvp = NULL;
|
|
||||||
*argcp = 0;
|
|
||||||
|
|
||||||
for (i = 0; s[i] != '\0'; i++) {
|
|
||||||
/* Skip leading whitespace */
|
|
||||||
if (s[i] == ' ' || s[i] == '\t')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Start of a token */
|
|
||||||
quote = 0;
|
|
||||||
if (s[i] == '\\' &&
|
|
||||||
(s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\'))
|
|
||||||
i++;
|
|
||||||
else if (s[i] == '\'' || s[i] == '"')
|
|
||||||
quote = s[i++];
|
|
||||||
|
|
||||||
argv = xreallocarray(argv, (argc + 2), sizeof(*argv));
|
|
||||||
arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1);
|
|
||||||
argv[argc] = NULL;
|
|
||||||
|
|
||||||
/* Copy the token in, removing escapes */
|
|
||||||
for (j = 0; s[i] != '\0'; i++) {
|
|
||||||
if (s[i] == '\\') {
|
|
||||||
if (s[i + 1] == '\'' ||
|
|
||||||
s[i + 1] == '\"' ||
|
|
||||||
s[i + 1] == '\\') {
|
|
||||||
i++; /* Skip '\' */
|
|
||||||
arg[j++] = s[i];
|
|
||||||
} else {
|
|
||||||
/* Unrecognised escape */
|
|
||||||
arg[j++] = s[i];
|
|
||||||
}
|
|
||||||
} else if (quote == 0 && (s[i] == ' ' || s[i] == '\t'))
|
|
||||||
break; /* done */
|
|
||||||
else if (quote != 0 && s[i] == quote)
|
|
||||||
break; /* done */
|
|
||||||
else
|
|
||||||
arg[j++] = s[i];
|
|
||||||
}
|
|
||||||
if (s[i] == '\0') {
|
|
||||||
if (quote != 0) {
|
|
||||||
/* Ran out of string looking for close quote */
|
|
||||||
r = SSH_ERR_INVALID_FORMAT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Success */
|
|
||||||
*argcp = argc;
|
|
||||||
*argvp = argv;
|
|
||||||
argc = 0;
|
|
||||||
argv = NULL;
|
|
||||||
r = 0;
|
|
||||||
out:
|
|
||||||
if (argc != 0 && argv != NULL) {
|
|
||||||
for (i = 0; i < argc; i++)
|
|
||||||
free(argv[i]);
|
|
||||||
free(argv);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reassemble an argument vector into a string, quoting and escaping as
|
|
||||||
* necessary. Caller must free returned string.
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
assemble_argv(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i, j, ws, r;
|
|
||||||
char c, *ret;
|
|
||||||
struct sshbuf *buf, *arg;
|
|
||||||
|
|
||||||
if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
|
|
||||||
fatal("%s: sshbuf_new failed", __func__);
|
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
ws = 0;
|
|
||||||
sshbuf_reset(arg);
|
|
||||||
for (j = 0; argv[i][j] != '\0'; j++) {
|
|
||||||
r = 0;
|
|
||||||
c = argv[i][j];
|
|
||||||
switch (c) {
|
|
||||||
case ' ':
|
|
||||||
case '\t':
|
|
||||||
ws = 1;
|
|
||||||
r = sshbuf_put_u8(arg, c);
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
case '\'':
|
|
||||||
case '"':
|
|
||||||
if ((r = sshbuf_put_u8(arg, '\\')) != 0)
|
|
||||||
break;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
default:
|
|
||||||
r = sshbuf_put_u8(arg, c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (r != 0)
|
|
||||||
fatal("%s: sshbuf_put_u8: %s",
|
|
||||||
__func__, ssh_err(r));
|
|
||||||
}
|
|
||||||
if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
|
|
||||||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
|
|
||||||
(r = sshbuf_putb(buf, arg)) != 0 ||
|
|
||||||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
|
|
||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
}
|
|
||||||
if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
|
|
||||||
fatal("%s: malloc failed", __func__);
|
|
||||||
memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
|
|
||||||
ret[sshbuf_len(buf)] = '\0';
|
|
||||||
sshbuf_free(buf);
|
|
||||||
sshbuf_free(arg);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Runs command in a subprocess. Returns pid on success and a FILE* to the
|
|
||||||
* subprocess' stdout or 0 on failure.
|
|
||||||
* NB. "command" is only used for logging.
|
|
||||||
*/
|
|
||||||
static pid_t
|
|
||||||
subprocess(const char *tag, struct passwd *pw, const char *command,
|
|
||||||
int ac, char **av, FILE **child)
|
|
||||||
{
|
|
||||||
#ifdef WINDOWS
|
|
||||||
logit("AuthorizedPrincipalsCommand and AuthorizedKeysCommand are not supported in Windows yet");
|
|
||||||
return 0;
|
|
||||||
#else /* !WINDOWS */
|
|
||||||
FILE *f;
|
|
||||||
struct stat st;
|
|
||||||
int devnull, p[2], i;
|
|
||||||
pid_t pid;
|
|
||||||
char *cp, errmsg[512];
|
|
||||||
u_int envsize;
|
|
||||||
char **child_env;
|
|
||||||
|
|
||||||
*child = NULL;
|
|
||||||
|
|
||||||
debug3("%s: %s command \"%s\" running as %s", __func__,
|
|
||||||
tag, command, pw->pw_name);
|
|
||||||
|
|
||||||
/* Verify the path exists and is safe-ish to execute */
|
|
||||||
if (*av[0] != '/') {
|
|
||||||
error("%s path is not absolute", tag);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
temporarily_use_uid(pw);
|
|
||||||
if (stat(av[0], &st) < 0) {
|
|
||||||
error("Could not stat %s \"%s\": %s", tag,
|
|
||||||
av[0], strerror(errno));
|
|
||||||
restore_uid();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (auth_secure_path(av[0], &st, NULL, 0,
|
|
||||||
errmsg, sizeof(errmsg)) != 0) {
|
|
||||||
error("Unsafe %s \"%s\": %s", tag, av[0], errmsg);
|
|
||||||
restore_uid();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Run the command; stderr is left in place, stdout is the
|
|
||||||
* authorized_keys output.
|
|
||||||
*/
|
|
||||||
if (pipe(p) != 0) {
|
|
||||||
error("%s: pipe: %s", tag, strerror(errno));
|
|
||||||
restore_uid();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't want to call this in the child, where it can fatal() and
|
|
||||||
* run cleanup_exit() code.
|
|
||||||
*/
|
|
||||||
restore_uid();
|
|
||||||
|
|
||||||
switch ((pid = fork())) {
|
|
||||||
case -1: /* error */
|
|
||||||
error("%s: fork: %s", tag, strerror(errno));
|
|
||||||
close(p[0]);
|
|
||||||
close(p[1]);
|
|
||||||
return 0;
|
|
||||||
case 0: /* child */
|
|
||||||
/* Prepare a minimal environment for the child. */
|
|
||||||
envsize = 5;
|
|
||||||
child_env = xcalloc(sizeof(*child_env), envsize);
|
|
||||||
child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH);
|
|
||||||
child_set_env(&child_env, &envsize, "USER", pw->pw_name);
|
|
||||||
child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name);
|
|
||||||
child_set_env(&child_env, &envsize, "HOME", pw->pw_dir);
|
|
||||||
if ((cp = getenv("LANG")) != NULL)
|
|
||||||
child_set_env(&child_env, &envsize, "LANG", cp);
|
|
||||||
|
|
||||||
for (i = 0; i < NSIG; i++)
|
|
||||||
signal(i, SIG_DFL);
|
|
||||||
|
|
||||||
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
|
|
||||||
error("%s: open %s: %s", tag, _PATH_DEVNULL,
|
|
||||||
strerror(errno));
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
/* Keep stderr around a while longer to catch errors */
|
|
||||||
if (dup2(devnull, STDIN_FILENO) == -1 ||
|
|
||||||
dup2(p[1], STDOUT_FILENO) == -1) {
|
|
||||||
error("%s: dup2: %s", tag, strerror(errno));
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
closefrom(STDERR_FILENO + 1);
|
|
||||||
|
|
||||||
/* Don't use permanently_set_uid() here to avoid fatal() */
|
|
||||||
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
|
|
||||||
error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
|
|
||||||
strerror(errno));
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
|
|
||||||
error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid,
|
|
||||||
strerror(errno));
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
/* stdin is pointed to /dev/null at this point */
|
|
||||||
if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
|
|
||||||
error("%s: dup2: %s", tag, strerror(errno));
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
execve(av[0], av, child_env);
|
|
||||||
error("%s exec \"%s\": %s", tag, command, strerror(errno));
|
|
||||||
_exit(127);
|
|
||||||
default: /* parent */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(p[1]);
|
|
||||||
if ((f = fdopen(p[0], "r")) == NULL) {
|
|
||||||
error("%s: fdopen: %s", tag, strerror(errno));
|
|
||||||
close(p[0]);
|
|
||||||
/* Don't leave zombie child */
|
|
||||||
kill(pid, SIGTERM);
|
|
||||||
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Success */
|
|
||||||
debug3("%s: %s pid %ld", __func__, tag, (long)pid);
|
|
||||||
*child = f;
|
|
||||||
return pid;
|
|
||||||
#endif /* !WINDOWS */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns 0 if pid exited cleanly, non-zero otherwise */
|
|
||||||
static int
|
|
||||||
exited_cleanly(pid_t pid, const char *tag, const char *cmd)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
while (waitpid(pid, &status, 0) == -1) {
|
|
||||||
if (errno != EINTR) {
|
|
||||||
error("%s: waitpid: %s", tag, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (WIFSIGNALED(status)) {
|
|
||||||
error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status));
|
|
||||||
return -1;
|
|
||||||
} else if (WEXITSTATUS(status) != 0) {
|
|
||||||
error("%s %s failed, status %d", tag, cmd, WEXITSTATUS(status));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
match_principals_option(const char *principal_list, struct sshkey_cert *cert)
|
match_principals_option(const char *principal_list, struct sshkey_cert *cert)
|
||||||
{
|
{
|
||||||
@ -668,7 +380,7 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Turn the command into an argument vector */
|
/* Turn the command into an argument vector */
|
||||||
if (split_argv(options.authorized_principals_command, &ac, &av) != 0) {
|
if (argv_split(options.authorized_principals_command, &ac, &av) != 0) {
|
||||||
error("AuthorizedPrincipalsCommand \"%s\" contains "
|
error("AuthorizedPrincipalsCommand \"%s\" contains "
|
||||||
"invalid quotes", command);
|
"invalid quotes", command);
|
||||||
goto out;
|
goto out;
|
||||||
@ -717,10 +429,11 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
|
|||||||
av[i] = tmp;
|
av[i] = tmp;
|
||||||
}
|
}
|
||||||
/* Prepare a printable command for logs, etc. */
|
/* Prepare a printable command for logs, etc. */
|
||||||
command = assemble_argv(ac, av);
|
command = argv_assemble(ac, av);
|
||||||
|
|
||||||
if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command,
|
if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command,
|
||||||
ac, av, &f)) == 0)
|
ac, av, &f,
|
||||||
|
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
uid_swapped = 1;
|
uid_swapped = 1;
|
||||||
@ -731,7 +444,7 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
f = NULL;
|
f = NULL;
|
||||||
|
|
||||||
if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0)
|
if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command, 0) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Read completed successfully */
|
/* Read completed successfully */
|
||||||
@ -1008,7 +721,7 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Turn the command into an argument vector */
|
/* Turn the command into an argument vector */
|
||||||
if (split_argv(options.authorized_keys_command, &ac, &av) != 0) {
|
if (argv_split(options.authorized_keys_command, &ac, &av) != 0) {
|
||||||
error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
|
error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
|
||||||
command);
|
command);
|
||||||
goto out;
|
goto out;
|
||||||
@ -1032,7 +745,7 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
|
|||||||
av[i] = tmp;
|
av[i] = tmp;
|
||||||
}
|
}
|
||||||
/* Prepare a printable command for logs, etc. */
|
/* Prepare a printable command for logs, etc. */
|
||||||
command = assemble_argv(ac, av);
|
command = argv_assemble(ac, av);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If AuthorizedKeysCommand was run without arguments
|
* If AuthorizedKeysCommand was run without arguments
|
||||||
@ -1049,7 +762,8 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((pid = subprocess("AuthorizedKeysCommand", pw, command,
|
if ((pid = subprocess("AuthorizedKeysCommand", pw, command,
|
||||||
ac, av, &f)) == 0)
|
ac, av, &f,
|
||||||
|
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
uid_swapped = 1;
|
uid_swapped = 1;
|
||||||
@ -1060,7 +774,7 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
f = NULL;
|
f = NULL;
|
||||||
|
|
||||||
if (exited_cleanly(pid, "AuthorizedKeysCommand", command) != 0)
|
if (exited_cleanly(pid, "AuthorizedKeysCommand", command, 0) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Read completed successfully */
|
/* Read completed successfully */
|
||||||
|
3
authfd.c
3
authfd.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: authfd.c,v 1.104 2017/06/28 01:09:22 djm Exp $ */
|
/* $OpenBSD: authfd.c,v 1.105 2017/07/01 13:50:45 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
|
||||||
@ -51,7 +51,6 @@
|
|||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "rsa.h"
|
|
||||||
#include "sshbuf.h"
|
#include "sshbuf.h"
|
||||||
#include "sshkey.h"
|
#include "sshkey.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: authfile.c,v 1.126 2017/05/31 09:15:42 deraadt Exp $ */
|
/* $OpenBSD: authfile.c,v 1.127 2017/07/01 13:50:45 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -42,7 +42,6 @@
|
|||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
#include "rsa.h"
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "atomicio.h"
|
#include "atomicio.h"
|
||||||
#include "sshkey.h"
|
#include "sshkey.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: clientloop.c,v 1.300 2017/06/23 07:24:48 mestre Exp $ */
|
/* $OpenBSD: clientloop.c,v 1.301 2017/07/14 03:18:21 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
|
||||||
@ -1422,8 +1422,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
|||||||
exit_status = 0;
|
exit_status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (received_signal)
|
if (received_signal) {
|
||||||
fatal("Killed by signal %d.", (int) received_signal);
|
verbose("Killed by signal %d.", (int) received_signal);
|
||||||
|
cleanup_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In interactive mode (with pseudo tty) display a message indicating
|
* In interactive mode (with pseudo tty) display a message indicating
|
||||||
|
11
compat.c
11
compat.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: compat.c,v 1.103 2017/04/30 23:13:25 djm Exp $ */
|
/* $OpenBSD: compat.c,v 1.104 2017/07/25 09:22:25 dtucker Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
|
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -177,9 +177,12 @@ compat_datafellows(const char *version)
|
|||||||
"TTSSH/2.72*", SSH_BUG_HOSTKEYS },
|
"TTSSH/2.72*", SSH_BUG_HOSTKEYS },
|
||||||
{ "WinSCP_release_4*,"
|
{ "WinSCP_release_4*,"
|
||||||
"WinSCP_release_5.0*,"
|
"WinSCP_release_5.0*,"
|
||||||
"WinSCP_release_5.1*,"
|
"WinSCP_release_5.1,"
|
||||||
"WinSCP_release_5.5*,"
|
"WinSCP_release_5.1.*,"
|
||||||
"WinSCP_release_5.6*,"
|
"WinSCP_release_5.5,"
|
||||||
|
"WinSCP_release_5.5.*,"
|
||||||
|
"WinSCP_release_5.6,"
|
||||||
|
"WinSCP_release_5.6.*,"
|
||||||
"WinSCP_release_5.7,"
|
"WinSCP_release_5.7,"
|
||||||
"WinSCP_release_5.7.1,"
|
"WinSCP_release_5.7.1,"
|
||||||
"WinSCP_release_5.7.2,"
|
"WinSCP_release_5.7.2,"
|
||||||
|
@ -980,6 +980,7 @@ mips-sony-bsd|mips-sony-newsos4)
|
|||||||
AC_DEFINE([BROKEN_SETREUID])
|
AC_DEFINE([BROKEN_SETREUID])
|
||||||
AC_DEFINE([BROKEN_SETREGID])
|
AC_DEFINE([BROKEN_SETREGID])
|
||||||
AC_DEFINE([PASSWD_NEEDS_USERNAME])
|
AC_DEFINE([PASSWD_NEEDS_USERNAME])
|
||||||
|
AC_DEFINE([BROKEN_TCGETATTR_ICANON])
|
||||||
TEST_SHELL=$SHELL # let configure find us a capable shell
|
TEST_SHELL=$SHELL # let configure find us a capable shell
|
||||||
case "$host" in
|
case "$host" in
|
||||||
*-*-sysv5SCO_SV*) # SCO OpenServer 6.x
|
*-*-sysv5SCO_SV*) # SCO OpenServer 6.x
|
||||||
|
@ -168,7 +168,9 @@ function Repair-AuthorizedKeyPermission
|
|||||||
$userProfilePath = $properties.ProfileImagePath
|
$userProfilePath = $properties.ProfileImagePath
|
||||||
}
|
}
|
||||||
$userProfilePath = $userProfilePath.Replace("\", "\\")
|
$userProfilePath = $userProfilePath.Replace("\", "\\")
|
||||||
$fullPath -match "^$userProfilePath[\\|\W|\w]+authorized_keys$"
|
if ( $properties.PSChildName -notmatch '\.bak$') {
|
||||||
|
$fullPath -match "^$userProfilePath\\[\\|\W|\w]+authorized_keys$"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if($profileItem)
|
if($profileItem)
|
||||||
{
|
{
|
||||||
|
@ -248,9 +248,6 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)progressmeter.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)progressmeter.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)readpass.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)readpass.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)rijndael.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)rijndael.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)rsa.c">
|
|
||||||
<ExcludedFromBuild Condition="$(UseOpenSSL)==false">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)sc25519.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)sc25519.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)smult_curve25519_ref.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)smult_curve25519_ref.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)ssh-dss.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)ssh-dss.c">
|
||||||
@ -275,6 +272,7 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)uuencode.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)uuencode.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)verify.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)verify.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)xmalloc.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)xmalloc.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)platform-misc.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)platform-pledge.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)platform-pledge.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)platform-tracing.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)platform-tracing.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)platform.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)platform.c" />
|
||||||
|
@ -14,17 +14,14 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)canohost.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)canohost.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)chacha.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)chacha.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)channels.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)channels.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)cipher-3des1.c" />
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)cipher-aes.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)cipher-aes.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)cipher-aesctr.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)cipher-aesctr.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)cipher-bf1.c" />
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)cipher-chachapoly.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)cipher-chachapoly.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)cipher-ctr.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)cipher-ctr.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)cipher.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)cipher.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)cleanup.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)cleanup.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)compat.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)compat.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)crc32.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)crc32.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)deattack.c" />
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)dh.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)dh.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)digest-libc.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)digest-libc.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)dispatch.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)dispatch.c" />
|
||||||
@ -60,7 +57,6 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)opacket.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)opacket.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)packet.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)packet.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)poly1305.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)poly1305.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)rsa.c" />
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)sc25519.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)sc25519.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)smult_curve25519_ref.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)smult_curve25519_ref.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)ssh-dss.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)ssh-dss.c" />
|
||||||
@ -83,7 +79,15 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\ttymodes_windows.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\ttymodes_windows.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\w32-sshfileperm.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\w32-sshfileperm.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)digest-openssl.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)digest-openssl.c" />
|
||||||
<ClCompile Include="..\..\..\kexgexs.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)match.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)misc.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)moduli.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)progressmeter.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)readpass.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)rijndael.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)uuencode.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)verify.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)xmalloc.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)addrmatch.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)addrmatch.c">
|
||||||
@ -245,15 +249,6 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)mac.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)mac.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)match.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)misc.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)moduli.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)monitor_fdpass.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)monitor_fdpass.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -272,15 +267,6 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)poly1305.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)poly1305.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)progressmeter.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)readpass.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)rijndael.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)rsa.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)rsa.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -329,15 +315,6 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)umac.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)umac.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)uuencode.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)verify.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)xmalloc.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)platform-pledge.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)platform-pledge.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -361,11 +338,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="$(OpenSSH-Src-Path)crypto-wrap.h">
|
<ClInclude Include="$(OpenSSH-Src-Path)crypto-wrap.h" />
|
||||||
<Filter>Header Files</Filter>
|
<ClInclude Include="$(OpenSSH-Src-Path)sshfileperm.h" />
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(OpenSSH-Src-Path)sshfileperm.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Binary file not shown.
@ -1,6 +1,16 @@
|
|||||||
#ifndef COMPAT_GRP_H
|
#ifndef COMPAT_GRP_H
|
||||||
#define COMPAT_GRP_H 1
|
#define COMPAT_GRP_H 1
|
||||||
|
#include <Windows.h>
|
||||||
|
#include "sys/types.h"
|
||||||
|
|
||||||
char *group_from_gid(gid_t gid, int nogroup);
|
typedef enum {
|
||||||
|
LOCAL_GROUP = 0,
|
||||||
|
DOMAIN_GROUP = 1,
|
||||||
|
GLOBAL_UNIVERSAL_GROUP = 2
|
||||||
|
} group_type;
|
||||||
|
|
||||||
|
char ** getusergroups(const char *user, int *numgroups);
|
||||||
|
void populate_user_groups(char **group_name, int *group_index, DWORD groupsread, DWORD totalgroups, LPBYTE buf, group_type groupType);
|
||||||
|
void print_user_groups(const char *user, char **user_groups, int num_user_groups);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -91,4 +91,8 @@ int w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
|
|||||||
#define SIG_IGN W32_SIG_IGN
|
#define SIG_IGN W32_SIG_IGN
|
||||||
#define SIG_ERR W32_SIG_ERR
|
#define SIG_ERR W32_SIG_ERR
|
||||||
|
|
||||||
|
/* TOTO - implement http://www.manpagez.com/man/3/sys_siglist/*/
|
||||||
|
#undef NSIG
|
||||||
|
#define NSIG 0
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -33,6 +33,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <Shlwapi.h>
|
#include <Shlwapi.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
#include <LM.h>
|
||||||
|
|
||||||
#include "inc\unistd.h"
|
#include "inc\unistd.h"
|
||||||
#include "inc\sys\stat.h"
|
#include "inc\sys\stat.h"
|
||||||
@ -49,6 +50,7 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "w32fd.h"
|
#include "w32fd.h"
|
||||||
#include "inc\string.h"
|
#include "inc\string.h"
|
||||||
|
#include "inc\grp.h"
|
||||||
|
|
||||||
static char* s_programdir = NULL;
|
static char* s_programdir = NULL;
|
||||||
|
|
||||||
@ -1046,8 +1048,259 @@ readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags)
|
|||||||
return outBuf;
|
return outBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void invalid_parameter_handler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
|
void
|
||||||
|
invalid_parameter_handler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
|
||||||
{
|
{
|
||||||
debug3("Invalid parameter in function: %ls. File: %ls Line: %d.", function, file, line);
|
debug3("Invalid parameter in function: %ls. File: %ls Line: %d.", function, file, line);
|
||||||
debug3("Expression: %s", expression);
|
debug3("Expression: %s", expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_machine_domain_name(wchar_t *domain, int size)
|
||||||
|
{
|
||||||
|
LPWKSTA_INFO_100 pBuf = NULL;
|
||||||
|
NET_API_STATUS nStatus;
|
||||||
|
LPWSTR pszServerName = NULL;
|
||||||
|
|
||||||
|
nStatus = NetWkstaGetInfo(pszServerName, 100, (LPBYTE *)&pBuf);
|
||||||
|
if (nStatus != NERR_Success) {
|
||||||
|
error("Unable to fetch the machine domain, error:%d\n", nStatus);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug3("Machine domain:%ls", pBuf->wki100_langroup);
|
||||||
|
wcscpy_s(domain, size, pBuf->wki100_langroup);
|
||||||
|
|
||||||
|
if (pBuf != NULL)
|
||||||
|
NetApiBufferFree(pBuf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method will fetch all the groups (listed below) even if the user is indirectly a member.
|
||||||
|
* - Local machine groups
|
||||||
|
* - Domain groups
|
||||||
|
* - global group
|
||||||
|
* - universal groups
|
||||||
|
*/
|
||||||
|
char **
|
||||||
|
getusergroups(const char *user, int *ngroups)
|
||||||
|
{
|
||||||
|
LPGROUP_USERS_INFO_0 local_groups = NULL;
|
||||||
|
LPGROUP_USERS_INFO_0 domain_groups = NULL;
|
||||||
|
LPGROUP_USERS_INFO_0 global_universal_groups = NULL;
|
||||||
|
DWORD num_local_groups_read = 0;
|
||||||
|
DWORD total_local_groups = 0;
|
||||||
|
DWORD num_domain_groups_read = 0;
|
||||||
|
DWORD total_domain_groups = 0;
|
||||||
|
DWORD num_global_universal_groups_read = 0;
|
||||||
|
DWORD total_global_universal_groups = 0;
|
||||||
|
|
||||||
|
DWORD flags = LG_INCLUDE_INDIRECT;
|
||||||
|
NET_API_STATUS nStatus;
|
||||||
|
wchar_t *user_name_utf16 = NULL;
|
||||||
|
char *user_domain = NULL;
|
||||||
|
LPWSTR dc_name_utf16 = NULL;
|
||||||
|
char **user_groups = NULL;
|
||||||
|
int num_user_groups = 0;
|
||||||
|
wchar_t machine_domain_name_utf16[DNLEN + 1] = { 0 };
|
||||||
|
wchar_t local_user_fmt_utf16[UNLEN + DNLEN + 2] = { 0 };
|
||||||
|
size_t local_user_fmt_len = UNLEN + DNLEN + 2;
|
||||||
|
char *user_name = NULL;
|
||||||
|
|
||||||
|
user_name = malloc(strlen(user)+1);
|
||||||
|
if(!user_name) {
|
||||||
|
error("failed to allocate memory!");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(user_name, user, strlen(user)+1);
|
||||||
|
|
||||||
|
if (user_domain = strchr(user_name, '@')) {
|
||||||
|
char *t = user_domain;
|
||||||
|
user_domain++;
|
||||||
|
*t='\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
user_name_utf16 = utf8_to_utf16(user_name);
|
||||||
|
if (!user_name_utf16) {
|
||||||
|
error("utf8_to_utf16 failed! for %s", user_name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch groups on the Local machine */
|
||||||
|
if(get_machine_domain_name(machine_domain_name_utf16, DNLEN+1)) {
|
||||||
|
if (machine_domain_name_utf16) {
|
||||||
|
if(!machine_domain_name)
|
||||||
|
machine_domain_name = utf16_to_utf8(machine_domain_name_utf16);
|
||||||
|
|
||||||
|
if (user_domain) {
|
||||||
|
wcscpy_s(local_user_fmt_utf16, local_user_fmt_len, machine_domain_name_utf16);
|
||||||
|
wcscat_s(local_user_fmt_utf16, local_user_fmt_len, L"\\");
|
||||||
|
}
|
||||||
|
|
||||||
|
wcscat_s(local_user_fmt_utf16, local_user_fmt_len, user_name_utf16);
|
||||||
|
nStatus = NetUserGetLocalGroups(NULL,
|
||||||
|
local_user_fmt_utf16,
|
||||||
|
0,
|
||||||
|
flags,
|
||||||
|
(LPBYTE *)&local_groups,
|
||||||
|
MAX_PREFERRED_LENGTH,
|
||||||
|
&num_local_groups_read,
|
||||||
|
&total_local_groups);
|
||||||
|
|
||||||
|
if (NERR_Success != nStatus)
|
||||||
|
error("Failed to get local groups on this machine, error: %d\n", nStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user_domain) {
|
||||||
|
/* Fetch Domain groups */
|
||||||
|
nStatus = NetGetDCName(NULL, machine_domain_name_utf16, (LPBYTE *)&dc_name_utf16);
|
||||||
|
if (NERR_Success == nStatus) {
|
||||||
|
debug3("domain controller name: %ls", dc_name_utf16);
|
||||||
|
|
||||||
|
nStatus = NetUserGetLocalGroups(dc_name_utf16,
|
||||||
|
user_name_utf16,
|
||||||
|
0,
|
||||||
|
flags,
|
||||||
|
(LPBYTE *)&domain_groups,
|
||||||
|
MAX_PREFERRED_LENGTH,
|
||||||
|
&num_domain_groups_read,
|
||||||
|
&total_domain_groups);
|
||||||
|
|
||||||
|
if (NERR_Success != nStatus)
|
||||||
|
error("Failed to get domain groups from DC:%s error: %d\n", dc_name_utf16, nStatus);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error("Failed to get the domain controller name, error: %d\n", nStatus);
|
||||||
|
|
||||||
|
/* Fetch global, universal groups */
|
||||||
|
nStatus = NetUserGetGroups(dc_name_utf16,
|
||||||
|
user_name_utf16,
|
||||||
|
0,
|
||||||
|
(LPBYTE *)&global_universal_groups,
|
||||||
|
MAX_PREFERRED_LENGTH,
|
||||||
|
&num_global_universal_groups_read,
|
||||||
|
&total_global_universal_groups);
|
||||||
|
|
||||||
|
if (NERR_Success != nStatus)
|
||||||
|
error("Failed to get global,universal groups from DC:%ls error: %d\n", dc_name_utf16, nStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
int total_user_groups = num_local_groups_read + num_domain_groups_read + num_global_universal_groups_read;
|
||||||
|
|
||||||
|
/* populate the output */
|
||||||
|
user_groups = malloc(total_user_groups * sizeof(*user_groups));
|
||||||
|
|
||||||
|
populate_user_groups(user_groups, &num_user_groups, num_local_groups_read, total_local_groups, (LPBYTE) local_groups, LOCAL_GROUP);
|
||||||
|
if (user_domain) {
|
||||||
|
populate_user_groups(user_groups, &num_user_groups, num_domain_groups_read, total_domain_groups, (LPBYTE)domain_groups, DOMAIN_GROUP);
|
||||||
|
populate_user_groups(user_groups, &num_user_groups, num_global_universal_groups_read, total_global_universal_groups, (LPBYTE)global_universal_groups, GLOBAL_UNIVERSAL_GROUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_user_groups; i++)
|
||||||
|
to_lower_case(user_groups[i]);
|
||||||
|
|
||||||
|
print_user_groups(user, user_groups, num_user_groups);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if(local_groups)
|
||||||
|
NetApiBufferFree(local_groups);
|
||||||
|
|
||||||
|
if(domain_groups)
|
||||||
|
NetApiBufferFree(domain_groups);
|
||||||
|
|
||||||
|
if(global_universal_groups)
|
||||||
|
NetApiBufferFree(global_universal_groups);
|
||||||
|
|
||||||
|
if(dc_name_utf16)
|
||||||
|
NetApiBufferFree(dc_name_utf16);
|
||||||
|
|
||||||
|
if(user_name_utf16)
|
||||||
|
free(user_name_utf16);
|
||||||
|
|
||||||
|
if(user_name)
|
||||||
|
free(user_name);
|
||||||
|
|
||||||
|
*ngroups = num_user_groups;
|
||||||
|
return user_groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This method will return in "group@domain" format */
|
||||||
|
char *
|
||||||
|
append_domain_to_groupname(char *groupname)
|
||||||
|
{
|
||||||
|
if(!groupname) return NULL;
|
||||||
|
|
||||||
|
int len = (int) strlen(machine_domain_name) + (int) strlen(groupname) + 2;
|
||||||
|
char *groupname_with_domain = malloc(len);
|
||||||
|
if(!groupname_with_domain) {
|
||||||
|
error("failed to allocate memory!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy_s(groupname_with_domain, len, groupname);
|
||||||
|
strcat_s(groupname_with_domain, len, "@");
|
||||||
|
strcat_s(groupname_with_domain, len, machine_domain_name);
|
||||||
|
|
||||||
|
groupname_with_domain[len-1]= '\0';
|
||||||
|
|
||||||
|
return groupname_with_domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
populate_user_groups(char **group_name, int *group_index, DWORD groupsread, DWORD totalgroups, LPBYTE buf, group_type groupType)
|
||||||
|
{
|
||||||
|
if(0 == groupsread) return;
|
||||||
|
char *user_group_name = NULL;
|
||||||
|
|
||||||
|
if (groupType == GLOBAL_UNIVERSAL_GROUP) {
|
||||||
|
LPGROUP_USERS_INFO_0 pTmpBuf = (LPGROUP_USERS_INFO_0)buf;
|
||||||
|
for (DWORD i = 0; (i < groupsread) && pTmpBuf; i++, pTmpBuf++) {
|
||||||
|
if (!(user_group_name = utf16_to_utf8(pTmpBuf->grui0_name))) {
|
||||||
|
error("utf16_to_utf8 failed to convert:%ls", pTmpBuf->grui0_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
group_name[*group_index] = append_domain_to_groupname(user_group_name);
|
||||||
|
if(group_name[*group_index])
|
||||||
|
(*group_index)++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LPLOCALGROUP_USERS_INFO_0 pTmpBuf = (LPLOCALGROUP_USERS_INFO_0)buf;
|
||||||
|
for (DWORD i = 0; (i < groupsread) && pTmpBuf; i++, pTmpBuf++) {
|
||||||
|
if (!(user_group_name = utf16_to_utf8(pTmpBuf->lgrui0_name))) {
|
||||||
|
error("utf16_to_utf8 failed to convert:%ls", pTmpBuf->lgrui0_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(groupType == DOMAIN_GROUP)
|
||||||
|
group_name[*group_index] = append_domain_to_groupname(user_group_name);
|
||||||
|
else
|
||||||
|
group_name[*group_index] = user_group_name;
|
||||||
|
|
||||||
|
if (group_name[*group_index])
|
||||||
|
(*group_index)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupsread < totalgroups)
|
||||||
|
error("groupsread:%d totalgroups:%d groupType:%d", groupsread, totalgroups, groupType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_user_groups(const char *user, char **user_groups, int num_user_groups)
|
||||||
|
{
|
||||||
|
debug3("Group list for user:%s", user);
|
||||||
|
for(int i=0; i < num_user_groups; i++)
|
||||||
|
debug3("group name:%s", user_groups[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
to_lower_case(char *s)
|
||||||
|
{
|
||||||
|
for (; *s; s++)
|
||||||
|
*s = tolower((u_char)*s);
|
||||||
|
}
|
||||||
|
@ -32,3 +32,6 @@ void unix_time_to_file_time(ULONG, LPFILETIME);
|
|||||||
void file_time_to_unix_time(const LPFILETIME, time_t *);
|
void file_time_to_unix_time(const LPFILETIME, time_t *);
|
||||||
int file_attr_to_st_mode(wchar_t * path, DWORD attributes);
|
int file_attr_to_st_mode(wchar_t * path, DWORD attributes);
|
||||||
void invalid_parameter_handler(const wchar_t *, const wchar_t *, const wchar_t *, unsigned int, uintptr_t);
|
void invalid_parameter_handler(const wchar_t *, const wchar_t *, const wchar_t *, unsigned int, uintptr_t);
|
||||||
|
static char *machine_domain_name;
|
||||||
|
void to_lower_case(char *s);
|
||||||
|
int get_machine_domain_name(wchar_t *domain, int size);
|
@ -203,6 +203,8 @@ get_passwd(const char *user_utf8, LPWSTR user_sid)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to_lower_case(uname_upn);
|
||||||
pw.pw_name = uname_upn;
|
pw.pw_name = uname_upn;
|
||||||
uname_upn = NULL;
|
uname_upn = NULL;
|
||||||
pw.pw_dir = pw_home_utf8;
|
pw.pw_dir = pw_home_utf8;
|
||||||
|
@ -164,7 +164,6 @@ struct key_translation keys[] = {
|
|||||||
{ L"\x1bOQ", VK_F2, 0 , 0 , 0},
|
{ L"\x1bOQ", VK_F2, 0 , 0 , 0},
|
||||||
{ L"\x1bOR", VK_F3, 0 , 0 , 0},
|
{ L"\x1bOR", VK_F3, 0 , 0 , 0},
|
||||||
{ L"\x1bOS", VK_F4, 0 , 0 , 0},
|
{ L"\x1bOS", VK_F4, 0 , 0 , 0},
|
||||||
{ L"\x1b?", VK_OEM_2, L'?' , 0 , SHIFT_PRESSED | LEFT_ALT_PRESSED},
|
|
||||||
{ L"\x1", VK_A, L'\x1' , 0 , LEFT_CTRL_PRESSED},
|
{ L"\x1", VK_A, L'\x1' , 0 , LEFT_CTRL_PRESSED},
|
||||||
{ L"\x2", VK_B, L'\x2' , 0 , LEFT_CTRL_PRESSED},
|
{ L"\x2", VK_B, L'\x2' , 0 , LEFT_CTRL_PRESSED},
|
||||||
//{ L"\x3", VK_C, L'\x3' , 0 , LEFT_CTRL_PRESSED}, /* Control + C is handled differently */
|
//{ L"\x3", VK_C, L'\x3' , 0 , LEFT_CTRL_PRESSED}, /* Control + C is handled differently */
|
||||||
@ -311,7 +310,7 @@ SendKeyStrokeEx(HANDLE hInput, int vKey, wchar_t character, DWORD ctrlState, BOO
|
|||||||
|
|
||||||
ir.EventType = KEY_EVENT;
|
ir.EventType = KEY_EVENT;
|
||||||
ir.Event.KeyEvent.bKeyDown = keyDown;
|
ir.Event.KeyEvent.bKeyDown = keyDown;
|
||||||
ir.Event.KeyEvent.wRepeatCount = 0;
|
ir.Event.KeyEvent.wRepeatCount = 1;
|
||||||
ir.Event.KeyEvent.wVirtualKeyCode = vKey;
|
ir.Event.KeyEvent.wVirtualKeyCode = vKey;
|
||||||
ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKeyA(vKey, MAPVK_VK_TO_VSC);
|
ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKeyA(vKey, MAPVK_VK_TO_VSC);
|
||||||
ir.Event.KeyEvent.dwControlKeyState = ctrlState;
|
ir.Event.KeyEvent.dwControlKeyState = ctrlState;
|
||||||
|
@ -31,9 +31,10 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "w32fd.h"
|
#include "w32fd.h"
|
||||||
#include "signal_internal.h"
|
#include "signal_internal.h"
|
||||||
#include "inc\signal.h"
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
/* Apply caution while changing this order of inclusion of below 2 signal.h headers */
|
||||||
|
#include "inc\signal.h"
|
||||||
#undef signal
|
#undef signal
|
||||||
#undef raise
|
#undef raise
|
||||||
#undef SIGINT
|
#undef SIGINT
|
||||||
@ -46,7 +47,11 @@
|
|||||||
#undef SIG_DFL
|
#undef SIG_DFL
|
||||||
#undef SIG_IGN
|
#undef SIG_IGN
|
||||||
#undef SIG_ERR
|
#undef SIG_ERR
|
||||||
|
#undef NSIG
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#undef NSIG
|
||||||
|
#define NSIG 0
|
||||||
|
|
||||||
|
|
||||||
/* pending signals to be processed */
|
/* pending signals to be processed */
|
||||||
sigset_t pending_signals;
|
sigset_t pending_signals;
|
||||||
|
@ -3,9 +3,9 @@ typedef unsigned short u_int16_t;
|
|||||||
typedef unsigned int u_int32_t;
|
typedef unsigned int u_int32_t;
|
||||||
typedef unsigned __int64 u_int64_t;
|
typedef unsigned __int64 u_int64_t;
|
||||||
#define __attribute__(a)
|
#define __attribute__(a)
|
||||||
#include "rsa.h"
|
|
||||||
#include "sshbuf.h"
|
#include "sshbuf.h"
|
||||||
#include "sshkey.h"
|
#include "sshkey.h"
|
||||||
|
#include <openssl/bn.h>
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "digest.h"
|
#include "digest.h"
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
|
|||||||
switch (InputRecord.Event.KeyEvent.uChar.UnicodeChar) {
|
switch (InputRecord.Event.KeyEvent.uChar.UnicodeChar) {
|
||||||
case 0xd:
|
case 0xd:
|
||||||
if (pParams->nReceiveCRLF == ENUM_LF)
|
if (pParams->nReceiveCRLF == ENUM_LF)
|
||||||
NetWriteString2(pParams->Socket, "\n", 1, 0);
|
NetWriteString2(pParams->Socket, "\r", 1, 0);
|
||||||
else
|
else
|
||||||
NetWriteString2(pParams->Socket, "\r\n", 2, 0);
|
NetWriteString2(pParams->Socket, "\r\n", 2, 0);
|
||||||
break;
|
break;
|
||||||
@ -208,9 +208,6 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
|
|||||||
case VK_ESCAPE:
|
case VK_ESCAPE:
|
||||||
NetWriteString2(pParams->Socket, (char *)ESCAPE_KEY, 1, 0);
|
NetWriteString2(pParams->Socket, (char *)ESCAPE_KEY, 1, 0);
|
||||||
break;
|
break;
|
||||||
case VK_OEM_2:
|
|
||||||
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_Q, 2, 0);
|
|
||||||
break;
|
|
||||||
case VK_SHIFT:
|
case VK_SHIFT:
|
||||||
case VK_CONTROL:
|
case VK_CONTROL:
|
||||||
case VK_CAPITAL:
|
case VK_CAPITAL:
|
||||||
|
@ -54,84 +54,13 @@ int
|
|||||||
ga_init(const char *user, gid_t base)
|
ga_init(const char *user, gid_t base)
|
||||||
{
|
{
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
#pragma warning(push, 3)
|
ngroups = 0;
|
||||||
LPLOCALGROUP_USERS_INFO_0 local_groups_info = NULL, tmp_groups_info;
|
groups_byname = NULL;
|
||||||
wchar_t *user_utf16 = NULL, *full_name_utf16 = NULL, *udom_utf16 = NULL, *tmp;
|
|
||||||
char *group_utf8 = NULL;
|
|
||||||
DWORD i = 0, j = 0;
|
|
||||||
DWORD entries_read = 0, total_entries = 0, full_name_len = 0, index = 0;
|
|
||||||
NET_API_STATUS nStatus;
|
|
||||||
|
|
||||||
if (ngroups > 0)
|
|
||||||
ga_free();
|
|
||||||
|
|
||||||
if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
full_name_len = (DWORD)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 = (DWORD)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);
|
|
||||||
|
|
||||||
#pragma warning(pop)
|
|
||||||
|
|
||||||
|
groups_byname = getusergroups(user, &ngroups);
|
||||||
|
return ngroups;
|
||||||
#else /* !WINDOWS */
|
#else /* !WINDOWS */
|
||||||
|
|
||||||
gid_t *groups_bygid;
|
gid_t *groups_bygid;
|
||||||
int i, j;
|
int i, j;
|
||||||
struct group *gr;
|
struct group *gr;
|
||||||
@ -153,8 +82,8 @@ done:
|
|||||||
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);
|
||||||
|
#endif /* !WINDOWS */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
474
misc.c
474
misc.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: misc.c,v 1.110 2017/05/31 09:15:42 deraadt Exp $ */
|
/* $OpenBSD: misc.c,v 1.113 2017/08/18 05:48:04 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
||||||
@ -29,10 +29,16 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#ifdef HAVE_LIBGEN_H
|
||||||
|
# include <libgen.h>
|
||||||
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -61,6 +67,10 @@
|
|||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
|
#include "sshbuf.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
#include "uidswap.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
/* remove newline at end of string */
|
/* remove newline at end of string */
|
||||||
char *
|
char *
|
||||||
@ -1105,6 +1115,7 @@ static const struct {
|
|||||||
const char *name;
|
const char *name;
|
||||||
int value;
|
int value;
|
||||||
} ipqos[] = {
|
} ipqos[] = {
|
||||||
|
{ "none", INT_MAX }, /* can't use 0 here; that's CS0 */
|
||||||
{ "af11", IPTOS_DSCP_AF11 },
|
{ "af11", IPTOS_DSCP_AF11 },
|
||||||
{ "af12", IPTOS_DSCP_AF12 },
|
{ "af12", IPTOS_DSCP_AF12 },
|
||||||
{ "af13", IPTOS_DSCP_AF13 },
|
{ "af13", IPTOS_DSCP_AF13 },
|
||||||
@ -1303,3 +1314,464 @@ daemonized(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif /* !WINDOWS */
|
#endif /* !WINDOWS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Splits 's' into an argument vector. Handles quoted string and basic
|
||||||
|
* escape characters (\\, \", \'). Caller must free the argument vector
|
||||||
|
* and its members.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
argv_split(const char *s, int *argcp, char ***argvp)
|
||||||
|
{
|
||||||
|
int r = SSH_ERR_INTERNAL_ERROR;
|
||||||
|
int argc = 0, quote, i, j;
|
||||||
|
char *arg, **argv = xcalloc(1, sizeof(*argv));
|
||||||
|
|
||||||
|
*argvp = NULL;
|
||||||
|
*argcp = 0;
|
||||||
|
|
||||||
|
for (i = 0; s[i] != '\0'; i++) {
|
||||||
|
/* Skip leading whitespace */
|
||||||
|
if (s[i] == ' ' || s[i] == '\t')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Start of a token */
|
||||||
|
quote = 0;
|
||||||
|
if (s[i] == '\\' &&
|
||||||
|
(s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\'))
|
||||||
|
i++;
|
||||||
|
else if (s[i] == '\'' || s[i] == '"')
|
||||||
|
quote = s[i++];
|
||||||
|
|
||||||
|
argv = xreallocarray(argv, (argc + 2), sizeof(*argv));
|
||||||
|
arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1);
|
||||||
|
argv[argc] = NULL;
|
||||||
|
|
||||||
|
/* Copy the token in, removing escapes */
|
||||||
|
for (j = 0; s[i] != '\0'; i++) {
|
||||||
|
if (s[i] == '\\') {
|
||||||
|
if (s[i + 1] == '\'' ||
|
||||||
|
s[i + 1] == '\"' ||
|
||||||
|
s[i + 1] == '\\') {
|
||||||
|
i++; /* Skip '\' */
|
||||||
|
arg[j++] = s[i];
|
||||||
|
} else {
|
||||||
|
/* Unrecognised escape */
|
||||||
|
arg[j++] = s[i];
|
||||||
|
}
|
||||||
|
} else if (quote == 0 && (s[i] == ' ' || s[i] == '\t'))
|
||||||
|
break; /* done */
|
||||||
|
else if (quote != 0 && s[i] == quote)
|
||||||
|
break; /* done */
|
||||||
|
else
|
||||||
|
arg[j++] = s[i];
|
||||||
|
}
|
||||||
|
if (s[i] == '\0') {
|
||||||
|
if (quote != 0) {
|
||||||
|
/* Ran out of string looking for close quote */
|
||||||
|
r = SSH_ERR_INVALID_FORMAT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Success */
|
||||||
|
*argcp = argc;
|
||||||
|
*argvp = argv;
|
||||||
|
argc = 0;
|
||||||
|
argv = NULL;
|
||||||
|
r = 0;
|
||||||
|
out:
|
||||||
|
if (argc != 0 && argv != NULL) {
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
free(argv[i]);
|
||||||
|
free(argv);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reassemble an argument vector into a string, quoting and escaping as
|
||||||
|
* necessary. Caller must free returned string.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
argv_assemble(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i, j, ws, r;
|
||||||
|
char c, *ret;
|
||||||
|
struct sshbuf *buf, *arg;
|
||||||
|
|
||||||
|
if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
|
||||||
|
fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
ws = 0;
|
||||||
|
sshbuf_reset(arg);
|
||||||
|
for (j = 0; argv[i][j] != '\0'; j++) {
|
||||||
|
r = 0;
|
||||||
|
c = argv[i][j];
|
||||||
|
switch (c) {
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
ws = 1;
|
||||||
|
r = sshbuf_put_u8(arg, c);
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
case '\'':
|
||||||
|
case '"':
|
||||||
|
if ((r = sshbuf_put_u8(arg, '\\')) != 0)
|
||||||
|
break;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
default:
|
||||||
|
r = sshbuf_put_u8(arg, c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (r != 0)
|
||||||
|
fatal("%s: sshbuf_put_u8: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
|
}
|
||||||
|
if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
|
||||||
|
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
|
||||||
|
(r = sshbuf_putb(buf, arg)) != 0 ||
|
||||||
|
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
}
|
||||||
|
if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
|
||||||
|
fatal("%s: malloc failed", __func__);
|
||||||
|
memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
|
||||||
|
ret[sshbuf_len(buf)] = '\0';
|
||||||
|
sshbuf_free(buf);
|
||||||
|
sshbuf_free(arg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runs command in a subprocess wuth a minimal environment.
|
||||||
|
* Returns pid on success, 0 on failure.
|
||||||
|
* The child stdout and stderr maybe captured, left attached or sent to
|
||||||
|
* /dev/null depending on the contents of flags.
|
||||||
|
* "tag" is prepended to log messages.
|
||||||
|
* NB. "command" is only used for logging; the actual command executed is
|
||||||
|
* av[0].
|
||||||
|
*/
|
||||||
|
pid_t
|
||||||
|
subprocess(const char *tag, struct passwd *pw, const char *command,
|
||||||
|
int ac, char **av, FILE **child, u_int flags)
|
||||||
|
{
|
||||||
|
#ifdef WINDOWS
|
||||||
|
error("subprocess is not implemented in Windows yet");
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
FILE *f = NULL;
|
||||||
|
struct stat st;
|
||||||
|
int fd, devnull, p[2], i;
|
||||||
|
pid_t pid;
|
||||||
|
char *cp, errmsg[512];
|
||||||
|
u_int envsize;
|
||||||
|
char **child_env;
|
||||||
|
|
||||||
|
if (child != NULL)
|
||||||
|
*child = NULL;
|
||||||
|
|
||||||
|
debug3("%s: %s command \"%s\" running as %s (flags 0x%x)", __func__,
|
||||||
|
tag, command, pw->pw_name, flags);
|
||||||
|
|
||||||
|
/* Check consistency */
|
||||||
|
if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
|
||||||
|
(flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) {
|
||||||
|
error("%s: inconsistent flags", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) {
|
||||||
|
error("%s: inconsistent flags/output", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If executing an explicit binary, then verify the it exists
|
||||||
|
* and appears safe-ish to execute
|
||||||
|
*/
|
||||||
|
if (*av[0] != '/') {
|
||||||
|
error("%s path is not absolute", tag);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
temporarily_use_uid(pw);
|
||||||
|
if (stat(av[0], &st) < 0) {
|
||||||
|
error("Could not stat %s \"%s\": %s", tag,
|
||||||
|
av[0], strerror(errno));
|
||||||
|
restore_uid();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) {
|
||||||
|
error("Unsafe %s \"%s\": %s", tag, av[0], errmsg);
|
||||||
|
restore_uid();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Prepare to keep the child's stdout if requested */
|
||||||
|
if (pipe(p) != 0) {
|
||||||
|
error("%s: pipe: %s", tag, strerror(errno));
|
||||||
|
restore_uid();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
restore_uid();
|
||||||
|
|
||||||
|
switch ((pid = fork())) {
|
||||||
|
case -1: /* error */
|
||||||
|
error("%s: fork: %s", tag, strerror(errno));
|
||||||
|
close(p[0]);
|
||||||
|
close(p[1]);
|
||||||
|
return 0;
|
||||||
|
case 0: /* child */
|
||||||
|
/* Prepare a minimal environment for the child. */
|
||||||
|
envsize = 5;
|
||||||
|
child_env = xcalloc(sizeof(*child_env), envsize);
|
||||||
|
child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH);
|
||||||
|
child_set_env(&child_env, &envsize, "USER", pw->pw_name);
|
||||||
|
child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name);
|
||||||
|
child_set_env(&child_env, &envsize, "HOME", pw->pw_dir);
|
||||||
|
if ((cp = getenv("LANG")) != NULL)
|
||||||
|
child_set_env(&child_env, &envsize, "LANG", cp);
|
||||||
|
|
||||||
|
for (i = 0; i < NSIG; i++)
|
||||||
|
signal(i, SIG_DFL);
|
||||||
|
|
||||||
|
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
|
||||||
|
error("%s: open %s: %s", tag, _PATH_DEVNULL,
|
||||||
|
strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
if (dup2(devnull, STDIN_FILENO) == -1) {
|
||||||
|
error("%s: dup2: %s", tag, strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up stdout as requested; leave stderr in place for now. */
|
||||||
|
fd = -1;
|
||||||
|
if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0)
|
||||||
|
fd = p[1];
|
||||||
|
else if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0)
|
||||||
|
fd = devnull;
|
||||||
|
if (fd != -1 && dup2(fd, STDOUT_FILENO) == -1) {
|
||||||
|
error("%s: dup2: %s", tag, strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
closefrom(STDERR_FILENO + 1);
|
||||||
|
|
||||||
|
/* Don't use permanently_set_uid() here to avoid fatal() */
|
||||||
|
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
|
||||||
|
error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
|
||||||
|
strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
|
||||||
|
error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid,
|
||||||
|
strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
/* stdin is pointed to /dev/null at this point */
|
||||||
|
if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
|
||||||
|
dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
|
||||||
|
error("%s: dup2: %s", tag, strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
execve(av[0], av, child_env);
|
||||||
|
error("%s exec \"%s\": %s", tag, command, strerror(errno));
|
||||||
|
_exit(127);
|
||||||
|
default: /* parent */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(p[1]);
|
||||||
|
if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0)
|
||||||
|
close(p[0]);
|
||||||
|
else if ((f = fdopen(p[0], "r")) == NULL) {
|
||||||
|
error("%s: fdopen: %s", tag, strerror(errno));
|
||||||
|
close(p[0]);
|
||||||
|
/* Don't leave zombie child */
|
||||||
|
kill(pid, SIGTERM);
|
||||||
|
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Success */
|
||||||
|
debug3("%s: %s pid %ld", __func__, tag, (long)pid);
|
||||||
|
if (child != NULL)
|
||||||
|
*child = f;
|
||||||
|
return pid;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns 0 if pid exited cleanly, non-zero otherwise */
|
||||||
|
int
|
||||||
|
exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
while (waitpid(pid, &status, 0) == -1) {
|
||||||
|
if (errno != EINTR) {
|
||||||
|
error("%s: waitpid: %s", tag, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (WIFSIGNALED(status)) {
|
||||||
|
error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status));
|
||||||
|
return -1;
|
||||||
|
} else if (WEXITSTATUS(status) != 0) {
|
||||||
|
do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO,
|
||||||
|
"%s %s failed, status %d", tag, cmd, WEXITSTATUS(status));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check a given path for security. This is defined as all components
|
||||||
|
* of the path to the file must be owned by either the owner of
|
||||||
|
* of the file or root and no directories must be group or world writable.
|
||||||
|
*
|
||||||
|
* XXX Should any specific check be done for sym links ?
|
||||||
|
*
|
||||||
|
* Takes a file name, its stat information (preferably from fstat() to
|
||||||
|
* avoid races), the uid of the expected owner, their home directory and an
|
||||||
|
* error buffer plus max size as arguments.
|
||||||
|
*
|
||||||
|
* Returns 0 on success and -1 on failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
safe_path(const char *name, struct stat *stp, const char *pw_dir,
|
||||||
|
uid_t uid, char *err, size_t errlen)
|
||||||
|
{
|
||||||
|
char buf[PATH_MAX], homedir[PATH_MAX];
|
||||||
|
char *cp;
|
||||||
|
int comparehome = 0;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (realpath(name, buf) == NULL) {
|
||||||
|
snprintf(err, errlen, "realpath %s failed: %s", name,
|
||||||
|
strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
|
||||||
|
comparehome = 1;
|
||||||
|
|
||||||
|
if (!S_ISREG(stp->st_mode)) {
|
||||||
|
snprintf(err, errlen, "%s is not a regular file", buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
|
||||||
|
(stp->st_mode & 022) != 0) {
|
||||||
|
snprintf(err, errlen, "bad ownership or modes for file %s",
|
||||||
|
buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for each component of the canonical path, walking upwards */
|
||||||
|
for (;;) {
|
||||||
|
if ((cp = dirname(buf)) == NULL) {
|
||||||
|
snprintf(err, errlen, "dirname() failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strlcpy(buf, cp, sizeof(buf));
|
||||||
|
|
||||||
|
if (stat(buf, &st) < 0 ||
|
||||||
|
(!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
|
||||||
|
(st.st_mode & 022) != 0) {
|
||||||
|
snprintf(err, errlen,
|
||||||
|
"bad ownership or modes for directory %s", buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If are past the homedir then we can stop */
|
||||||
|
if (comparehome && strcmp(homedir, buf) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dirname should always complete with a "/" path,
|
||||||
|
* but we can be paranoid and check for "." too
|
||||||
|
*/
|
||||||
|
if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version of safe_path() that accepts an open file descriptor to
|
||||||
|
* avoid races.
|
||||||
|
*
|
||||||
|
* Returns 0 on success and -1 on failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
safe_path_fd(int fd, const char *file, struct passwd *pw,
|
||||||
|
char *err, size_t errlen)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
/* check the open file to avoid races */
|
||||||
|
if (fstat(fd, &st) < 0) {
|
||||||
|
snprintf(err, errlen, "cannot stat file %s: %s",
|
||||||
|
file, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the value of the given variable in the environment. If the variable
|
||||||
|
* already exists, its value is overridden.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
child_set_env(char ***envp, u_int *envsizep, const char *name,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
char **env;
|
||||||
|
u_int envsize;
|
||||||
|
u_int i, namelen;
|
||||||
|
|
||||||
|
if (strchr(name, '=') != NULL) {
|
||||||
|
error("Invalid environment variable \"%.100s\"", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're passed an uninitialized list, allocate a single null
|
||||||
|
* entry before continuing.
|
||||||
|
*/
|
||||||
|
if (*envp == NULL && *envsizep == 0) {
|
||||||
|
*envp = xmalloc(sizeof(char *));
|
||||||
|
*envp[0] = NULL;
|
||||||
|
*envsizep = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the slot where the value should be stored. If the variable
|
||||||
|
* already exists, we reuse the slot; otherwise we append a new slot
|
||||||
|
* at the end of the array, expanding if necessary.
|
||||||
|
*/
|
||||||
|
env = *envp;
|
||||||
|
namelen = strlen(name);
|
||||||
|
for (i = 0; env[i]; i++)
|
||||||
|
if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
|
||||||
|
break;
|
||||||
|
if (env[i]) {
|
||||||
|
/* Reuse the slot. */
|
||||||
|
free(env[i]);
|
||||||
|
} else {
|
||||||
|
/* New variable. Expand if necessary. */
|
||||||
|
envsize = *envsizep;
|
||||||
|
if (i >= envsize - 1) {
|
||||||
|
if (envsize >= 1000)
|
||||||
|
fatal("child_set_env: too many env vars");
|
||||||
|
envsize += 50;
|
||||||
|
env = (*envp) = xreallocarray(env, envsize, sizeof(char *));
|
||||||
|
*envsizep = envsize;
|
||||||
|
}
|
||||||
|
/* Need to set the NULL pointer at end of array beyond the new slot. */
|
||||||
|
env[i + 1] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate space and format the variable in the appropriate slot. */
|
||||||
|
env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
|
||||||
|
snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
|
||||||
|
}
|
||||||
|
22
misc.h
22
misc.h
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: misc.h,v 1.61 2016/11/30 00:28:31 dtucker Exp $ */
|
/* $OpenBSD: misc.h,v 1.63 2017/08/18 05:48:04 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#define _MISC_H
|
#define _MISC_H
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
/* Data structure for representing a forwarding request. */
|
/* Data structure for representing a forwarding request. */
|
||||||
struct Forward {
|
struct Forward {
|
||||||
@ -132,6 +133,25 @@ int parse_ipqos(const char *);
|
|||||||
const char *iptos2str(int);
|
const char *iptos2str(int);
|
||||||
void mktemp_proto(char *, size_t);
|
void mktemp_proto(char *, size_t);
|
||||||
|
|
||||||
|
void child_set_env(char ***envp, u_int *envsizep, const char *name,
|
||||||
|
const char *value);
|
||||||
|
|
||||||
|
int argv_split(const char *, int *, char ***);
|
||||||
|
char *argv_assemble(int, char **argv);
|
||||||
|
int exited_cleanly(pid_t, const char *, const char *, int);
|
||||||
|
|
||||||
|
#define SSH_SUBPROCESS_STDOUT_DISCARD (1) /* Discard stdout */
|
||||||
|
#define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */
|
||||||
|
#define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */
|
||||||
|
pid_t subprocess(const char *, struct passwd *,
|
||||||
|
const char *, int, char **, FILE **, u_int flags);
|
||||||
|
|
||||||
|
struct stat;
|
||||||
|
int safe_path(const char *, struct stat *, const char *, uid_t,
|
||||||
|
char *, size_t);
|
||||||
|
int safe_path_fd(int, const char *, struct passwd *,
|
||||||
|
char *err, size_t errlen);
|
||||||
|
|
||||||
/* readpass.c */
|
/* readpass.c */
|
||||||
|
|
||||||
#define RP_ECHO 0x0001
|
#define RP_ECHO 0x0001
|
||||||
|
@ -27,6 +27,12 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef HAVE_ERR
|
#ifndef HAVE_ERR
|
||||||
void
|
void
|
||||||
err(int r, const char *fmt, ...)
|
err(int r, const char *fmt, ...)
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
void
|
void
|
||||||
explicit_bzero(void *p, size_t n)
|
explicit_bzero(void *p, size_t n)
|
||||||
{
|
{
|
||||||
|
if (n == 0)
|
||||||
|
return;
|
||||||
(void)memset_s(p, n, 0, n);
|
(void)memset_s(p, n, 0, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,6 +36,8 @@ static void (* volatile ssh_bzero)(void *, size_t) = bzero;
|
|||||||
void
|
void
|
||||||
explicit_bzero(void *p, size_t n)
|
explicit_bzero(void *p, size_t n)
|
||||||
{
|
{
|
||||||
|
if (n == 0)
|
||||||
|
return;
|
||||||
/*
|
/*
|
||||||
* clang -fsanitize=memory needs to intercept memset-like functions
|
* clang -fsanitize=memory needs to intercept memset-like functions
|
||||||
* to correctly detect memory initialisation. Make sure one is called
|
* to correctly detect memory initialisation. Make sure one is called
|
||||||
|
@ -199,49 +199,50 @@ sys_tun_open(int tun, int mode)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(SSH_TUN_FILTER)
|
#if defined(SSH_TUN_FILTER)
|
||||||
|
/*
|
||||||
|
* The tunnel forwarding protocol prepends the address family of forwarded
|
||||||
|
* IP packets using OpenBSD's numbers.
|
||||||
|
*/
|
||||||
#define OPENBSD_AF_INET 2
|
#define OPENBSD_AF_INET 2
|
||||||
#define OPENBSD_AF_INET6 24
|
#define OPENBSD_AF_INET6 24
|
||||||
|
|
||||||
int
|
int
|
||||||
sys_tun_infilter(struct Channel *c, char *buf, int len)
|
sys_tun_infilter(struct Channel *c, char *buf, int _len)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
|
size_t len;
|
||||||
|
char *ptr = buf;
|
||||||
#if defined(SSH_TUN_PREPEND_AF)
|
#if defined(SSH_TUN_PREPEND_AF)
|
||||||
char rbuf[CHAN_RBUF];
|
char rbuf[CHAN_RBUF];
|
||||||
struct ip *iph;
|
struct ip iph;
|
||||||
#endif
|
#endif
|
||||||
u_int32_t *af;
|
#if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF)
|
||||||
char *ptr = buf;
|
u_int32_t af;
|
||||||
int r;
|
#endif
|
||||||
|
|
||||||
|
/* XXX update channel input filter API to use unsigned length */
|
||||||
|
if (_len < 0)
|
||||||
|
return -1;
|
||||||
|
len = _len;
|
||||||
|
|
||||||
#if defined(SSH_TUN_PREPEND_AF)
|
#if defined(SSH_TUN_PREPEND_AF)
|
||||||
if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af)))
|
if (len <= sizeof(iph) || len > sizeof(rbuf) - 4)
|
||||||
return (-1);
|
return -1;
|
||||||
ptr = (char *)&rbuf[0];
|
/* Determine address family from packet IP header. */
|
||||||
bcopy(buf, ptr + sizeof(u_int32_t), len);
|
memcpy(&iph, buf, sizeof(iph));
|
||||||
len += sizeof(u_int32_t);
|
af = iph.ip_v == 6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET;
|
||||||
af = (u_int32_t *)ptr;
|
/* Prepend address family to packet using OpenBSD constants */
|
||||||
|
memcpy(rbuf + 4, buf, len);
|
||||||
iph = (struct ip *)(ptr + sizeof(u_int32_t));
|
len += 4;
|
||||||
switch (iph->ip_v) {
|
POKE_U32(rbuf, af);
|
||||||
case 6:
|
ptr = rbuf;
|
||||||
*af = AF_INET6;
|
#elif defined(SSH_TUN_COMPAT_AF)
|
||||||
break;
|
/* Convert existing address family header to OpenBSD value */
|
||||||
case 4:
|
if (len <= 4)
|
||||||
default:
|
return -1;
|
||||||
*af = AF_INET;
|
af = PEEK_U32(buf);
|
||||||
break;
|
/* Put it back */
|
||||||
}
|
POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SSH_TUN_COMPAT_AF)
|
|
||||||
if (len < (int)sizeof(u_int32_t))
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
af = (u_int32_t *)ptr;
|
|
||||||
if (*af == htonl(AF_INET6))
|
|
||||||
*af = htonl(OPENBSD_AF_INET6);
|
|
||||||
else
|
|
||||||
*af = htonl(OPENBSD_AF_INET);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0)
|
if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0)
|
||||||
@ -253,7 +254,7 @@ u_char *
|
|||||||
sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen)
|
sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen)
|
||||||
{
|
{
|
||||||
u_char *buf;
|
u_char *buf;
|
||||||
u_int32_t *af;
|
u_int32_t af;
|
||||||
int r;
|
int r;
|
||||||
size_t xxx_dlen;
|
size_t xxx_dlen;
|
||||||
|
|
||||||
@ -262,21 +263,19 @@ sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen)
|
|||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
if (dlen != NULL)
|
if (dlen != NULL)
|
||||||
*dlen = xxx_dlen;
|
*dlen = xxx_dlen;
|
||||||
if (*dlen < sizeof(*af))
|
if (*dlen < sizeof(af))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
buf = *data;
|
buf = *data;
|
||||||
|
|
||||||
#if defined(SSH_TUN_PREPEND_AF)
|
#if defined(SSH_TUN_PREPEND_AF)
|
||||||
*dlen -= sizeof(u_int32_t);
|
/* skip address family */
|
||||||
buf = *data + sizeof(u_int32_t);
|
*dlen -= sizeof(af);
|
||||||
|
buf = *data + sizeof(af);
|
||||||
#elif defined(SSH_TUN_COMPAT_AF)
|
#elif defined(SSH_TUN_COMPAT_AF)
|
||||||
af = ntohl(*(u_int32_t *)buf);
|
/* translate address family */
|
||||||
if (*af == OPENBSD_AF_INET6)
|
af = (PEEK_U32(buf) == OPENBSD_AF_INET6) ? AF_INET6 : AF_INET;
|
||||||
*af = htonl(AF_INET6);
|
POKE_U32(buf, af);
|
||||||
else
|
|
||||||
*af = htonl(AF_INET);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
#endif /* SSH_TUN_FILTER */
|
#endif /* SSH_TUN_FILTER */
|
||||||
|
4
packet.c
4
packet.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: packet.c,v 1.262 2017/06/24 06:38:11 djm Exp $ */
|
/* $OpenBSD: packet.c,v 1.263 2017/07/23 23:37:02 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
|
||||||
@ -1997,7 +1997,7 @@ void
|
|||||||
ssh_packet_set_tos(struct ssh *ssh, int tos)
|
ssh_packet_set_tos(struct ssh *ssh, int tos)
|
||||||
{
|
{
|
||||||
#ifndef IP_TOS_IS_BROKEN
|
#ifndef IP_TOS_IS_BROKEN
|
||||||
if (!ssh_packet_connection_is_on_socket(ssh))
|
if (!ssh_packet_connection_is_on_socket(ssh) || tos == INT_MAX)
|
||||||
return;
|
return;
|
||||||
switch (ssh_packet_connection_af(ssh)) {
|
switch (ssh_packet_connection_af(ssh)) {
|
||||||
# ifdef IP_TOS
|
# ifdef IP_TOS
|
||||||
|
35
platform-misc.c
Normal file
35
platform-misc.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Darren Tucker. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
#include "openbsd-compat/openbsd-compat.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return 1 if the specified uid is a uid that may own a system directory
|
||||||
|
* otherwise 0.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
platform_sys_dir_uid(uid_t uid)
|
||||||
|
{
|
||||||
|
if (uid == 0)
|
||||||
|
return 1;
|
||||||
|
#ifdef PLATFORM_SYS_DIR_UID
|
||||||
|
if (uid == PLATFORM_SYS_DIR_UID)
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
16
platform.c
16
platform.c
@ -197,19 +197,3 @@ platform_krb5_get_principal_name(const char *pw_name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* return 1 if the specified uid is a uid that may own a system directory
|
|
||||||
* otherwise 0.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
platform_sys_dir_uid(uid_t uid)
|
|
||||||
{
|
|
||||||
if (uid == 0)
|
|
||||||
return 1;
|
|
||||||
#ifdef PLATFORM_SYS_DIR_UID
|
|
||||||
if (uid == PLATFORM_SYS_DIR_UID)
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -38,7 +38,10 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
|
|
||||||
#only validate owner and ACEs of the file
|
#only validate owner and ACEs of the file
|
||||||
function ValidateKeyFile {
|
function ValidateKeyFile {
|
||||||
param([string]$FilePath)
|
param(
|
||||||
|
[string]$FilePath,
|
||||||
|
[bool]$IsHostKey = $true
|
||||||
|
)
|
||||||
|
|
||||||
$myACL = Get-ACL $FilePath
|
$myACL = Get-ACL $FilePath
|
||||||
$currentOwnerSid = Get-UserSid -User $myACL.Owner
|
$currentOwnerSid = Get-UserSid -User $myACL.Owner
|
||||||
@ -53,9 +56,15 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
$FullControlPerm = [System.UInt32] [System.Security.AccessControl.FileSystemRights]::FullControl.value__
|
$FullControlPerm = [System.UInt32] [System.Security.AccessControl.FileSystemRights]::FullControl.value__
|
||||||
|
|
||||||
if($FilePath.EndsWith(".pub")) {
|
if($FilePath.EndsWith(".pub")) {
|
||||||
|
if ($IsHostKey) {
|
||||||
|
$myACL.Access.Count | Should Be 3
|
||||||
|
$identities = @($systemSid, $adminsSid, $currentUserSid)
|
||||||
|
}
|
||||||
|
else {
|
||||||
$myACL.Access.Count | Should Be 4
|
$myACL.Access.Count | Should Be 4
|
||||||
$identities = @($systemSid, $adminsSid, $currentUserSid, $everyoneSid)
|
$identities = @($systemSid, $adminsSid, $currentUserSid, $everyoneSid)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
$myACL.Access.Count | Should Be 3
|
$myACL.Access.Count | Should Be 3
|
||||||
$identities = @($systemSid, $adminsSid, $currentUserSid)
|
$identities = @($systemSid, $adminsSid, $currentUserSid)
|
||||||
@ -135,7 +144,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
ssh-keygen -t $type -P $keypassphrase -f $keyPath
|
ssh-keygen -t $type -P $keypassphrase -f $keyPath
|
||||||
}
|
}
|
||||||
ValidateKeyFile -FilePath $keyPath
|
ValidateKeyFile -FilePath $keyPath
|
||||||
ValidateKeyFile -FilePath "$keyPath.pub"
|
ValidateKeyFile -FilePath "$keyPath.pub" -IsHostKey $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,133 @@
|
|||||||
Describe "Tests of sshd_config" -Tags "Scenario" {
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
|
$tC = 1
|
||||||
|
$tI = 0
|
||||||
|
$suite = "sshdConfig"
|
||||||
|
Describe "Tests of sshd_config" -Tags "CI" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$fileName = "test.txt"
|
if($OpenSSHTestInfo -eq $null)
|
||||||
$filePath = Join-Path ${TestDrive} $fileName
|
{
|
||||||
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
||||||
[Machine] $client = [Machine]::new([MachineRole]::Client)
|
|
||||||
[Machine] $server = [Machine]::new([MachineRole]::Server)
|
|
||||||
$client.SetupClient($server)
|
|
||||||
$server.SetupServer($client)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
|
||||||
|
if( -not (Test-path $testDir -PathType Container))
|
||||||
|
{
|
||||||
|
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileName = "test.txt"
|
||||||
|
$logName = "sshdlog.txt"
|
||||||
|
$server = $OpenSSHTestInfo["Target"]
|
||||||
|
$port = 47003
|
||||||
|
Remove-Item -Path (Join-Path $testDir "*$fileName") -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
|
||||||
|
$ContextName = $env:COMPUTERNAME
|
||||||
|
$ContextType = [System.DirectoryServices.AccountManagement.ContextType]::Machine
|
||||||
|
$PrincipalContext = [System.DirectoryServices.AccountManagement.PrincipalContext]::new($ContextType, $ContextName)
|
||||||
|
$IdentityType = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
|
||||||
|
|
||||||
|
function Add-LocalUser
|
||||||
|
{
|
||||||
|
param([string] $UserName, [string] $Password)
|
||||||
|
$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($PrincipalContext, $IdentityType, $UserName)
|
||||||
|
if($user -eq $null)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::new($PrincipalContext,$UserName,$Password, $true)
|
||||||
|
$user.Save()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$user.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-LocalGroup
|
||||||
|
{
|
||||||
|
param([string] $groupName)
|
||||||
|
$group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($PrincipalContext, $IdentityType, $GroupName)
|
||||||
|
if($group -eq $null)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::new($PrincipalContext,$groupName)
|
||||||
|
$group.Save()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$group.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-UserToLocalGroup
|
||||||
|
{
|
||||||
|
param([string]$UserName, [string]$Password, [string]$GroupName)
|
||||||
|
Add-LocalGroup -groupName $GroupName
|
||||||
|
Add-LocalUser -UserName $UserName -Password $Password
|
||||||
|
$group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($PrincipalContext, $IdentityType, $GroupName)
|
||||||
|
$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($PrincipalContext, $IdentityType, $UserName)
|
||||||
|
|
||||||
|
if(-not $group.Members.Contains($user))
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$group.Members.Add($user)
|
||||||
|
$group.save()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$group.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Remove-UserFromLocalGroup
|
||||||
|
{
|
||||||
|
param([string]$UserName, [string]$GroupName)
|
||||||
|
$group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($PrincipalContext, $IdentityType, $GroupName)
|
||||||
|
$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($PrincipalContext, $IdentityType, $UserName)
|
||||||
|
if($group.Members.Contains($user))
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$group.Members.Remove($user)
|
||||||
|
$group.save()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$group.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Clenaup-LocalGroup
|
||||||
|
{
|
||||||
|
param([string]$GroupName)
|
||||||
|
$group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($PrincipalContext, $IdentityType, $GroupName)
|
||||||
|
if($group -ne $null)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$group.Delete()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$group.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$platform = Get-Platform
|
||||||
|
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
|
||||||
|
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
|
||||||
|
{
|
||||||
|
#suppress the firewall blocking dialogue on win7
|
||||||
|
netsh advfirewall firewall add rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any action=allow dir=in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AfterEach { $tI++ }
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
$client.CleanupClient()
|
$PrincipalContext.Dispose()
|
||||||
$server.CleanupServer()
|
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
|
||||||
|
{
|
||||||
|
netsh advfirewall firewall delete rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any dir=in
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
@ -24,7 +140,6 @@
|
|||||||
#>
|
#>
|
||||||
Context "Tests of AllowGroups, AllowUsers, DenyUsers, DenyGroups" {
|
Context "Tests of AllowGroups, AllowUsers, DenyUsers, DenyGroups" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
||||||
$password = "Bull_dog1"
|
$password = "Bull_dog1"
|
||||||
|
|
||||||
$allowUser1 = "allowuser1"
|
$allowUser1 = "allowuser1"
|
||||||
@ -47,113 +162,183 @@
|
|||||||
$denyGroup1 = "denygroup1"
|
$denyGroup1 = "denygroup1"
|
||||||
$denyGroup2 = "denygroup2"
|
$denyGroup2 = "denygroup2"
|
||||||
$denyGroup3 = "denygroup3"
|
$denyGroup3 = "denygroup3"
|
||||||
$client.AddPasswordSetting($password)
|
$sshdConfigPath = Join-Path $PSScriptRoot testdata\SSHD_Config
|
||||||
|
$testknownhosts = Join-path $PSScriptRoot testdata\test_known_hosts
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
|
#add wrong password so ssh does not prompt password if failed with authorized keys
|
||||||
|
Add-PasswordSetting -Pass $password
|
||||||
|
$tI=1
|
||||||
}
|
}
|
||||||
AfterEach {
|
|
||||||
Remove-Item -Path $filePath -Force -ea SilentlyContinue
|
BeforeEach {
|
||||||
|
$filePath = Join-Path $testDir "$tC.$tI.$fileName"
|
||||||
|
$logPath = Join-Path $testDir "$tC.$tI.$logName"
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
$client.CleanupPasswordSetting()
|
Remove-PasswordSetting
|
||||||
|
$tC++
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User with full name in the list of AllowUsers' {
|
It "$tC.$tI-User with full name in the list of AllowUsers" {
|
||||||
$server.AddUserToLocalGroup($allowUser1, $password, $allowGroup1)
|
#Run
|
||||||
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
|
||||||
$client.RunCmd(".\ssh $($allowUser1)@$($server.MachineName) hostname > $filePath")
|
Add-UserToLocalGroup -UserName $allowUser1 -Password $password -GroupName $allowGroup1
|
||||||
Get-Content $filePath | Should be $server.MachineName
|
|
||||||
$server.RemoveUserFromLocalGroup($allowUser1, $allowGroup1)
|
$o = ssh -p $port $allowUser1@$server -o "UserKnownHostsFile $testknownhosts" echo 1234
|
||||||
|
$o | Should Be "1234"
|
||||||
|
Remove-UserFromLocalGroup -UserName $allowUser1 -GroupName $allowGroup1
|
||||||
|
|
||||||
|
#Cleanup
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User with * wildcard' {
|
It "$tC.$tI-User with * wildcard" {
|
||||||
$server.AddUserToLocalGroup($allowUser2, $password, $allowGroup1)
|
#Run
|
||||||
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
|
||||||
$client.RunCmd(".\ssh $($allowUser2)@$($server.MachineName) hostname > $filePath")
|
Add-UserToLocalGroup -UserName $allowUser2 -Password $password -GroupName $allowGroup1
|
||||||
$LASTEXITCODE | Should Be 0
|
|
||||||
Get-Content $filePath | Should be $server.MachineName
|
$o = ssh -p $port $allowUser2@$server -o "UserKnownHostsFile $testknownhosts" echo 1234
|
||||||
$server.RemoveUserFromLocalGroup($allowUser2, $allowGroup1)
|
$o | Should Be "1234"
|
||||||
|
Remove-UserFromLocalGroup -UserName $allowUser2 -GroupName $allowGroup1
|
||||||
|
|
||||||
|
#Cleanup
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User with ? wildcard' {
|
It "$tC.$tI-User with ? wildcard" {
|
||||||
$server.AddUserToLocalGroup($allowUser3, $password, $allowGroup1)
|
#Run
|
||||||
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
Add-UserToLocalGroup -UserName $allowUser3 -Password $password -GroupName $allowGroup1
|
||||||
|
|
||||||
$client.RunCmd(".\ssh $($allowUser3)@$($server.MachineName) hostname > $filePath")
|
$o = ssh -p $port $allowUser3@$server -o "UserKnownHostsFile $testknownhosts" echo 1234
|
||||||
$LASTEXITCODE | Should Be 0
|
$o | Should Be "1234"
|
||||||
Get-Content $filePath | Should be $server.MachineName
|
Remove-UserFromLocalGroup -UserName $allowUser3 -GroupName $allowGroup1
|
||||||
$server.RemoveUserFromLocalGroup($allowUser3, $allowGroup1)
|
|
||||||
|
#Cleanup
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User with full name in the list of AllowUsers but not in any AllowGroups' {
|
It "$tC.$tI-User with full name in the list of AllowUsers but not in any AllowGroups" {
|
||||||
$server.AddLocalUser($allowUser4, $password)
|
#Run
|
||||||
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
|
||||||
$client.RunCmd(".\ssh $($allowUser4)@$($server.MachineName) hostname > $filePath")
|
Add-LocalUser -UserName $allowUser4 -Password $password
|
||||||
|
|
||||||
|
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $allowUser4@$server echo 1234
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
Get-Content $filePath | Should BeNullOrEmpty
|
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||||
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
|
#Cleanup
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User with full name in the list of DenyUsers' {
|
It "$tC.$tI-User with full name in the list of DenyUsers" {
|
||||||
$server.AddUserToLocalGroup($denyUser1, $password, $allowGroup1)
|
#Run
|
||||||
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
|
||||||
$client.RunCmd(".\ssh $($denyUser1)@$($server.MachineName) hostname > $filePath")
|
Add-UserToLocalGroup -UserName $denyUser1 -Password $password -GroupName $allowGroup1
|
||||||
|
|
||||||
|
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $denyUser1@$server echo 1234
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
Get-Content $filePath | Should BeNullOrEmpty
|
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||||
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
$server.RemoveUserFromLocalGroup($denyUser1, $allowGroup1)
|
Remove-UserFromLocalGroup -UserName $denyUser1 -GroupName $allowGroup1
|
||||||
|
|
||||||
|
#Cleanup
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User with * wildcard in the list of DenyUsers' {
|
It "$tC.$tI-User with * wildcard in the list of DenyUsers" {
|
||||||
$server.AddUserToLocalGroup($denyUser2, $password, $allowGroup1)
|
#Run
|
||||||
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
|
||||||
$str = ".\ssh $($denyUser2)@$($server.MachineName) hostname > $filePath"
|
Add-UserToLocalGroup -UserName $denyUser2 -Password $password -GroupName $allowGroup1
|
||||||
$client.RunCmd(".\ssh $($denyUser2)@$($server.MachineName) hostname > $filePath")
|
|
||||||
|
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $denyUser2@$server echo 1234
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
Get-Content $filePath | Should BeNullOrEmpty
|
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||||
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
$server.RemoveUserFromLocalGroup($denyUser2, $allowGroup1)
|
Remove-UserFromLocalGroup -UserName $denyUser2 -GroupName $allowGroup1
|
||||||
|
|
||||||
|
#Cleanup
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User with ? wildcard in the list of DenyUsers' {
|
It "$tC.$tI-User with ? wildcard in the list of DenyUsers" {
|
||||||
$server.AddUserToLocalGroup($denyUser3, $password, $allowGroup1)
|
#Run
|
||||||
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
|
||||||
$client.RunCmd(".\ssh $($denyUser3)@$($server.MachineName) hostname > $filePath")
|
Add-UserToLocalGroup -UserName $denyUser3 -Password $password -GroupName $allowGroup1
|
||||||
|
|
||||||
|
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $denyUser3@$server echo 1234
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
Get-Content $filePath | Should BeNullOrEmpty
|
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||||
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
$server.RemoveUserFromLocalGroup($denyUser3, $allowGroup1)
|
Remove-UserFromLocalGroup -UserName $denyUser3 -GroupName $allowGroup1
|
||||||
|
|
||||||
|
#Cleanup
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User is listed in the list of AllowUsers but also in a full name DenyGroups and AllowGroups' {
|
It "$tC.$tI-User is listed in the list of AllowUsers but also in a full name DenyGroups and AllowGroups" {
|
||||||
$server.AddUserToLocalGroup($localuser1, $password, $allowGroup1)
|
#Run
|
||||||
$server.AddUserToLocalGroup($localuser1, $password, $denyGroup1)
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
|
||||||
$client.RunCmd(".\ssh $($localuser1)@$($server.MachineName) hostname > $filePath")
|
Add-UserToLocalGroup -UserName $localuser1 -Password $password -GroupName $allowGroup1
|
||||||
|
Add-UserToLocalGroup -UserName $localuser1 -Password $password -GroupName $denyGroup1
|
||||||
|
|
||||||
|
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $localuser1@$server echo 1234
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
Get-Content $filePath | Should BeNullOrEmpty
|
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||||
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
|
Remove-UserFromLocalGroup -UserName $localuser1 -GroupName $allowGroup1
|
||||||
|
Remove-UserFromLocalGroup -UserName $localuser1 -GroupName $denyGroup1
|
||||||
|
|
||||||
$server.RemoveUserFromLocalGroup($localuser1, $allowGroup1)
|
#Cleanup
|
||||||
$server.RemoveUserFromLocalGroup($localuser1, $denyGroup1)
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User is listed in the list of AllowUsers but also in a wildcard * DenyGroups' {
|
It "$tC.$tI-User is listed in the list of AllowUsers but also in a wildcard * DenyGroups" {
|
||||||
$server.AddUserToLocalGroup($localuser2, $password, $denyGroup2)
|
#Run
|
||||||
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
|
||||||
$client.RunCmd(".\ssh $($localuser2)@$($server.MachineName) hostname > $filePath")
|
Add-UserToLocalGroup -UserName $localuser2 -Password $password -GroupName $denyGroup2
|
||||||
|
|
||||||
|
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $localuser2@$server echo 1234
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
Get-Content $filePath | Should BeNullOrEmpty
|
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||||
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
$server.RemoveUserFromLocalGroup($localuser2, $denyGroup2)
|
Remove-UserFromLocalGroup -UserName $localuser2 -GroupName $denyGroup2
|
||||||
|
|
||||||
|
#Cleanup
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'User is listed in the list of AllowUsers but also in a wildcard ? DenyGroups' {
|
It "$tC.$tI-User is listed in the list of AllowUsers but also in a wildcard ? DenyGroups" {
|
||||||
$server.AddUserToLocalGroup($localuser3, $password, $denyGroup3)
|
#Run
|
||||||
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-f $sshdConfigPath", "-E $logPath") -NoNewWindow
|
||||||
|
|
||||||
$client.RunCmd(".\ssh $($localuser3)@$($server.MachineName) hostname > $filePath")
|
Add-UserToLocalGroup -UserName $localuser3 -Password $password -GroupName $denyGroup3
|
||||||
|
|
||||||
|
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $localuser3@$server echo 1234
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
Get-Content $filePath | Should BeNullOrEmpty
|
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||||
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
$server.RemoveUserFromLocalGroup($localuser3, $denyGroup3)
|
Remove-UserFromLocalGroup -UserName $localuser3 -GroupName $denyGroup3
|
||||||
|
|
||||||
|
#Cleanup
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
119
regress/pesterTests/testdata/SSHD_Config
vendored
Normal file
119
regress/pesterTests/testdata/SSHD_Config
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# test usage of sshd_config
|
||||||
|
|
||||||
|
Port 47003
|
||||||
|
#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 sshtest_hostkey_rsa
|
||||||
|
HostKey sshtest_hostkey_dsa
|
||||||
|
HostKey sshtest_hostkey_ecdsa
|
||||||
|
HostKey sshtest_hostkey_ed25519
|
||||||
|
|
||||||
|
# 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 -l DEBUG3
|
||||||
|
|
||||||
|
# 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*
|
||||||
|
hostkeyagent \\.\pipe\openssh-ssh-agent
|
26
servconf.c
26
servconf.c
@ -2084,6 +2084,32 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
|
|||||||
fatal("%s: terminating, %d bad configuration options",
|
fatal("%s: terminating, %d bad configuration options",
|
||||||
filename, bad_options);
|
filename, bad_options);
|
||||||
process_queued_listen_addrs(options);
|
process_queued_listen_addrs(options);
|
||||||
|
|
||||||
|
#ifdef WINDOWS
|
||||||
|
/* TODO - Refactor this into a platform specific post-read config processing routine.
|
||||||
|
* TODO - support all forms of username, groupname.
|
||||||
|
* a) domain\groupname
|
||||||
|
* b) domain\groupname@hostip
|
||||||
|
* c) full_domain_name\groupname
|
||||||
|
* d) full_domain_name\groupname@hostip
|
||||||
|
* e) user@domain
|
||||||
|
* f) domain\user
|
||||||
|
* g) fulldomain\user
|
||||||
|
* h) user@domain@hostip
|
||||||
|
*/
|
||||||
|
/* convert the users, user groups to lower case */
|
||||||
|
for(int i = 0; i < options->num_allow_users; i++)
|
||||||
|
lowercase(options->allow_users[i]);
|
||||||
|
|
||||||
|
for (int i = 0; i < options->num_deny_users; i++)
|
||||||
|
lowercase(options->deny_users[i]);
|
||||||
|
|
||||||
|
for (int i = 0; i < options->num_allow_groups; i++)
|
||||||
|
lowercase(options->allow_groups[i]);
|
||||||
|
|
||||||
|
for (int i = 0; i < options->num_deny_groups; i++)
|
||||||
|
lowercase(options->deny_groups[i]);
|
||||||
|
#endif // WINDOWS
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
16
serverloop.c
16
serverloop.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: serverloop.c,v 1.193 2017/05/31 07:00:13 markus Exp $ */
|
/* $OpenBSD: serverloop.c,v 1.195 2017/08/11 04:16:35 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
|
||||||
@ -204,6 +204,7 @@ wait_until_can_do_something(int connection_in, int connection_out,
|
|||||||
int ret;
|
int ret;
|
||||||
time_t minwait_secs = 0;
|
time_t minwait_secs = 0;
|
||||||
int client_alive_scheduled = 0;
|
int client_alive_scheduled = 0;
|
||||||
|
static time_t last_client_time;
|
||||||
|
|
||||||
/* Allocate and update select() masks for channel descriptors. */
|
/* Allocate and update select() masks for channel descriptors. */
|
||||||
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
|
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
|
||||||
@ -268,8 +269,19 @@ wait_until_can_do_something(int connection_in, int connection_out,
|
|||||||
memset(*writesetp, 0, *nallocp);
|
memset(*writesetp, 0, *nallocp);
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
error("select: %.100s", strerror(errno));
|
error("select: %.100s", strerror(errno));
|
||||||
} else if (ret == 0 && client_alive_scheduled)
|
} else if (client_alive_scheduled) {
|
||||||
|
time_t now = monotime();
|
||||||
|
|
||||||
|
if (ret == 0) { /* timeout */
|
||||||
client_alive_check();
|
client_alive_check();
|
||||||
|
} else if (FD_ISSET(connection_in, *readsetp)) {
|
||||||
|
last_client_time = now;
|
||||||
|
} else if (last_client_time != 0 && last_client_time +
|
||||||
|
options.client_alive_interval <= now) {
|
||||||
|
client_alive_check();
|
||||||
|
last_client_time = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
notify_done(*readsetp);
|
notify_done(*readsetp);
|
||||||
}
|
}
|
||||||
|
83
session.c
83
session.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: session.c,v 1.290 2017/06/24 06:34:38 djm Exp $ */
|
/* $OpenBSD: session.c,v 1.291 2017/08/18 05:36:45 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
|
||||||
@ -1102,65 +1102,6 @@ check_quietlogin(Session *s, const char *command)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Sets the value of the given variable in the environment. If the variable
|
|
||||||
* already exists, its value is overridden.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
child_set_env(char ***envp, u_int *envsizep, const char *name,
|
|
||||||
const char *value)
|
|
||||||
{
|
|
||||||
char **env;
|
|
||||||
u_int envsize;
|
|
||||||
u_int i, namelen;
|
|
||||||
|
|
||||||
if (strchr(name, '=') != NULL) {
|
|
||||||
error("Invalid environment variable \"%.100s\"", name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're passed an uninitialized list, allocate a single null
|
|
||||||
* entry before continuing.
|
|
||||||
*/
|
|
||||||
if (*envp == NULL && *envsizep == 0) {
|
|
||||||
*envp = xmalloc(sizeof(char *));
|
|
||||||
*envp[0] = NULL;
|
|
||||||
*envsizep = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the slot where the value should be stored. If the variable
|
|
||||||
* already exists, we reuse the slot; otherwise we append a new slot
|
|
||||||
* at the end of the array, expanding if necessary.
|
|
||||||
*/
|
|
||||||
env = *envp;
|
|
||||||
namelen = strlen(name);
|
|
||||||
for (i = 0; env[i]; i++)
|
|
||||||
if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
|
|
||||||
break;
|
|
||||||
if (env[i]) {
|
|
||||||
/* Reuse the slot. */
|
|
||||||
free(env[i]);
|
|
||||||
} else {
|
|
||||||
/* New variable. Expand if necessary. */
|
|
||||||
envsize = *envsizep;
|
|
||||||
if (i >= envsize - 1) {
|
|
||||||
if (envsize >= 1000)
|
|
||||||
fatal("child_set_env: too many env vars");
|
|
||||||
envsize += 50;
|
|
||||||
env = (*envp) = xreallocarray(env, envsize, sizeof(char *));
|
|
||||||
*envsizep = envsize;
|
|
||||||
}
|
|
||||||
/* Need to set the NULL pointer at end of array beyond the new slot. */
|
|
||||||
env[i + 1] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate space and format the variable in the appropriate slot. */
|
|
||||||
env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
|
|
||||||
snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads environment variables from the given file and adds/overrides them
|
* Reads environment variables from the given file and adds/overrides them
|
||||||
* into the environment. If the file does not exist, this does nothing.
|
* into the environment. If the file does not exist, this does nothing.
|
||||||
@ -1262,8 +1203,9 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_ETC_DEFAULT_LOGIN */
|
#endif /* HAVE_ETC_DEFAULT_LOGIN */
|
||||||
|
|
||||||
void
|
static void
|
||||||
copy_environment(char **source, char ***env, u_int *envsize)
|
copy_environment_blacklist(char **source, char ***env, u_int *envsize,
|
||||||
|
const char *blacklist)
|
||||||
{
|
{
|
||||||
char *var_name, *var_val;
|
char *var_name, *var_val;
|
||||||
int i;
|
int i;
|
||||||
@ -1279,13 +1221,22 @@ copy_environment(char **source, char ***env, u_int *envsize)
|
|||||||
}
|
}
|
||||||
*var_val++ = '\0';
|
*var_val++ = '\0';
|
||||||
|
|
||||||
|
if (blacklist == NULL ||
|
||||||
|
match_pattern_list(var_name, blacklist, 0) != 1) {
|
||||||
debug3("Copy environment: %s=%s", var_name, var_val);
|
debug3("Copy environment: %s=%s", var_name, var_val);
|
||||||
child_set_env(env, envsize, var_name, var_val);
|
child_set_env(env, envsize, var_name, var_val);
|
||||||
|
}
|
||||||
|
|
||||||
free(var_name);
|
free(var_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
copy_environment(char **source, char ***env, u_int *envsize)
|
||||||
|
{
|
||||||
|
copy_environment_blacklist(source, env, envsize, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static char **
|
static char **
|
||||||
do_setup_env(Session *s, const char *shell)
|
do_setup_env(Session *s, const char *shell)
|
||||||
{
|
{
|
||||||
@ -1447,12 +1398,16 @@ do_setup_env(Session *s, const char *shell)
|
|||||||
if (options.use_pam) {
|
if (options.use_pam) {
|
||||||
char **p;
|
char **p;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't allow SSH_AUTH_INFO variables posted to PAM to leak
|
||||||
|
* back into the environment.
|
||||||
|
*/
|
||||||
p = fetch_pam_child_environment();
|
p = fetch_pam_child_environment();
|
||||||
copy_environment(p, &env, &envsize);
|
copy_environment_blacklist(p, &env, &envsize, "SSH_AUTH_INFO*");
|
||||||
free_pam_environment(p);
|
free_pam_environment(p);
|
||||||
|
|
||||||
p = fetch_pam_environment();
|
p = fetch_pam_environment();
|
||||||
copy_environment(p, &env, &envsize);
|
copy_environment_blacklist(p, &env, &envsize, "SSH_AUTH_INFO*");
|
||||||
free_pam_environment(p);
|
free_pam_environment(p);
|
||||||
}
|
}
|
||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: session.h,v 1.33 2016/08/13 17:47:41 markus Exp $ */
|
/* $OpenBSD: session.h,v 1.34 2017/08/18 05:36:45 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
@ -77,8 +77,6 @@ Session *session_new(void);
|
|||||||
Session *session_by_tty(char *);
|
Session *session_by_tty(char *);
|
||||||
void session_close(Session *);
|
void session_close(Session *);
|
||||||
void do_setusercontext(struct passwd *);
|
void do_setusercontext(struct passwd *);
|
||||||
void child_set_env(char ***envp, u_int *envsizep, const char *name,
|
|
||||||
const char *value);
|
|
||||||
|
|
||||||
const char *session_get_remote_name_or_ip(struct ssh *, u_int, int);
|
const char *session_get_remote_name_or_ip(struct ssh *, u_int, int);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sftp-client.c,v 1.126 2017/01/03 05:46:51 djm Exp $ */
|
/* $OpenBSD: sftp-client.c,v 1.127 2017/08/11 04:41:08 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||||
*
|
*
|
||||||
@ -140,7 +140,7 @@ get_msg(struct sftp_conn *conn, struct sshbuf *m)
|
|||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
if (atomicio6(read, conn->fd_in, p, 4,
|
if (atomicio6(read, conn->fd_in, p, 4,
|
||||||
conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
|
conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
|
||||||
if (errno == EPIPE)
|
if (errno == EPIPE || errno == ECONNRESET)
|
||||||
fatal("Connection closed");
|
fatal("Connection closed");
|
||||||
else
|
else
|
||||||
fatal("Couldn't read packet: %s", strerror(errno));
|
fatal("Couldn't read packet: %s", strerror(errno));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-add.c,v 1.132 2017/05/30 14:16:41 markus Exp $ */
|
/* $OpenBSD: ssh-add.c,v 1.133 2017/07/01 13:50:45 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
|
||||||
@ -55,7 +55,6 @@
|
|||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "rsa.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "sshkey.h"
|
#include "sshkey.h"
|
||||||
#include "sshbuf.h"
|
#include "sshbuf.h"
|
||||||
|
315
ssh-agent.c
315
ssh-agent.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-agent.c,v 1.221 2017/04/30 23:29:10 djm Exp $ */
|
/* $OpenBSD: ssh-agent.c,v 1.224 2017/07/24 04:34:28 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
|
||||||
@ -60,6 +60,9 @@
|
|||||||
#ifdef HAVE_PATHS_H
|
#ifdef HAVE_PATHS_H
|
||||||
# include <paths.h>
|
# include <paths.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_POLL_H
|
||||||
|
# include <poll.h>
|
||||||
|
#endif
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -73,7 +76,6 @@
|
|||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "rsa.h"
|
|
||||||
#include "sshbuf.h"
|
#include "sshbuf.h"
|
||||||
#include "sshkey.h"
|
#include "sshkey.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
@ -92,6 +94,9 @@
|
|||||||
# define DEFAULT_PKCS11_WHITELIST "/usr/lib*/*,/usr/local/lib*/*"
|
# define DEFAULT_PKCS11_WHITELIST "/usr/lib*/*,/usr/local/lib*/*"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Maximum accepted message length */
|
||||||
|
#define AGENT_MAX_LEN (256*1024)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AUTH_UNUSED,
|
AUTH_UNUSED,
|
||||||
AUTH_SOCKET,
|
AUTH_SOCKET,
|
||||||
@ -635,30 +640,46 @@ send:
|
|||||||
|
|
||||||
/* dispatch incoming messages */
|
/* dispatch incoming messages */
|
||||||
|
|
||||||
static void
|
static int
|
||||||
process_message(SocketEntry *e)
|
process_message(u_int socknum)
|
||||||
{
|
{
|
||||||
u_int msg_len;
|
u_int msg_len;
|
||||||
u_char type;
|
u_char type;
|
||||||
const u_char *cp;
|
const u_char *cp;
|
||||||
int r;
|
int r;
|
||||||
|
SocketEntry *e;
|
||||||
|
|
||||||
|
if (socknum >= sockets_alloc) {
|
||||||
|
fatal("%s: socket number %u >= allocated %u",
|
||||||
|
__func__, socknum, sockets_alloc);
|
||||||
|
}
|
||||||
|
e = &sockets[socknum];
|
||||||
|
|
||||||
if (sshbuf_len(e->input) < 5)
|
if (sshbuf_len(e->input) < 5)
|
||||||
return; /* Incomplete message. */
|
return 0; /* Incomplete message header. */
|
||||||
cp = sshbuf_ptr(e->input);
|
cp = sshbuf_ptr(e->input);
|
||||||
msg_len = PEEK_U32(cp);
|
msg_len = PEEK_U32(cp);
|
||||||
if (msg_len > 256 * 1024) {
|
if (msg_len > AGENT_MAX_LEN) {
|
||||||
close_socket(e);
|
debug("%s: socket %u (fd=%d) message too long %u > %u",
|
||||||
return;
|
__func__, socknum, e->fd, msg_len, AGENT_MAX_LEN);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (sshbuf_len(e->input) < msg_len + 4)
|
if (sshbuf_len(e->input) < msg_len + 4)
|
||||||
return;
|
return 0; /* Incomplete message body. */
|
||||||
|
|
||||||
/* move the current input to e->request */
|
/* move the current input to e->request */
|
||||||
sshbuf_reset(e->request);
|
sshbuf_reset(e->request);
|
||||||
if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 ||
|
if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 ||
|
||||||
(r = sshbuf_get_u8(e->request, &type)) != 0)
|
(r = sshbuf_get_u8(e->request, &type)) != 0) {
|
||||||
|
if (r == SSH_ERR_MESSAGE_INCOMPLETE ||
|
||||||
|
r == SSH_ERR_STRING_TOO_LARGE) {
|
||||||
|
debug("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("%s: socket %u (fd=%d) type %d", __func__, socknum, e->fd, type);
|
||||||
|
|
||||||
/* check wheter agent is locked */
|
/* check wheter agent is locked */
|
||||||
if (locked && type != SSH_AGENTC_UNLOCK) {
|
if (locked && type != SSH_AGENTC_UNLOCK) {
|
||||||
@ -672,10 +693,9 @@ process_message(SocketEntry *e)
|
|||||||
/* send a fail message for all other request types */
|
/* send a fail message for all other request types */
|
||||||
send_status(e, 0);
|
send_status(e, 0);
|
||||||
}
|
}
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("type %d", type);
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SSH_AGENTC_LOCK:
|
case SSH_AGENTC_LOCK:
|
||||||
case SSH_AGENTC_UNLOCK:
|
case SSH_AGENTC_UNLOCK:
|
||||||
@ -717,6 +737,7 @@ process_message(SocketEntry *e)
|
|||||||
send_status(e, 0);
|
send_status(e, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -758,19 +779,141 @@ new_socket(sock_type type, int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
|
handle_socket_read(u_int socknum)
|
||||||
struct timeval **tvpp)
|
|
||||||
{
|
{
|
||||||
u_int i, sz;
|
struct sockaddr_un sunaddr;
|
||||||
int n = 0;
|
socklen_t slen;
|
||||||
static struct timeval tv;
|
uid_t euid;
|
||||||
|
gid_t egid;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
slen = sizeof(sunaddr);
|
||||||
|
fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen);
|
||||||
|
if (fd < 0) {
|
||||||
|
error("accept from AUTH_SOCKET: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (getpeereid(fd, &euid, &egid) < 0) {
|
||||||
|
error("getpeereid %d failed: %s", fd, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((euid != 0) && (getuid() != euid)) {
|
||||||
|
error("uid mismatch: peer euid %u != uid %u",
|
||||||
|
(u_int) euid, (u_int) getuid());
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
new_socket(AUTH_CONNECTION, fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
handle_conn_read(u_int socknum)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
ssize_t len;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) {
|
||||||
|
if (len == -1) {
|
||||||
|
if (errno == EAGAIN || errno == EINTR)
|
||||||
|
return 0;
|
||||||
|
error("%s: read error on socket %u (fd %d): %s",
|
||||||
|
__func__, socknum, sockets[socknum].fd,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0)
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
explicit_bzero(buf, sizeof(buf));
|
||||||
|
process_message(socknum);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
handle_conn_write(u_int socknum)
|
||||||
|
{
|
||||||
|
ssize_t len;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (sshbuf_len(sockets[socknum].output) == 0)
|
||||||
|
return 0; /* shouldn't happen */
|
||||||
|
if ((len = write(sockets[socknum].fd,
|
||||||
|
sshbuf_ptr(sockets[socknum].output),
|
||||||
|
sshbuf_len(sockets[socknum].output))) <= 0) {
|
||||||
|
if (len == -1) {
|
||||||
|
if (errno == EAGAIN || errno == EINTR)
|
||||||
|
return 0;
|
||||||
|
error("%s: read error on socket %u (fd %d): %s",
|
||||||
|
__func__, socknum, sockets[socknum].fd,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0)
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
after_poll(struct pollfd *pfd, size_t npfd)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
u_int socknum;
|
||||||
|
|
||||||
|
for (i = 0; i < npfd; i++) {
|
||||||
|
if (pfd[i].revents == 0)
|
||||||
|
continue;
|
||||||
|
/* Find sockets entry */
|
||||||
|
for (socknum = 0; socknum < sockets_alloc; socknum++) {
|
||||||
|
if (sockets[socknum].type != AUTH_SOCKET &&
|
||||||
|
sockets[socknum].type != AUTH_CONNECTION)
|
||||||
|
continue;
|
||||||
|
if (pfd[i].fd == sockets[socknum].fd)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (socknum >= sockets_alloc) {
|
||||||
|
error("%s: no socket for fd %d", __func__, pfd[i].fd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Process events */
|
||||||
|
switch (sockets[socknum].type) {
|
||||||
|
case AUTH_SOCKET:
|
||||||
|
if ((pfd[i].revents & (POLLIN|POLLERR)) != 0 &&
|
||||||
|
handle_socket_read(socknum) != 0)
|
||||||
|
close_socket(&sockets[socknum]);
|
||||||
|
break;
|
||||||
|
case AUTH_CONNECTION:
|
||||||
|
if ((pfd[i].revents & (POLLIN|POLLERR)) != 0 &&
|
||||||
|
handle_conn_read(socknum) != 0) {
|
||||||
|
close_socket(&sockets[socknum]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((pfd[i].revents & (POLLOUT|POLLHUP)) != 0 &&
|
||||||
|
handle_conn_write(socknum) != 0)
|
||||||
|
close_socket(&sockets[socknum]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp)
|
||||||
|
{
|
||||||
|
struct pollfd *pfd = *pfdp;
|
||||||
|
size_t i, j, npfd = 0;
|
||||||
time_t deadline;
|
time_t deadline;
|
||||||
|
|
||||||
|
/* Count active sockets */
|
||||||
for (i = 0; i < sockets_alloc; i++) {
|
for (i = 0; i < sockets_alloc; i++) {
|
||||||
switch (sockets[i].type) {
|
switch (sockets[i].type) {
|
||||||
case AUTH_SOCKET:
|
case AUTH_SOCKET:
|
||||||
case AUTH_CONNECTION:
|
case AUTH_CONNECTION:
|
||||||
n = MAXIMUM(n, sockets[i].fd);
|
npfd++;
|
||||||
break;
|
break;
|
||||||
case AUTH_UNUSED:
|
case AUTH_UNUSED:
|
||||||
break;
|
break;
|
||||||
@ -779,28 +922,23 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (npfd != *npfdp &&
|
||||||
|
(pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL)
|
||||||
|
fatal("%s: recallocarray failed", __func__);
|
||||||
|
*pfdp = pfd;
|
||||||
|
*npfdp = npfd;
|
||||||
|
|
||||||
sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
|
for (i = j = 0; i < sockets_alloc; i++) {
|
||||||
if (*fdrp == NULL || sz > *nallocp) {
|
|
||||||
free(*fdrp);
|
|
||||||
free(*fdwp);
|
|
||||||
*fdrp = xmalloc(sz);
|
|
||||||
*fdwp = xmalloc(sz);
|
|
||||||
*nallocp = sz;
|
|
||||||
}
|
|
||||||
if (n < *fdl)
|
|
||||||
debug("XXX shrink: %d < %d", n, *fdl);
|
|
||||||
*fdl = n;
|
|
||||||
memset(*fdrp, 0, sz);
|
|
||||||
memset(*fdwp, 0, sz);
|
|
||||||
|
|
||||||
for (i = 0; i < sockets_alloc; i++) {
|
|
||||||
switch (sockets[i].type) {
|
switch (sockets[i].type) {
|
||||||
case AUTH_SOCKET:
|
case AUTH_SOCKET:
|
||||||
case AUTH_CONNECTION:
|
case AUTH_CONNECTION:
|
||||||
FD_SET(sockets[i].fd, *fdrp);
|
pfd[j].fd = sockets[i].fd;
|
||||||
|
pfd[j].revents = 0;
|
||||||
|
/* XXX backoff when input buffer full */
|
||||||
|
pfd[j].events = POLLIN;
|
||||||
if (sshbuf_len(sockets[i].output) > 0)
|
if (sshbuf_len(sockets[i].output) > 0)
|
||||||
FD_SET(sockets[i].fd, *fdwp);
|
pfd[j].events |= POLLOUT;
|
||||||
|
j++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -811,98 +949,16 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
|
|||||||
deadline = (deadline == 0) ? parent_alive_interval :
|
deadline = (deadline == 0) ? parent_alive_interval :
|
||||||
MINIMUM(deadline, parent_alive_interval);
|
MINIMUM(deadline, parent_alive_interval);
|
||||||
if (deadline == 0) {
|
if (deadline == 0) {
|
||||||
*tvpp = NULL;
|
*timeoutp = -1; /* INFTIM */
|
||||||
} else {
|
} else {
|
||||||
tv.tv_sec = deadline;
|
if (deadline > INT_MAX / 1000)
|
||||||
tv.tv_usec = 0;
|
*timeoutp = INT_MAX / 1000;
|
||||||
*tvpp = &tv;
|
else
|
||||||
|
*timeoutp = deadline * 1000;
|
||||||
}
|
}
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
after_select(fd_set *readset, fd_set *writeset)
|
|
||||||
{
|
|
||||||
struct sockaddr_un sunaddr;
|
|
||||||
socklen_t slen;
|
|
||||||
char buf[1024];
|
|
||||||
int len, sock, r;
|
|
||||||
u_int i, orig_alloc;
|
|
||||||
uid_t euid;
|
|
||||||
gid_t egid;
|
|
||||||
|
|
||||||
for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++)
|
|
||||||
switch (sockets[i].type) {
|
|
||||||
case AUTH_UNUSED:
|
|
||||||
break;
|
|
||||||
case AUTH_SOCKET:
|
|
||||||
if (FD_ISSET(sockets[i].fd, readset)) {
|
|
||||||
slen = sizeof(sunaddr);
|
|
||||||
sock = accept(sockets[i].fd,
|
|
||||||
(struct sockaddr *)&sunaddr, &slen);
|
|
||||||
if (sock < 0) {
|
|
||||||
error("accept from AUTH_SOCKET: %s",
|
|
||||||
strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (getpeereid(sock, &euid, &egid) < 0) {
|
|
||||||
error("getpeereid %d failed: %s",
|
|
||||||
sock, strerror(errno));
|
|
||||||
close(sock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((euid != 0) && (getuid() != euid)) {
|
|
||||||
error("uid mismatch: "
|
|
||||||
"peer euid %u != uid %u",
|
|
||||||
(u_int) euid, (u_int) getuid());
|
|
||||||
close(sock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
new_socket(AUTH_CONNECTION, sock);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AUTH_CONNECTION:
|
|
||||||
if (sshbuf_len(sockets[i].output) > 0 &&
|
|
||||||
FD_ISSET(sockets[i].fd, writeset)) {
|
|
||||||
len = write(sockets[i].fd,
|
|
||||||
sshbuf_ptr(sockets[i].output),
|
|
||||||
sshbuf_len(sockets[i].output));
|
|
||||||
if (len == -1 && (errno == EAGAIN ||
|
|
||||||
errno == EWOULDBLOCK ||
|
|
||||||
errno == EINTR))
|
|
||||||
continue;
|
|
||||||
if (len <= 0) {
|
|
||||||
close_socket(&sockets[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((r = sshbuf_consume(sockets[i].output,
|
|
||||||
len)) != 0)
|
|
||||||
fatal("%s: buffer error: %s",
|
|
||||||
__func__, ssh_err(r));
|
|
||||||
}
|
|
||||||
if (FD_ISSET(sockets[i].fd, readset)) {
|
|
||||||
len = read(sockets[i].fd, buf, sizeof(buf));
|
|
||||||
if (len == -1 && (errno == EAGAIN ||
|
|
||||||
errno == EWOULDBLOCK ||
|
|
||||||
errno == EINTR))
|
|
||||||
continue;
|
|
||||||
if (len <= 0) {
|
|
||||||
close_socket(&sockets[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((r = sshbuf_put(sockets[i].input,
|
|
||||||
buf, len)) != 0)
|
|
||||||
fatal("%s: buffer error: %s",
|
|
||||||
__func__, ssh_err(r));
|
|
||||||
explicit_bzero(buf, sizeof(buf));
|
|
||||||
process_message(&sockets[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fatal("Unknown type %d", sockets[i].type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cleanup_socket(void)
|
cleanup_socket(void)
|
||||||
{
|
{
|
||||||
@ -962,9 +1018,7 @@ main(int ac, char **av)
|
|||||||
{
|
{
|
||||||
int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0;
|
int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0;
|
||||||
int sock, fd, ch, result, saved_errno;
|
int sock, fd, ch, result, saved_errno;
|
||||||
u_int nalloc;
|
|
||||||
char *shell, *format, *pidstr, *agentsocket = NULL;
|
char *shell, *format, *pidstr, *agentsocket = NULL;
|
||||||
fd_set *readsetp = NULL, *writesetp = NULL;
|
|
||||||
#ifdef HAVE_SETRLIMIT
|
#ifdef HAVE_SETRLIMIT
|
||||||
struct rlimit rlim;
|
struct rlimit rlim;
|
||||||
#endif
|
#endif
|
||||||
@ -972,9 +1026,11 @@ main(int ac, char **av)
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char pidstrbuf[1 + 3 * sizeof pid];
|
char pidstrbuf[1 + 3 * sizeof pid];
|
||||||
struct timeval *tvp = NULL;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
mode_t prev_mask;
|
mode_t prev_mask;
|
||||||
|
int timeout = -1; /* INFTIM */
|
||||||
|
struct pollfd *pfd = NULL;
|
||||||
|
size_t npfd = 0;
|
||||||
|
|
||||||
ssh_malloc_init(); /* must be called before any mallocs */
|
ssh_malloc_init(); /* must be called before any mallocs */
|
||||||
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
|
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
|
||||||
@ -1195,15 +1251,14 @@ skip:
|
|||||||
signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN);
|
signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN);
|
||||||
signal(SIGHUP, cleanup_handler);
|
signal(SIGHUP, cleanup_handler);
|
||||||
signal(SIGTERM, cleanup_handler);
|
signal(SIGTERM, cleanup_handler);
|
||||||
nalloc = 0;
|
|
||||||
|
|
||||||
if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1)
|
if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1)
|
||||||
fatal("%s: pledge: %s", __progname, strerror(errno));
|
fatal("%s: pledge: %s", __progname, strerror(errno));
|
||||||
platform_pledge_agent();
|
platform_pledge_agent();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
|
prepare_poll(&pfd, &npfd, &timeout);
|
||||||
result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
|
result = poll(pfd, npfd, timeout);
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
if (parent_alive_interval != 0)
|
if (parent_alive_interval != 0)
|
||||||
check_parent_exists();
|
check_parent_exists();
|
||||||
@ -1211,9 +1266,9 @@ skip:
|
|||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
if (saved_errno == EINTR)
|
if (saved_errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
fatal("select: %s", strerror(saved_errno));
|
fatal("poll: %s", strerror(saved_errno));
|
||||||
} else if (result > 0)
|
} else if (result > 0)
|
||||||
after_select(readsetp, writesetp);
|
after_poll(pfd, npfd);
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: ssh-keygen.1,v 1.142 2017/06/28 01:09:22 djm Exp $
|
.\" $OpenBSD: ssh-keygen.1,v 1.144 2017/07/08 18:32:54 jmc 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
|
||||||
@ -35,7 +35,7 @@
|
|||||||
.\" (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.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: June 28 2017 $
|
.Dd $Mdocdate: July 8 2017 $
|
||||||
.Dt SSH-KEYGEN 1
|
.Dt SSH-KEYGEN 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -126,6 +126,7 @@
|
|||||||
.Op Fl f Ar input_keyfile
|
.Op Fl f Ar input_keyfile
|
||||||
.Nm ssh-keygen
|
.Nm ssh-keygen
|
||||||
.Fl A
|
.Fl A
|
||||||
|
.Op Fl f Ar prefix_path
|
||||||
.Nm ssh-keygen
|
.Nm ssh-keygen
|
||||||
.Fl k
|
.Fl k
|
||||||
.Fl f Ar krl_file
|
.Fl f Ar krl_file
|
||||||
@ -224,6 +225,10 @@ For each of the key types (rsa, dsa, ecdsa and ed25519)
|
|||||||
for which host keys
|
for which host keys
|
||||||
do not exist, generate the host keys with the default key file path,
|
do not exist, generate the host keys with the default key file path,
|
||||||
an empty passphrase, default bits for the key type, and default comment.
|
an empty passphrase, default bits for the key type, and default comment.
|
||||||
|
If
|
||||||
|
.Fl f
|
||||||
|
has also been specified, its argument is used as a prefix to the
|
||||||
|
default path for the resulting host key files.
|
||||||
This is used by
|
This is used by
|
||||||
.Pa /etc/rc
|
.Pa /etc/rc
|
||||||
to generate new host keys.
|
to generate new host keys.
|
||||||
|
109
ssh-keygen.c
109
ssh-keygen.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-keygen.c,v 1.305 2017/06/28 01:09:22 djm Exp $ */
|
/* $OpenBSD: ssh-keygen.c,v 1.307 2017/07/07 03:53:12 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -41,7 +41,6 @@
|
|||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "sshkey.h"
|
#include "sshkey.h"
|
||||||
#include "rsa.h"
|
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
#include "uuencode.h"
|
#include "uuencode.h"
|
||||||
#include "sshbuf.h"
|
#include "sshbuf.h"
|
||||||
@ -533,7 +532,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
|
|||||||
buffer_get_bignum_bits(b, key->rsa->iqmp);
|
buffer_get_bignum_bits(b, key->rsa->iqmp);
|
||||||
buffer_get_bignum_bits(b, key->rsa->q);
|
buffer_get_bignum_bits(b, key->rsa->q);
|
||||||
buffer_get_bignum_bits(b, key->rsa->p);
|
buffer_get_bignum_bits(b, key->rsa->p);
|
||||||
if ((r = rsa_generate_additional_parameters(key->rsa)) != 0)
|
if ((r = ssh_rsa_generate_additional_parameters(key)) != 0)
|
||||||
fatal("generate RSA parameters failed: %s", ssh_err(r));
|
fatal("generate RSA parameters failed: %s", ssh_err(r));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1003,20 +1002,38 @@ do_gen_all_hostkeys(struct passwd *pw)
|
|||||||
int first = 0;
|
int first = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct sshkey *private, *public;
|
struct sshkey *private, *public;
|
||||||
char comment[1024];
|
char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
|
||||||
int i, type, fd, r;
|
int i, type, fd, r;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
for (i = 0; key_types[i].key_type; i++) {
|
for (i = 0; key_types[i].key_type; i++) {
|
||||||
if (stat(key_types[i].path, &st) == 0)
|
public = private = NULL;
|
||||||
continue;
|
prv_tmp = pub_tmp = prv_file = pub_file = NULL;
|
||||||
if (errno != ENOENT) {
|
|
||||||
|
xasprintf(&prv_file, "%s%s",
|
||||||
|
identity_file, key_types[i].path);
|
||||||
|
|
||||||
|
/* Check whether private key exists and is not zero-length */
|
||||||
|
if (stat(prv_file, &st) == 0) {
|
||||||
|
if (st.st_size != 0)
|
||||||
|
goto next;
|
||||||
|
} else if (errno != ENOENT) {
|
||||||
error("Could not stat %s: %s", key_types[i].path,
|
error("Could not stat %s: %s", key_types[i].path,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
first = 0;
|
goto failnext;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private key doesn't exist or is invalid; proceed with
|
||||||
|
* key generation.
|
||||||
|
*/
|
||||||
|
xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX",
|
||||||
|
identity_file, key_types[i].path);
|
||||||
|
xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX",
|
||||||
|
identity_file, key_types[i].path);
|
||||||
|
xasprintf(&pub_file, "%s%s.pub",
|
||||||
|
identity_file, key_types[i].path);
|
||||||
|
|
||||||
if (first == 0) {
|
if (first == 0) {
|
||||||
first = 1;
|
first = 1;
|
||||||
printf("%s: generating new host keys: ", __progname);
|
printf("%s: generating new host keys: ", __progname);
|
||||||
@ -1024,63 +1041,87 @@ do_gen_all_hostkeys(struct passwd *pw)
|
|||||||
printf("%s ", key_types[i].key_type_display);
|
printf("%s ", key_types[i].key_type_display);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
type = sshkey_type_from_name(key_types[i].key_type);
|
type = sshkey_type_from_name(key_types[i].key_type);
|
||||||
strlcpy(identity_file, key_types[i].path, sizeof(identity_file));
|
if ((fd = mkstemp(prv_tmp)) == -1) {
|
||||||
|
error("Could not save your public key in %s: %s",
|
||||||
|
prv_tmp, strerror(errno));
|
||||||
|
goto failnext;
|
||||||
|
}
|
||||||
|
close(fd); /* just using mkstemp() to generate/reserve a name */
|
||||||
bits = 0;
|
bits = 0;
|
||||||
type_bits_valid(type, NULL, &bits);
|
type_bits_valid(type, NULL, &bits);
|
||||||
if ((r = sshkey_generate(type, bits, &private)) != 0) {
|
if ((r = sshkey_generate(type, bits, &private)) != 0) {
|
||||||
error("sshkey_generate failed: %s", ssh_err(r));
|
error("sshkey_generate failed: %s", ssh_err(r));
|
||||||
first = 0;
|
goto failnext;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if ((r = sshkey_from_private(private, &public)) != 0)
|
if ((r = sshkey_from_private(private, &public)) != 0)
|
||||||
fatal("sshkey_from_private failed: %s", ssh_err(r));
|
fatal("sshkey_from_private failed: %s", ssh_err(r));
|
||||||
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
|
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
|
||||||
hostname);
|
hostname);
|
||||||
if ((r = sshkey_save_private(private, identity_file, "",
|
if ((r = sshkey_save_private(private, prv_tmp, "",
|
||||||
comment, use_new_format, new_format_cipher, rounds)) != 0) {
|
comment, use_new_format, new_format_cipher, rounds)) != 0) {
|
||||||
error("Saving key \"%s\" failed: %s",
|
error("Saving key \"%s\" failed: %s",
|
||||||
identity_file, ssh_err(r));
|
prv_tmp, ssh_err(r));
|
||||||
sshkey_free(private);
|
goto failnext;
|
||||||
sshkey_free(public);
|
|
||||||
first = 0;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
sshkey_free(private);
|
if ((fd = mkstemp(pub_tmp)) == -1) {
|
||||||
strlcat(identity_file, ".pub", sizeof(identity_file));
|
error("Could not save your public key in %s: %s",
|
||||||
fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
pub_tmp, strerror(errno));
|
||||||
if (fd == -1) {
|
goto failnext;
|
||||||
error("Could not save your public key in %s",
|
|
||||||
identity_file);
|
|
||||||
sshkey_free(public);
|
|
||||||
first = 0;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
/* Windows POSIX adpater does not support fdopen() on open(file)*/
|
/* Windows POSIX adpater does not support fdopen() on open(file)*/
|
||||||
close(fd);
|
close(fd);
|
||||||
if ((f = fopen(identity_file, "w")) == NULL) {
|
chmod(pub_tmp, 0644);
|
||||||
error("fopen %s failed: %s", identity_file, strerror(errno));
|
if ((f = fopen(pub_tmp, "w")) == NULL) {
|
||||||
|
error("fopen %s failed: %s", pub_tmp, strerror(errno));
|
||||||
#else /* !WINDOWS */
|
#else /* !WINDOWS */
|
||||||
|
(void)fchmod(fd, 0644);
|
||||||
f = fdopen(fd, "w");
|
f = fdopen(fd, "w");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
error("fdopen %s failed", identity_file);
|
error("fdopen %s failed: %s", pub_tmp, strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
#endif /* !WINDOWS */
|
#endif /* !WINDOWS */
|
||||||
sshkey_free(public);
|
sshkey_free(public);
|
||||||
first = 0;
|
first = 0;
|
||||||
continue;
|
continue;
|
||||||
|
goto failnext;
|
||||||
}
|
}
|
||||||
if ((r = sshkey_write(public, f)) != 0) {
|
if ((r = sshkey_write(public, f)) != 0) {
|
||||||
error("write key failed: %s", ssh_err(r));
|
error("write key failed: %s", ssh_err(r));
|
||||||
fclose(f);
|
fclose(f);
|
||||||
sshkey_free(public);
|
goto failnext;
|
||||||
first = 0;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
fprintf(f, " %s\n", comment);
|
fprintf(f, " %s\n", comment);
|
||||||
|
if (ferror(f) != 0) {
|
||||||
|
error("write key failed: %s", strerror(errno));
|
||||||
fclose(f);
|
fclose(f);
|
||||||
sshkey_free(public);
|
goto failnext;
|
||||||
|
}
|
||||||
|
if (fclose(f) != 0) {
|
||||||
|
error("key close failed: %s", strerror(errno));
|
||||||
|
goto failnext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rename temporary files to their permanent locations. */
|
||||||
|
if (rename(pub_tmp, pub_file) != 0) {
|
||||||
|
error("Unable to move %s into position: %s",
|
||||||
|
pub_file, strerror(errno));
|
||||||
|
goto failnext;
|
||||||
|
}
|
||||||
|
if (rename(prv_tmp, prv_file) != 0) {
|
||||||
|
error("Unable to move %s into position: %s",
|
||||||
|
key_types[i].path, strerror(errno));
|
||||||
|
failnext:
|
||||||
|
first = 0;
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
next:
|
||||||
|
sshkey_free(private);
|
||||||
|
sshkey_free(public);
|
||||||
|
free(prv_tmp);
|
||||||
|
free(pub_tmp);
|
||||||
|
free(prv_file);
|
||||||
|
free(pub_file);
|
||||||
}
|
}
|
||||||
if (first != 0)
|
if (first != 0)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
37
ssh-rsa.c
37
ssh-rsa.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-rsa.c,v 1.61 2017/05/07 23:15:59 djm Exp $ */
|
/* $OpenBSD: ssh-rsa.c,v 1.62 2017/07/01 13:50:45 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
|
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
|
||||||
*
|
*
|
||||||
@ -78,6 +78,41 @@ rsa_hash_alg_nid(int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* calculate p-1 and q-1 */
|
||||||
|
int
|
||||||
|
ssh_rsa_generate_additional_parameters(struct sshkey *key)
|
||||||
|
{
|
||||||
|
RSA *rsa;
|
||||||
|
BIGNUM *aux = NULL;
|
||||||
|
BN_CTX *ctx = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (key == NULL || key->rsa == NULL ||
|
||||||
|
sshkey_type_plain(key->type) != KEY_RSA)
|
||||||
|
return SSH_ERR_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
if ((ctx = BN_CTX_new()) == NULL)
|
||||||
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
|
if ((aux = BN_new()) == NULL) {
|
||||||
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
rsa = key->rsa;
|
||||||
|
|
||||||
|
if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) ||
|
||||||
|
(BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) ||
|
||||||
|
(BN_sub(aux, rsa->p, BN_value_one()) == 0) ||
|
||||||
|
(BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) {
|
||||||
|
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
r = 0;
|
||||||
|
out:
|
||||||
|
BN_clear_free(aux);
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
|
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
|
||||||
int
|
int
|
||||||
ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||||
|
11
ssh.c
11
ssh.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh.c,v 1.461 2017/05/30 18:58:37 bluhm Exp $ */
|
/* $OpenBSD: ssh.c,v 1.462 2017/08/12 06:46:01 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
|
||||||
@ -509,13 +509,13 @@ int
|
|||||||
main(int ac, char **av)
|
main(int ac, char **av)
|
||||||
{
|
{
|
||||||
struct ssh *ssh = NULL;
|
struct ssh *ssh = NULL;
|
||||||
int i, r, opt, exit_status, use_syslog, direct, config_test = 0;
|
int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
|
||||||
|
int config_test = 0, opt_terminated = 0;
|
||||||
char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile;
|
char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile;
|
||||||
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
|
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
|
||||||
char cname[NI_MAXHOST], uidstr[32], *conn_hash_hex;
|
char cname[NI_MAXHOST], uidstr[32], *conn_hash_hex;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
int timeout_ms;
|
|
||||||
extern int optind, optreset;
|
extern int optind, optreset;
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
struct Forward fwd;
|
struct Forward fwd;
|
||||||
@ -917,6 +917,9 @@ main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (optind > 1 && strcmp(av[optind - 1], "--") == 0)
|
||||||
|
opt_terminated = 1;
|
||||||
|
|
||||||
ac -= optind;
|
ac -= optind;
|
||||||
av += optind;
|
av += optind;
|
||||||
|
|
||||||
@ -931,7 +934,7 @@ main(int ac, char **av)
|
|||||||
host = xstrdup(++cp);
|
host = xstrdup(++cp);
|
||||||
} else
|
} else
|
||||||
host = xstrdup(*av);
|
host = xstrdup(*av);
|
||||||
if (ac > 1) {
|
if (ac > 1 && !opt_terminated) {
|
||||||
optind = optreset = 1;
|
optind = optreset = 1;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
11
ssh_config.5
11
ssh_config.5
@ -33,16 +33,13 @@
|
|||||||
.\" (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.251 2017/06/24 05:35:05 djm Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.253 2017/07/23 23:37:02 djm Exp $
|
||||||
.Dd $Mdocdate: June 24 2017 $
|
.Dd $Mdocdate: July 23 2017 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm ssh_config
|
.Nm ssh_config
|
||||||
.Nd OpenSSH SSH client configuration files
|
.Nd OpenSSH SSH client configuration files
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm ~/.ssh/config
|
|
||||||
.Nm /etc/ssh/ssh_config
|
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Xr ssh 1
|
.Xr ssh 1
|
||||||
obtains configuration data from the following sources in
|
obtains configuration data from the following sources in
|
||||||
@ -972,7 +969,9 @@ Accepted values are
|
|||||||
.Cm lowdelay ,
|
.Cm lowdelay ,
|
||||||
.Cm throughput ,
|
.Cm throughput ,
|
||||||
.Cm reliability ,
|
.Cm reliability ,
|
||||||
or a numeric value.
|
a numeric value, or
|
||||||
|
.Cm none
|
||||||
|
to use the operating system default.
|
||||||
This option may take one or two arguments, separated by whitespace.
|
This option may take one or two arguments, separated by whitespace.
|
||||||
If one argument is specified, it is used as the packet class unconditionally.
|
If one argument is specified, it is used as the packet class unconditionally.
|
||||||
If two values are specified, the first is automatically selected for
|
If two values are specified, the first is automatically selected for
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshconnect.c,v 1.282 2017/06/24 05:37:44 djm Exp $ */
|
/* $OpenBSD: sshconnect.c,v 1.283 2017/07/01 13:50:45 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
|
||||||
@ -48,7 +48,6 @@
|
|||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "rsa.h"
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshconnect2.c,v 1.264 2017/06/14 00:31:38 dtucker Exp $ */
|
/* $OpenBSD: sshconnect2.c,v 1.265 2017/08/11 04:47:12 djm 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.
|
||||||
@ -1042,6 +1042,11 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
|
|||||||
/* load the private key from the file */
|
/* load the private key from the file */
|
||||||
if ((prv = load_identity_file(id)) == NULL)
|
if ((prv = load_identity_file(id)) == NULL)
|
||||||
return SSH_ERR_KEY_NOT_FOUND;
|
return SSH_ERR_KEY_NOT_FOUND;
|
||||||
|
if (id->key != NULL && !sshkey_equal_public(prv, id->key)) {
|
||||||
|
error("%s: private key %s contents do not match public",
|
||||||
|
__func__, id->filename);
|
||||||
|
return SSH_ERR_KEY_NOT_FOUND;
|
||||||
|
}
|
||||||
ret = sshkey_sign(prv, sigp, lenp, data, datalen,
|
ret = sshkey_sign(prv, sigp, lenp, data, datalen,
|
||||||
key_sign_encode(prv), compat);
|
key_sign_encode(prv), compat);
|
||||||
sshkey_free(prv);
|
sshkey_free(prv);
|
||||||
|
3
sshd.c
3
sshd.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshd.c,v 1.490 2017/05/31 08:09:45 markus Exp $ */
|
/* $OpenBSD: sshd.c,v 1.491 2017/07/01 13:50:45 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
|
||||||
@ -88,7 +88,6 @@
|
|||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "ssh2.h"
|
#include "ssh2.h"
|
||||||
#include "rsa.h"
|
|
||||||
#include "sshpty.h"
|
#include "sshpty.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -33,15 +33,13 @@
|
|||||||
.\" (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.248 2017/06/24 07:08:57 djm Exp $
|
.\" $OpenBSD: sshd_config.5,v 1.250 2017/07/23 23:37:02 djm Exp $
|
||||||
.Dd $Mdocdate: June 24 2017 $
|
.Dd $Mdocdate: July 23 2017 $
|
||||||
.Dt SSHD_CONFIG 5
|
.Dt SSHD_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm sshd_config
|
.Nm sshd_config
|
||||||
.Nd OpenSSH SSH daemon configuration file
|
.Nd OpenSSH SSH daemon configuration file
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm /etc/ssh/sshd_config
|
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Xr sshd 8
|
.Xr sshd 8
|
||||||
reads configuration data from
|
reads configuration data from
|
||||||
@ -794,7 +792,9 @@ Accepted values are
|
|||||||
.Cm lowdelay ,
|
.Cm lowdelay ,
|
||||||
.Cm throughput ,
|
.Cm throughput ,
|
||||||
.Cm reliability ,
|
.Cm reliability ,
|
||||||
or a numeric value.
|
a numeric value, or
|
||||||
|
.Cm none
|
||||||
|
to use the operating system default.
|
||||||
This option may take one or two arguments, separated by whitespace.
|
This option may take one or two arguments, separated by whitespace.
|
||||||
If one argument is specified, it is used as the packet class unconditionally.
|
If one argument is specified, it is used as the packet class unconditionally.
|
||||||
If two values are specified, the first is automatically selected for
|
If two values are specified, the first is automatically selected for
|
||||||
|
14
sshkey.c
14
sshkey.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshkey.c,v 1.53 2017/06/28 01:09:22 djm Exp $ */
|
/* $OpenBSD: sshkey.c,v 1.56 2017/08/12 06:42:52 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
||||||
@ -51,7 +51,6 @@
|
|||||||
#include "ssherr.h"
|
#include "ssherr.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "sshbuf.h"
|
#include "sshbuf.h"
|
||||||
#include "rsa.h"
|
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "digest.h"
|
#include "digest.h"
|
||||||
#define SSHKEY_INTERNAL
|
#define SSHKEY_INTERNAL
|
||||||
@ -66,7 +65,7 @@
|
|||||||
#define KDFNAME "bcrypt"
|
#define KDFNAME "bcrypt"
|
||||||
#define AUTH_MAGIC "openssh-key-v1"
|
#define AUTH_MAGIC "openssh-key-v1"
|
||||||
#define SALT_LEN 16
|
#define SALT_LEN 16
|
||||||
#define DEFAULT_CIPHERNAME "aes256-cbc"
|
#define DEFAULT_CIPHERNAME "aes256-ctr"
|
||||||
#define DEFAULT_ROUNDS 16
|
#define DEFAULT_ROUNDS 16
|
||||||
|
|
||||||
/* Version identification string for SSH v1 identity files. */
|
/* Version identification string for SSH v1 identity files. */
|
||||||
@ -1987,11 +1986,6 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
|
|||||||
pk = NULL;
|
pk = NULL;
|
||||||
break;
|
break;
|
||||||
case KEY_UNSPEC:
|
case KEY_UNSPEC:
|
||||||
if ((key = sshkey_new(type)) == NULL) {
|
|
||||||
ret = SSH_ERR_ALLOC_FAIL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
ret = SSH_ERR_KEY_TYPE_UNKNOWN;
|
ret = SSH_ERR_KEY_TYPE_UNKNOWN;
|
||||||
goto out;
|
goto out;
|
||||||
@ -2667,7 +2661,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
|
|||||||
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
|
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
|
||||||
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
|
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
|
||||||
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
|
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
|
||||||
(r = rsa_generate_additional_parameters(k->rsa)) != 0)
|
(r = ssh_rsa_generate_additional_parameters(k)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
|
if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
|
||||||
r = SSH_ERR_KEY_LENGTH;
|
r = SSH_ERR_KEY_LENGTH;
|
||||||
@ -2681,7 +2675,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
|
|||||||
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
|
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
|
||||||
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
|
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
|
||||||
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
|
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
|
||||||
(r = rsa_generate_additional_parameters(k->rsa)) != 0)
|
(r = ssh_rsa_generate_additional_parameters(k)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
|
if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
|
||||||
r = SSH_ERR_KEY_LENGTH;
|
r = SSH_ERR_KEY_LENGTH;
|
||||||
|
5
sshkey.h
5
sshkey.h
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshkey.h,v 1.20 2017/06/28 01:09:22 djm Exp $ */
|
/* $OpenBSD: sshkey.h,v 1.21 2017/07/01 13:50:45 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
@ -196,6 +196,9 @@ int sshkey_parse_private_fileblob(struct sshbuf *buffer,
|
|||||||
int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
|
int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
|
||||||
const char *passphrase, struct sshkey **keyp, char **commentp);
|
const char *passphrase, struct sshkey **keyp, char **commentp);
|
||||||
|
|
||||||
|
/* XXX should be internal, but used by ssh-keygen */
|
||||||
|
int ssh_rsa_generate_additional_parameters(struct sshkey *);
|
||||||
|
|
||||||
#ifdef SSHKEY_INTERNAL
|
#ifdef SSHKEY_INTERNAL
|
||||||
int ssh_rsa_sign(const struct sshkey *key,
|
int ssh_rsa_sign(const struct sshkey *key,
|
||||||
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
|
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user