Source snapshot from Powershell/openssh-portable:latestw_all
This commit is contained in:
parent
7580216f04
commit
993c15663a
|
@ -17,3 +17,5 @@ f6ae971186ba68d066cd102e57d5b0b2c211a5ee systrace is dead.
|
|||
fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits
|
||||
5781670c0578fe89663c9085ed3ba477cf7e7913 Delete sshconnect1.c
|
||||
ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags
|
||||
b92c93266d8234d493857bb822260dacf4366157 moduli-gen.sh tweak
|
||||
b25bf747544265b39af74fe0716dc8d9f5b63b95 Updated moduli
|
||||
|
|
2
INSTALL
2
INSTALL
|
@ -99,7 +99,7 @@ http://www.gnu.org/software/autoconf/
|
|||
|
||||
Basic Security Module (BSM):
|
||||
|
||||
Native BSM support is know to exist in Solaris from at least 2.5.1,
|
||||
Native BSM support is known to exist in Solaris from at least 2.5.1,
|
||||
FreeBSD 6.1 and OS X. Alternatively, you may use the OpenBSM
|
||||
implementation (http://www.openbsm.org).
|
||||
|
||||
|
|
62
auth.c
62
auth.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth.c,v 1.121 2017/05/30 08:52:19 markus Exp $ */
|
||||
/* $OpenBSD: auth.c,v 1.122 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -268,21 +268,41 @@ allowed_user(struct passwd * pw)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
auth_info(Authctxt *authctxt, const char *fmt, ...)
|
||||
/*
|
||||
* Formats any key left in authctxt->auth_method_key for inclusion in
|
||||
* auth_log()'s message. Also includes authxtct->auth_method_info if present.
|
||||
*/
|
||||
static char *
|
||||
format_method_key(Authctxt *authctxt)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
const struct sshkey *key = authctxt->auth_method_key;
|
||||
const char *methinfo = authctxt->auth_method_info;
|
||||
char *fp, *ret = NULL;
|
||||
|
||||
free(authctxt->info);
|
||||
authctxt->info = NULL;
|
||||
if (key == NULL)
|
||||
return NULL;
|
||||
|
||||
va_start(ap, fmt);
|
||||
i = vasprintf(&authctxt->info, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (i < 0 || authctxt->info == NULL)
|
||||
fatal("vasprintf failed");
|
||||
if (key_is_cert(key)) {
|
||||
fp = sshkey_fingerprint(key->cert->signature_key,
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||
xasprintf(&ret, "%s ID %s (serial %llu) CA %s %s%s%s",
|
||||
sshkey_type(key), key->cert->key_id,
|
||||
(unsigned long long)key->cert->serial,
|
||||
sshkey_type(key->cert->signature_key),
|
||||
fp == NULL ? "(null)" : fp,
|
||||
methinfo == NULL ? "" : ", ",
|
||||
methinfo == NULL ? "" : methinfo);
|
||||
free(fp);
|
||||
} else {
|
||||
fp = sshkey_fingerprint(key, options.fingerprint_hash,
|
||||
SSH_FP_DEFAULT);
|
||||
xasprintf(&ret, "%s %s%s%s", sshkey_type(key),
|
||||
fp == NULL ? "(null)" : fp,
|
||||
methinfo == NULL ? "" : ", ",
|
||||
methinfo == NULL ? "" : methinfo);
|
||||
free(fp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -291,7 +311,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
|
|||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
void (*authlog) (const char *fmt,...) = verbose;
|
||||
char *authmsg;
|
||||
const char *authmsg;
|
||||
char *extra = NULL;
|
||||
|
||||
if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
|
||||
return;
|
||||
|
@ -310,6 +331,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
|
|||
else
|
||||
authmsg = authenticated ? "Accepted" : "Failed";
|
||||
|
||||
if ((extra = format_method_key(authctxt)) == NULL) {
|
||||
if (authctxt->auth_method_info != NULL)
|
||||
extra = xstrdup(authctxt->auth_method_info);
|
||||
}
|
||||
|
||||
authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
|
||||
authmsg,
|
||||
method,
|
||||
|
@ -318,10 +344,10 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
|
|||
authctxt->user,
|
||||
ssh_remote_ipaddr(ssh),
|
||||
ssh_remote_port(ssh),
|
||||
authctxt->info != NULL ? ": " : "",
|
||||
authctxt->info != NULL ? authctxt->info : "");
|
||||
free(authctxt->info);
|
||||
authctxt->info = NULL;
|
||||
extra != NULL ? ": " : "",
|
||||
extra != NULL ? extra : "");
|
||||
|
||||
free(extra);
|
||||
|
||||
#ifdef CUSTOM_FAILED_LOGIN
|
||||
if (authenticated == 0 && !authctxt->postponed &&
|
||||
|
|
49
auth.h
49
auth.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth.h,v 1.91 2017/05/30 14:29:59 markus Exp $ */
|
||||
/* $OpenBSD: auth.h,v 1.92 2017/06/24 06:34:38 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
|
@ -44,6 +44,7 @@
|
|||
|
||||
struct ssh;
|
||||
struct sshkey;
|
||||
struct sshbuf;
|
||||
|
||||
typedef struct Authctxt Authctxt;
|
||||
typedef struct Authmethod Authmethod;
|
||||
|
@ -62,13 +63,17 @@ struct Authctxt {
|
|||
char *service;
|
||||
struct passwd *pw; /* set if 'valid' */
|
||||
char *style;
|
||||
|
||||
/* Method lists for multiple authentication */
|
||||
char **auth_methods; /* modified from server config */
|
||||
u_int num_auth_methods;
|
||||
|
||||
/* Authentication method-specific data */
|
||||
void *methoddata;
|
||||
void *kbdintctxt;
|
||||
char *info; /* Extra info for next auth_log */
|
||||
#ifdef BSD_AUTH
|
||||
auth_session_t *as;
|
||||
#endif
|
||||
char **auth_methods; /* modified from server config */
|
||||
u_int num_auth_methods;
|
||||
#ifdef KRB5
|
||||
krb5_context krb5_ctx;
|
||||
krb5_ccache krb5_fwd_ccache;
|
||||
|
@ -76,14 +81,23 @@ struct Authctxt {
|
|||
char *krb5_ticket_file;
|
||||
char *krb5_ccname;
|
||||
#endif
|
||||
Buffer *loginmsg;
|
||||
void *methoddata;
|
||||
struct sshbuf *loginmsg;
|
||||
|
||||
/* Authentication keys already used; these will be refused henceforth */
|
||||
struct sshkey **prev_keys;
|
||||
u_int nprev_keys;
|
||||
|
||||
/* Last used key and ancilliary information from active auth method */
|
||||
struct sshkey *auth_method_key;
|
||||
char *auth_method_info;
|
||||
|
||||
/* Information exposed to session */
|
||||
struct sshbuf *session_info; /* Auth info for environment */
|
||||
#ifdef WINDOWS
|
||||
void *auth_token;
|
||||
#endif
|
||||
struct sshkey **prev_userkeys;
|
||||
u_int nprev_userkeys;
|
||||
};
|
||||
|
||||
/*
|
||||
* Every authentication method has to handle authentication requests for
|
||||
* non-existing users, or for users that are not allowed to login. In this
|
||||
|
@ -122,10 +136,18 @@ int auth_password(Authctxt *, const char *);
|
|||
int hostbased_key_allowed(struct passwd *, const char *, char *,
|
||||
struct sshkey *);
|
||||
int user_key_allowed(struct passwd *, struct sshkey *, int);
|
||||
void pubkey_auth_info(Authctxt *, const struct sshkey *, const char *, ...)
|
||||
__attribute__((__format__ (printf, 3, 4)));
|
||||
void auth2_record_userkey(Authctxt *, struct sshkey *);
|
||||
int auth2_userkey_already_used(Authctxt *, struct sshkey *);
|
||||
int auth2_key_already_used(Authctxt *, const struct sshkey *);
|
||||
|
||||
/*
|
||||
* Handling auth method-specific information for logging and prevention
|
||||
* of key reuse during multiple authentication.
|
||||
*/
|
||||
void auth2_authctxt_reset_info(Authctxt *);
|
||||
void auth2_record_key(Authctxt *, int, const struct sshkey *);
|
||||
void auth2_record_info(Authctxt *authctxt, const char *, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)))
|
||||
__attribute__((__nonnull__ (2)));
|
||||
void auth2_update_session_info(Authctxt *, const char *, const char *);
|
||||
|
||||
struct stat;
|
||||
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
|
||||
|
@ -152,9 +174,6 @@ void disable_forwarding(void);
|
|||
|
||||
void do_authentication2(Authctxt *);
|
||||
|
||||
void auth_info(Authctxt *authctxt, const char *, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)))
|
||||
__attribute__((__nonnull__ (2)));
|
||||
void auth_log(Authctxt *, int, int, const char *, const char *);
|
||||
void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
|
||||
void userauth_finish(struct ssh *, int, const char *, const char *);
|
||||
|
|
12
auth2-gss.c
12
auth2-gss.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth2-gss.c,v 1.25 2017/05/30 14:29:59 markus Exp $ */
|
||||
/* $OpenBSD: auth2-gss.c,v 1.26 2017/06/24 06:34:38 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
|
||||
|
@ -228,6 +228,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
|
|||
{
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
int authenticated;
|
||||
const char *displayname;
|
||||
|
||||
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
|
||||
fatal("No authentication or GSSAPI context");
|
||||
|
@ -241,6 +242,10 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
|
|||
|
||||
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
|
||||
|
||||
if ((!use_privsep || mm_is_monitor()) &&
|
||||
(displayname = ssh_gssapi_displayname()) != NULL)
|
||||
auth2_record_info(authctxt, "%s", displayname);
|
||||
|
||||
authctxt->postponed = 0;
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
|
@ -259,6 +264,7 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
|
|||
Buffer b;
|
||||
gss_buffer_desc mic, gssbuf;
|
||||
u_int len;
|
||||
const char *displayname;
|
||||
|
||||
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
|
||||
fatal("No authentication or GSSAPI context");
|
||||
|
@ -282,6 +288,10 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
|
|||
buffer_free(&b);
|
||||
free(mic.value);
|
||||
|
||||
if ((!use_privsep || mm_is_monitor()) &&
|
||||
(displayname = ssh_gssapi_displayname()) != NULL)
|
||||
auth2_record_info(authctxt, "%s", displayname);
|
||||
|
||||
authctxt->postponed = 0;
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth2-hostbased.c,v 1.30 2017/05/30 14:29:59 markus Exp $ */
|
||||
/* $OpenBSD: auth2-hostbased.c,v 1.31 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -137,7 +137,7 @@ userauth_hostbased(struct ssh *ssh)
|
|||
sshbuf_dump(b, stderr);
|
||||
#endif
|
||||
|
||||
pubkey_auth_info(authctxt, key,
|
||||
auth2_record_info(authctxt,
|
||||
"client user \"%.100s\", client host \"%.100s\"", cuser, chost);
|
||||
|
||||
/* test for allowed key and correct signature */
|
||||
|
@ -147,11 +147,11 @@ userauth_hostbased(struct ssh *ssh)
|
|||
sshbuf_ptr(b), sshbuf_len(b), ssh->compat)) == 0)
|
||||
authenticated = 1;
|
||||
|
||||
auth2_record_key(authctxt, authenticated, key);
|
||||
sshbuf_free(b);
|
||||
done:
|
||||
debug2("%s: authenticated %d", __func__, authenticated);
|
||||
if (key != NULL)
|
||||
sshkey_free(key);
|
||||
sshkey_free(key);
|
||||
free(pkalg);
|
||||
free(pkblob);
|
||||
free(cuser);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth2-pubkey.c,v 1.67 2017/05/31 10:54:00 markus Exp $ */
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.68 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -138,7 +138,7 @@ userauth_pubkey(struct ssh *ssh)
|
|||
goto done;
|
||||
}
|
||||
fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||
if (auth2_userkey_already_used(authctxt, key)) {
|
||||
if (auth2_key_already_used(authctxt, key)) {
|
||||
logit("refusing previously-used %s key", sshkey_type(key));
|
||||
goto done;
|
||||
}
|
||||
|
@ -195,7 +195,6 @@ userauth_pubkey(struct ssh *ssh)
|
|||
#ifdef DEBUG_PK
|
||||
sshbuf_dump(b, stderr);
|
||||
#endif
|
||||
pubkey_auth_info(authctxt, key, NULL);
|
||||
|
||||
/* test for correct signature */
|
||||
authenticated = 0;
|
||||
|
@ -209,13 +208,10 @@ userauth_pubkey(struct ssh *ssh)
|
|||
sshbuf_len(b), ssh->compat)) == 0) {
|
||||
#endif
|
||||
authenticated = 1;
|
||||
/* Record the successful key to prevent reuse */
|
||||
auth2_record_userkey(authctxt, key);
|
||||
key = NULL; /* Don't free below */
|
||||
}
|
||||
sshbuf_free(b);
|
||||
free(sig);
|
||||
|
||||
auth2_record_key(authctxt, authenticated, key);
|
||||
} else {
|
||||
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
|
||||
__func__, sshkey_type(key), fp);
|
||||
|
@ -245,8 +241,7 @@ userauth_pubkey(struct ssh *ssh)
|
|||
auth_clear_options();
|
||||
done:
|
||||
debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
|
||||
if (key != NULL)
|
||||
sshkey_free(key);
|
||||
sshkey_free(key);
|
||||
free(userstyle);
|
||||
free(pkalg);
|
||||
free(pkblob);
|
||||
|
@ -254,44 +249,6 @@ done:
|
|||
return authenticated;
|
||||
}
|
||||
|
||||
void
|
||||
pubkey_auth_info(Authctxt *authctxt, const struct sshkey *key,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
char *fp, *extra;
|
||||
va_list ap;
|
||||
int i;
|
||||
|
||||
extra = NULL;
|
||||
if (fmt != NULL) {
|
||||
va_start(ap, fmt);
|
||||
i = vasprintf(&extra, fmt, ap);
|
||||
va_end(ap);
|
||||
if (i < 0 || extra == NULL)
|
||||
fatal("%s: vasprintf failed", __func__);
|
||||
}
|
||||
|
||||
if (sshkey_is_cert(key)) {
|
||||
fp = sshkey_fingerprint(key->cert->signature_key,
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||
auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
|
||||
sshkey_type(key), key->cert->key_id,
|
||||
(unsigned long long)key->cert->serial,
|
||||
sshkey_type(key->cert->signature_key),
|
||||
fp == NULL ? "(null)" : fp,
|
||||
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
|
||||
free(fp);
|
||||
} else {
|
||||
fp = sshkey_fingerprint(key, options.fingerprint_hash,
|
||||
SSH_FP_DEFAULT);
|
||||
auth_info(authctxt, "%s %s%s%s", sshkey_type(key),
|
||||
fp == NULL ? "(null)" : fp,
|
||||
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
|
||||
free(fp);
|
||||
}
|
||||
free(extra);
|
||||
}
|
||||
|
||||
/*
|
||||
* Splits 's' into an argument vector. Handles quoted string and basic
|
||||
* escape characters (\\, \", \'). Caller must free the argument vector
|
||||
|
@ -1161,36 +1118,6 @@ user_key_allowed(struct passwd *pw, struct sshkey *key, int auth_attempt)
|
|||
return success;
|
||||
}
|
||||
|
||||
/* Records a public key in the list of previously-successful keys */
|
||||
void
|
||||
auth2_record_userkey(Authctxt *authctxt, struct sshkey *key)
|
||||
{
|
||||
struct sshkey **tmp;
|
||||
|
||||
if (authctxt->nprev_userkeys >= INT_MAX ||
|
||||
(tmp = recallocarray(authctxt->prev_userkeys,
|
||||
authctxt->nprev_userkeys, authctxt->nprev_userkeys + 1,
|
||||
sizeof(*tmp))) == NULL)
|
||||
fatal("%s: recallocarray failed", __func__);
|
||||
authctxt->prev_userkeys = tmp;
|
||||
authctxt->prev_userkeys[authctxt->nprev_userkeys] = key;
|
||||
authctxt->nprev_userkeys++;
|
||||
}
|
||||
|
||||
/* Checks whether a key has already been used successfully for authentication */
|
||||
int
|
||||
auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < authctxt->nprev_userkeys; i++) {
|
||||
if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Authmethod method_pubkey = {
|
||||
"publickey",
|
||||
userauth_pubkey,
|
||||
|
|
133
auth2.c
133
auth2.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth2.c,v 1.142 2017/05/31 07:00:13 markus Exp $ */
|
||||
/* $OpenBSD: auth2.c,v 1.143 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -30,6 +30,7 @@
|
|||
#include <sys/uio.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
@ -55,6 +56,7 @@
|
|||
#include "ssh-gss.h"
|
||||
#endif
|
||||
#include "monitor_wrap.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
/* import */
|
||||
extern ServerOptions options;
|
||||
|
@ -277,6 +279,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
|
|||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||
#endif
|
||||
|
||||
auth2_authctxt_reset_info(authctxt);
|
||||
authctxt->postponed = 0;
|
||||
authctxt->server_caused_failure = 0;
|
||||
|
||||
|
@ -327,6 +330,10 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method,
|
|||
/* Log before sending the reply */
|
||||
auth_log(authctxt, authenticated, partial, method, submethod);
|
||||
|
||||
/* Update information exposed to session */
|
||||
if (authenticated || partial)
|
||||
auth2_update_session_info(authctxt, method, submethod);
|
||||
|
||||
if (authctxt->postponed)
|
||||
return;
|
||||
|
||||
|
@ -624,4 +631,128 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Reset method-specific information */
|
||||
void auth2_authctxt_reset_info(Authctxt *authctxt)
|
||||
{
|
||||
sshkey_free(authctxt->auth_method_key);
|
||||
free(authctxt->auth_method_info);
|
||||
authctxt->auth_method_key = NULL;
|
||||
authctxt->auth_method_info = NULL;
|
||||
}
|
||||
|
||||
/* Record auth method-specific information for logs */
|
||||
void
|
||||
auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
|
||||
free(authctxt->auth_method_info);
|
||||
authctxt->auth_method_info = NULL;
|
||||
|
||||
va_start(ap, fmt);
|
||||
i = vasprintf(&authctxt->auth_method_info, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (i < 0 || authctxt->auth_method_info == NULL)
|
||||
fatal("%s: vasprintf failed", __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* Records a public key used in authentication. This is used for logging
|
||||
* and to ensure that the same key is not subsequently accepted again for
|
||||
* multiple authentication.
|
||||
*/
|
||||
void
|
||||
auth2_record_key(Authctxt *authctxt, int authenticated,
|
||||
const struct sshkey *key)
|
||||
{
|
||||
struct sshkey **tmp, *dup;
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_demote(key, &dup)) != 0)
|
||||
fatal("%s: copy key: %s", __func__, ssh_err(r));
|
||||
sshkey_free(authctxt->auth_method_key);
|
||||
authctxt->auth_method_key = dup;
|
||||
|
||||
if (!authenticated)
|
||||
return;
|
||||
|
||||
/* If authenticated, make sure we don't accept this key again */
|
||||
if ((r = sshkey_demote(key, &dup)) != 0)
|
||||
fatal("%s: copy key: %s", __func__, ssh_err(r));
|
||||
if (authctxt->nprev_keys >= INT_MAX ||
|
||||
(tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
|
||||
authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL)
|
||||
fatal("%s: reallocarray failed", __func__);
|
||||
authctxt->prev_keys = tmp;
|
||||
authctxt->prev_keys[authctxt->nprev_keys] = dup;
|
||||
authctxt->nprev_keys++;
|
||||
|
||||
}
|
||||
|
||||
/* Checks whether a key has already been previously used for authentication */
|
||||
int
|
||||
auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
|
||||
{
|
||||
u_int i;
|
||||
char *fp;
|
||||
|
||||
for (i = 0; i < authctxt->nprev_keys; i++) {
|
||||
if (sshkey_equal_public(key, authctxt->prev_keys[i])) {
|
||||
fp = sshkey_fingerprint(authctxt->prev_keys[i],
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||
debug3("%s: key already used: %s %s", __func__,
|
||||
sshkey_type(authctxt->prev_keys[i]),
|
||||
fp == NULL ? "UNKNOWN" : fp);
|
||||
free(fp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates authctxt->session_info with details of authentication. Should be
|
||||
* whenever an authentication method succeeds.
|
||||
*/
|
||||
void
|
||||
auth2_update_session_info(Authctxt *authctxt, const char *method,
|
||||
const char *submethod)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (authctxt->session_info == NULL) {
|
||||
if ((authctxt->session_info = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new", __func__);
|
||||
}
|
||||
|
||||
/* Append method[/submethod] */
|
||||
if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s",
|
||||
method, submethod == NULL ? "" : "/",
|
||||
submethod == NULL ? "" : submethod)) != 0)
|
||||
fatal("%s: append method: %s", __func__, ssh_err(r));
|
||||
|
||||
/* Append key if present */
|
||||
if (authctxt->auth_method_key != NULL) {
|
||||
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
|
||||
(r = sshkey_format_text(authctxt->auth_method_key,
|
||||
authctxt->session_info)) != 0)
|
||||
fatal("%s: append key: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
if (authctxt->auth_method_info != NULL) {
|
||||
/* Ensure no ambiguity here */
|
||||
if (strchr(authctxt->auth_method_info, '\n') != NULL)
|
||||
fatal("%s: auth_method_info contains \\n", __func__);
|
||||
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
|
||||
(r = sshbuf_putf(authctxt->session_info, "%s",
|
||||
authctxt->auth_method_info)) != 0) {
|
||||
fatal("%s: append method info: %s",
|
||||
__func__, ssh_err(r));
|
||||
}
|
||||
}
|
||||
if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0)
|
||||
fatal("%s: append: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
|
|
6
authfd.c
6
authfd.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: authfd.c,v 1.103 2017/05/05 10:42:49 naddy Exp $ */
|
||||
/* $OpenBSD: authfd.c,v 1.104 2017/06/28 01:09:22 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -331,7 +331,7 @@ ssh_free_identitylist(struct ssh_identitylist *idl)
|
|||
|
||||
/* encode signature algoritm in flag bits, so we can keep the msg format */
|
||||
static u_int
|
||||
agent_encode_alg(struct sshkey *key, const char *alg)
|
||||
agent_encode_alg(const struct sshkey *key, const char *alg)
|
||||
{
|
||||
if (alg != NULL && key->type == KEY_RSA) {
|
||||
if (strcmp(alg, "rsa-sha2-256") == 0)
|
||||
|
@ -344,7 +344,7 @@ agent_encode_alg(struct sshkey *key, const char *alg)
|
|||
|
||||
/* ask agent to sign data, returns err.h code on error, 0 on success */
|
||||
int
|
||||
ssh_agent_sign(int sock, struct sshkey *key,
|
||||
ssh_agent_sign(int sock, const struct sshkey *key,
|
||||
u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, const char *alg, u_int compat)
|
||||
{
|
||||
|
|
4
authfd.h
4
authfd.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: authfd.h,v 1.40 2017/05/05 10:42:49 naddy Exp $ */
|
||||
/* $OpenBSD: authfd.h,v 1.41 2017/06/28 01:09:22 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
@ -38,7 +38,7 @@ int ssh_remove_all_identities(int sock, int version);
|
|||
|
||||
int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
|
||||
u_char session_id[16], u_char response[16]);
|
||||
int ssh_agent_sign(int sock, struct sshkey *key,
|
||||
int ssh_agent_sign(int sock, const struct sshkey *key,
|
||||
u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, const char *alg, u_int compat);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: clientloop.c,v 1.299 2017/05/31 09:15:42 deraadt Exp $ */
|
||||
/* $OpenBSD: clientloop.c,v 1.300 2017/06/23 07:24:48 mestre Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -1259,7 +1259,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
|||
|
||||
} else {
|
||||
debug("pledge: network");
|
||||
if (pledge("stdio unix inet dns tty", NULL) == -1)
|
||||
if (pledge("stdio unix inet dns proc tty", NULL) == -1)
|
||||
fatal("%s pledge(): %s", __func__, strerror(errno));
|
||||
}
|
||||
|
||||
|
|
|
@ -3814,6 +3814,8 @@ OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmpx.h], [HAVE_TIME_IN_UTMPX])
|
|||
OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmpx.h], [HAVE_TV_IN_UTMPX])
|
||||
|
||||
AC_CHECK_MEMBERS([struct stat.st_blksize])
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtim])
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtime])
|
||||
AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_class,
|
||||
struct passwd.pw_change, struct passwd.pw_expire],
|
||||
[], [], [[
|
||||
|
|
|
@ -35,7 +35,7 @@ The script treats all packages as USR packages (not ROOT+USR when
|
|||
appropriate). It seems to work, though......
|
||||
|
||||
If there are any patches to this that have not yet been integrated they
|
||||
may be found at http://www.zip.com.au/~dtucker/openssh/.
|
||||
may be found at http://www.dtucker.net/openssh/.
|
||||
|
||||
|
||||
Disclaimer:
|
||||
|
|
|
@ -342,7 +342,14 @@ function Repair-FilePermissionInternal {
|
|||
|
||||
foreach($a in $acl.Access)
|
||||
{
|
||||
$IdentityReferenceSid = Get-UserSid -User $a.IdentityReference
|
||||
if ($a.IdentityReference -is [System.Security.Principal.SecurityIdentifier])
|
||||
{
|
||||
$IdentityReferenceSid = $a.IdentityReference
|
||||
}
|
||||
Else
|
||||
{
|
||||
$IdentityReferenceSid = Get-UserSid -User $a.IdentityReference
|
||||
}
|
||||
if($IdentityReferenceSid -eq $null)
|
||||
{
|
||||
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# @manojampalam - authored initial script
|
||||
# @friism - Fixed issue with invalid SDDL on Set-Acl
|
||||
# @manojampalam - removed ntrights.exe dependency
|
||||
# @bingbing8 - removed secedit.exe dependency
|
||||
|
||||
$scriptpath = $MyInvocation.MyCommand.Path
|
||||
$scriptdir = Split-Path $scriptpath
|
||||
|
@ -10,68 +11,240 @@ $sshagentpath = Join-Path $scriptdir "ssh-agent.exe"
|
|||
$logsdir = Join-Path $scriptdir "logs"
|
||||
|
||||
$sshdAccount = "NT SERVICE\SSHD"
|
||||
$sshdSid = "S-1-5-80-3847866527-469524349-687026318-516638107-1125189541"
|
||||
|
||||
#Idea borrowed from https://gallery.technet.microsoft.com/scriptcenter/Grant-Revoke-Query-user-26e259b0
|
||||
$definition = @'
|
||||
using System;
|
||||
|
||||
namespace MyLsaWrapper
|
||||
{
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.ComponentModel;
|
||||
using System.Security.Principal;
|
||||
|
||||
using LSA_HANDLE = IntPtr;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct LSA_OBJECT_ATTRIBUTES
|
||||
{
|
||||
internal int Length;
|
||||
internal IntPtr RootDirectory;
|
||||
internal IntPtr ObjectName;
|
||||
internal int Attributes;
|
||||
internal IntPtr SecurityDescriptor;
|
||||
internal IntPtr SecurityQualityOfService;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
struct LSA_UNICODE_STRING
|
||||
{
|
||||
internal ushort Length;
|
||||
internal ushort MaximumLength;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
internal string Buffer;
|
||||
}
|
||||
sealed class Win32Sec
|
||||
{
|
||||
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern uint LsaOpenPolicy(
|
||||
LSA_UNICODE_STRING[] SystemName,
|
||||
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
|
||||
int AccessMask,
|
||||
out IntPtr PolicyHandle
|
||||
);
|
||||
|
||||
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern uint LsaAddAccountRights(
|
||||
LSA_HANDLE PolicyHandle,
|
||||
IntPtr pSID,
|
||||
LSA_UNICODE_STRING[] UserRights,
|
||||
int CountOfRights
|
||||
);
|
||||
|
||||
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern uint LsaRemoveAccountRights(
|
||||
LSA_HANDLE PolicyHandle,
|
||||
IntPtr pSID,
|
||||
bool AllRights,
|
||||
LSA_UNICODE_STRING[] UserRights,
|
||||
int CountOfRights
|
||||
);
|
||||
|
||||
[DllImport("advapi32")]
|
||||
internal static extern int LsaNtStatusToWinError(int NTSTATUS);
|
||||
|
||||
[DllImport("advapi32")]
|
||||
internal static extern int LsaClose(IntPtr PolicyHandle);
|
||||
}
|
||||
|
||||
internal sealed class Sid : IDisposable
|
||||
{
|
||||
public IntPtr pSid = IntPtr.Zero;
|
||||
public System.Security.Principal.SecurityIdentifier sid = null;
|
||||
|
||||
public Sid(string account)
|
||||
{
|
||||
try { sid = new SecurityIdentifier(account); }
|
||||
catch { sid = (SecurityIdentifier)(new NTAccount(account)).Translate(typeof(SecurityIdentifier)); }
|
||||
Byte[] buffer = new Byte[sid.BinaryLength];
|
||||
sid.GetBinaryForm(buffer, 0);
|
||||
|
||||
pSid = Marshal.AllocHGlobal(sid.BinaryLength);
|
||||
Marshal.Copy(buffer, 0, pSid, sid.BinaryLength);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (pSid != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(pSid);
|
||||
pSid = IntPtr.Zero;
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
~Sid() { Dispose(); }
|
||||
}
|
||||
|
||||
public sealed class LsaWrapper : IDisposable
|
||||
{
|
||||
enum Access : int
|
||||
{
|
||||
POLICY_READ = 0x20006,
|
||||
POLICY_ALL_ACCESS = 0x00F0FFF,
|
||||
POLICY_EXECUTE = 0X20801,
|
||||
POLICY_WRITE = 0X207F8
|
||||
}
|
||||
const uint STATUS_ACCESS_DENIED = 0xc0000022;
|
||||
const uint STATUS_INSUFFICIENT_RESOURCES = 0xc000009a;
|
||||
const uint STATUS_NO_MEMORY = 0xc0000017;
|
||||
const uint STATUS_OBJECT_NAME_NOT_FOUND = 0xc0000034;
|
||||
const uint STATUS_NO_MORE_ENTRIES = 0x8000001a;
|
||||
|
||||
IntPtr lsaHandle;
|
||||
|
||||
public LsaWrapper() : this(null) { } // local system if systemName is null
|
||||
public LsaWrapper(string systemName)
|
||||
{
|
||||
LSA_OBJECT_ATTRIBUTES lsaAttr;
|
||||
lsaAttr.RootDirectory = IntPtr.Zero;
|
||||
lsaAttr.ObjectName = IntPtr.Zero;
|
||||
lsaAttr.Attributes = 0;
|
||||
lsaAttr.SecurityDescriptor = IntPtr.Zero;
|
||||
lsaAttr.SecurityQualityOfService = IntPtr.Zero;
|
||||
lsaAttr.Length = Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES));
|
||||
lsaHandle = IntPtr.Zero;
|
||||
LSA_UNICODE_STRING[] system = null;
|
||||
if (systemName != null)
|
||||
{
|
||||
system = new LSA_UNICODE_STRING[1];
|
||||
system[0] = InitLsaString(systemName);
|
||||
}
|
||||
|
||||
uint ret = Win32Sec.LsaOpenPolicy(system, ref lsaAttr, (int)Access.POLICY_ALL_ACCESS, out lsaHandle);
|
||||
if (ret == 0) return;
|
||||
if (ret == STATUS_ACCESS_DENIED) throw new UnauthorizedAccessException();
|
||||
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY)) throw new OutOfMemoryException();
|
||||
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
|
||||
}
|
||||
|
||||
public void AddPrivilege(string account, string privilege)
|
||||
{
|
||||
uint ret = 0;
|
||||
using (Sid sid = new Sid(account))
|
||||
{
|
||||
LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
|
||||
privileges[0] = InitLsaString(privilege);
|
||||
ret = Win32Sec.LsaAddAccountRights(lsaHandle, sid.pSid, privileges, 1);
|
||||
}
|
||||
if (ret == 0) return;
|
||||
if (ret == STATUS_ACCESS_DENIED) throw new UnauthorizedAccessException();
|
||||
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY)) throw new OutOfMemoryException();
|
||||
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
|
||||
}
|
||||
|
||||
public void RemovePrivilege(string account, string privilege)
|
||||
{
|
||||
uint ret = 0;
|
||||
using (Sid sid = new Sid(account))
|
||||
{
|
||||
LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
|
||||
privileges[0] = InitLsaString(privilege);
|
||||
ret = Win32Sec.LsaRemoveAccountRights(lsaHandle, sid.pSid, false, privileges, 1);
|
||||
}
|
||||
if (ret == 0) return;
|
||||
if (ret == STATUS_ACCESS_DENIED) throw new UnauthorizedAccessException();
|
||||
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY)) throw new OutOfMemoryException();
|
||||
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (lsaHandle != IntPtr.Zero)
|
||||
{
|
||||
Win32Sec.LsaClose(lsaHandle);
|
||||
lsaHandle = IntPtr.Zero;
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
~LsaWrapper() { Dispose(); }
|
||||
|
||||
// helper functions:
|
||||
static LSA_UNICODE_STRING InitLsaString(string s)
|
||||
{
|
||||
// Unicode strings max. 32KB
|
||||
if (s.Length > 0x7ffe) throw new ArgumentException("String too long");
|
||||
LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING();
|
||||
lus.Buffer = s;
|
||||
lus.Length = (ushort)(s.Length * sizeof(char));
|
||||
lus.MaximumLength = (ushort)(lus.Length + sizeof(char));
|
||||
return lus;
|
||||
}
|
||||
}
|
||||
public class LsaWrapperCaller
|
||||
{
|
||||
public static void AddPrivilege(string account, string privilege)
|
||||
{
|
||||
using (LsaWrapper lsaWrapper = new LsaWrapper())
|
||||
{
|
||||
lsaWrapper.AddPrivilege(account, privilege);
|
||||
}
|
||||
}
|
||||
public static void RemovePrivilege(string account, string privilege)
|
||||
{
|
||||
using (LsaWrapper lsaWrapper = new LsaWrapper())
|
||||
{
|
||||
lsaWrapper.RemovePrivilege(account, privilege);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'@
|
||||
$references = @()
|
||||
if(($psversiontable.Containskey("psedition")) -and ($psversiontable.PSEdition -ieq "core"))
|
||||
{
|
||||
$references = "System.Security.Principal.Windows", "Microsoft.Win32.Primitives"
|
||||
}
|
||||
|
||||
try {
|
||||
$null = [MyLsaWrapper.LsaWrapperCaller]
|
||||
}
|
||||
catch {
|
||||
$types = Add-Type $definition -ref $references -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
|
||||
#Idea borrowed from http://sqldbamusings.blogspot.com/2012/03/powershell-adding-accounts-to-local.html
|
||||
function Add-Privilege
|
||||
{
|
||||
param(
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $Account,
|
||||
|
||||
[ValidateSet("SeAssignPrimaryTokenPrivilege", "SeServiceLogonRight")]
|
||||
[string] $Privilege
|
||||
)
|
||||
|
||||
#Get $Account SID
|
||||
$account_sid = $null
|
||||
try
|
||||
{
|
||||
$ntprincipal = new-object System.Security.Principal.NTAccount "$Account"
|
||||
$sid = $ntprincipal.Translate([System.Security.Principal.SecurityIdentifier])
|
||||
$account_sid = $sid.Value.ToString()
|
||||
}
|
||||
catch
|
||||
{
|
||||
Throw 'Unable to resolve '+ $Account
|
||||
}
|
||||
|
||||
#Prepare policy settings file to be applied
|
||||
$settings_to_export = [System.IO.Path]::GetTempFileName()
|
||||
"[Unicode]" | Set-Content $settings_to_export -Encoding Unicode
|
||||
"Unicode=yes" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
"[Version]" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
"signature=`"`$CHICAGO`$`"" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
"Revision=1" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
"[Privilege Rights]" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
|
||||
#Get Current policy settings
|
||||
$imported_settings = [System.IO.Path]::GetTempFileName()
|
||||
secedit.exe /export /areas USER_RIGHTS /cfg "$($imported_settings)" > $null
|
||||
|
||||
if (-not(Test-Path $imported_settings)) {
|
||||
Throw "Unable to import current security policy settings"
|
||||
}
|
||||
|
||||
#find current assigned accounts to $Privilege and add it to $settings_to_export
|
||||
$current_settings = Get-Content $imported_settings -Encoding Unicode
|
||||
$existing_setting = $null
|
||||
foreach ($setting in $current_settings) {
|
||||
if ($setting -like "$Privilege`*") {
|
||||
$existing_setting = $setting
|
||||
}
|
||||
}
|
||||
|
||||
#Add $account_sid to list
|
||||
if ($existing_setting -eq $null) {
|
||||
$Privilege + " = *" + $account_sid | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
}
|
||||
else
|
||||
{
|
||||
$existing_setting + ",*" + $account_sid | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
}
|
||||
|
||||
#export
|
||||
secedit.exe /configure /db "secedit.sdb" /cfg "$($settings_to_export)" /areas USER_RIGHTS > $null
|
||||
|
||||
[MyLsaWrapper.LsaWrapperCaller]::AddPrivilege($Account, $Privilege)
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,7 +271,7 @@ New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Daemon" -Star
|
|||
sc.exe config sshd obj= $sshdAccount
|
||||
sc.exe privs sshd SeAssignPrimaryTokenPrivilege
|
||||
|
||||
Add-Privilege -Account $sshdAccount -Privilege SeAssignPrimaryTokenPrivilege
|
||||
Add-Privilege -Account $sshdSid -Privilege SeAssignPrimaryTokenPrivilege
|
||||
|
||||
if(-not (test-path $logsdir -PathType Container))
|
||||
{
|
||||
|
|
|
@ -56,6 +56,19 @@ struct passwd *privsep_pw = NULL;
|
|||
static char *config_file_name = _PATH_SERVER_CONFIG_FILE;
|
||||
int auth_sock = -1;
|
||||
|
||||
int
|
||||
auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
auth2_record_key(Authctxt *authctxt, int authenticated,
|
||||
const struct sshkey *key)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
auth2_methods_valid(const char * c, int i) {
|
||||
return 1;
|
||||
|
|
|
@ -332,7 +332,7 @@ process_remove_all(struct sshbuf* request, struct sshbuf* response, struct agent
|
|||
int r = 0;
|
||||
|
||||
if (get_user_root(con, &user_root) != 0 ||
|
||||
RegOpenKeyExW(user_root, SSH_ROOT, 0,
|
||||
RegOpenKeyExW(user_root, SSH_AGENT_ROOT, 0,
|
||||
DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &root) != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -519,6 +519,13 @@ struct winsize {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef timespeccmp
|
||||
#define timespeccmp(tsp, usp, cmp) \
|
||||
(((tsp)->tv_sec == (usp)->tv_sec) ? \
|
||||
((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
|
||||
((tsp)->tv_sec cmp (usp)->tv_sec))
|
||||
#endif
|
||||
|
||||
#ifndef __P
|
||||
# define __P(x) x
|
||||
#endif
|
||||
|
|
11
gss-serv.c
11
gss-serv.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: gss-serv.c,v 1.29 2015/05/22 03:50:02 djm Exp $ */
|
||||
/* $OpenBSD: gss-serv.c,v 1.30 2017/06/24 06:34:38 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
|
||||
|
@ -393,4 +393,13 @@ ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
|
|||
return (ctx->major);
|
||||
}
|
||||
|
||||
/* Privileged */
|
||||
const char *ssh_gssapi_displayname(void)
|
||||
{
|
||||
if (gssapi_client.displayname.length == 0 ||
|
||||
gssapi_client.displayname.value == NULL)
|
||||
return NULL;
|
||||
return (char *)gssapi_client.displayname.value;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -93,6 +93,9 @@
|
|||
#ifdef HAVE_SYS_SYSMACROS_H
|
||||
# include <sys/sysmacros.h> /* For MIN, MAX, etc */
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h> /* for timespeccmp if present */
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h> /* for MAP_ANONYMOUS */
|
||||
#endif
|
||||
|
|
18
kex.c
18
kex.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: kex.c,v 1.133 2017/05/30 14:23:52 markus Exp $ */
|
||||
/* $OpenBSD: kex.c,v 1.134 2017/06/13 12:13:59 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -378,7 +378,9 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
|
|||
{
|
||||
struct kex *kex = ssh->kex;
|
||||
u_int32_t i, ninfo;
|
||||
char *name, *val, *found;
|
||||
char *name, *found;
|
||||
u_char *val;
|
||||
size_t vlen;
|
||||
int r;
|
||||
|
||||
debug("SSH2_MSG_EXT_INFO received");
|
||||
|
@ -388,12 +390,17 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
|
|||
for (i = 0; i < ninfo; i++) {
|
||||
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
|
||||
return r;
|
||||
if ((r = sshpkt_get_cstring(ssh, &val, NULL)) != 0) {
|
||||
if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
|
||||
free(name);
|
||||
return r;
|
||||
}
|
||||
debug("%s: %s=<%s>", __func__, name, val);
|
||||
if (strcmp(name, "server-sig-algs") == 0) {
|
||||
/* Ensure no \0 lurking in value */
|
||||
if (memchr(val, '\0', vlen) != NULL) {
|
||||
error("%s: nul byte in %s", __func__, name);
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
}
|
||||
debug("%s: %s=<%s>", __func__, name, val);
|
||||
found = match_list("rsa-sha2-256", val, NULL);
|
||||
if (found) {
|
||||
kex->rsa_sha2 = 256;
|
||||
|
@ -404,7 +411,8 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
|
|||
kex->rsa_sha2 = 512;
|
||||
free(found);
|
||||
}
|
||||
}
|
||||
} else
|
||||
debug("%s: %s (unrecognised)", __func__, name);
|
||||
free(name);
|
||||
free(val);
|
||||
}
|
||||
|
|
41
monitor.c
41
monitor.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: monitor.c,v 1.171 2017/05/31 10:04:29 markus Exp $ */
|
||||
/* $OpenBSD: monitor.c,v 1.172 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
|
@ -308,6 +308,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
|||
partial = 0;
|
||||
auth_method = "unknown";
|
||||
auth_submethod = NULL;
|
||||
auth2_authctxt_reset_info(authctxt);
|
||||
|
||||
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
|
||||
|
||||
/* Special handling for multiple required authentications */
|
||||
|
@ -347,6 +349,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
|||
auth_method, auth_submethod);
|
||||
if (!partial && !authenticated)
|
||||
authctxt->failures++;
|
||||
if (authenticated || partial) {
|
||||
auth2_update_session_info(authctxt,
|
||||
auth_method, auth_submethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1147,12 +1153,11 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
|||
switch (type) {
|
||||
case MM_USERKEY:
|
||||
allowed = options.pubkey_authentication &&
|
||||
!auth2_userkey_already_used(authctxt, key) &&
|
||||
!auth2_key_already_used(authctxt, key) &&
|
||||
match_pattern_list(sshkey_ssh_name(key),
|
||||
options.pubkey_key_types, 0) == 1 &&
|
||||
user_key_allowed(authctxt->pw, key,
|
||||
pubkey_auth_attempt);
|
||||
pubkey_auth_info(authctxt, key, NULL);
|
||||
auth_method = "publickey";
|
||||
if (options.pubkey_authentication &&
|
||||
(!pubkey_auth_attempt || allowed != 1))
|
||||
|
@ -1160,11 +1165,12 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
|||
break;
|
||||
case MM_HOSTKEY:
|
||||
allowed = options.hostbased_authentication &&
|
||||
!auth2_key_already_used(authctxt, key) &&
|
||||
match_pattern_list(sshkey_ssh_name(key),
|
||||
options.hostbased_key_types, 0) == 1 &&
|
||||
hostbased_key_allowed(authctxt->pw,
|
||||
cuser, chost, key);
|
||||
pubkey_auth_info(authctxt, key,
|
||||
auth2_record_info(authctxt,
|
||||
"client user \"%.100s\", client host \"%.100s\"",
|
||||
cuser, chost);
|
||||
auth_method = "hostbased";
|
||||
|
@ -1175,11 +1181,10 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
|||
}
|
||||
}
|
||||
|
||||
debug3("%s: key %p is %s",
|
||||
__func__, key, allowed ? "allowed" : "not allowed");
|
||||
debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed");
|
||||
|
||||
if (key != NULL)
|
||||
key_free(key);
|
||||
auth2_record_key(authctxt, 0, key);
|
||||
sshkey_free(key);
|
||||
|
||||
/* clear temporarily storage (used by verify) */
|
||||
monitor_reset_key_state();
|
||||
|
@ -1353,10 +1358,12 @@ mm_answer_keyverify(int sock, struct sshbuf *m)
|
|||
switch (key_blobtype) {
|
||||
case MM_USERKEY:
|
||||
valid_data = monitor_valid_userblob(data, datalen);
|
||||
auth_method = "publickey";
|
||||
break;
|
||||
case MM_HOSTKEY:
|
||||
valid_data = monitor_valid_hostbasedblob(data, datalen,
|
||||
hostbased_cuser, hostbased_chost);
|
||||
auth_method = "hostbased";
|
||||
break;
|
||||
default:
|
||||
valid_data = 0;
|
||||
|
@ -1367,23 +1374,17 @@ mm_answer_keyverify(int sock, struct sshbuf *m)
|
|||
|
||||
ret = sshkey_verify(key, signature, signaturelen, data, datalen,
|
||||
active_state->compat);
|
||||
debug3("%s: key %p signature %s",
|
||||
__func__, key, (ret == 0) ? "verified" : "unverified");
|
||||
|
||||
/* If auth was successful then record key to ensure it isn't reused */
|
||||
if (ret == 0 && key_blobtype == MM_USERKEY)
|
||||
auth2_record_userkey(authctxt, key);
|
||||
else
|
||||
sshkey_free(key);
|
||||
debug3("%s: %s %p signature %s", __func__, auth_method, key,
|
||||
(ret == 0) ? "verified" : "unverified");
|
||||
auth2_record_key(authctxt, ret == 0, key);
|
||||
|
||||
free(blob);
|
||||
free(signature);
|
||||
free(data);
|
||||
|
||||
auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
|
||||
|
||||
monitor_reset_key_state();
|
||||
|
||||
sshkey_free(key);
|
||||
sshbuf_reset(m);
|
||||
|
||||
/* encode ret != 0 as positive integer, since we're sending u32 */
|
||||
|
@ -1799,6 +1800,7 @@ int
|
|||
mm_answer_gss_userok(int sock, Buffer *m)
|
||||
{
|
||||
int authenticated;
|
||||
const char *displayname;
|
||||
|
||||
if (!options.gss_authentication)
|
||||
fatal("%s: GSSAPI authentication not enabled", __func__);
|
||||
|
@ -1813,6 +1815,9 @@ mm_answer_gss_userok(int sock, Buffer *m)
|
|||
|
||||
auth_method = "gssapi-with-mic";
|
||||
|
||||
if ((displayname = ssh_gssapi_displayname()) != NULL)
|
||||
auth2_record_info(authctxt, "%s", displayname);
|
||||
|
||||
/* Monitor loop will terminate if authenticated */
|
||||
return (authenticated);
|
||||
}
|
||||
|
|
30
mux.c
30
mux.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: mux.c,v 1.64 2017/01/21 11:32:04 guenther Exp $ */
|
||||
/* $OpenBSD: mux.c,v 1.65 2017/06/09 06:47:13 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
|
@ -1570,31 +1570,38 @@ mux_client_hello_exchange(int fd)
|
|||
{
|
||||
Buffer m;
|
||||
u_int type, ver;
|
||||
int ret = -1;
|
||||
|
||||
buffer_init(&m);
|
||||
buffer_put_int(&m, MUX_MSG_HELLO);
|
||||
buffer_put_int(&m, SSHMUX_VER);
|
||||
/* no extensions */
|
||||
|
||||
if (mux_client_write_packet(fd, &m) != 0)
|
||||
fatal("%s: write packet: %s", __func__, strerror(errno));
|
||||
if (mux_client_write_packet(fd, &m) != 0) {
|
||||
debug("%s: write packet: %s", __func__, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
buffer_clear(&m);
|
||||
|
||||
/* Read their HELLO */
|
||||
if (mux_client_read_packet(fd, &m) != 0) {
|
||||
buffer_free(&m);
|
||||
return -1;
|
||||
debug("%s: read packet failed", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
type = buffer_get_int(&m);
|
||||
if (type != MUX_MSG_HELLO)
|
||||
fatal("%s: expected HELLO (%u) received %u",
|
||||
if (type != MUX_MSG_HELLO) {
|
||||
error("%s: expected HELLO (%u) received %u",
|
||||
__func__, MUX_MSG_HELLO, type);
|
||||
goto out;
|
||||
}
|
||||
ver = buffer_get_int(&m);
|
||||
if (ver != SSHMUX_VER)
|
||||
fatal("Unsupported multiplexing protocol version %d "
|
||||
if (ver != SSHMUX_VER) {
|
||||
error("Unsupported multiplexing protocol version %d "
|
||||
"(expected %d)", ver, SSHMUX_VER);
|
||||
goto out;
|
||||
}
|
||||
debug2("%s: master version %u", __func__, ver);
|
||||
/* No extensions are presently defined */
|
||||
while (buffer_len(&m) > 0) {
|
||||
|
@ -1605,8 +1612,11 @@ mux_client_hello_exchange(int fd)
|
|||
free(name);
|
||||
free(value);
|
||||
}
|
||||
/* success */
|
||||
ret = 0;
|
||||
out:
|
||||
buffer_free(&m);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u_int
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
20
packet.c
20
packet.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: packet.c,v 1.260 2017/06/06 09:12:17 dtucker Exp $ */
|
||||
/* $OpenBSD: packet.c,v 1.262 2017/06/24 06:38:11 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -901,6 +901,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
|
|||
/*
|
||||
* The 2^(blocksize*2) limit is too expensive for 3DES,
|
||||
* so enforce a 1GB limit for small blocksizes.
|
||||
* See RFC4344 section 3.2.
|
||||
*/
|
||||
if (enc->block_size >= 16)
|
||||
*max_blocks = (u_int64_t)1 << (enc->block_size*2);
|
||||
|
@ -944,7 +945,10 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
|
|||
(int64_t)state->rekey_time + state->rekey_interval <= monotime())
|
||||
return 1;
|
||||
|
||||
/* Always rekey when MAX_PACKETS sent in either direction */
|
||||
/*
|
||||
* Always rekey when MAX_PACKETS sent in either direction
|
||||
* As per RFC4344 section 3.1 we do this after 2^31 packets.
|
||||
*/
|
||||
if (state->p_send.packets > MAX_PACKETS ||
|
||||
state->p_read.packets > MAX_PACKETS)
|
||||
return 1;
|
||||
|
@ -2218,9 +2222,7 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode)
|
|||
return r;
|
||||
if ((b = sshbuf_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
/* The cipher struct is constant and shared, you export pointer */
|
||||
if ((r = sshbuf_put_cstring(b, enc->name)) != 0 ||
|
||||
(r = sshbuf_put(b, &enc->cipher, sizeof(enc->cipher))) != 0 ||
|
||||
(r = sshbuf_put_u32(b, enc->enabled)) != 0 ||
|
||||
(r = sshbuf_put_u32(b, enc->block_size)) != 0 ||
|
||||
(r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 ||
|
||||
|
@ -2294,12 +2296,15 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode)
|
|||
comp = &newkey->comp;
|
||||
|
||||
if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 ||
|
||||
(r = sshbuf_get(b, &enc->cipher, sizeof(enc->cipher))) != 0 ||
|
||||
(r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 ||
|
||||
(r = sshbuf_get_u32(b, &enc->block_size)) != 0 ||
|
||||
(r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 ||
|
||||
(r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0)
|
||||
goto out;
|
||||
if ((enc->cipher = cipher_by_name(enc->name)) == NULL) {
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (cipher_authlen(enc->cipher) == 0) {
|
||||
if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0)
|
||||
goto out;
|
||||
|
@ -2317,11 +2322,6 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode)
|
|||
if ((r = sshbuf_get_u32(b, &comp->type)) != 0 ||
|
||||
(r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0)
|
||||
goto out;
|
||||
if (enc->name == NULL ||
|
||||
cipher_by_name(enc->name) != enc->cipher) {
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (sshbuf_len(b) != 0) {
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: Makefile,v 1.94 2016/12/16 03:51:19 dtucker Exp $
|
||||
# $OpenBSD: Makefile,v 1.95 2017/06/24 06:35:24 djm Exp $
|
||||
|
||||
REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t-exec
|
||||
tests: prep $(REGRESS_TARGETS)
|
||||
|
@ -79,7 +79,8 @@ LTESTS= connect \
|
|||
principals-command \
|
||||
cert-file \
|
||||
cfginclude \
|
||||
allow-deny-users
|
||||
allow-deny-users \
|
||||
authinfo
|
||||
|
||||
|
||||
# dhgex \
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# $OpenBSD: authinfo.sh,v 1.1 2017/06/24 06:35:24 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="authinfo"
|
||||
|
||||
# Ensure the environment variable doesn't leak when ExposeAuthInfo=no.
|
||||
verbose "ExposeAuthInfo=no"
|
||||
env SSH_USER_AUTH=blah ${SSH} -F $OBJ/ssh_proxy x \
|
||||
'test -z "$SSH_USER_AUTH"' || fail "SSH_USER_AUTH present"
|
||||
|
||||
verbose "ExposeAuthInfo=yes"
|
||||
echo ExposeAuthInfo=yes >> $OBJ/sshd_proxy
|
||||
${SSH} -F $OBJ/ssh_proxy x \
|
||||
'grep ^publickey "$SSH_USER_AUTH" /dev/null >/dev/null' ||
|
||||
fail "ssh with ExposeAuthInfo failed"
|
||||
|
||||
# XXX test multiple auth and key contents
|
|
@ -146,7 +146,7 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $ssouser@$server echo 1234
|
||||
$LASTEXITCODE | Should Not Be 0
|
||||
$matches = Get-Content $filePath | Select-String -pattern "^Permission denied"
|
||||
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||
$matches.Count | Should BeGreaterThan 2
|
||||
|
||||
#Cleanup
|
||||
|
@ -165,7 +165,7 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $ssouser@$server echo 1234
|
||||
$LASTEXITCODE | Should Not Be 0
|
||||
$matches = Get-Content $filePath | Select-String -pattern "^Permission denied"
|
||||
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||
$matches.Count | Should BeGreaterThan 2
|
||||
|
||||
#Cleanup
|
||||
|
@ -181,7 +181,7 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||
ssh -p $port -E $FilePath -o "UserKnownHostsFile $testknownhosts" $ssouser@$server echo 1234
|
||||
$LASTEXITCODE | Should Not Be 0
|
||||
$matches = Get-Content $filePath | Select-String -pattern "^Permission denied"
|
||||
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||
$matches.Count | Should BeGreaterThan 2
|
||||
|
||||
#Cleanup
|
||||
|
@ -197,7 +197,7 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||
ssh -p $port -E $filePath -o "UserKnownHostsFile $testknownhosts" $ssouser@$server echo 1234
|
||||
$LASTEXITCODE | Should Not Be 0
|
||||
|
||||
$matches = Get-Content $filePath | Select-String -pattern "^Permission denied"
|
||||
$matches = Get-Content $filePath | Select-String -pattern "Permission denied"
|
||||
$matches.Count | Should BeGreaterThan 2
|
||||
|
||||
#Cleanup
|
||||
|
|
|
@ -37,38 +37,35 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||
Title = 'Simple copy local file to local file'
|
||||
Source = $SourceFilePath
|
||||
Destination = $DestinationFilePath
|
||||
Options = "-P $port "
|
||||
},
|
||||
@{
|
||||
Title = 'Simple copy local file to remote file'
|
||||
Source = $SourceFilePath
|
||||
Destination = "test_target:$DestinationFilePath"
|
||||
Options = "-P $port -S $sshcmd"
|
||||
Options = "-S '$sshcmd'"
|
||||
},
|
||||
@{
|
||||
Title = 'Simple copy remote file to local file'
|
||||
Source = "test_target:$SourceFilePath"
|
||||
Destination = $DestinationFilePath
|
||||
Options = "-P $port -p -c aes128-ctr -C"
|
||||
Options = "-p -c aes128-ctr -C"
|
||||
},
|
||||
@{
|
||||
Title = 'Simple copy local file to local dir'
|
||||
Source = $SourceFilePath
|
||||
Destination = $DestinationDir
|
||||
Options = "-P $port "
|
||||
},
|
||||
@{
|
||||
Title = 'simple copy local file to remote dir'
|
||||
Source = $SourceFilePath
|
||||
Destination = "test_target:$DestinationDir"
|
||||
Options = "-P $port -C -q"
|
||||
}<#,
|
||||
Options = "-C -q"
|
||||
},
|
||||
@{
|
||||
Title = 'simple copy remote file to local dir'
|
||||
Source = "test_target:$SourceFilePath"
|
||||
Destination = $DestinationDir
|
||||
Options = "-P $port "
|
||||
}#>
|
||||
}
|
||||
)
|
||||
|
||||
$testData1 = @(
|
||||
|
@ -76,7 +73,7 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||
Title = 'copy from local dir to remote dir'
|
||||
Source = $sourceDir
|
||||
Destination = "test_target:$DestinationDir"
|
||||
Options = "-P $port -r -p -c aes128-ctr"
|
||||
Options = "-r -p -c aes128-ctr"
|
||||
},
|
||||
@{
|
||||
Title = 'copy from local dir to local dir'
|
||||
|
@ -88,7 +85,7 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||
Title = 'copy from remote dir to local dir'
|
||||
Source = "test_target:$sourceDir"
|
||||
Destination = $DestinationDir
|
||||
Options = "-P $port -C -r -q"
|
||||
Options = "-C -r -q"
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -150,7 +147,7 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||
|
||||
|
||||
It 'File copy: <Title> ' -TestCases:$testData {
|
||||
param([string]$Title, $Source, $Destination, $Options)
|
||||
param([string]$Title, $Source, $Destination, [string]$Options)
|
||||
|
||||
iex "scp $Options $Source $Destination"
|
||||
$LASTEXITCODE | Should Be 0
|
||||
|
@ -168,7 +165,7 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||
}
|
||||
|
||||
It 'Directory recursive copy: <Title> ' -TestCases:$testData1 {
|
||||
param([string]$Title, $Source, $Destination, $Options)
|
||||
param([string]$Title, $Source, $Destination, [string]$Options)
|
||||
|
||||
iex "scp $Options $Source $Destination"
|
||||
$LASTEXITCODE | Should Be 0
|
||||
|
|
|
@ -61,6 +61,12 @@ ssh_sandbox_init(struct monitor *monitor)
|
|||
if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 ||
|
||||
#ifdef PRIV_NET_ACCESS
|
||||
priv_delset(box->pset, PRIV_NET_ACCESS) != 0 ||
|
||||
#endif
|
||||
#ifdef PRIV_DAX_ACCESS
|
||||
priv_delset(box->pset, PRIV_DAX_ACCESS) != 0 ||
|
||||
#endif
|
||||
#ifdef PRIV_SYS_IB_INFO
|
||||
priv_delset(box->pset, PRIV_SYS_IB_INFO) != 0 ||
|
||||
#endif
|
||||
priv_delset(box->pset, PRIV_PROC_EXEC) != 0 ||
|
||||
priv_delset(box->pset, PRIV_PROC_FORK) != 0 ||
|
||||
|
|
13
servconf.c
13
servconf.c
|
@ -1,5 +1,5 @@
|
|||
|
||||
/* $OpenBSD: servconf.c,v 1.308 2017/05/17 01:24:17 djm Exp $ */
|
||||
/* $OpenBSD: servconf.c,v 1.309 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
|
@ -164,6 +164,7 @@ initialize_server_options(ServerOptions *options)
|
|||
options->version_addendum = NULL;
|
||||
options->fingerprint_hash = -1;
|
||||
options->disable_forwarding = -1;
|
||||
options->expose_userauth_info = -1;
|
||||
}
|
||||
|
||||
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
|
||||
|
@ -333,6 +334,8 @@ fill_default_server_options(ServerOptions *options)
|
|||
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
|
||||
if (options->disable_forwarding == -1)
|
||||
options->disable_forwarding = 0;
|
||||
if (options->expose_userauth_info == -1)
|
||||
options->expose_userauth_info = 0;
|
||||
|
||||
assemble_algorithms(options);
|
||||
|
||||
|
@ -418,6 +421,7 @@ typedef enum {
|
|||
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
|
||||
sStreamLocalBindMask, sStreamLocalBindUnlink,
|
||||
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
|
||||
sExposeAuthInfo,
|
||||
sDeprecated, sIgnore, sUnsupported
|
||||
} ServerOpCodes;
|
||||
|
||||
|
@ -561,6 +565,7 @@ static struct {
|
|||
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
|
||||
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
|
||||
{ "disableforwarding", sDisableForwarding, SSHCFG_ALL },
|
||||
{ "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
|
||||
|
@ -1841,6 +1846,10 @@ process_server_config_line(ServerOptions *options, char *line,
|
|||
options->fingerprint_hash = value;
|
||||
break;
|
||||
|
||||
case sExposeAuthInfo:
|
||||
intptr = &options->expose_userauth_info;
|
||||
goto parse_flag;
|
||||
|
||||
case sDeprecated:
|
||||
case sIgnore:
|
||||
case sUnsupported:
|
||||
|
@ -1979,6 +1988,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
|
|||
M_CP_INTOPT(allow_streamlocal_forwarding);
|
||||
M_CP_INTOPT(allow_agent_forwarding);
|
||||
M_CP_INTOPT(disable_forwarding);
|
||||
M_CP_INTOPT(expose_userauth_info);
|
||||
M_CP_INTOPT(permit_tun);
|
||||
M_CP_INTOPT(fwd_opts.gateway_ports);
|
||||
M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
|
||||
|
@ -2278,6 +2288,7 @@ dump_config(ServerOptions *o)
|
|||
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
|
||||
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
|
||||
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
|
||||
dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
|
||||
|
||||
/* string arguments */
|
||||
dump_cfg_string(sPidFile, o->pid_file);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: servconf.h,v 1.123 2016/11/30 03:00:05 djm Exp $ */
|
||||
/* $OpenBSD: servconf.h,v 1.124 2017/06/24 06:34:38 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
@ -189,6 +189,7 @@ typedef struct {
|
|||
char *auth_methods[MAX_AUTH_METHODS];
|
||||
|
||||
int fingerprint_hash;
|
||||
int expose_userauth_info;
|
||||
} ServerOptions;
|
||||
|
||||
/* Information about the incoming connection as used by Match */
|
||||
|
|
62
session.c
62
session.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: session.c,v 1.288 2017/05/31 09:15:42 deraadt Exp $ */
|
||||
/* $OpenBSD: session.c,v 1.290 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
|
@ -94,6 +94,7 @@
|
|||
#include "kex.h"
|
||||
#include "monitor_wrap.h"
|
||||
#include "sftp.h"
|
||||
#include "atomicio.h"
|
||||
|
||||
#if defined(KRB5) && defined(USE_AFS)
|
||||
#include <kafs.h>
|
||||
|
@ -134,7 +135,6 @@ static int session_pty_req(Session *);
|
|||
/* import */
|
||||
extern ServerOptions options;
|
||||
extern char *__progname;
|
||||
extern int log_stderr;
|
||||
extern int debug_flag;
|
||||
extern u_int utmp_len;
|
||||
extern int startup_pipe;
|
||||
|
@ -161,6 +161,9 @@ login_cap_t *lc;
|
|||
static int is_child = 0;
|
||||
static int in_chroot = 0;
|
||||
|
||||
/* File containing userauth info, if ExposeAuthInfo set */
|
||||
static char *auth_info_file = NULL;
|
||||
|
||||
/* Name and directory of socket for authentication agent forwarding. */
|
||||
static char *auth_sock_name = NULL;
|
||||
static char *auth_sock_dir = NULL;
|
||||
|
@ -255,6 +258,40 @@ display_loginmsg(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_auth_info_file(struct passwd *pw, struct sshbuf *info)
|
||||
{
|
||||
int fd = -1, success = 0;
|
||||
|
||||
if (!options.expose_userauth_info || info == NULL)
|
||||
return;
|
||||
|
||||
temporarily_use_uid(pw);
|
||||
auth_info_file = xstrdup("/tmp/sshauth.XXXXXXXXXXXXXXX");
|
||||
if ((fd = mkstemp(auth_info_file)) == -1) {
|
||||
error("%s: mkstemp: %s", __func__, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
if (atomicio(vwrite, fd, sshbuf_mutable_ptr(info),
|
||||
sshbuf_len(info)) != sshbuf_len(info)) {
|
||||
error("%s: write: %s", __func__, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
if (close(fd) != 0) {
|
||||
error("%s: close: %s", __func__, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
success = 1;
|
||||
out:
|
||||
if (!success) {
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
free(auth_info_file);
|
||||
auth_info_file = NULL;
|
||||
}
|
||||
restore_uid();
|
||||
}
|
||||
|
||||
void
|
||||
do_authenticated(Authctxt *authctxt)
|
||||
{
|
||||
|
@ -270,7 +307,10 @@ do_authenticated(Authctxt *authctxt)
|
|||
|
||||
auth_debug_send();
|
||||
|
||||
prepare_auth_info_file(authctxt->pw, authctxt->session_info);
|
||||
|
||||
do_authenticated2(authctxt);
|
||||
|
||||
do_cleanup(authctxt);
|
||||
}
|
||||
|
||||
|
@ -641,10 +681,6 @@ do_exec_no_pty(Session *s, const char *command)
|
|||
case 0:
|
||||
is_child = 1;
|
||||
|
||||
/* Child. Reinitialize the log since the pid has changed. */
|
||||
log_init(__progname, options.log_level,
|
||||
options.log_facility, log_stderr);
|
||||
|
||||
/*
|
||||
* Create a new session and process group since the 4.4BSD
|
||||
* setlogin() affects the entire process group.
|
||||
|
@ -799,9 +835,6 @@ do_exec_pty(Session *s, const char *command)
|
|||
close(fdout);
|
||||
close(ptymaster);
|
||||
|
||||
/* Child. Reinitialize the log because the pid has changed. */
|
||||
log_init(__progname, options.log_level,
|
||||
options.log_facility, log_stderr);
|
||||
/* Close the master side of the pseudo tty. */
|
||||
close(ptyfd);
|
||||
|
||||
|
@ -1363,6 +1396,8 @@ do_setup_env(Session *s, const char *shell)
|
|||
free(laddr);
|
||||
child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
|
||||
|
||||
if (auth_info_file != NULL)
|
||||
child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info_file);
|
||||
if (s->ttyfd != -1)
|
||||
child_set_env(&env, &envsize, "SSH_TTY", s->tty);
|
||||
if (s->term)
|
||||
|
@ -2840,6 +2875,15 @@ do_cleanup(Authctxt *authctxt)
|
|||
/* remove agent socket */
|
||||
auth_sock_cleanup_proc(authctxt->pw);
|
||||
|
||||
/* remove userauth info */
|
||||
if (auth_info_file != NULL) {
|
||||
temporarily_use_uid(authctxt->pw);
|
||||
unlink(auth_info_file);
|
||||
restore_uid();
|
||||
free(auth_info_file);
|
||||
auth_info_file = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup ptys/utmp only if privsep is disabled,
|
||||
* or if running in monitor.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sftp-common.c,v 1.29 2016/09/12 01:22:38 deraadt Exp $ */
|
||||
/* $OpenBSD: sftp-common.c,v 1.30 2017/06/10 06:36:46 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||
|
@ -216,22 +216,21 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units)
|
|||
int ulen, glen, sz = 0;
|
||||
struct tm *ltime = localtime(&st->st_mtime);
|
||||
char *user, *group;
|
||||
char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
|
||||
char buf[1024], lc[8], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
|
||||
char sbuf[FMT_SCALED_STRSIZE];
|
||||
time_t now;
|
||||
|
||||
strmode(st->st_mode, mode);
|
||||
if (!remote) {
|
||||
user = user_from_uid(st->st_uid, 0);
|
||||
} else {
|
||||
if (remote) {
|
||||
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
|
||||
user = ubuf;
|
||||
}
|
||||
if (!remote) {
|
||||
group = group_from_gid(st->st_gid, 0);
|
||||
} else {
|
||||
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
|
||||
group = gbuf;
|
||||
strlcpy(lc, "?", sizeof(lc));
|
||||
} else {
|
||||
user = user_from_uid(st->st_uid, 0);
|
||||
group = group_from_gid(st->st_gid, 0);
|
||||
snprintf(lc, sizeof(lc), "%u", (u_int)st->st_nlink);
|
||||
}
|
||||
if (ltime != NULL) {
|
||||
now = time(NULL);
|
||||
|
@ -247,12 +246,12 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units)
|
|||
glen = MAXIMUM(strlen(group), 8);
|
||||
if (si_units) {
|
||||
fmt_scaled((long long)st->st_size, sbuf);
|
||||
snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8s %s %s", mode,
|
||||
(u_int)st->st_nlink, ulen, user, glen, group,
|
||||
snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8s %s %s",
|
||||
mode, lc, ulen, user, glen, group,
|
||||
sbuf, tbuf, name);
|
||||
} else {
|
||||
snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode,
|
||||
(u_int)st->st_nlink, ulen, user, glen, group,
|
||||
snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8llu %s %s",
|
||||
mode, lc, ulen, user, glen, group,
|
||||
(unsigned long long)st->st_size, tbuf, name);
|
||||
}
|
||||
return xstrdup(buf);
|
||||
|
|
56
sftp.c
56
sftp.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sftp.c,v 1.179 2017/05/02 08:54:19 djm Exp $ */
|
||||
/* $OpenBSD: sftp.c,v 1.180 2017/06/10 06:33:34 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
|
@ -106,6 +106,7 @@ volatile sig_atomic_t interrupted = 0;
|
|||
|
||||
/* I wish qsort() took a separate ctx for the comparison function...*/
|
||||
int sort_flag;
|
||||
glob_t *sort_glob;
|
||||
|
||||
/* Context used for commandline completion */
|
||||
struct complete_ctx {
|
||||
|
@ -927,6 +928,34 @@ do_ls_dir(struct sftp_conn *conn, const char *path,
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
sglob_comp(const void *aa, const void *bb)
|
||||
{
|
||||
u_int a = *(const u_int *)aa;
|
||||
u_int b = *(const u_int *)bb;
|
||||
const char *ap = sort_glob->gl_pathv[a];
|
||||
const char *bp = sort_glob->gl_pathv[b];
|
||||
const struct stat *as = sort_glob->gl_statv[a];
|
||||
const struct stat *bs = sort_glob->gl_statv[b];
|
||||
int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
|
||||
|
||||
#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
|
||||
if (sort_flag & LS_NAME_SORT)
|
||||
return (rmul * strcmp(ap, bp));
|
||||
else if (sort_flag & LS_TIME_SORT) {
|
||||
#if defined(HAVE_STRUCT_STAT_ST_MTIM)
|
||||
return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <));
|
||||
#elif defined(HAVE_STRUCT_STAT_ST_MTIME)
|
||||
return (rmul * NCMP(as->st_mtime, bs->st_mtime));
|
||||
#else
|
||||
return rmul * 1;
|
||||
#endif
|
||||
} else if (sort_flag & LS_SIZE_SORT)
|
||||
return (rmul * NCMP(as->st_size, bs->st_size));
|
||||
|
||||
fatal("Unknown ls sort type");
|
||||
}
|
||||
|
||||
/* sftp ls.1 replacement which handles path globs */
|
||||
static int
|
||||
do_globbed_ls(struct sftp_conn *conn, const char *path,
|
||||
|
@ -936,7 +965,8 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
|
|||
glob_t g;
|
||||
int err, r;
|
||||
struct winsize ws;
|
||||
u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80;
|
||||
u_int i, j, nentries, *indices = NULL, c = 1;
|
||||
u_int colspace = 0, columns = 1, m = 0, width = 80;
|
||||
|
||||
memset(&g, 0, sizeof(g));
|
||||
|
||||
|
@ -981,7 +1011,26 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
|
|||
colspace = width / columns;
|
||||
}
|
||||
|
||||
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
|
||||
/*
|
||||
* Sorting: rather than mess with the contents of glob_t, prepare
|
||||
* an array of indices into it and sort that. For the usual
|
||||
* unsorted case, the indices are just the identity 1=1, 2=2, etc.
|
||||
*/
|
||||
for (nentries = 0; g.gl_pathv[nentries] != NULL; nentries++)
|
||||
; /* count entries */
|
||||
indices = calloc(nentries, sizeof(*indices));
|
||||
for (i = 0; i < nentries; i++)
|
||||
indices[i] = i;
|
||||
|
||||
if (lflag & SORT_FLAGS) {
|
||||
sort_glob = &g;
|
||||
sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
|
||||
qsort(indices, nentries, sizeof(*indices), sglob_comp);
|
||||
sort_glob = NULL;
|
||||
}
|
||||
|
||||
for (j = 0; j < nentries && !interrupted; j++) {
|
||||
i = indices[j];
|
||||
fname = path_strip(g.gl_pathv[i], strip_path);
|
||||
if (lflag & LS_LONG_VIEW) {
|
||||
if (g.gl_statv[i] == NULL) {
|
||||
|
@ -1009,6 +1058,7 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
|
|||
out:
|
||||
if (g.gl_pathc)
|
||||
globfree(&g);
|
||||
free(indices);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */
|
||||
/* $OpenBSD: ssh-gss.h,v 1.12 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
|
||||
*
|
||||
|
@ -128,6 +128,7 @@ OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
|
|||
void ssh_gssapi_do_child(char ***, u_int *);
|
||||
void ssh_gssapi_cleanup_creds(void);
|
||||
void ssh_gssapi_storecreds(void);
|
||||
const char *ssh_gssapi_displayname(void);
|
||||
|
||||
#endif /* GSSAPI */
|
||||
|
||||
|
|
22
ssh-keygen.1
22
ssh-keygen.1
|
@ -1,4 +1,4 @@
|
|||
.\" $OpenBSD: ssh-keygen.1,v 1.141 2017/05/05 10:41:58 naddy Exp $
|
||||
.\" $OpenBSD: ssh-keygen.1,v 1.142 2017/06/28 01:09:22 djm Exp $
|
||||
.\"
|
||||
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
.\" 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
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd $Mdocdate: May 5 2017 $
|
||||
.Dd $Mdocdate: June 28 2017 $
|
||||
.Dt SSH-KEYGEN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -114,6 +114,8 @@
|
|||
.Fl s Ar ca_key
|
||||
.Fl I Ar certificate_identity
|
||||
.Op Fl h
|
||||
.Op Fl U
|
||||
.Op Fl D Ar pkcs11_provider
|
||||
.Op Fl n Ar principals
|
||||
.Op Fl O Ar option
|
||||
.Op Fl V Ar validity_interval
|
||||
|
@ -558,6 +560,14 @@ The possible values are
|
|||
.Dq ed25519 ,
|
||||
or
|
||||
.Dq rsa .
|
||||
.It Fl U
|
||||
When used in combination with
|
||||
.Fl s ,
|
||||
this option indicates that a CA key resides in a
|
||||
.Xr ssh-agent 1 .
|
||||
See the
|
||||
.Sx CERTIFICATES
|
||||
section for more information.
|
||||
.It Fl u
|
||||
Update a KRL.
|
||||
When specified with
|
||||
|
@ -705,6 +715,14 @@ to
|
|||
.Pp
|
||||
.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub
|
||||
.Pp
|
||||
Similarly, it is possible for the CA key to be hosted in a
|
||||
.Xr ssh-agent 1 .
|
||||
This is indicated by the
|
||||
.Fl U
|
||||
flag and, again, the CA key must be identified by its public half.
|
||||
.Pp
|
||||
.Dl $ ssh-keygen -Us ca_key.pub -I key_id user_key.pub
|
||||
.Pp
|
||||
In all cases,
|
||||
.Ar key_id
|
||||
is a "key identifier" that is logged by the server when the certificate
|
||||
|
|
76
ssh-keygen.c
76
ssh-keygen.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-keygen.c,v 1.304 2017/05/30 14:16:41 markus Exp $ */
|
||||
/* $OpenBSD: ssh-keygen.c,v 1.305 2017/06/28 01:09:22 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -59,6 +59,7 @@
|
|||
#include "krl.h"
|
||||
#include "digest.h"
|
||||
#include "utf8.h"
|
||||
#include "authfd.h"
|
||||
#include "sshfileperm.h"
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
|
@ -122,6 +123,9 @@ char *identity_comment = NULL;
|
|||
/* Path to CA key when certifying keys. */
|
||||
char *ca_key_path = NULL;
|
||||
|
||||
/* Prefer to use agent keys for CA signing */
|
||||
int prefer_agent = 0;
|
||||
|
||||
/* Certificate serial number */
|
||||
unsigned long long cert_serial = 0;
|
||||
|
||||
|
@ -1615,24 +1619,66 @@ load_pkcs11_key(char *path)
|
|||
#endif /* ENABLE_PKCS11 */
|
||||
}
|
||||
|
||||
/* Signer for sshkey_certify_custom that uses the agent */
|
||||
static int
|
||||
agent_signer(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen,
|
||||
const char *alg, u_int compat, void *ctx)
|
||||
{
|
||||
int *agent_fdp = (int *)ctx;
|
||||
|
||||
return ssh_agent_sign(*agent_fdp, key, sigp, lenp,
|
||||
data, datalen, alg, compat);
|
||||
}
|
||||
|
||||
static void
|
||||
do_ca_sign(struct passwd *pw, int argc, char **argv)
|
||||
{
|
||||
int r, i, fd;
|
||||
int r, i, fd, found, agent_fd = -1;
|
||||
u_int n;
|
||||
struct sshkey *ca, *public;
|
||||
char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
|
||||
FILE *f;
|
||||
struct ssh_identitylist *agent_ids;
|
||||
size_t j;
|
||||
|
||||
#ifdef ENABLE_PKCS11
|
||||
pkcs11_init(1);
|
||||
#endif
|
||||
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
|
||||
if (pkcs11provider != NULL) {
|
||||
/* If a PKCS#11 token was specified then try to use it */
|
||||
if ((ca = load_pkcs11_key(tmp)) == NULL)
|
||||
fatal("No PKCS#11 key matching %s found", ca_key_path);
|
||||
} else
|
||||
} else if (prefer_agent) {
|
||||
/*
|
||||
* Agent signature requested. Try to use agent after making
|
||||
* sure the public key specified is actually present in the
|
||||
* agent.
|
||||
*/
|
||||
if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
|
||||
fatal("Cannot load CA public key %s: %s",
|
||||
tmp, ssh_err(r));
|
||||
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
|
||||
fatal("Cannot use public key for CA signature: %s",
|
||||
ssh_err(r));
|
||||
if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0)
|
||||
fatal("Retrieve agent key list: %s", ssh_err(r));
|
||||
found = 0;
|
||||
for (j = 0; j < agent_ids->nkeys; j++) {
|
||||
if (sshkey_equal(ca, agent_ids->keys[j])) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
fatal("CA key %s not found in agent", tmp);
|
||||
ssh_free_identitylist(agent_ids);
|
||||
ca->flags |= SSHKEY_FLAG_EXT;
|
||||
} else {
|
||||
/* CA key is assumed to be a private key on the filesystem */
|
||||
ca = load_identity(tmp);
|
||||
}
|
||||
free(tmp);
|
||||
|
||||
if (key_type_name != NULL &&
|
||||
|
@ -1682,8 +1728,16 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
|
|||
&public->cert->signature_key)) != 0)
|
||||
fatal("sshkey_from_private (ca key): %s", ssh_err(r));
|
||||
|
||||
if ((r = sshkey_certify(public, ca, key_type_name)) != 0)
|
||||
fatal("Couldn't certify key %s: %s", tmp, ssh_err(r));
|
||||
if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) {
|
||||
if ((r = sshkey_certify_custom(public, ca,
|
||||
key_type_name, agent_signer, &agent_fd)) != 0)
|
||||
fatal("Couldn't certify key %s via agent: %s",
|
||||
tmp, ssh_err(r));
|
||||
} else {
|
||||
if ((sshkey_certify(public, ca, key_type_name)) != 0)
|
||||
fatal("Couldn't certify key %s: %s",
|
||||
tmp, ssh_err(r));
|
||||
}
|
||||
|
||||
if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
|
||||
*cp = '\0';
|
||||
|
@ -2279,8 +2333,9 @@ usage(void)
|
|||
" ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n"
|
||||
" [-j start_line] [-K checkpt] [-W generator]\n"
|
||||
#endif
|
||||
" ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals]\n"
|
||||
" [-O option] [-V validity_interval] [-z serial_number] file ...\n"
|
||||
" ssh-keygen -s ca_key -I certificate_identity [-h] [-U]\n"
|
||||
" [-D pkcs11_provider] [-n principals] [-O option]\n"
|
||||
" [-V validity_interval] [-z serial_number] file ...\n"
|
||||
" ssh-keygen -L [-f input_keyfile]\n"
|
||||
" ssh-keygen -A\n"
|
||||
" ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
|
||||
|
@ -2338,8 +2393,8 @@ main(int argc, char **argv)
|
|||
if (gethostname(hostname, sizeof(hostname)) < 0)
|
||||
fatal("gethostname: %s", strerror(errno));
|
||||
|
||||
/* Remaining characters: UYdw */
|
||||
while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy"
|
||||
/* Remaining characters: Ydw */
|
||||
while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvxy"
|
||||
"C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:"
|
||||
"a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
|
||||
switch (opt) {
|
||||
|
@ -2466,6 +2521,9 @@ main(int argc, char **argv)
|
|||
case 'D':
|
||||
pkcs11provider = optarg;
|
||||
break;
|
||||
case 'U':
|
||||
prefer_agent = 1;
|
||||
break;
|
||||
case 'u':
|
||||
update_krl = 1;
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-keyscan.c,v 1.114 2017/05/31 07:00:13 markus Exp $ */
|
||||
/* $OpenBSD: ssh-keyscan.c,v 1.115 2017/06/30 04:17:23 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
|
||||
*
|
||||
|
@ -395,7 +395,6 @@ confree(int s)
|
|||
{
|
||||
if (s >= maxfd || fdcon[s].c_status == CS_UNUSED)
|
||||
fatal("confree: attempt to free bad fdno %d", s);
|
||||
|
||||
free(fdcon[s].c_namebase);
|
||||
free(fdcon[s].c_output_name);
|
||||
if (fdcon[s].c_status == CS_KEYS)
|
||||
|
|
15
ssh.1
15
ssh.1
|
@ -33,8 +33,8 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: ssh.1,v 1.382 2017/05/30 18:58:37 bluhm Exp $
|
||||
.Dd $Mdocdate: May 30 2017 $
|
||||
.\" $OpenBSD: ssh.1,v 1.383 2017/06/09 06:43:01 djm Exp $
|
||||
.Dd $Mdocdate: June 9 2017 $
|
||||
.Dt SSH 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -846,6 +846,17 @@ The client proves that it has access to the private key
|
|||
and the server checks that the corresponding public key
|
||||
is authorized to accept the account.
|
||||
.Pp
|
||||
The server may inform the client of errors that prevented public key
|
||||
authentication from succeeding after authentication completes using a
|
||||
different method.
|
||||
These may be viewed by increasing the
|
||||
.Cm LogLevel
|
||||
to
|
||||
.Cm DEBUG
|
||||
or higher (e.g. by using the
|
||||
.Fl v
|
||||
flag).
|
||||
.Pp
|
||||
The user creates his/her key pair by running
|
||||
.Xr ssh-keygen 1 .
|
||||
This stores the private key in
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: ssh_config.5,v 1.250 2017/05/30 19:38:17 jmc Exp $
|
||||
.Dd $Mdocdate: May 30 2017 $
|
||||
.\" $OpenBSD: ssh_config.5,v 1.251 2017/06/24 05:35:05 djm Exp $
|
||||
.Dd $Mdocdate: June 24 2017 $
|
||||
.Dt SSH_CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -809,7 +809,7 @@ The list of available key types may also be obtained using
|
|||
.It Cm HostKeyAlias
|
||||
Specifies an alias that should be used instead of the
|
||||
real host name when looking up or saving the host key
|
||||
in the host key database files.
|
||||
in the host key database files and when validating host certificates.
|
||||
This option is useful for tunneling SSH connections
|
||||
or for multiple servers running on a single host.
|
||||
.It Cm HostName
|
||||
|
|
166
sshconnect.c
166
sshconnect.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshconnect.c,v 1.280 2017/05/30 14:13:40 markus Exp $ */
|
||||
/* $OpenBSD: sshconnect.c,v 1.282 2017/06/24 05:37:44 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -34,6 +34,9 @@
|
|||
#include <paths.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
@ -344,87 +347,71 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
|
|||
return sock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait up to *timeoutp milliseconds for fd to be readable. Updates
|
||||
* *timeoutp with time remaining.
|
||||
* Returns 0 if fd ready or -1 on timeout or error (see errno).
|
||||
*/
|
||||
static int
|
||||
waitrfd(int fd, int *timeoutp)
|
||||
{
|
||||
struct pollfd pfd;
|
||||
struct timeval t_start;
|
||||
int oerrno, r;
|
||||
|
||||
gettimeofday(&t_start, NULL);
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLIN;
|
||||
for (; *timeoutp >= 0;) {
|
||||
r = poll(&pfd, 1, *timeoutp);
|
||||
oerrno = errno;
|
||||
ms_subtract_diff(&t_start, timeoutp);
|
||||
errno = oerrno;
|
||||
if (r > 0)
|
||||
return 0;
|
||||
else if (r == -1 && errno != EAGAIN)
|
||||
return -1;
|
||||
else if (r == 0)
|
||||
break;
|
||||
}
|
||||
/* timeout */
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
timeout_connect(int sockfd, const struct sockaddr *serv_addr,
|
||||
socklen_t addrlen, int *timeoutp)
|
||||
{
|
||||
fd_set *fdset;
|
||||
struct timeval tv, t_start;
|
||||
socklen_t optlen;
|
||||
int optval, rc, result = -1;
|
||||
int optval = 0;
|
||||
socklen_t optlen = sizeof(optval);
|
||||
|
||||
gettimeofday(&t_start, NULL);
|
||||
|
||||
if (*timeoutp <= 0) {
|
||||
result = connect(sockfd, serv_addr, addrlen);
|
||||
goto done;
|
||||
}
|
||||
/* No timeout: just do a blocking connect() */
|
||||
if (*timeoutp <= 0)
|
||||
return connect(sockfd, serv_addr, addrlen);
|
||||
|
||||
set_nonblock(sockfd);
|
||||
rc = connect(sockfd, serv_addr, addrlen);
|
||||
if (rc == 0) {
|
||||
if (connect(sockfd, serv_addr, addrlen) == 0) {
|
||||
/* Succeeded already? */
|
||||
unset_nonblock(sockfd);
|
||||
result = 0;
|
||||
goto done;
|
||||
return 0;
|
||||
} else if (errno != EINPROGRESS)
|
||||
return -1;
|
||||
|
||||
if (waitrfd(sockfd, timeoutp) == -1)
|
||||
return -1;
|
||||
|
||||
/* Completed or failed */
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) {
|
||||
debug("getsockopt: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (errno != EINPROGRESS) {
|
||||
result = -1;
|
||||
goto done;
|
||||
if (optval != 0) {
|
||||
errno = optval;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fdset = xcalloc(howmany(sockfd + 1, NFDBITS),
|
||||
sizeof(fd_mask));
|
||||
FD_SET(sockfd, fdset);
|
||||
ms_to_timeval(&tv, *timeoutp);
|
||||
|
||||
for (;;) {
|
||||
rc = select(sockfd + 1, NULL, fdset, NULL, &tv);
|
||||
if (rc != -1 || errno != EINTR)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
case 0:
|
||||
/* Timed out */
|
||||
errno = ETIMEDOUT;
|
||||
break;
|
||||
case -1:
|
||||
/* Select error */
|
||||
debug("select: %s", strerror(errno));
|
||||
break;
|
||||
case 1:
|
||||
/* Completed or failed */
|
||||
optval = 0;
|
||||
optlen = sizeof(optval);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval,
|
||||
&optlen) == -1) {
|
||||
debug("getsockopt: %s", strerror(errno));
|
||||
break;
|
||||
}
|
||||
if (optval != 0) {
|
||||
errno = optval;
|
||||
break;
|
||||
}
|
||||
result = 0;
|
||||
unset_nonblock(sockfd);
|
||||
break;
|
||||
default:
|
||||
/* Should not occur */
|
||||
fatal("Bogus return (%d) from select()", rc);
|
||||
}
|
||||
|
||||
free(fdset);
|
||||
|
||||
done:
|
||||
if (result == 0 && *timeoutp > 0) {
|
||||
ms_subtract_diff(&t_start, timeoutp);
|
||||
if (*timeoutp <= 0) {
|
||||
errno = ETIMEDOUT;
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
unset_nonblock(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -562,42 +549,25 @@ ssh_exchange_identification(int timeout_ms)
|
|||
int connection_out = packet_get_connection_out();
|
||||
u_int i, n;
|
||||
size_t len;
|
||||
int fdsetsz, remaining, rc;
|
||||
struct timeval t_start, t_remaining;
|
||||
fd_set *readfds;
|
||||
fd_set *exceptfds;
|
||||
|
||||
fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
|
||||
readfds = xcalloc(1, fdsetsz);
|
||||
exceptfds = xcalloc(1, fdsetsz);
|
||||
int rc;
|
||||
|
||||
send_client_banner(connection_out, 0);
|
||||
|
||||
/* Read other side's version identification. */
|
||||
remaining = timeout_ms;
|
||||
for (n = 0;;) {
|
||||
for (i = 0; i < sizeof(buf) - 1; i++) {
|
||||
if (timeout_ms > 0) {
|
||||
gettimeofday(&t_start, NULL);
|
||||
ms_to_timeval(&t_remaining, remaining);
|
||||
FD_SET(connection_in, readfds);
|
||||
FD_SET(connection_in, exceptfds);
|
||||
rc = select(connection_in + 1, readfds, NULL,
|
||||
exceptfds, &t_remaining);
|
||||
ms_subtract_diff(&t_start, &remaining);
|
||||
if (rc == 0 || remaining <= 0)
|
||||
rc = waitrfd(connection_in, &timeout_ms);
|
||||
if (rc == -1 && errno == ETIMEDOUT) {
|
||||
fatal("Connection timed out during "
|
||||
"banner exchange");
|
||||
if (rc == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
fatal("ssh_exchange_identification: "
|
||||
"select: %s", strerror(errno));
|
||||
} else if (rc == -1) {
|
||||
fatal("%s: %s",
|
||||
__func__, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
len = atomicio(read, connection_in, &buf[i], 1);
|
||||
|
||||
if (len != 1 && errno == EPIPE)
|
||||
fatal("ssh_exchange_identification: "
|
||||
"Connection closed by remote host");
|
||||
|
@ -623,8 +593,6 @@ ssh_exchange_identification(int timeout_ms)
|
|||
debug("ssh_exchange_identification: %s", buf);
|
||||
}
|
||||
server_version_string = xstrdup(buf);
|
||||
free(readfds);
|
||||
free(exceptfds);
|
||||
|
||||
/*
|
||||
* Check that the versions match. In future this might accept
|
||||
|
@ -883,7 +851,9 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
|
|||
host, type, want_cert ? "certificate" : "key");
|
||||
debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
|
||||
host_found->file, host_found->line);
|
||||
if (want_cert && !check_host_cert(hostname, host_key))
|
||||
if (want_cert &&
|
||||
!check_host_cert(options.host_key_alias == NULL ?
|
||||
hostname : options.host_key_alias, host_key))
|
||||
goto fail;
|
||||
if (options.check_host_ip && ip_status == HOST_NEW) {
|
||||
if (readonly || want_cert)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshconnect2.c,v 1.263 2017/05/31 07:00:13 markus Exp $ */
|
||||
/* $OpenBSD: sshconnect2.c,v 1.264 2017/06/14 00:31:38 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
||||
|
@ -474,7 +474,8 @@ userauth(Authctxt *authctxt, char *authlist)
|
|||
for (;;) {
|
||||
Authmethod *method = authmethod_get(authlist);
|
||||
if (method == NULL)
|
||||
fatal("Permission denied (%s).", authlist);
|
||||
fatal("%s@%s: Permission denied (%s).",
|
||||
authctxt->server_user, authctxt->host, authlist);
|
||||
authctxt->method = method;
|
||||
|
||||
/* reset the per method handler */
|
||||
|
|
24
sshd.8
24
sshd.8
|
@ -33,8 +33,8 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: sshd.8,v 1.289 2017/05/07 23:12:57 djm Exp $
|
||||
.Dd $Mdocdate: May 7 2017 $
|
||||
.\" $OpenBSD: sshd.8,v 1.291 2017/06/24 06:28:50 jmc Exp $
|
||||
.Dd $Mdocdate: June 24 2017 $
|
||||
.Dt SSHD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -652,9 +652,23 @@ Hostnames is a comma-separated list of patterns
|
|||
and
|
||||
.Ql \&?
|
||||
act as
|
||||
wildcards); each pattern in turn is matched against the canonical host
|
||||
name (when authenticating a client) or against the user-supplied
|
||||
name (when authenticating a server).
|
||||
wildcards); each pattern in turn is matched against the host name.
|
||||
When
|
||||
.Nm sshd
|
||||
is authenticating a client, such as when using
|
||||
.Cm HostbasedAuthentication ,
|
||||
this will be the canonical client host name.
|
||||
When
|
||||
.Xr ssh 1
|
||||
is authenticating a server, this will be the host name
|
||||
given by the user, the value of the
|
||||
.Xr ssh 1
|
||||
.Cm HostkeyAlias
|
||||
if it was specified, or the canonical server hostname if the
|
||||
.Xr ssh 1
|
||||
.Cm CanonicalizeHostname
|
||||
option was used.
|
||||
.Pp
|
||||
A pattern may also be preceded by
|
||||
.Ql \&!
|
||||
to indicate negation: if the host name matches a negated
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: sshd_config.5,v 1.245 2017/05/17 01:24:17 djm Exp $
|
||||
.Dd $Mdocdate: May 17 2017 $
|
||||
.\" $OpenBSD: sshd_config.5,v 1.248 2017/06/24 07:08:57 djm Exp $
|
||||
.Dd $Mdocdate: June 24 2017 $
|
||||
.Dt SSHD_CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -564,6 +564,12 @@ Disables all forwarding features, including X11,
|
|||
TCP and StreamLocal.
|
||||
This option overrides all other forwarding-related options and may
|
||||
simplify restricted configurations.
|
||||
.It Cm ExposeAuthInfo
|
||||
Enables writing a file containing a list of authentication methods and
|
||||
public credentials (e.g. keys) used to authenticate the user.
|
||||
The location of the file is exposed to the user session through the
|
||||
.Ev SSH_USER_AUTH
|
||||
environment variable.
|
||||
.It Cm FingerprintHash
|
||||
Specifies the hash algorithm used when logging key fingerprints.
|
||||
Valid options are:
|
||||
|
|
127
sshkey.c
127
sshkey.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshkey.c,v 1.51 2017/05/31 09:15:42 deraadt Exp $ */
|
||||
/* $OpenBSD: sshkey.c,v 1.53 2017/06/28 01:09:22 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
||||
|
@ -1331,7 +1331,7 @@ sshkey_to_base64(const struct sshkey *key, char **b64p)
|
|||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
|
||||
{
|
||||
int r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
@ -2253,7 +2253,8 @@ sshkey_drop_cert(struct sshkey *k)
|
|||
|
||||
/* Sign a certified key, (re-)generating the signed certblob. */
|
||||
int
|
||||
sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
|
||||
sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
|
||||
sshkey_certify_signer *signer, void *signer_ctx)
|
||||
{
|
||||
struct sshbuf *principals = NULL;
|
||||
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
|
||||
|
@ -2342,8 +2343,8 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
|
|||
goto out;
|
||||
|
||||
/* Sign the whole mess */
|
||||
if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
|
||||
sshbuf_len(cert), alg, 0)) != 0)
|
||||
if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
|
||||
sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
|
||||
goto out;
|
||||
|
||||
/* Append signature and we are done */
|
||||
|
@ -2359,6 +2360,22 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen,
|
||||
const char *alg, u_int compat, void *ctx)
|
||||
{
|
||||
if (ctx != NULL)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
return sshkey_sign(key, sigp, lenp, data, datalen, alg, compat);
|
||||
}
|
||||
|
||||
int
|
||||
sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
|
||||
{
|
||||
return sshkey_certify_custom(k, ca, alg, default_key_sign, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
sshkey_cert_check_authority(const struct sshkey *k,
|
||||
int want_host, int require_principal,
|
||||
|
@ -3365,6 +3382,64 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
|
|||
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
static int
|
||||
translate_libcrypto_error(unsigned long pem_err)
|
||||
{
|
||||
int pem_reason = ERR_GET_REASON(pem_err);
|
||||
|
||||
switch (ERR_GET_LIB(pem_err)) {
|
||||
case ERR_LIB_PEM:
|
||||
switch (pem_reason) {
|
||||
case PEM_R_BAD_PASSWORD_READ:
|
||||
case PEM_R_PROBLEMS_GETTING_PASSWORD:
|
||||
case PEM_R_BAD_DECRYPT:
|
||||
return SSH_ERR_KEY_WRONG_PASSPHRASE;
|
||||
default:
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
}
|
||||
case ERR_LIB_EVP:
|
||||
switch (pem_reason) {
|
||||
case EVP_R_BAD_DECRYPT:
|
||||
return SSH_ERR_KEY_WRONG_PASSPHRASE;
|
||||
case EVP_R_BN_DECODE_ERROR:
|
||||
case EVP_R_DECODE_ERROR:
|
||||
#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
|
||||
case EVP_R_PRIVATE_KEY_DECODE_ERROR:
|
||||
#endif
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
default:
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
}
|
||||
case ERR_LIB_ASN1:
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
}
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_libcrypto_errors(void)
|
||||
{
|
||||
while (ERR_get_error() != 0)
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate OpenSSL error codes to determine whether
|
||||
* passphrase is required/incorrect.
|
||||
*/
|
||||
static int
|
||||
convert_libcrypto_error(void)
|
||||
{
|
||||
/*
|
||||
* Some password errors are reported at the beginning
|
||||
* of the error queue.
|
||||
*/
|
||||
if (translate_libcrypto_error(ERR_peek_error()) ==
|
||||
SSH_ERR_KEY_WRONG_PASSPHRASE)
|
||||
return SSH_ERR_KEY_WRONG_PASSPHRASE;
|
||||
return translate_libcrypto_error(ERR_peek_last_error());
|
||||
}
|
||||
|
||||
static int
|
||||
sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
||||
const char *passphrase, struct sshkey **keyp)
|
||||
|
@ -3385,48 +3460,10 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
|||
goto out;
|
||||
}
|
||||
|
||||
clear_libcrypto_errors();
|
||||
if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
|
||||
(char *)passphrase)) == NULL) {
|
||||
unsigned long pem_err = ERR_peek_last_error();
|
||||
int pem_reason = ERR_GET_REASON(pem_err);
|
||||
|
||||
/*
|
||||
* Translate OpenSSL error codes to determine whether
|
||||
* passphrase is required/incorrect.
|
||||
*/
|
||||
switch (ERR_GET_LIB(pem_err)) {
|
||||
case ERR_LIB_PEM:
|
||||
switch (pem_reason) {
|
||||
case PEM_R_BAD_PASSWORD_READ:
|
||||
case PEM_R_PROBLEMS_GETTING_PASSWORD:
|
||||
case PEM_R_BAD_DECRYPT:
|
||||
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
|
||||
goto out;
|
||||
default:
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
case ERR_LIB_EVP:
|
||||
switch (pem_reason) {
|
||||
case EVP_R_BAD_DECRYPT:
|
||||
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
|
||||
goto out;
|
||||
case EVP_R_BN_DECODE_ERROR:
|
||||
case EVP_R_DECODE_ERROR:
|
||||
#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
|
||||
case EVP_R_PRIVATE_KEY_DECODE_ERROR:
|
||||
#endif
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
default:
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
case ERR_LIB_ASN1:
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
r = convert_libcrypto_error();
|
||||
goto out;
|
||||
}
|
||||
if (pk->type == EVP_PKEY_RSA &&
|
||||
|
|
11
sshkey.h
11
sshkey.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshkey.h,v 1.18 2017/05/07 23:15:59 djm Exp $ */
|
||||
/* $OpenBSD: sshkey.h,v 1.20 2017/06/28 01:09:22 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
|
@ -124,6 +124,7 @@ int sshkey_fingerprint_raw(const struct sshkey *k,
|
|||
int, u_char **retp, size_t *lenp);
|
||||
const char *sshkey_type(const struct sshkey *);
|
||||
const char *sshkey_cert_type(const struct sshkey *);
|
||||
int sshkey_format_text(const struct sshkey *, struct sshbuf *);
|
||||
int sshkey_write(const struct sshkey *, FILE *);
|
||||
int sshkey_read(struct sshkey *, char **);
|
||||
u_int sshkey_size(const struct sshkey *);
|
||||
|
@ -136,13 +137,19 @@ int sshkey_type_is_cert(int);
|
|||
int sshkey_type_plain(int);
|
||||
int sshkey_to_certified(struct sshkey *);
|
||||
int sshkey_drop_cert(struct sshkey *);
|
||||
int sshkey_certify(struct sshkey *, struct sshkey *, const char *);
|
||||
int sshkey_cert_copy(const struct sshkey *, struct sshkey *);
|
||||
int sshkey_cert_check_authority(const struct sshkey *, int, int,
|
||||
const char *, const char **);
|
||||
size_t sshkey_format_cert_validity(const struct sshkey_cert *,
|
||||
char *, size_t) __attribute__((__bounded__(__string__, 2, 3)));
|
||||
|
||||
int sshkey_certify(struct sshkey *, struct sshkey *, const char *);
|
||||
/* Variant allowing use of a custom signature function (e.g. for ssh-agent) */
|
||||
typedef int sshkey_certify_signer(const struct sshkey *, u_char **, size_t *,
|
||||
const u_char *, size_t, const char *, u_int, void *);
|
||||
int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *,
|
||||
sshkey_certify_signer *, void *);
|
||||
|
||||
int sshkey_ecdsa_nid_from_name(const char *);
|
||||
int sshkey_curve_name_to_nid(const char *);
|
||||
const char * sshkey_curve_nid_to_name(int);
|
||||
|
|
Loading…
Reference in New Issue