Merge branch 'master' of https://github.com/openssh/openssh-portable into latestw
This commit is contained in:
commit
3dd748c035
|
@ -17,3 +17,5 @@ f6ae971186ba68d066cd102e57d5b0b2c211a5ee systrace is dead.
|
||||||
fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits
|
fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits
|
||||||
5781670c0578fe89663c9085ed3ba477cf7e7913 Delete sshconnect1.c
|
5781670c0578fe89663c9085ed3ba477cf7e7913 Delete sshconnect1.c
|
||||||
ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags
|
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):
|
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
|
FreeBSD 6.1 and OS X. Alternatively, you may use the OpenBSM
|
||||||
implementation (http://www.openbsm.org).
|
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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -268,21 +268,41 @@ allowed_user(struct passwd * pw)
|
||||||
return 1;
|
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;
|
const struct sshkey *key = authctxt->auth_method_key;
|
||||||
int i;
|
const char *methinfo = authctxt->auth_method_info;
|
||||||
|
char *fp, *ret = NULL;
|
||||||
|
|
||||||
free(authctxt->info);
|
if (key == NULL)
|
||||||
authctxt->info = NULL;
|
return NULL;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
if (key_is_cert(key)) {
|
||||||
i = vasprintf(&authctxt->info, fmt, ap);
|
fp = sshkey_fingerprint(key->cert->signature_key,
|
||||||
va_end(ap);
|
options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||||
|
xasprintf(&ret, "%s ID %s (serial %llu) CA %s %s%s%s",
|
||||||
if (i < 0 || authctxt->info == NULL)
|
sshkey_type(key), key->cert->key_id,
|
||||||
fatal("vasprintf failed");
|
(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
|
void
|
||||||
|
@ -291,7 +311,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
|
||||||
{
|
{
|
||||||
struct ssh *ssh = active_state; /* XXX */
|
struct ssh *ssh = active_state; /* XXX */
|
||||||
void (*authlog) (const char *fmt,...) = verbose;
|
void (*authlog) (const char *fmt,...) = verbose;
|
||||||
char *authmsg;
|
const char *authmsg;
|
||||||
|
char *extra = NULL;
|
||||||
|
|
||||||
if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
|
if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
|
||||||
return;
|
return;
|
||||||
|
@ -310,6 +331,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
|
||||||
else
|
else
|
||||||
authmsg = authenticated ? "Accepted" : "Failed";
|
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",
|
authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
|
||||||
authmsg,
|
authmsg,
|
||||||
method,
|
method,
|
||||||
|
@ -318,10 +344,10 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
|
||||||
authctxt->user,
|
authctxt->user,
|
||||||
ssh_remote_ipaddr(ssh),
|
ssh_remote_ipaddr(ssh),
|
||||||
ssh_remote_port(ssh),
|
ssh_remote_port(ssh),
|
||||||
authctxt->info != NULL ? ": " : "",
|
extra != NULL ? ": " : "",
|
||||||
authctxt->info != NULL ? authctxt->info : "");
|
extra != NULL ? extra : "");
|
||||||
free(authctxt->info);
|
|
||||||
authctxt->info = NULL;
|
free(extra);
|
||||||
|
|
||||||
#ifdef CUSTOM_FAILED_LOGIN
|
#ifdef CUSTOM_FAILED_LOGIN
|
||||||
if (authenticated == 0 && !authctxt->postponed &&
|
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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
struct ssh;
|
struct ssh;
|
||||||
struct sshkey;
|
struct sshkey;
|
||||||
|
struct sshbuf;
|
||||||
|
|
||||||
typedef struct Authctxt Authctxt;
|
typedef struct Authctxt Authctxt;
|
||||||
typedef struct Authmethod Authmethod;
|
typedef struct Authmethod Authmethod;
|
||||||
|
@ -62,13 +63,17 @@ struct Authctxt {
|
||||||
char *service;
|
char *service;
|
||||||
struct passwd *pw; /* set if 'valid' */
|
struct passwd *pw; /* set if 'valid' */
|
||||||
char *style;
|
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;
|
void *kbdintctxt;
|
||||||
char *info; /* Extra info for next auth_log */
|
|
||||||
#ifdef BSD_AUTH
|
#ifdef BSD_AUTH
|
||||||
auth_session_t *as;
|
auth_session_t *as;
|
||||||
#endif
|
#endif
|
||||||
char **auth_methods; /* modified from server config */
|
|
||||||
u_int num_auth_methods;
|
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
krb5_context krb5_ctx;
|
krb5_context krb5_ctx;
|
||||||
krb5_ccache krb5_fwd_ccache;
|
krb5_ccache krb5_fwd_ccache;
|
||||||
|
@ -76,14 +81,23 @@ struct Authctxt {
|
||||||
char *krb5_ticket_file;
|
char *krb5_ticket_file;
|
||||||
char *krb5_ccname;
|
char *krb5_ccname;
|
||||||
#endif
|
#endif
|
||||||
Buffer *loginmsg;
|
struct sshbuf *loginmsg;
|
||||||
void *methoddata;
|
|
||||||
|
/* 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
|
#ifdef WINDOWS
|
||||||
void *auth_token;
|
void *auth_token;
|
||||||
#endif
|
#endif
|
||||||
struct sshkey **prev_userkeys;
|
|
||||||
u_int nprev_userkeys;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Every authentication method has to handle authentication requests for
|
* Every authentication method has to handle authentication requests for
|
||||||
* non-existing users, or for users that are not allowed to login. In this
|
* 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 *,
|
int hostbased_key_allowed(struct passwd *, const char *, char *,
|
||||||
struct sshkey *);
|
struct sshkey *);
|
||||||
int user_key_allowed(struct passwd *, struct sshkey *, int);
|
int user_key_allowed(struct passwd *, struct sshkey *, int);
|
||||||
void pubkey_auth_info(Authctxt *, const struct sshkey *, const char *, ...)
|
int auth2_key_already_used(Authctxt *, const struct sshkey *);
|
||||||
__attribute__((__format__ (printf, 3, 4)));
|
|
||||||
void auth2_record_userkey(Authctxt *, struct sshkey *);
|
/*
|
||||||
int auth2_userkey_already_used(Authctxt *, 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;
|
struct stat;
|
||||||
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
|
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 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_log(Authctxt *, int, int, const char *, const char *);
|
||||||
void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
|
void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
|
||||||
void userauth_finish(struct ssh *, int, const char *, const char *);
|
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.
|
* 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;
|
Authctxt *authctxt = ssh->authctxt;
|
||||||
int authenticated;
|
int authenticated;
|
||||||
|
const char *displayname;
|
||||||
|
|
||||||
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
|
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
|
||||||
fatal("No authentication or GSSAPI context");
|
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));
|
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;
|
authctxt->postponed = 0;
|
||||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, 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;
|
Buffer b;
|
||||||
gss_buffer_desc mic, gssbuf;
|
gss_buffer_desc mic, gssbuf;
|
||||||
u_int len;
|
u_int len;
|
||||||
|
const char *displayname;
|
||||||
|
|
||||||
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
|
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
|
||||||
fatal("No authentication or GSSAPI context");
|
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);
|
buffer_free(&b);
|
||||||
free(mic.value);
|
free(mic.value);
|
||||||
|
|
||||||
|
if ((!use_privsep || mm_is_monitor()) &&
|
||||||
|
(displayname = ssh_gssapi_displayname()) != NULL)
|
||||||
|
auth2_record_info(authctxt, "%s", displayname);
|
||||||
|
|
||||||
authctxt->postponed = 0;
|
authctxt->postponed = 0;
|
||||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, 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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -137,7 +137,7 @@ userauth_hostbased(struct ssh *ssh)
|
||||||
sshbuf_dump(b, stderr);
|
sshbuf_dump(b, stderr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pubkey_auth_info(authctxt, key,
|
auth2_record_info(authctxt,
|
||||||
"client user \"%.100s\", client host \"%.100s\"", cuser, chost);
|
"client user \"%.100s\", client host \"%.100s\"", cuser, chost);
|
||||||
|
|
||||||
/* test for allowed key and correct signature */
|
/* 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)
|
sshbuf_ptr(b), sshbuf_len(b), ssh->compat)) == 0)
|
||||||
authenticated = 1;
|
authenticated = 1;
|
||||||
|
|
||||||
|
auth2_record_key(authctxt, authenticated, key);
|
||||||
sshbuf_free(b);
|
sshbuf_free(b);
|
||||||
done:
|
done:
|
||||||
debug2("%s: authenticated %d", __func__, authenticated);
|
debug2("%s: authenticated %d", __func__, authenticated);
|
||||||
if (key != NULL)
|
sshkey_free(key);
|
||||||
sshkey_free(key);
|
|
||||||
free(pkalg);
|
free(pkalg);
|
||||||
free(pkblob);
|
free(pkblob);
|
||||||
free(cuser);
|
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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -138,7 +138,7 @@ userauth_pubkey(struct ssh *ssh)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
|
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));
|
logit("refusing previously-used %s key", sshkey_type(key));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,6 @@ userauth_pubkey(struct ssh *ssh)
|
||||||
#ifdef DEBUG_PK
|
#ifdef DEBUG_PK
|
||||||
sshbuf_dump(b, stderr);
|
sshbuf_dump(b, stderr);
|
||||||
#endif
|
#endif
|
||||||
pubkey_auth_info(authctxt, key, NULL);
|
|
||||||
|
|
||||||
/* test for correct signature */
|
/* test for correct signature */
|
||||||
authenticated = 0;
|
authenticated = 0;
|
||||||
|
@ -209,13 +208,10 @@ userauth_pubkey(struct ssh *ssh)
|
||||||
sshbuf_len(b), ssh->compat)) == 0) {
|
sshbuf_len(b), ssh->compat)) == 0) {
|
||||||
#endif
|
#endif
|
||||||
authenticated = 1;
|
authenticated = 1;
|
||||||
/* Record the successful key to prevent reuse */
|
|
||||||
auth2_record_userkey(authctxt, key);
|
|
||||||
key = NULL; /* Don't free below */
|
|
||||||
}
|
}
|
||||||
sshbuf_free(b);
|
sshbuf_free(b);
|
||||||
free(sig);
|
free(sig);
|
||||||
|
auth2_record_key(authctxt, authenticated, key);
|
||||||
} else {
|
} else {
|
||||||
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
|
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
|
||||||
__func__, sshkey_type(key), fp);
|
__func__, sshkey_type(key), fp);
|
||||||
|
@ -245,8 +241,7 @@ userauth_pubkey(struct ssh *ssh)
|
||||||
auth_clear_options();
|
auth_clear_options();
|
||||||
done:
|
done:
|
||||||
debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
|
debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
|
||||||
if (key != NULL)
|
sshkey_free(key);
|
||||||
sshkey_free(key);
|
|
||||||
free(userstyle);
|
free(userstyle);
|
||||||
free(pkalg);
|
free(pkalg);
|
||||||
free(pkblob);
|
free(pkblob);
|
||||||
|
@ -254,44 +249,6 @@ done:
|
||||||
return authenticated;
|
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
|
* Splits 's' into an argument vector. Handles quoted string and basic
|
||||||
* escape characters (\\, \", \'). Caller must free the argument vector
|
* 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;
|
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 = {
|
Authmethod method_pubkey = {
|
||||||
"publickey",
|
"publickey",
|
||||||
userauth_pubkey,
|
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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -55,6 +56,7 @@
|
||||||
#include "ssh-gss.h"
|
#include "ssh-gss.h"
|
||||||
#endif
|
#endif
|
||||||
#include "monitor_wrap.h"
|
#include "monitor_wrap.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
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);
|
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
auth2_authctxt_reset_info(authctxt);
|
||||||
authctxt->postponed = 0;
|
authctxt->postponed = 0;
|
||||||
authctxt->server_caused_failure = 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 */
|
/* Log before sending the reply */
|
||||||
auth_log(authctxt, authenticated, partial, method, submethod);
|
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)
|
if (authctxt->postponed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -624,4 +631,128 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method,
|
||||||
return 0;
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -331,7 +331,7 @@ ssh_free_identitylist(struct ssh_identitylist *idl)
|
||||||
|
|
||||||
/* encode signature algoritm in flag bits, so we can keep the msg format */
|
/* encode signature algoritm in flag bits, so we can keep the msg format */
|
||||||
static u_int
|
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 (alg != NULL && key->type == KEY_RSA) {
|
||||||
if (strcmp(alg, "rsa-sha2-256") == 0)
|
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 */
|
/* ask agent to sign data, returns err.h code on error, 0 on success */
|
||||||
int
|
int
|
||||||
ssh_agent_sign(int sock, struct sshkey *key,
|
ssh_agent_sign(int sock, const struct sshkey *key,
|
||||||
u_char **sigp, size_t *lenp,
|
u_char **sigp, size_t *lenp,
|
||||||
const u_char *data, size_t datalen, const char *alg, u_int compat)
|
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>
|
* 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,
|
int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
|
||||||
u_char session_id[16], u_char response[16]);
|
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,
|
u_char **sigp, size_t *lenp,
|
||||||
const u_char *data, size_t datalen, const char *alg, u_int compat);
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -1259,7 +1259,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
debug("pledge: network");
|
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));
|
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])
|
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_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,
|
AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_class,
|
||||||
struct passwd.pw_change, struct passwd.pw_expire],
|
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......
|
appropriate). It seems to work, though......
|
||||||
|
|
||||||
If there are any patches to this that have not yet been integrated they
|
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:
|
Disclaimer:
|
||||||
|
|
|
@ -519,6 +519,13 @@ struct winsize {
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#ifndef __P
|
||||||
# define __P(x) x
|
# define __P(x) x
|
||||||
#endif
|
#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.
|
* 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);
|
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
|
#endif
|
||||||
|
|
|
@ -93,6 +93,9 @@
|
||||||
#ifdef HAVE_SYS_SYSMACROS_H
|
#ifdef HAVE_SYS_SYSMACROS_H
|
||||||
# include <sys/sysmacros.h> /* For MIN, MAX, etc */
|
# include <sys/sysmacros.h> /* For MIN, MAX, etc */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
# include <sys/time.h> /* for timespeccmp if present */
|
||||||
|
#endif
|
||||||
#ifdef HAVE_SYS_MMAN_H
|
#ifdef HAVE_SYS_MMAN_H
|
||||||
#include <sys/mman.h> /* for MAP_ANONYMOUS */
|
#include <sys/mman.h> /* for MAP_ANONYMOUS */
|
||||||
#endif
|
#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.
|
* 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;
|
struct kex *kex = ssh->kex;
|
||||||
u_int32_t i, ninfo;
|
u_int32_t i, ninfo;
|
||||||
char *name, *val, *found;
|
char *name, *found;
|
||||||
|
u_char *val;
|
||||||
|
size_t vlen;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
debug("SSH2_MSG_EXT_INFO received");
|
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++) {
|
for (i = 0; i < ninfo; i++) {
|
||||||
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
|
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
|
||||||
return r;
|
return r;
|
||||||
if ((r = sshpkt_get_cstring(ssh, &val, NULL)) != 0) {
|
if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
|
||||||
free(name);
|
free(name);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
debug("%s: %s=<%s>", __func__, name, val);
|
|
||||||
if (strcmp(name, "server-sig-algs") == 0) {
|
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);
|
found = match_list("rsa-sha2-256", val, NULL);
|
||||||
if (found) {
|
if (found) {
|
||||||
kex->rsa_sha2 = 256;
|
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;
|
kex->rsa_sha2 = 512;
|
||||||
free(found);
|
free(found);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
|
debug("%s: %s (unrecognised)", __func__, name);
|
||||||
free(name);
|
free(name);
|
||||||
free(val);
|
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 Niels Provos <provos@citi.umich.edu>
|
||||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||||
|
@ -308,6 +308,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
||||||
partial = 0;
|
partial = 0;
|
||||||
auth_method = "unknown";
|
auth_method = "unknown";
|
||||||
auth_submethod = NULL;
|
auth_submethod = NULL;
|
||||||
|
auth2_authctxt_reset_info(authctxt);
|
||||||
|
|
||||||
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
|
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
|
||||||
|
|
||||||
/* Special handling for multiple required authentications */
|
/* Special handling for multiple required authentications */
|
||||||
|
@ -347,6 +349,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
||||||
auth_method, auth_submethod);
|
auth_method, auth_submethod);
|
||||||
if (!partial && !authenticated)
|
if (!partial && !authenticated)
|
||||||
authctxt->failures++;
|
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) {
|
switch (type) {
|
||||||
case MM_USERKEY:
|
case MM_USERKEY:
|
||||||
allowed = options.pubkey_authentication &&
|
allowed = options.pubkey_authentication &&
|
||||||
!auth2_userkey_already_used(authctxt, key) &&
|
!auth2_key_already_used(authctxt, key) &&
|
||||||
match_pattern_list(sshkey_ssh_name(key),
|
match_pattern_list(sshkey_ssh_name(key),
|
||||||
options.pubkey_key_types, 0) == 1 &&
|
options.pubkey_key_types, 0) == 1 &&
|
||||||
user_key_allowed(authctxt->pw, key,
|
user_key_allowed(authctxt->pw, key,
|
||||||
pubkey_auth_attempt);
|
pubkey_auth_attempt);
|
||||||
pubkey_auth_info(authctxt, key, NULL);
|
|
||||||
auth_method = "publickey";
|
auth_method = "publickey";
|
||||||
if (options.pubkey_authentication &&
|
if (options.pubkey_authentication &&
|
||||||
(!pubkey_auth_attempt || allowed != 1))
|
(!pubkey_auth_attempt || allowed != 1))
|
||||||
|
@ -1160,11 +1165,12 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||||
break;
|
break;
|
||||||
case MM_HOSTKEY:
|
case MM_HOSTKEY:
|
||||||
allowed = options.hostbased_authentication &&
|
allowed = options.hostbased_authentication &&
|
||||||
|
!auth2_key_already_used(authctxt, key) &&
|
||||||
match_pattern_list(sshkey_ssh_name(key),
|
match_pattern_list(sshkey_ssh_name(key),
|
||||||
options.hostbased_key_types, 0) == 1 &&
|
options.hostbased_key_types, 0) == 1 &&
|
||||||
hostbased_key_allowed(authctxt->pw,
|
hostbased_key_allowed(authctxt->pw,
|
||||||
cuser, chost, key);
|
cuser, chost, key);
|
||||||
pubkey_auth_info(authctxt, key,
|
auth2_record_info(authctxt,
|
||||||
"client user \"%.100s\", client host \"%.100s\"",
|
"client user \"%.100s\", client host \"%.100s\"",
|
||||||
cuser, chost);
|
cuser, chost);
|
||||||
auth_method = "hostbased";
|
auth_method = "hostbased";
|
||||||
|
@ -1175,11 +1181,10 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug3("%s: key %p is %s",
|
debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed");
|
||||||
__func__, key, allowed ? "allowed" : "not allowed");
|
|
||||||
|
|
||||||
if (key != NULL)
|
auth2_record_key(authctxt, 0, key);
|
||||||
key_free(key);
|
sshkey_free(key);
|
||||||
|
|
||||||
/* clear temporarily storage (used by verify) */
|
/* clear temporarily storage (used by verify) */
|
||||||
monitor_reset_key_state();
|
monitor_reset_key_state();
|
||||||
|
@ -1353,10 +1358,12 @@ mm_answer_keyverify(int sock, struct sshbuf *m)
|
||||||
switch (key_blobtype) {
|
switch (key_blobtype) {
|
||||||
case MM_USERKEY:
|
case MM_USERKEY:
|
||||||
valid_data = monitor_valid_userblob(data, datalen);
|
valid_data = monitor_valid_userblob(data, datalen);
|
||||||
|
auth_method = "publickey";
|
||||||
break;
|
break;
|
||||||
case MM_HOSTKEY:
|
case MM_HOSTKEY:
|
||||||
valid_data = monitor_valid_hostbasedblob(data, datalen,
|
valid_data = monitor_valid_hostbasedblob(data, datalen,
|
||||||
hostbased_cuser, hostbased_chost);
|
hostbased_cuser, hostbased_chost);
|
||||||
|
auth_method = "hostbased";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
valid_data = 0;
|
valid_data = 0;
|
||||||
|
@ -1367,23 +1374,17 @@ mm_answer_keyverify(int sock, struct sshbuf *m)
|
||||||
|
|
||||||
ret = sshkey_verify(key, signature, signaturelen, data, datalen,
|
ret = sshkey_verify(key, signature, signaturelen, data, datalen,
|
||||||
active_state->compat);
|
active_state->compat);
|
||||||
debug3("%s: key %p signature %s",
|
debug3("%s: %s %p signature %s", __func__, auth_method, key,
|
||||||
__func__, key, (ret == 0) ? "verified" : "unverified");
|
(ret == 0) ? "verified" : "unverified");
|
||||||
|
auth2_record_key(authctxt, ret == 0, key);
|
||||||
/* 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);
|
|
||||||
|
|
||||||
free(blob);
|
free(blob);
|
||||||
free(signature);
|
free(signature);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
|
|
||||||
|
|
||||||
monitor_reset_key_state();
|
monitor_reset_key_state();
|
||||||
|
|
||||||
|
sshkey_free(key);
|
||||||
sshbuf_reset(m);
|
sshbuf_reset(m);
|
||||||
|
|
||||||
/* encode ret != 0 as positive integer, since we're sending u32 */
|
/* encode ret != 0 as positive integer, since we're sending u32 */
|
||||||
|
@ -1799,6 +1800,7 @@ int
|
||||||
mm_answer_gss_userok(int sock, Buffer *m)
|
mm_answer_gss_userok(int sock, Buffer *m)
|
||||||
{
|
{
|
||||||
int authenticated;
|
int authenticated;
|
||||||
|
const char *displayname;
|
||||||
|
|
||||||
if (!options.gss_authentication)
|
if (!options.gss_authentication)
|
||||||
fatal("%s: GSSAPI authentication not enabled", __func__);
|
fatal("%s: GSSAPI authentication not enabled", __func__);
|
||||||
|
@ -1813,6 +1815,9 @@ mm_answer_gss_userok(int sock, Buffer *m)
|
||||||
|
|
||||||
auth_method = "gssapi-with-mic";
|
auth_method = "gssapi-with-mic";
|
||||||
|
|
||||||
|
if ((displayname = ssh_gssapi_displayname()) != NULL)
|
||||||
|
auth2_record_info(authctxt, "%s", displayname);
|
||||||
|
|
||||||
/* Monitor loop will terminate if authenticated */
|
/* Monitor loop will terminate if authenticated */
|
||||||
return (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>
|
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
|
||||||
*
|
*
|
||||||
|
@ -1570,31 +1570,38 @@ mux_client_hello_exchange(int fd)
|
||||||
{
|
{
|
||||||
Buffer m;
|
Buffer m;
|
||||||
u_int type, ver;
|
u_int type, ver;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
buffer_init(&m);
|
buffer_init(&m);
|
||||||
buffer_put_int(&m, MUX_MSG_HELLO);
|
buffer_put_int(&m, MUX_MSG_HELLO);
|
||||||
buffer_put_int(&m, SSHMUX_VER);
|
buffer_put_int(&m, SSHMUX_VER);
|
||||||
/* no extensions */
|
/* no extensions */
|
||||||
|
|
||||||
if (mux_client_write_packet(fd, &m) != 0)
|
if (mux_client_write_packet(fd, &m) != 0) {
|
||||||
fatal("%s: write packet: %s", __func__, strerror(errno));
|
debug("%s: write packet: %s", __func__, strerror(errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
buffer_clear(&m);
|
buffer_clear(&m);
|
||||||
|
|
||||||
/* Read their HELLO */
|
/* Read their HELLO */
|
||||||
if (mux_client_read_packet(fd, &m) != 0) {
|
if (mux_client_read_packet(fd, &m) != 0) {
|
||||||
buffer_free(&m);
|
debug("%s: read packet failed", __func__);
|
||||||
return -1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = buffer_get_int(&m);
|
type = buffer_get_int(&m);
|
||||||
if (type != MUX_MSG_HELLO)
|
if (type != MUX_MSG_HELLO) {
|
||||||
fatal("%s: expected HELLO (%u) received %u",
|
error("%s: expected HELLO (%u) received %u",
|
||||||
__func__, MUX_MSG_HELLO, type);
|
__func__, MUX_MSG_HELLO, type);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
ver = buffer_get_int(&m);
|
ver = buffer_get_int(&m);
|
||||||
if (ver != SSHMUX_VER)
|
if (ver != SSHMUX_VER) {
|
||||||
fatal("Unsupported multiplexing protocol version %d "
|
error("Unsupported multiplexing protocol version %d "
|
||||||
"(expected %d)", ver, SSHMUX_VER);
|
"(expected %d)", ver, SSHMUX_VER);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
debug2("%s: master version %u", __func__, ver);
|
debug2("%s: master version %u", __func__, ver);
|
||||||
/* No extensions are presently defined */
|
/* No extensions are presently defined */
|
||||||
while (buffer_len(&m) > 0) {
|
while (buffer_len(&m) > 0) {
|
||||||
|
@ -1605,8 +1612,11 @@ mux_client_hello_exchange(int fd)
|
||||||
free(name);
|
free(name);
|
||||||
free(value);
|
free(value);
|
||||||
}
|
}
|
||||||
|
/* success */
|
||||||
|
ret = 0;
|
||||||
|
out:
|
||||||
buffer_free(&m);
|
buffer_free(&m);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u_int
|
static u_int
|
||||||
|
|
|
@ -22,7 +22,9 @@
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -901,6 +901,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
|
||||||
/*
|
/*
|
||||||
* The 2^(blocksize*2) limit is too expensive for 3DES,
|
* The 2^(blocksize*2) limit is too expensive for 3DES,
|
||||||
* so enforce a 1GB limit for small blocksizes.
|
* so enforce a 1GB limit for small blocksizes.
|
||||||
|
* See RFC4344 section 3.2.
|
||||||
*/
|
*/
|
||||||
if (enc->block_size >= 16)
|
if (enc->block_size >= 16)
|
||||||
*max_blocks = (u_int64_t)1 << (enc->block_size*2);
|
*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())
|
(int64_t)state->rekey_time + state->rekey_interval <= monotime())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Always rekey when MAX_PACKETS sent in either direction */
|
/*
|
||||||
|
* Always rekey when MAX_PACKETS sent in either direction
|
||||||
|
* As per RFC4344 section 3.1 we do this after 2^31 packets.
|
||||||
|
*/
|
||||||
if (state->p_send.packets > MAX_PACKETS ||
|
if (state->p_send.packets > MAX_PACKETS ||
|
||||||
state->p_read.packets > MAX_PACKETS)
|
state->p_read.packets > MAX_PACKETS)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2218,9 +2222,7 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode)
|
||||||
return r;
|
return r;
|
||||||
if ((b = sshbuf_new()) == NULL)
|
if ((b = sshbuf_new()) == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
/* The cipher struct is constant and shared, you export pointer */
|
|
||||||
if ((r = sshbuf_put_cstring(b, enc->name)) != 0 ||
|
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->enabled)) != 0 ||
|
||||||
(r = sshbuf_put_u32(b, enc->block_size)) != 0 ||
|
(r = sshbuf_put_u32(b, enc->block_size)) != 0 ||
|
||||||
(r = sshbuf_put_string(b, enc->key, enc->key_len)) != 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;
|
comp = &newkey->comp;
|
||||||
|
|
||||||
if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 ||
|
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, (u_int *)&enc->enabled)) != 0 ||
|
||||||
(r = sshbuf_get_u32(b, &enc->block_size)) != 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->key, &keylen)) != 0 ||
|
||||||
(r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0)
|
(r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0)
|
||||||
goto out;
|
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 (cipher_authlen(enc->cipher) == 0) {
|
||||||
if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0)
|
if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0)
|
||||||
goto out;
|
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 ||
|
if ((r = sshbuf_get_u32(b, &comp->type)) != 0 ||
|
||||||
(r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0)
|
(r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0)
|
||||||
goto out;
|
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) {
|
if (sshbuf_len(b) != 0) {
|
||||||
r = SSH_ERR_INVALID_FORMAT;
|
r = SSH_ERR_INVALID_FORMAT;
|
||||||
goto out;
|
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
|
REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t-exec
|
||||||
tests: prep $(REGRESS_TARGETS)
|
tests: prep $(REGRESS_TARGETS)
|
||||||
|
@ -79,7 +79,8 @@ LTESTS= connect \
|
||||||
principals-command \
|
principals-command \
|
||||||
cert-file \
|
cert-file \
|
||||||
cfginclude \
|
cfginclude \
|
||||||
allow-deny-users
|
allow-deny-users \
|
||||||
|
authinfo
|
||||||
|
|
||||||
|
|
||||||
# dhgex \
|
# 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
|
|
@ -61,6 +61,12 @@ ssh_sandbox_init(struct monitor *monitor)
|
||||||
if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 ||
|
if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 ||
|
||||||
#ifdef PRIV_NET_ACCESS
|
#ifdef PRIV_NET_ACCESS
|
||||||
priv_delset(box->pset, PRIV_NET_ACCESS) != 0 ||
|
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
|
#endif
|
||||||
priv_delset(box->pset, PRIV_PROC_EXEC) != 0 ||
|
priv_delset(box->pset, PRIV_PROC_EXEC) != 0 ||
|
||||||
priv_delset(box->pset, PRIV_PROC_FORK) != 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
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
@ -164,6 +164,7 @@ initialize_server_options(ServerOptions *options)
|
||||||
options->version_addendum = NULL;
|
options->version_addendum = NULL;
|
||||||
options->fingerprint_hash = -1;
|
options->fingerprint_hash = -1;
|
||||||
options->disable_forwarding = -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. */
|
/* 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;
|
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
|
||||||
if (options->disable_forwarding == -1)
|
if (options->disable_forwarding == -1)
|
||||||
options->disable_forwarding = 0;
|
options->disable_forwarding = 0;
|
||||||
|
if (options->expose_userauth_info == -1)
|
||||||
|
options->expose_userauth_info = 0;
|
||||||
|
|
||||||
assemble_algorithms(options);
|
assemble_algorithms(options);
|
||||||
|
|
||||||
|
@ -418,6 +421,7 @@ typedef enum {
|
||||||
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
|
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
|
||||||
sStreamLocalBindMask, sStreamLocalBindUnlink,
|
sStreamLocalBindMask, sStreamLocalBindUnlink,
|
||||||
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
|
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
|
||||||
|
sExposeAuthInfo,
|
||||||
sDeprecated, sIgnore, sUnsupported
|
sDeprecated, sIgnore, sUnsupported
|
||||||
} ServerOpCodes;
|
} ServerOpCodes;
|
||||||
|
|
||||||
|
@ -561,6 +565,7 @@ static struct {
|
||||||
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
|
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
|
||||||
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
|
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
|
||||||
{ "disableforwarding", sDisableForwarding, SSHCFG_ALL },
|
{ "disableforwarding", sDisableForwarding, SSHCFG_ALL },
|
||||||
|
{ "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
|
||||||
{ NULL, sBadOption, 0 }
|
{ NULL, sBadOption, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1841,6 +1846,10 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||||
options->fingerprint_hash = value;
|
options->fingerprint_hash = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case sExposeAuthInfo:
|
||||||
|
intptr = &options->expose_userauth_info;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
case sDeprecated:
|
case sDeprecated:
|
||||||
case sIgnore:
|
case sIgnore:
|
||||||
case sUnsupported:
|
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_streamlocal_forwarding);
|
||||||
M_CP_INTOPT(allow_agent_forwarding);
|
M_CP_INTOPT(allow_agent_forwarding);
|
||||||
M_CP_INTOPT(disable_forwarding);
|
M_CP_INTOPT(disable_forwarding);
|
||||||
|
M_CP_INTOPT(expose_userauth_info);
|
||||||
M_CP_INTOPT(permit_tun);
|
M_CP_INTOPT(permit_tun);
|
||||||
M_CP_INTOPT(fwd_opts.gateway_ports);
|
M_CP_INTOPT(fwd_opts.gateway_ports);
|
||||||
M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
|
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(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
|
||||||
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
|
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
|
||||||
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
|
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
|
||||||
|
dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
|
||||||
|
|
||||||
/* string arguments */
|
/* string arguments */
|
||||||
dump_cfg_string(sPidFile, o->pid_file);
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -189,6 +189,7 @@ typedef struct {
|
||||||
char *auth_methods[MAX_AUTH_METHODS];
|
char *auth_methods[MAX_AUTH_METHODS];
|
||||||
|
|
||||||
int fingerprint_hash;
|
int fingerprint_hash;
|
||||||
|
int expose_userauth_info;
|
||||||
} ServerOptions;
|
} ServerOptions;
|
||||||
|
|
||||||
/* Information about the incoming connection as used by Match */
|
/* 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
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
@ -94,6 +94,7 @@
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "monitor_wrap.h"
|
#include "monitor_wrap.h"
|
||||||
#include "sftp.h"
|
#include "sftp.h"
|
||||||
|
#include "atomicio.h"
|
||||||
|
|
||||||
#if defined(KRB5) && defined(USE_AFS)
|
#if defined(KRB5) && defined(USE_AFS)
|
||||||
#include <kafs.h>
|
#include <kafs.h>
|
||||||
|
@ -134,7 +135,6 @@ static int session_pty_req(Session *);
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
extern int log_stderr;
|
|
||||||
extern int debug_flag;
|
extern int debug_flag;
|
||||||
extern u_int utmp_len;
|
extern u_int utmp_len;
|
||||||
extern int startup_pipe;
|
extern int startup_pipe;
|
||||||
|
@ -161,6 +161,9 @@ login_cap_t *lc;
|
||||||
static int is_child = 0;
|
static int is_child = 0;
|
||||||
static int in_chroot = 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. */
|
/* Name and directory of socket for authentication agent forwarding. */
|
||||||
static char *auth_sock_name = NULL;
|
static char *auth_sock_name = NULL;
|
||||||
static char *auth_sock_dir = 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
|
void
|
||||||
do_authenticated(Authctxt *authctxt)
|
do_authenticated(Authctxt *authctxt)
|
||||||
{
|
{
|
||||||
|
@ -270,7 +307,10 @@ do_authenticated(Authctxt *authctxt)
|
||||||
|
|
||||||
auth_debug_send();
|
auth_debug_send();
|
||||||
|
|
||||||
|
prepare_auth_info_file(authctxt->pw, authctxt->session_info);
|
||||||
|
|
||||||
do_authenticated2(authctxt);
|
do_authenticated2(authctxt);
|
||||||
|
|
||||||
do_cleanup(authctxt);
|
do_cleanup(authctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,10 +681,6 @@ do_exec_no_pty(Session *s, const char *command)
|
||||||
case 0:
|
case 0:
|
||||||
is_child = 1;
|
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
|
* Create a new session and process group since the 4.4BSD
|
||||||
* setlogin() affects the entire process group.
|
* setlogin() affects the entire process group.
|
||||||
|
@ -799,9 +835,6 @@ do_exec_pty(Session *s, const char *command)
|
||||||
close(fdout);
|
close(fdout);
|
||||||
close(ptymaster);
|
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 the master side of the pseudo tty. */
|
||||||
close(ptyfd);
|
close(ptyfd);
|
||||||
|
|
||||||
|
@ -1363,6 +1396,8 @@ do_setup_env(Session *s, const char *shell)
|
||||||
free(laddr);
|
free(laddr);
|
||||||
child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
|
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)
|
if (s->ttyfd != -1)
|
||||||
child_set_env(&env, &envsize, "SSH_TTY", s->tty);
|
child_set_env(&env, &envsize, "SSH_TTY", s->tty);
|
||||||
if (s->term)
|
if (s->term)
|
||||||
|
@ -2840,6 +2875,15 @@ do_cleanup(Authctxt *authctxt)
|
||||||
/* remove agent socket */
|
/* remove agent socket */
|
||||||
auth_sock_cleanup_proc(authctxt->pw);
|
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,
|
* Cleanup ptys/utmp only if privsep is disabled,
|
||||||
* or if running in monitor.
|
* 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 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2001 Damien Miller. 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;
|
int ulen, glen, sz = 0;
|
||||||
struct tm *ltime = localtime(&st->st_mtime);
|
struct tm *ltime = localtime(&st->st_mtime);
|
||||||
char *user, *group;
|
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];
|
char sbuf[FMT_SCALED_STRSIZE];
|
||||||
time_t now;
|
time_t now;
|
||||||
|
|
||||||
strmode(st->st_mode, mode);
|
strmode(st->st_mode, mode);
|
||||||
if (!remote) {
|
if (remote) {
|
||||||
user = user_from_uid(st->st_uid, 0);
|
|
||||||
} else {
|
|
||||||
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
|
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
|
||||||
user = ubuf;
|
user = ubuf;
|
||||||
}
|
|
||||||
if (!remote) {
|
|
||||||
group = group_from_gid(st->st_gid, 0);
|
|
||||||
} else {
|
|
||||||
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
|
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
|
||||||
group = gbuf;
|
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) {
|
if (ltime != NULL) {
|
||||||
now = time(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);
|
glen = MAXIMUM(strlen(group), 8);
|
||||||
if (si_units) {
|
if (si_units) {
|
||||||
fmt_scaled((long long)st->st_size, sbuf);
|
fmt_scaled((long long)st->st_size, sbuf);
|
||||||
snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8s %s %s", mode,
|
snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8s %s %s",
|
||||||
(u_int)st->st_nlink, ulen, user, glen, group,
|
mode, lc, ulen, user, glen, group,
|
||||||
sbuf, tbuf, name);
|
sbuf, tbuf, name);
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode,
|
snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8llu %s %s",
|
||||||
(u_int)st->st_nlink, ulen, user, glen, group,
|
mode, lc, ulen, user, glen, group,
|
||||||
(unsigned long long)st->st_size, tbuf, name);
|
(unsigned long long)st->st_size, tbuf, name);
|
||||||
}
|
}
|
||||||
return xstrdup(buf);
|
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>
|
* 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...*/
|
/* I wish qsort() took a separate ctx for the comparison function...*/
|
||||||
int sort_flag;
|
int sort_flag;
|
||||||
|
glob_t *sort_glob;
|
||||||
|
|
||||||
/* Context used for commandline completion */
|
/* Context used for commandline completion */
|
||||||
struct complete_ctx {
|
struct complete_ctx {
|
||||||
|
@ -927,6 +928,34 @@ do_ls_dir(struct sftp_conn *conn, const char *path,
|
||||||
return (0);
|
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 */
|
/* sftp ls.1 replacement which handles path globs */
|
||||||
static int
|
static int
|
||||||
do_globbed_ls(struct sftp_conn *conn, const char *path,
|
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;
|
glob_t g;
|
||||||
int err, r;
|
int err, r;
|
||||||
struct winsize ws;
|
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));
|
memset(&g, 0, sizeof(g));
|
||||||
|
|
||||||
|
@ -981,7 +1011,26 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
|
||||||
colspace = width / columns;
|
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);
|
fname = path_strip(g.gl_pathv[i], strip_path);
|
||||||
if (lflag & LS_LONG_VIEW) {
|
if (lflag & LS_LONG_VIEW) {
|
||||||
if (g.gl_statv[i] == NULL) {
|
if (g.gl_statv[i] == NULL) {
|
||||||
|
@ -1009,6 +1058,7 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
|
||||||
out:
|
out:
|
||||||
if (g.gl_pathc)
|
if (g.gl_pathc)
|
||||||
globfree(&g);
|
globfree(&g);
|
||||||
|
free(indices);
|
||||||
|
|
||||||
return 0;
|
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.
|
* 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_do_child(char ***, u_int *);
|
||||||
void ssh_gssapi_cleanup_creds(void);
|
void ssh_gssapi_cleanup_creds(void);
|
||||||
void ssh_gssapi_storecreds(void);
|
void ssh_gssapi_storecreds(void);
|
||||||
|
const char *ssh_gssapi_displayname(void);
|
||||||
|
|
||||||
#endif /* GSSAPI */
|
#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>
|
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: May 5 2017 $
|
.Dd $Mdocdate: June 28 2017 $
|
||||||
.Dt SSH-KEYGEN 1
|
.Dt SSH-KEYGEN 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -114,6 +114,8 @@
|
||||||
.Fl s Ar ca_key
|
.Fl s Ar ca_key
|
||||||
.Fl I Ar certificate_identity
|
.Fl I Ar certificate_identity
|
||||||
.Op Fl h
|
.Op Fl h
|
||||||
|
.Op Fl U
|
||||||
|
.Op Fl D Ar pkcs11_provider
|
||||||
.Op Fl n Ar principals
|
.Op Fl n Ar principals
|
||||||
.Op Fl O Ar option
|
.Op Fl O Ar option
|
||||||
.Op Fl V Ar validity_interval
|
.Op Fl V Ar validity_interval
|
||||||
|
@ -558,6 +560,14 @@ The possible values are
|
||||||
.Dq ed25519 ,
|
.Dq ed25519 ,
|
||||||
or
|
or
|
||||||
.Dq rsa .
|
.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
|
.It Fl u
|
||||||
Update a KRL.
|
Update a KRL.
|
||||||
When specified with
|
When specified with
|
||||||
|
@ -705,6 +715,14 @@ to
|
||||||
.Pp
|
.Pp
|
||||||
.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub
|
.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub
|
||||||
.Pp
|
.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,
|
In all cases,
|
||||||
.Ar key_id
|
.Ar key_id
|
||||||
is a "key identifier" that is logged by the server when the certificate
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -59,6 +59,7 @@
|
||||||
#include "krl.h"
|
#include "krl.h"
|
||||||
#include "digest.h"
|
#include "digest.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
#include "authfd.h"
|
||||||
#include "sshfileperm.h"
|
#include "sshfileperm.h"
|
||||||
|
|
||||||
#ifdef WITH_OPENSSL
|
#ifdef WITH_OPENSSL
|
||||||
|
@ -122,6 +123,9 @@ char *identity_comment = NULL;
|
||||||
/* Path to CA key when certifying keys. */
|
/* Path to CA key when certifying keys. */
|
||||||
char *ca_key_path = NULL;
|
char *ca_key_path = NULL;
|
||||||
|
|
||||||
|
/* Prefer to use agent keys for CA signing */
|
||||||
|
int prefer_agent = 0;
|
||||||
|
|
||||||
/* Certificate serial number */
|
/* Certificate serial number */
|
||||||
unsigned long long cert_serial = 0;
|
unsigned long long cert_serial = 0;
|
||||||
|
|
||||||
|
@ -1615,24 +1619,66 @@ load_pkcs11_key(char *path)
|
||||||
#endif /* ENABLE_PKCS11 */
|
#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
|
static void
|
||||||
do_ca_sign(struct passwd *pw, int argc, char **argv)
|
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;
|
u_int n;
|
||||||
struct sshkey *ca, *public;
|
struct sshkey *ca, *public;
|
||||||
char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
|
char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
struct ssh_identitylist *agent_ids;
|
||||||
|
size_t j;
|
||||||
|
|
||||||
#ifdef ENABLE_PKCS11
|
#ifdef ENABLE_PKCS11
|
||||||
pkcs11_init(1);
|
pkcs11_init(1);
|
||||||
#endif
|
#endif
|
||||||
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
|
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
|
||||||
if (pkcs11provider != NULL) {
|
if (pkcs11provider != NULL) {
|
||||||
|
/* If a PKCS#11 token was specified then try to use it */
|
||||||
if ((ca = load_pkcs11_key(tmp)) == NULL)
|
if ((ca = load_pkcs11_key(tmp)) == NULL)
|
||||||
fatal("No PKCS#11 key matching %s found", ca_key_path);
|
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);
|
ca = load_identity(tmp);
|
||||||
|
}
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
|
||||||
if (key_type_name != NULL &&
|
if (key_type_name != NULL &&
|
||||||
|
@ -1682,8 +1728,16 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
|
||||||
&public->cert->signature_key)) != 0)
|
&public->cert->signature_key)) != 0)
|
||||||
fatal("sshkey_from_private (ca key): %s", ssh_err(r));
|
fatal("sshkey_from_private (ca key): %s", ssh_err(r));
|
||||||
|
|
||||||
if ((r = sshkey_certify(public, ca, key_type_name)) != 0)
|
if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) {
|
||||||
fatal("Couldn't certify key %s: %s", tmp, ssh_err(r));
|
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)
|
if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
|
@ -2279,8 +2333,9 @@ usage(void)
|
||||||
" ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n"
|
" ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n"
|
||||||
" [-j start_line] [-K checkpt] [-W generator]\n"
|
" [-j start_line] [-K checkpt] [-W generator]\n"
|
||||||
#endif
|
#endif
|
||||||
" ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals]\n"
|
" ssh-keygen -s ca_key -I certificate_identity [-h] [-U]\n"
|
||||||
" [-O option] [-V validity_interval] [-z serial_number] file ...\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 -L [-f input_keyfile]\n"
|
||||||
" ssh-keygen -A\n"
|
" ssh-keygen -A\n"
|
||||||
" ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\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)
|
if (gethostname(hostname, sizeof(hostname)) < 0)
|
||||||
fatal("gethostname: %s", strerror(errno));
|
fatal("gethostname: %s", strerror(errno));
|
||||||
|
|
||||||
/* Remaining characters: UYdw */
|
/* Remaining characters: Ydw */
|
||||||
while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy"
|
while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvxy"
|
||||||
"C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:"
|
"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) {
|
"a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
@ -2466,6 +2521,9 @@ main(int argc, char **argv)
|
||||||
case 'D':
|
case 'D':
|
||||||
pkcs11provider = optarg;
|
pkcs11provider = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'U':
|
||||||
|
prefer_agent = 1;
|
||||||
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
update_krl = 1;
|
update_krl = 1;
|
||||||
break;
|
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>.
|
* 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)
|
if (s >= maxfd || fdcon[s].c_status == CS_UNUSED)
|
||||||
fatal("confree: attempt to free bad fdno %d", s);
|
fatal("confree: attempt to free bad fdno %d", s);
|
||||||
|
|
||||||
free(fdcon[s].c_namebase);
|
free(fdcon[s].c_namebase);
|
||||||
free(fdcon[s].c_output_name);
|
free(fdcon[s].c_output_name);
|
||||||
if (fdcon[s].c_status == CS_KEYS)
|
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
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh.1,v 1.382 2017/05/30 18:58:37 bluhm Exp $
|
.\" $OpenBSD: ssh.1,v 1.383 2017/06/09 06:43:01 djm Exp $
|
||||||
.Dd $Mdocdate: May 30 2017 $
|
.Dd $Mdocdate: June 9 2017 $
|
||||||
.Dt SSH 1
|
.Dt SSH 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.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
|
and the server checks that the corresponding public key
|
||||||
is authorized to accept the account.
|
is authorized to accept the account.
|
||||||
.Pp
|
.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
|
The user creates his/her key pair by running
|
||||||
.Xr ssh-keygen 1 .
|
.Xr ssh-keygen 1 .
|
||||||
This stores the private key in
|
This stores the private key in
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh_config.5,v 1.250 2017/05/30 19:38:17 jmc Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.251 2017/06/24 05:35:05 djm Exp $
|
||||||
.Dd $Mdocdate: May 30 2017 $
|
.Dd $Mdocdate: June 24 2017 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -809,7 +809,7 @@ The list of available key types may also be obtained using
|
||||||
.It Cm HostKeyAlias
|
.It Cm HostKeyAlias
|
||||||
Specifies an alias that should be used instead of the
|
Specifies an alias that should be used instead of the
|
||||||
real host name when looking up or saving the host key
|
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
|
This option is useful for tunneling SSH connections
|
||||||
or for multiple servers running on a single host.
|
or for multiple servers running on a single host.
|
||||||
.It Cm HostName
|
.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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -34,6 +34,9 @@
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#endif
|
#endif
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#ifdef HAVE_POLL_H
|
||||||
|
#include <poll.h>
|
||||||
|
#endif
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -344,87 +347,71 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
|
||||||
return sock;
|
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
|
static int
|
||||||
timeout_connect(int sockfd, const struct sockaddr *serv_addr,
|
timeout_connect(int sockfd, const struct sockaddr *serv_addr,
|
||||||
socklen_t addrlen, int *timeoutp)
|
socklen_t addrlen, int *timeoutp)
|
||||||
{
|
{
|
||||||
fd_set *fdset;
|
int optval = 0;
|
||||||
struct timeval tv, t_start;
|
socklen_t optlen = sizeof(optval);
|
||||||
socklen_t optlen;
|
|
||||||
int optval, rc, result = -1;
|
|
||||||
|
|
||||||
gettimeofday(&t_start, NULL);
|
/* No timeout: just do a blocking connect() */
|
||||||
|
if (*timeoutp <= 0)
|
||||||
if (*timeoutp <= 0) {
|
return connect(sockfd, serv_addr, addrlen);
|
||||||
result = connect(sockfd, serv_addr, addrlen);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_nonblock(sockfd);
|
set_nonblock(sockfd);
|
||||||
rc = connect(sockfd, serv_addr, addrlen);
|
if (connect(sockfd, serv_addr, addrlen) == 0) {
|
||||||
if (rc == 0) {
|
/* Succeeded already? */
|
||||||
unset_nonblock(sockfd);
|
unset_nonblock(sockfd);
|
||||||
result = 0;
|
return 0;
|
||||||
goto done;
|
} 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) {
|
if (optval != 0) {
|
||||||
result = -1;
|
errno = optval;
|
||||||
goto done;
|
return -1;
|
||||||
}
|
}
|
||||||
|
unset_nonblock(sockfd);
|
||||||
fdset = xcalloc(howmany(sockfd + 1, NFDBITS),
|
return 0;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -562,42 +549,25 @@ ssh_exchange_identification(int timeout_ms)
|
||||||
int connection_out = packet_get_connection_out();
|
int connection_out = packet_get_connection_out();
|
||||||
u_int i, n;
|
u_int i, n;
|
||||||
size_t len;
|
size_t len;
|
||||||
int fdsetsz, remaining, rc;
|
int 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);
|
|
||||||
|
|
||||||
send_client_banner(connection_out, 0);
|
send_client_banner(connection_out, 0);
|
||||||
|
|
||||||
/* Read other side's version identification. */
|
/* Read other side's version identification. */
|
||||||
remaining = timeout_ms;
|
|
||||||
for (n = 0;;) {
|
for (n = 0;;) {
|
||||||
for (i = 0; i < sizeof(buf) - 1; i++) {
|
for (i = 0; i < sizeof(buf) - 1; i++) {
|
||||||
if (timeout_ms > 0) {
|
if (timeout_ms > 0) {
|
||||||
gettimeofday(&t_start, NULL);
|
rc = waitrfd(connection_in, &timeout_ms);
|
||||||
ms_to_timeval(&t_remaining, remaining);
|
if (rc == -1 && errno == ETIMEDOUT) {
|
||||||
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)
|
|
||||||
fatal("Connection timed out during "
|
fatal("Connection timed out during "
|
||||||
"banner exchange");
|
"banner exchange");
|
||||||
if (rc == -1) {
|
} else if (rc == -1) {
|
||||||
if (errno == EINTR)
|
fatal("%s: %s",
|
||||||
continue;
|
__func__, strerror(errno));
|
||||||
fatal("ssh_exchange_identification: "
|
|
||||||
"select: %s", strerror(errno));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
len = atomicio(read, connection_in, &buf[i], 1);
|
len = atomicio(read, connection_in, &buf[i], 1);
|
||||||
|
|
||||||
if (len != 1 && errno == EPIPE)
|
if (len != 1 && errno == EPIPE)
|
||||||
fatal("ssh_exchange_identification: "
|
fatal("ssh_exchange_identification: "
|
||||||
"Connection closed by remote host");
|
"Connection closed by remote host");
|
||||||
|
@ -623,8 +593,6 @@ ssh_exchange_identification(int timeout_ms)
|
||||||
debug("ssh_exchange_identification: %s", buf);
|
debug("ssh_exchange_identification: %s", buf);
|
||||||
}
|
}
|
||||||
server_version_string = xstrdup(buf);
|
server_version_string = xstrdup(buf);
|
||||||
free(readfds);
|
|
||||||
free(exceptfds);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the versions match. In future this might accept
|
* 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");
|
host, type, want_cert ? "certificate" : "key");
|
||||||
debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
|
debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
|
||||||
host_found->file, host_found->line);
|
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;
|
goto fail;
|
||||||
if (options.check_host_ip && ip_status == HOST_NEW) {
|
if (options.check_host_ip && ip_status == HOST_NEW) {
|
||||||
if (readonly || want_cert)
|
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) 2000 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
||||||
|
@ -474,7 +474,8 @@ userauth(Authctxt *authctxt, char *authlist)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Authmethod *method = authmethod_get(authlist);
|
Authmethod *method = authmethod_get(authlist);
|
||||||
if (method == NULL)
|
if (method == NULL)
|
||||||
fatal("Permission denied (%s).", authlist);
|
fatal("%s@%s: Permission denied (%s).",
|
||||||
|
authctxt->server_user, authctxt->host, authlist);
|
||||||
authctxt->method = method;
|
authctxt->method = method;
|
||||||
|
|
||||||
/* reset the per method handler */
|
/* 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
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: sshd.8,v 1.289 2017/05/07 23:12:57 djm Exp $
|
.\" $OpenBSD: sshd.8,v 1.291 2017/06/24 06:28:50 jmc Exp $
|
||||||
.Dd $Mdocdate: May 7 2017 $
|
.Dd $Mdocdate: June 24 2017 $
|
||||||
.Dt SSHD 8
|
.Dt SSHD 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -652,9 +652,23 @@ Hostnames is a comma-separated list of patterns
|
||||||
and
|
and
|
||||||
.Ql \&?
|
.Ql \&?
|
||||||
act as
|
act as
|
||||||
wildcards); each pattern in turn is matched against the canonical host
|
wildcards); each pattern in turn is matched against the host name.
|
||||||
name (when authenticating a client) or against the user-supplied
|
When
|
||||||
name (when authenticating a server).
|
.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
|
A pattern may also be preceded by
|
||||||
.Ql \&!
|
.Ql \&!
|
||||||
to indicate negation: if the host name matches a negated
|
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
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: sshd_config.5,v 1.245 2017/05/17 01:24:17 djm Exp $
|
.\" $OpenBSD: sshd_config.5,v 1.248 2017/06/24 07:08:57 djm Exp $
|
||||||
.Dd $Mdocdate: May 17 2017 $
|
.Dd $Mdocdate: June 24 2017 $
|
||||||
.Dt SSHD_CONFIG 5
|
.Dt SSHD_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -564,6 +564,12 @@ Disables all forwarding features, including X11,
|
||||||
TCP and StreamLocal.
|
TCP and StreamLocal.
|
||||||
This option overrides all other forwarding-related options and may
|
This option overrides all other forwarding-related options and may
|
||||||
simplify restricted configurations.
|
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
|
.It Cm FingerprintHash
|
||||||
Specifies the hash algorithm used when logging key fingerprints.
|
Specifies the hash algorithm used when logging key fingerprints.
|
||||||
Valid options are:
|
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) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
||||||
|
@ -1331,7 +1331,7 @@ sshkey_to_base64(const struct sshkey *key, char **b64p)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
|
sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
|
||||||
{
|
{
|
||||||
int r = SSH_ERR_INTERNAL_ERROR;
|
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. */
|
/* Sign a certified key, (re-)generating the signed certblob. */
|
||||||
int
|
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;
|
struct sshbuf *principals = NULL;
|
||||||
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
|
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;
|
goto out;
|
||||||
|
|
||||||
/* Sign the whole mess */
|
/* Sign the whole mess */
|
||||||
if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
|
if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
|
||||||
sshbuf_len(cert), alg, 0)) != 0)
|
sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Append signature and we are done */
|
/* Append signature and we are done */
|
||||||
|
@ -2359,6 +2360,22 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
|
||||||
return ret;
|
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
|
int
|
||||||
sshkey_cert_check_authority(const struct sshkey *k,
|
sshkey_cert_check_authority(const struct sshkey *k,
|
||||||
int want_host, int require_principal,
|
int want_host, int require_principal,
|
||||||
|
@ -3365,6 +3382,64 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_OPENSSL
|
#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
|
static int
|
||||||
sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
||||||
const char *passphrase, struct sshkey **keyp)
|
const char *passphrase, struct sshkey **keyp)
|
||||||
|
@ -3385,48 +3460,10 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_libcrypto_errors();
|
||||||
if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
|
if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
|
||||||
(char *)passphrase)) == NULL) {
|
(char *)passphrase)) == NULL) {
|
||||||
unsigned long pem_err = ERR_peek_last_error();
|
r = convert_libcrypto_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;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (pk->type == EVP_PKEY_RSA &&
|
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.
|
* 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);
|
int, u_char **retp, size_t *lenp);
|
||||||
const char *sshkey_type(const struct sshkey *);
|
const char *sshkey_type(const struct sshkey *);
|
||||||
const char *sshkey_cert_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_write(const struct sshkey *, FILE *);
|
||||||
int sshkey_read(struct sshkey *, char **);
|
int sshkey_read(struct sshkey *, char **);
|
||||||
u_int sshkey_size(const struct sshkey *);
|
u_int sshkey_size(const struct sshkey *);
|
||||||
|
@ -136,13 +137,19 @@ int sshkey_type_is_cert(int);
|
||||||
int sshkey_type_plain(int);
|
int sshkey_type_plain(int);
|
||||||
int sshkey_to_certified(struct sshkey *);
|
int sshkey_to_certified(struct sshkey *);
|
||||||
int sshkey_drop_cert(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_copy(const struct sshkey *, struct sshkey *);
|
||||||
int sshkey_cert_check_authority(const struct sshkey *, int, int,
|
int sshkey_cert_check_authority(const struct sshkey *, int, int,
|
||||||
const char *, const char **);
|
const char *, const char **);
|
||||||
size_t sshkey_format_cert_validity(const struct sshkey_cert *,
|
size_t sshkey_format_cert_validity(const struct sshkey_cert *,
|
||||||
char *, size_t) __attribute__((__bounded__(__string__, 2, 3)));
|
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_ecdsa_nid_from_name(const char *);
|
||||||
int sshkey_curve_name_to_nid(const char *);
|
int sshkey_curve_name_to_nid(const char *);
|
||||||
const char * sshkey_curve_nid_to_name(int);
|
const char * sshkey_curve_nid_to_name(int);
|
||||||
|
|
Loading…
Reference in New Issue