from openbsd

This commit is contained in:
christos 2013-03-29 14:52:38 +00:00
parent d4e6ea9d15
commit 2a5e17aeda
56 changed files with 3468 additions and 472 deletions

View File

@ -51,6 +51,46 @@ and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic
curve points encoded using point compression are NOT accepted or
generated.
1.5 transport: Protocol 2 Encrypt-then-MAC MAC algorithms
OpenSSH supports MAC algorithms, whose names contain "-etm", that
perform the calculations in a different order to that defined in RFC
4253. These variants use the so-called "encrypt then MAC" ordering,
calculating the MAC over the packet ciphertext rather than the
plaintext. This ordering closes a security flaw in the SSH transport
protocol, where decryption of unauthenticated ciphertext provided a
"decryption oracle" that could, in conjunction with cipher flaws, reveal
session plaintext.
Specifically, the "-etm" MAC algorithms modify the transport protocol
to calculate the MAC over the packet ciphertext and to send the packet
length unencrypted. This is necessary for the transport to obtain the
length of the packet and location of the MAC tag so that it may be
verified without decrypting unauthenticated data.
As such, the MAC covers:
mac = MAC(key, sequence_number || packet_length || encrypted_packet)
where "packet_length" is encoded as a uint32 and "encrypted_packet"
contains:
byte padding_length
byte[n1] payload; n1 = packet_length - padding_length - 1
byte[n2] random padding; n2 = padding_length
1.6 transport: AES-GCM
OpenSSH supports the AES-GCM algorithm as specified in RFC 5647.
Because of problems with the specification of the key exchange
the behaviour of OpenSSH differs from the RFC as follows:
AES-GCM is only negotiated as the cipher algorithms
"aes128-gcm@openssh.com" or "aes256-gcm@openssh.com" and never as
an MAC algorithm. Additionally, if AES-GCM is selected as the cipher
the exchanged MAC algorithms are ignored and there doesn't have to be
a matching MAC.
2. Connection protocol changes
2.1. connection: Channel write close extension "eow@openssh.com"
@ -291,4 +331,4 @@ link(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
$OpenBSD: PROTOCOL,v 1.17 2010/12/04 00:18:01 djm Exp $
$OpenBSD: PROTOCOL,v 1.20 2013/01/08 18:49:04 markus Exp $

View File

@ -152,7 +152,7 @@ fully specified using just rsa_q, rsa_p and rsa_e at the cost of extra
computation.
"key_constraints" may only be present if the request type is
SSH_AGENTC_ADD_RSA_IDENTITY.
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED.
The agent will reply with a SSH_AGENT_SUCCESS if the key has been
successfully added or a SSH_AGENT_FAILURE if an error occurred.
@ -557,4 +557,4 @@ Locking and unlocking affects both protocol 1 and protocol 2 keys.
SSH_AGENT_CONSTRAIN_LIFETIME 1
SSH_AGENT_CONSTRAIN_CONFIRM 2
$OpenBSD: PROTOCOL.agent,v 1.6 2010/08/31 11:54:45 djm Exp $
$OpenBSD: PROTOCOL.agent,v 1.7 2013/01/02 00:33:49 djm Exp $

View File

@ -0,0 +1,164 @@
This describes the key/certificate revocation list format for OpenSSH.
1. Overall format
The KRL consists of a header and zero or more sections. The header is:
#define KRL_MAGIC 0x5353484b524c0a00ULL /* "SSHKRL\n\0" */
#define KRL_FORMAT_VERSION 1
uint64 KRL_MAGIC
uint32 KRL_FORMAT_VERSION
uint64 krl_version
uint64 generated_date
uint64 flags
string reserved
string comment
Where "krl_version" is a version number that increases each time the KRL
is modified, "generated_date" is the time in seconds since 1970-01-01
00:00:00 UTC that the KRL was generated, "comment" is an optional comment
and "reserved" an extension field whose contents are currently ignored.
No "flags" are currently defined.
Following the header are zero or more sections, each consisting of:
byte section_type
string section_data
Where "section_type" indicates the type of the "section_data". An exception
to this is the KRL_SECTION_SIGNATURE section, that has a slightly different
format (see below).
The available section types are:
#define KRL_SECTION_CERTIFICATES 1
#define KRL_SECTION_EXPLICIT_KEY 2
#define KRL_SECTION_FINGERPRINT_SHA1 3
#define KRL_SECTION_SIGNATURE 4
3. Certificate serial section
These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by
serial number or key ID. The consist of the CA key that issued the
certificates to be revoked and a reserved field whose contents is currently
ignored.
string ca_key
string reserved
Followed by one or more sections:
byte cert_section_type
string cert_section_data
The certificate section types are:
#define KRL_SECTION_CERT_SERIAL_LIST 0x20
#define KRL_SECTION_CERT_SERIAL_RANGE 0x21
#define KRL_SECTION_CERT_SERIAL_BITMAP 0x22
#define KRL_SECTION_CERT_KEY_ID 0x23
2.1 Certificate serial list section
This section is identified as KRL_SECTION_CERT_SERIAL_LIST. It revokes
certificates by listing their serial numbers. The cert_section_data in this
case contains:
uint64 revoked_cert_serial
uint64 ...
This section may appear multiple times.
2.2. Certificate serial range section
These sections use type KRL_SECTION_CERT_SERIAL_RANGE and hold
a range of serial numbers of certificates:
uint64 serial_min
uint64 serial_max
All certificates in the range serial_min <= serial <= serial_max are
revoked.
This section may appear multiple times.
2.3. Certificate serial bitmap section
Bitmap sections use type KRL_SECTION_CERT_SERIAL_BITMAP and revoke keys
by listing their serial number in a bitmap.
uint64 serial_offset
mpint revoked_keys_bitmap
A bit set at index N in the bitmap corresponds to revocation of a keys with
serial number (serial_offset + N).
This section may appear multiple times.
2.4. Revoked key ID sections
KRL_SECTION_CERT_KEY_ID sections revoke particular certificate "key
ID" strings. This may be useful in revoking all certificates
associated with a particular identity, e.g. a host or a user.
string key_id[0]
...
This section must contain at least one "key_id". This section may appear
multiple times.
3. Explicit key sections
These sections, identified as KRL_SECTION_EXPLICIT_KEY, revoke keys
(not certificates). They are less space efficient than serial numbers,
but are able to revoke plain keys.
string public_key_blob[0]
....
This section must contain at least one "public_key_blob". The blob
must be a raw key (i.e. not a certificate).
This section may appear multiple times.
4. SHA1 fingerprint sections
These sections, identified as KRL_SECTION_FINGERPRINT_SHA1, revoke
plain keys (i.e. not certificates) by listing their SHA1 hashes:
string public_key_hash[0]
....
This section must contain at least one "public_key_hash". The hash blob
is obtained by taking the SHA1 hash of the public key blob. Hashes in
this section must appear in numeric order, treating each hash as a big-
endian integer.
This section may appear multiple times.
5. KRL signature sections
The KRL_SECTION_SIGNATURE section serves a different purpose to the
preceeding ones: to provide cryptographic authentication of a KRL that
is retrieved over a channel that does not provide integrity protection.
Its format is slightly different to the previously-described sections:
in order to simplify the signature generation, it includes as a "body"
two string components instead of one.
byte KRL_SECTION_SIGNATURE
string signature_key
string signature
The signature is calculated over the entire KRL from the KRL_MAGIC
to this subsection's "signature_key", including both and using the
signature generation rules appropriate for the type of "signature_key".
This section must appear last in the KRL. If multiple signature sections
appear, they must appear consecutively at the end of the KRL file.
Implementations that retrieve KRLs over untrusted channels must verify
signatures. Signature sections are optional for KRLs distributed by
trusted means.
$OpenBSD: PROTOCOL.krl,v 1.2 2013/01/18 00:24:58 djm Exp $

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.c,v 1.56 2011/10/18 04:58:26 djm Exp $ */
/* $OpenBSD: auth-options.c,v 1.57 2012/12/02 20:46:11 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -347,7 +347,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
xfree(patterns);
goto bad_option;
}
if (options.allow_tcp_forwarding)
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0)
channel_add_permitted_opens(host, port);
xfree(patterns);
goto next_option;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rsa.c,v 1.80 2011/05/23 03:30:07 djm Exp $ */
/* $OpenBSD: auth-rsa.c,v 1.81 2012/10/30 21:29:54 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -273,6 +273,8 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
temporarily_use_uid(pw);
for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
continue;
file = expand_authorized_keys(
options.authorized_keys_files[i], pw);
allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.96 2012/05/13 01:42:32 dtucker Exp $ */
/* $OpenBSD: auth.c,v 1.101 2013/02/06 00:22:21 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -57,6 +57,7 @@
#endif
#include "authfile.h"
#include "monitor_wrap.h"
#include "krl.h"
/* import */
extern ServerOptions options;
@ -179,7 +180,8 @@ allowed_user(struct passwd * pw)
}
void
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
auth_log(Authctxt *authctxt, int authenticated, int partial,
const char *method, const char *submethod, const char *info)
{
void (*authlog) (const char *fmt,...) = verbose;
char *authmsg;
@ -196,12 +198,15 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
if (authctxt->postponed)
authmsg = "Postponed";
else if (partial)
authmsg = "Partial";
else
authmsg = authenticated ? "Accepted" : "Failed";
authlog("%s %s for %s%.100s from %.200s port %d%s",
authlog("%s %s%s%s for %s%.100s from %.200s port %d%s",
authmsg,
method,
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
authctxt->valid ? "" : "invalid user ",
authctxt->user,
get_remote_ipaddr(),
@ -213,7 +218,7 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
* Check whether root logins are disallowed.
*/
int
auth_root_allowed(char *method)
auth_root_allowed(const char *method)
{
switch (options.permit_root_login) {
case PERMIT_YES:
@ -319,41 +324,42 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
return host_status;
}
/*
* Check a given file for security. This is defined as all components
* Check a given path for security. This is defined as all components
* of the path to the file must be owned by either the owner of
* of the file or root and no directories must be group or world writable.
*
* XXX Should any specific check be done for sym links ?
*
* Takes an open file descriptor, the file name, a uid and and
* Takes a file name, its stat information (preferably from fstat() to
* avoid races), the uid of the expected owner, their home directory and an
* error buffer plus max size as arguments.
*
* Returns 0 on success and -1 on failure
*/
static int
secure_filename(FILE *f, const char *file, struct passwd *pw,
char *err, size_t errlen)
int
auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
uid_t uid, char *err, size_t errlen)
{
uid_t uid = pw->pw_uid;
char buf[MAXPATHLEN], homedir[MAXPATHLEN];
char *cp;
int comparehome = 0;
struct stat st;
if (realpath(file, buf) == NULL) {
snprintf(err, errlen, "realpath %s failed: %s", file,
if (realpath(name, buf) == NULL) {
snprintf(err, errlen, "realpath %s failed: %s", name,
strerror(errno));
return -1;
}
if (realpath(pw->pw_dir, homedir) != NULL)
if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
comparehome = 1;
/* check the open file to avoid races */
if (fstat(fileno(f), &st) < 0 ||
(st.st_uid != 0 && st.st_uid != uid) ||
(st.st_mode & 022) != 0) {
if (!S_ISREG(stp->st_mode)) {
snprintf(err, errlen, "%s is not a regular file", buf);
return -1;
}
if ((stp->st_uid != 0 && stp->st_uid != uid) ||
(stp->st_mode & 022) != 0) {
snprintf(err, errlen, "bad ownership or modes for file %s",
buf);
return -1;
@ -389,6 +395,27 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
return 0;
}
/*
* Version of secure_path() that accepts an open file descriptor to
* avoid races.
*
* Returns 0 on success and -1 on failure
*/
static int
secure_filename(FILE *f, const char *file, struct passwd *pw,
char *err, size_t errlen)
{
struct stat st;
/* check the open file to avoid races */
if (fstat(fileno(f), &st) < 0) {
snprintf(err, errlen, "cannot stat file %s: %s",
file, strerror(errno));
return -1;
}
return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
}
static FILE *
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
int log_missing, char *file_type)
@ -488,7 +515,16 @@ auth_key_is_revoked(Key *key)
if (options.revoked_keys_file == NULL)
return 0;
switch (ssh_krl_file_contains_key(options.revoked_keys_file, key)) {
case 0:
return 0; /* Not revoked */
case -2:
break; /* Not a KRL */
default:
goto revoked;
}
debug3("%s: treating %s as a key list", __func__,
options.revoked_keys_file);
switch (key_in_file(key, options.revoked_keys_file, 0)) {
case 0:
/* key not revoked */
@ -499,6 +535,7 @@ auth_key_is_revoked(Key *key)
"authentication");
return 1;
case 1:
revoked:
/* Key revoked */
key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
error("WARNING: authentication attempt with a revoked "

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.h,v 1.69 2011/05/23 03:30:07 djm Exp $ */
/* $OpenBSD: auth.h,v 1.72 2012/12/02 20:34:09 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -57,6 +57,8 @@ struct Authctxt {
void *kbdintctxt;
void *jpake_ctx;
auth_session_t *as;
char **auth_methods; /* modified from server config */
u_int num_auth_methods;
#ifdef KRB5
krb5_context krb5_ctx;
krb5_ccache krb5_fwd_ccache;
@ -111,6 +113,10 @@ int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
int user_key_allowed(struct passwd *, Key *);
struct stat;
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
char *, size_t);
#ifdef KRB5
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
@ -121,11 +127,15 @@ void krb5_cleanup_proc(Authctxt *authctxt);
void do_authentication(Authctxt *);
void do_authentication2(Authctxt *);
void auth_log(Authctxt *, int, char *, char *);
void userauth_finish(Authctxt *, int, char *);
int auth_root_allowed(char *);
void auth_log(Authctxt *, int, int, const char *, const char *,
const char *);
void userauth_finish(Authctxt *, int, const char *, const char *);
int auth_root_allowed(const char *);
char *auth2_read_banner(void);
int auth2_methods_valid(const char *, int);
int auth2_update_methods_lists(Authctxt *, const char *);
int auth2_setup_methods_lists(Authctxt *);
void privsep_challenge_enable(void);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth1.c,v 1.75 2010/08/31 09:58:37 djm Exp $ */
/* $OpenBSD: auth1.c,v 1.77 2012/12/02 20:34:09 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -244,7 +244,7 @@ do_authloop(Authctxt *authctxt)
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
PRIVSEP(auth_password(authctxt, ""))) {
auth_log(authctxt, 1, "without authentication", "");
auth_log(authctxt, 1, 0, "without authentication", NULL, "");
return;
}
@ -293,7 +293,8 @@ do_authloop(Authctxt *authctxt)
skip:
/* Log before sending the reply */
auth_log(authctxt, authenticated, get_authname(type), info);
auth_log(authctxt, authenticated, 0, get_authname(type),
NULL, info);
if (authenticated)
return;
@ -338,6 +339,11 @@ do_authentication(Authctxt *authctxt)
authctxt->pw = fakepw();
}
/* Configuration may have changed as a result of Match */
if (options.num_auth_methods != 0)
fatal("AuthenticationMethods is not supported with SSH "
"protocol 1");
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-chall.c,v 1.34 2008/12/09 04:32:22 djm Exp $ */
/* $OpenBSD: auth2-chall.c,v 1.36 2012/12/03 00:14:06 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Per Allansson. All rights reserved.
@ -238,7 +238,8 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
KbdintAuthctxt *kbdintctxt;
int authenticated = 0, res;
u_int i, nresp;
char **response = NULL, *method;
const char *devicename = NULL;
char **response = NULL;
if (authctxt == NULL)
fatal("input_userauth_info_response: no authctxt");
@ -284,9 +285,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
/* Failure! */
break;
}
xasprintf(&method, "keyboard-interactive/%s", kbdintctxt->device->name);
devicename = kbdintctxt->device->name;
if (!authctxt->postponed) {
if (authenticated) {
auth2_challenge_stop(authctxt);
@ -296,8 +295,8 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
auth2_challenge_start(authctxt);
}
}
userauth_finish(authctxt, authenticated, method);
xfree(method);
userauth_finish(authctxt, authenticated, "keyboard-interactive",
devicename);
}
void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-gss.c,v 1.17 2011/03/10 02:52:57 djm Exp $ */
/* $OpenBSD: auth2-gss.c,v 1.18 2012/12/02 20:34:09 djm Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@ -159,7 +159,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
}
authctxt->postponed = 0;
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
userauth_finish(authctxt, 0, "gssapi-with-mic");
userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
} else {
if (send_tok.length != 0) {
packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
@ -247,7 +247,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
userauth_finish(authctxt, authenticated, "gssapi-with-mic");
userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
}
static void
@ -287,7 +287,7 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
userauth_finish(authctxt, authenticated, "gssapi-with-mic");
userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
}
Authmethod method_gssapi = {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-jpake.c,v 1.4 2010/08/31 11:54:45 djm Exp $ */
/* $OpenBSD: auth2-jpake.c,v 1.5 2012/12/02 20:34:09 djm Exp $ */
/*
* Copyright (c) 2008 Damien Miller. All rights reserved.
*
@ -556,7 +556,7 @@ input_userauth_jpake_client_confirm(int type, u_int32_t seq, void *ctxt)
authctxt->postponed = 0;
jpake_free(authctxt->jpake_ctx);
authctxt->jpake_ctx = NULL;
userauth_finish(authctxt, authenticated, method_jpake.name);
userauth_finish(authctxt, authenticated, method_jpake.name, NULL);
}
#endif /* JPAKE */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.30 2011/09/25 05:44:47 djm Exp $ */
/* $OpenBSD: auth2-pubkey.c,v 1.34 2013/02/14 21:35:59 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -26,9 +26,13 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
@ -239,7 +243,7 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
if (strcmp(cp, cert->principals[i]) == 0) {
debug3("matched principal \"%.100s\" "
"from file \"%s\" on line %lu",
cert->principals[i], file, linenum);
cert->principals[i], file, linenum);
if (auth_parse_options(pw, line_opts,
file, linenum) != 1)
continue;
@ -252,31 +256,22 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
fclose(f);
restore_uid();
return 0;
}
}
/* return 1 if user allows given key */
/*
* Checks whether key is allowed in authorized_keys-format file,
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
{
char line[SSH_MAX_PUBKEY_BYTES];
const char *reason;
int found_key = 0;
FILE *f;
u_long linenum = 0;
Key *found;
char *fp;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
debug("trying public key file %s", file);
f = auth_openkeyfile(file, pw, options.strict_modes);
if (!f) {
restore_uid();
return 0;
}
found_key = 0;
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
@ -369,8 +364,6 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
break;
}
}
restore_uid();
fclose(f);
key_free(found);
if (!found_key)
debug2("key not found");
@ -432,7 +425,180 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
return ret;
}
/* check whether given key is in .ssh/authorized_keys* */
/*
* Checks whether key is allowed in file.
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
FILE *f;
int found_key = 0;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
debug("trying public key file %s", file);
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
found_key = check_authkeys_file(f, file, key, pw);
fclose(f);
}
restore_uid();
return found_key;
}
/*
* Checks whether key is allowed in output of command.
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
user_key_command_allowed2(struct passwd *user_pw, Key *key)
{
FILE *f;
int ok, found_key = 0;
struct passwd *pw;
struct stat st;
int status, devnull, p[2], i;
pid_t pid;
char *username, errmsg[512];
if (options.authorized_keys_command == NULL ||
options.authorized_keys_command[0] != '/')
return 0;
if (options.authorized_keys_command_user == NULL) {
error("No user for AuthorizedKeysCommand specified, skipping");
return 0;
}
username = percent_expand(options.authorized_keys_command_user,
"u", user_pw->pw_name, (char *)NULL);
pw = getpwnam(username);
if (pw == NULL) {
error("AuthorizedKeysCommandUser \"%s\" not found: %s",
username, strerror(errno));
free(username);
return 0;
}
free(username);
temporarily_use_uid(pw);
if (stat(options.authorized_keys_command, &st) < 0) {
error("Could not stat AuthorizedKeysCommand \"%s\": %s",
options.authorized_keys_command, strerror(errno));
goto out;
}
if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
errmsg, sizeof(errmsg)) != 0) {
error("Unsafe AuthorizedKeysCommand: %s", errmsg);
goto out;
}
if (pipe(p) != 0) {
error("%s: pipe: %s", __func__, strerror(errno));
goto out;
}
debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
/*
* Don't want to call this in the child, where it can fatal() and
* run cleanup_exit() code.
*/
restore_uid();
switch ((pid = fork())) {
case -1: /* error */
error("%s: fork: %s", __func__, strerror(errno));
close(p[0]);
close(p[1]);
return 0;
case 0: /* child */
for (i = 0; i < NSIG; i++)
signal(i, SIG_DFL);
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
error("%s: open %s: %s", __func__, _PATH_DEVNULL,
strerror(errno));
_exit(1);
}
/* Keep stderr around a while longer to catch errors */
if (dup2(devnull, STDIN_FILENO) == -1 ||
dup2(p[1], STDOUT_FILENO) == -1) {
error("%s: dup2: %s", __func__, strerror(errno));
_exit(1);
}
closefrom(STDERR_FILENO + 1);
/* Don't use permanently_set_uid() here to avoid fatal() */
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
error("setresgid %u: %s", (u_int)pw->pw_gid,
strerror(errno));
_exit(1);
}
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
error("setresuid %u: %s", (u_int)pw->pw_uid,
strerror(errno));
_exit(1);
}
/* stdin is pointed to /dev/null at this point */
if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
error("%s: dup2: %s", __func__, strerror(errno));
_exit(1);
}
execl(options.authorized_keys_command,
options.authorized_keys_command, user_pw->pw_name, NULL);
error("AuthorizedKeysCommand %s exec failed: %s",
options.authorized_keys_command, strerror(errno));
_exit(127);
default: /* parent */
break;
}
temporarily_use_uid(pw);
close(p[1]);
if ((f = fdopen(p[0], "r")) == NULL) {
error("%s: fdopen: %s", __func__, strerror(errno));
close(p[0]);
/* Don't leave zombie child */
kill(pid, SIGTERM);
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
;
goto out;
}
ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
fclose(f);
while (waitpid(pid, &status, 0) == -1) {
if (errno != EINTR) {
error("%s: waitpid: %s", __func__, strerror(errno));
goto out;
}
}
if (WIFSIGNALED(status)) {
error("AuthorizedKeysCommand %s exited on signal %d",
options.authorized_keys_command, WTERMSIG(status));
goto out;
} else if (WEXITSTATUS(status) != 0) {
error("AuthorizedKeysCommand %s returned status %d",
options.authorized_keys_command, WEXITSTATUS(status));
goto out;
}
found_key = ok;
out:
restore_uid();
return found_key;
}
/*
* Check whether key authenticates and authorises the user.
*/
int
user_key_allowed(struct passwd *pw, Key *key)
{
@ -448,9 +614,17 @@ user_key_allowed(struct passwd *pw, Key *key)
if (success)
return success;
success = user_key_command_allowed2(pw, key);
if (success > 0)
return success;
for (i = 0; !success && i < options.num_authkeys_files; i++) {
if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
continue;
file = expand_authorized_keys(
options.authorized_keys_files[i], pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2.c,v 1.124 2011/12/07 05:44:38 djm Exp $ */
/* $OpenBSD: auth2.c,v 1.126 2012/12/02 20:34:09 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -92,8 +92,10 @@ static void input_service_request(int, u_int32_t, void *);
static void input_userauth_request(int, u_int32_t, void *);
/* helper */
static Authmethod *authmethod_lookup(const char *);
static char *authmethods_get(void);
static Authmethod *authmethod_lookup(Authctxt *, const char *);
static char *authmethods_get(Authctxt *authctxt);
static int method_allowed(Authctxt *, const char *);
static int list_starts_with(const char *, const char *);
char *
auth2_read_banner(void)
@ -235,6 +237,8 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
if (use_privsep)
mm_inform_authserv(service, style);
userauth_banner();
if (auth2_setup_methods_lists(authctxt) != 0)
packet_disconnect("no authentication methods enabled");
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
packet_disconnect("Change of username or service not allowed: "
@ -257,12 +261,12 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
authctxt->server_caused_failure = 0;
/* try to authenticate user */
m = authmethod_lookup(method);
m = authmethod_lookup(authctxt, method);
if (m != NULL && authctxt->failures < options.max_authtries) {
debug2("input_userauth_request: try method %s", method);
authenticated = m->userauth(authctxt);
}
userauth_finish(authctxt, authenticated, method);
userauth_finish(authctxt, authenticated, method, NULL);
xfree(service);
xfree(user);
@ -270,26 +274,36 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
}
void
userauth_finish(Authctxt *authctxt, int authenticated, char *method)
userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
const char *submethod)
{
char *methods;
int partial = 0;
if (!authctxt->valid && authenticated)
fatal("INTERNAL ERROR: authenticated invalid user %s",
authctxt->user);
if (authenticated && authctxt->postponed)
fatal("INTERNAL ERROR: authenticated and postponed");
/* Special handling for root */
if (authenticated && authctxt->pw->pw_uid == 0 &&
!auth_root_allowed(method))
authenticated = 0;
if (authenticated && options.num_auth_methods != 0) {
if (!auth2_update_methods_lists(authctxt, method)) {
authenticated = 0;
partial = 1;
}
}
/* Log before sending the reply */
auth_log(authctxt, authenticated, method, " ssh2");
auth_log(authctxt, authenticated, partial, method, submethod, " ssh2");
if (authctxt->postponed)
return;
/* XXX todo: check if multiple auth methods are needed */
if (authenticated == 1) {
/* turn off userauth */
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
@ -305,34 +319,61 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
authctxt->failures++;
if (authctxt->failures >= options.max_authtries)
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
methods = authmethods_get();
methods = authmethods_get(authctxt);
debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
partial, methods);
packet_start(SSH2_MSG_USERAUTH_FAILURE);
packet_put_cstring(methods);
packet_put_char(0); /* XXX partial success, unused */
packet_put_char(partial);
packet_send();
packet_write_wait();
xfree(methods);
}
}
/*
* Checks whether method is allowed by at least one AuthenticationMethods
* methods list. Returns 1 if allowed, or no methods lists configured.
* 0 otherwise.
*/
static int
method_allowed(Authctxt *authctxt, const char *method)
{
u_int i;
/*
* NB. authctxt->num_auth_methods might be zero as a result of
* auth2_setup_methods_lists(), so check the configuration.
*/
if (options.num_auth_methods == 0)
return 1;
for (i = 0; i < authctxt->num_auth_methods; i++) {
if (list_starts_with(authctxt->auth_methods[i], method))
return 1;
}
return 0;
}
static char *
authmethods_get(void)
authmethods_get(Authctxt *authctxt)
{
Buffer b;
char *list;
int i;
u_int i;
buffer_init(&b);
for (i = 0; authmethods[i] != NULL; i++) {
if (strcmp(authmethods[i]->name, "none") == 0)
continue;
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, authmethods[i]->name,
strlen(authmethods[i]->name));
}
if (authmethods[i]->enabled == NULL ||
*(authmethods[i]->enabled) == 0)
continue;
if (!method_allowed(authctxt, authmethods[i]->name))
continue;
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, authmethods[i]->name,
strlen(authmethods[i]->name));
}
buffer_append(&b, "\0", 1);
list = xstrdup(buffer_ptr(&b));
@ -341,7 +382,7 @@ authmethods_get(void)
}
static Authmethod *
authmethod_lookup(const char *name)
authmethod_lookup(Authctxt *authctxt, const char *name)
{
int i;
@ -349,10 +390,154 @@ authmethod_lookup(const char *name)
for (i = 0; authmethods[i] != NULL; i++)
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0 &&
strcmp(name, authmethods[i]->name) == 0)
strcmp(name, authmethods[i]->name) == 0 &&
method_allowed(authctxt, authmethods[i]->name))
return authmethods[i];
debug2("Unrecognized authentication method name: %s",
name ? name : "NULL");
return NULL;
}
/*
* Check a comma-separated list of methods for validity. Is need_enable is
* non-zero, then also require that the methods are enabled.
* Returns 0 on success or -1 if the methods list is invalid.
*/
int
auth2_methods_valid(const char *_methods, int need_enable)
{
char *methods, *omethods, *method;
u_int i, found;
int ret = -1;
if (*_methods == '\0') {
error("empty authentication method list");
return -1;
}
omethods = methods = xstrdup(_methods);
while ((method = strsep(&methods, ",")) != NULL) {
for (found = i = 0; !found && authmethods[i] != NULL; i++) {
if (strcmp(method, authmethods[i]->name) != 0)
continue;
if (need_enable) {
if (authmethods[i]->enabled == NULL ||
*(authmethods[i]->enabled) == 0) {
error("Disabled method \"%s\" in "
"AuthenticationMethods list \"%s\"",
method, _methods);
goto out;
}
}
found = 1;
break;
}
if (!found) {
error("Unknown authentication method \"%s\" in list",
method);
goto out;
}
}
ret = 0;
out:
free(omethods);
return ret;
}
/*
* Prune the AuthenticationMethods supplied in the configuration, removing
* any methods lists that include disabled methods. Note that this might
* leave authctxt->num_auth_methods == 0, even when multiple required auth
* has been requested. For this reason, all tests for whether multiple is
* enabled should consult options.num_auth_methods directly.
*/
int
auth2_setup_methods_lists(Authctxt *authctxt)
{
u_int i;
if (options.num_auth_methods == 0)
return 0;
debug3("%s: checking methods", __func__);
authctxt->auth_methods = xcalloc(options.num_auth_methods,
sizeof(*authctxt->auth_methods));
authctxt->num_auth_methods = 0;
for (i = 0; i < options.num_auth_methods; i++) {
if (auth2_methods_valid(options.auth_methods[i], 1) != 0) {
logit("Authentication methods list \"%s\" contains "
"disabled method, skipping",
options.auth_methods[i]);
continue;
}
debug("authentication methods list %d: %s",
authctxt->num_auth_methods, options.auth_methods[i]);
authctxt->auth_methods[authctxt->num_auth_methods++] =
xstrdup(options.auth_methods[i]);
}
if (authctxt->num_auth_methods == 0) {
error("No AuthenticationMethods left after eliminating "
"disabled methods");
return -1;
}
return 0;
}
static int
list_starts_with(const char *methods, const char *method)
{
size_t l = strlen(method);
if (strncmp(methods, method, l) != 0)
return 0;
if (methods[l] != ',' && methods[l] != '\0')
return 0;
return 1;
}
/*
* Remove method from the start of a comma-separated list of methods.
* Returns 0 if the list of methods did not start with that method or 1
* if it did.
*/
static int
remove_method(char **methods, const char *method)
{
char *omethods = *methods;
size_t l = strlen(method);
if (!list_starts_with(omethods, method))
return 0;
*methods = xstrdup(omethods + l + (omethods[l] == ',' ? 1 : 0));
free(omethods);
return 1;
}
/*
* Called after successful authentication. Will remove the successful method
* from the start of each list in which it occurs. If it was the last method
* in any list, then authentication is deemed successful.
* Returns 1 if the method completed any authentication list or 0 otherwise.
*/
int
auth2_update_methods_lists(Authctxt *authctxt, const char *method)
{
u_int i, found = 0;
debug3("%s: updating methods list after \"%s\"", __func__, method);
for (i = 0; i < authctxt->num_auth_methods; i++) {
if (!remove_method(&(authctxt->auth_methods[i]), method))
continue;
found = 1;
if (*authctxt->auth_methods[i] == '\0') {
debug2("authentication methods list %d complete", i);
return 1;
}
debug3("authentication methods list %d remaining: \"%s\"",
i, authctxt->auth_methods[i]);
}
/* This should not happen, but would be bad if it did */
if (!found)
fatal("%s: method not in AuthenticationMethods", __func__);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfile.c,v 1.93 2012/01/25 19:36:31 markus Exp $ */
/* $OpenBSD: authfile.c,v 1.95 2013/01/08 18:49:04 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -145,7 +145,7 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_ENCRYPT);
cipher_crypt(&ciphercontext, cp,
buffer_ptr(&buffer), buffer_len(&buffer));
buffer_ptr(&buffer), buffer_len(&buffer), 0, 0);
cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext));
@ -463,7 +463,7 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_DECRYPT);
cipher_crypt(&ciphercontext, cp,
buffer_ptr(&copy), buffer_len(&copy));
buffer_ptr(&copy), buffer_len(&copy), 0, 0);
cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext));
buffer_free(&copy);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.c,v 1.318 2012/04/23 08:18:17 djm Exp $ */
/* $OpenBSD: channels.c,v 1.319 2012/12/02 20:46:11 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -3135,12 +3135,10 @@ channel_add_adm_permitted_opens(char *host, int port)
void
channel_disable_adm_local_opens(void)
{
if (num_adm_permitted_opens == 0) {
permitted_adm_opens = xmalloc(sizeof(*permitted_adm_opens));
permitted_adm_opens[num_adm_permitted_opens].host_to_connect
= NULL;
num_adm_permitted_opens = 1;
}
channel_clear_adm_permitted_opens();
permitted_adm_opens = xmalloc(sizeof(*permitted_adm_opens));
permitted_adm_opens[num_adm_permitted_opens].host_to_connect = NULL;
num_adm_permitted_opens = 1;
}
void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.c,v 1.82 2009/01/26 09:58:15 markus Exp $ */
/* $OpenBSD: cipher.c,v 1.87 2013/01/26 06:11:05 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -49,40 +49,45 @@
extern const EVP_CIPHER *evp_ssh1_bf(void);
extern const EVP_CIPHER *evp_ssh1_3des(void);
extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
extern const EVP_CIPHER *evp_aes_128_ctr(void);
extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
struct Cipher {
char *name;
int number; /* for ssh1 only */
u_int block_size;
u_int key_len;
u_int iv_len; /* defaults to block_size */
u_int auth_len;
u_int discard_len;
u_int cbc_mode;
const EVP_CIPHER *(*evptype)(void);
} ciphers[] = {
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, 0, 1, EVP_des_cbc },
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des },
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 1, evp_ssh1_bf },
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc },
{ "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_bf_cbc },
{ "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_cast5_cbc },
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, EVP_rc4 },
{ "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, 0, EVP_rc4 },
{ "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, 0, EVP_rc4 },
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
{ "blowfish-cbc",
SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc },
{ "cast128-cbc",
SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc },
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 },
{ "arcfour128", SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 },
{ "arcfour256", SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 },
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
{ "rijndael-cbc@lysator.liu.se",
SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr },
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr },
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr },
{ "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, 0, EVP_acss },
SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
{ "aes128-gcm@openssh.com",
SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
{ "aes256-gcm@openssh.com",
SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL }
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
};
/*--*/
@ -99,6 +104,18 @@ cipher_keylen(const Cipher *c)
return (c->key_len);
}
u_int
cipher_authlen(const Cipher *c)
{
return (c->auth_len);
}
u_int
cipher_ivlen(const Cipher *c)
{
return (c->iv_len ? c->iv_len : c->block_size);
}
u_int
cipher_get_number(const Cipher *c)
{
@ -214,11 +231,12 @@ cipher_init(CipherContext *cc, Cipher *cipher,
keylen = 8;
}
cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
cc->encrypt = do_encrypt;
if (keylen < cipher->key_len)
fatal("cipher_init: key length %d is insufficient for %s.",
keylen, cipher->name);
if (iv != NULL && ivlen < cipher->block_size)
if (iv != NULL && ivlen < cipher_ivlen(cipher))
fatal("cipher_init: iv length %d is insufficient for %s.",
ivlen, cipher->name);
cc->cipher = cipher;
@ -230,6 +248,11 @@ cipher_init(CipherContext *cc, Cipher *cipher,
(do_encrypt == CIPHER_ENCRYPT)) == 0)
fatal("cipher_init: EVP_CipherInit failed for %s",
cipher->name);
if (cipher_authlen(cipher) &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
-1, (u_char *)iv))
fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s",
cipher->name);
klen = EVP_CIPHER_CTX_key_length(&cc->evp);
if (klen > 0 && keylen != (u_int)klen) {
debug2("cipher_init: set keylen (%d -> %d)", klen, keylen);
@ -253,13 +276,59 @@ cipher_init(CipherContext *cc, Cipher *cipher,
}
}
/*
* cipher_crypt() operates as following:
* Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
* Theses bytes are treated as additional authenticated data for
* authenticated encryption modes.
* En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
* Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
* This tag is written on encryption and verified on decryption.
* Both 'aadlen' and 'authlen' can be set to 0.
*/
void
cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src,
u_int len, u_int aadlen, u_int authlen)
{
if (authlen) {
u_char lastiv[1];
if (authlen != cipher_authlen(cc->cipher))
fatal("%s: authlen mismatch %d", __func__, authlen);
/* increment IV */
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
1, lastiv))
fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__);
/* set tag on decyption */
if (!cc->encrypt &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG,
authlen, (u_char *)src + aadlen + len))
fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__);
}
if (aadlen) {
if (authlen &&
EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0)
fatal("%s: EVP_Cipher(aad) failed", __func__);
memcpy(dest, src, aadlen);
}
if (len % cc->cipher->block_size)
fatal("cipher_encrypt: bad plaintext length %d", len);
if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
fatal("evp_crypt: EVP_Cipher failed");
fatal("%s: bad plaintext length %d", __func__, len);
if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen,
len) < 0)
fatal("%s: EVP_Cipher failed", __func__);
if (authlen) {
/* compute tag (on encrypt) or verify tag (on decrypt) */
if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) {
if (cc->encrypt)
fatal("%s: EVP_Cipher(final) failed", __func__);
else
fatal("Decryption integrity check failed");
}
if (cc->encrypt &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
authlen, dest + aadlen + len))
fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__);
}
}
void
@ -326,9 +395,11 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
if ((u_int)evplen != len)
fatal("%s: wrong iv length %d != %d", __func__,
evplen, len);
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
else
if (cipher_authlen(c)) {
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
len, iv))
fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__);
} else
memcpy(iv, cc->evp.iv, len);
break;
case SSH_CIPHER_3DES:
@ -352,9 +423,12 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv)
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen == 0)
return;
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
else
if (cipher_authlen(c)) {
if (!EVP_CIPHER_CTX_ctrl(&cc->evp,
EVP_CTRL_GCM_SET_IV_FIXED, -1, iv))
fatal("%s: EVP_CTRL_GCM_SET_IV_FIXED failed",
__func__);
} else
memcpy(cc->evp.iv, iv, evplen);
break;
case SSH_CIPHER_3DES:
@ -374,7 +448,7 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat)
Cipher *c = cc->cipher;
int plen = 0;
if (c->evptype == EVP_rc4 || c->evptype == EVP_acss) {
if (c->evptype == EVP_rc4) {
plen = EVP_X_STATE_LEN(cc->evp);
if (dat == NULL)
return (plen);
@ -389,7 +463,7 @@ cipher_set_keycontext(CipherContext *cc, u_char *dat)
Cipher *c = cc->cipher;
int plen;
if (c->evptype == EVP_rc4 || c->evptype == EVP_acss) {
if (c->evptype == EVP_rc4) {
plen = EVP_X_STATE_LEN(cc->evp);
memcpy(EVP_X_STATE(cc->evp), dat, plen);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.h,v 1.37 2009/01/26 09:58:15 markus Exp $ */
/* $OpenBSD: cipher.h,v 1.39 2013/01/08 18:49:04 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -64,6 +64,7 @@ typedef struct CipherContext CipherContext;
struct Cipher;
struct CipherContext {
int plaintext;
int encrypt;
EVP_CIPHER_CTX evp;
Cipher *cipher;
};
@ -76,11 +77,14 @@ char *cipher_name(int);
int ciphers_valid(const char *);
void cipher_init(CipherContext *, Cipher *, const u_char *, u_int,
const u_char *, u_int, int);
void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int);
void cipher_crypt(CipherContext *, u_char *, const u_char *,
u_int, u_int, u_int);
void cipher_cleanup(CipherContext *);
void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
u_int cipher_blocksize(const Cipher *);
u_int cipher_keylen(const Cipher *);
u_int cipher_authlen(const Cipher *);
u_int cipher_ivlen(const Cipher *);
u_int cipher_is_cbc(const Cipher *);
u_int cipher_get_number(const Cipher *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.240 2012/06/20 04:42:58 djm Exp $ */
/* $OpenBSD: clientloop.c,v 1.248 2013/01/02 00:32:07 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -959,9 +959,9 @@ process_cmdline(void)
goto out;
}
if (local || dynamic) {
if (channel_setup_local_fwd_listener(fwd.listen_host,
if (!channel_setup_local_fwd_listener(fwd.listen_host,
fwd.listen_port, fwd.connect_host,
fwd.connect_port, options.gateway_ports) < 0) {
fwd.connect_port, options.gateway_ports)) {
logit("Port forwarding failed.");
goto out;
}
@ -987,6 +987,63 @@ out:
xfree(fwd.connect_host);
}
/* reasons to suppress output of an escape command in help output */
#define SUPPRESS_NEVER 0 /* never suppress, always show */
#define SUPPRESS_PROTO1 1 /* don't show in protocol 1 sessions */
#define SUPPRESS_MUXCLIENT 2 /* don't show in mux client sessions */
#define SUPPRESS_MUXMASTER 4 /* don't show in mux master sessions */
#define SUPPRESS_SYSLOG 8 /* don't show when logging to syslog */
struct escape_help_text {
const char *cmd;
const char *text;
unsigned int flags;
};
static struct escape_help_text esc_txt[] = {
{".", "terminate session", SUPPRESS_MUXMASTER},
{".", "terminate connection (and any multiplexed sessions)",
SUPPRESS_MUXCLIENT},
{"B", "send a BREAK to the remote system", SUPPRESS_PROTO1},
{"C", "open a command line", SUPPRESS_MUXCLIENT},
{"R", "request rekey", SUPPRESS_PROTO1},
{"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT},
{"^Z", "suspend ssh", SUPPRESS_MUXCLIENT},
{"#", "list forwarded connections", SUPPRESS_NEVER},
{"&", "background ssh (when waiting for connections to terminate)",
SUPPRESS_MUXCLIENT},
{"?", "this message", SUPPRESS_NEVER},
};
static void
print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client,
int using_stderr)
{
unsigned int i, suppress_flags;
char string[1024];
snprintf(string, sizeof string, "%c?\r\n"
"Supported escape sequences:\r\n", escape_char);
buffer_append(b, string, strlen(string));
suppress_flags = (protocol2 ? 0 : SUPPRESS_PROTO1) |
(mux_client ? SUPPRESS_MUXCLIENT : 0) |
(mux_client ? 0 : SUPPRESS_MUXMASTER) |
(using_stderr ? 0 : SUPPRESS_SYSLOG);
for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) {
if (esc_txt[i].flags & suppress_flags)
continue;
snprintf(string, sizeof string, " %c%-3s - %s\r\n",
escape_char, esc_txt[i].cmd, esc_txt[i].text);
buffer_append(b, string, strlen(string));
}
snprintf(string, sizeof string,
" %c%c - send the escape character by typing it twice\r\n"
"(Note that escapes are only recognized immediately after "
"newline.)\r\n", escape_char, escape_char);
buffer_append(b, string, strlen(string));
}
/*
* Process the characters one by one, call with c==NULL for proto1 case.
*/
@ -1037,6 +1094,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
if (c && c->ctl_chan != -1) {
chan_read_failed(c);
chan_write_failed(c);
mux_master_session_cleanup_cb(c->self,
NULL);
return 0;
} else
quit_pending = 1;
@ -1045,11 +1104,16 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
case 'Z' - 64:
/* XXX support this for mux clients */
if (c && c->ctl_chan != -1) {
char b[16];
noescape:
if (ch == 'Z' - 64)
snprintf(b, sizeof b, "^Z");
else
snprintf(b, sizeof b, "%c", ch);
snprintf(string, sizeof string,
"%c%c escape not available to "
"%c%s escape not available to "
"multiplexed sessions\r\n",
escape_char, ch);
escape_char, b);
buffer_append(berr, string,
strlen(string));
continue;
@ -1088,6 +1152,31 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
}
continue;
case 'V':
/* FALLTHROUGH */
case 'v':
if (c && c->ctl_chan != -1)
goto noescape;
if (!log_is_on_stderr()) {
snprintf(string, sizeof string,
"%c%c [Logging to syslog]\r\n",
escape_char, ch);
buffer_append(berr, string,
strlen(string));
continue;
}
if (ch == 'V' && options.log_level >
SYSLOG_LEVEL_QUIET)
log_change_level(--options.log_level);
if (ch == 'v' && options.log_level <
SYSLOG_LEVEL_DEBUG3)
log_change_level(++options.log_level);
snprintf(string, sizeof string,
"%c%c [LogLevel %s]\r\n", escape_char, ch,
log_level_name(options.log_level));
buffer_append(berr, string, strlen(string));
continue;
case '&':
if (c && c->ctl_chan != -1)
goto noescape;
@ -1141,43 +1230,9 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
continue;
case '?':
if (c && c->ctl_chan != -1) {
snprintf(string, sizeof string,
"%c?\r\n\
Supported escape sequences:\r\n\
%c. - terminate session\r\n\
%cB - send a BREAK to the remote system\r\n\
%cR - Request rekey (SSH protocol 2 only)\r\n\
%c# - list forwarded connections\r\n\
%c? - this message\r\n\
%c%c - send the escape character by typing it twice\r\n\
(Note that escapes are only recognized immediately after newline.)\r\n",
escape_char, escape_char,
escape_char, escape_char,
escape_char, escape_char,
escape_char, escape_char);
} else {
snprintf(string, sizeof string,
"%c?\r\n\
Supported escape sequences:\r\n\
%c. - terminate connection (and any multiplexed sessions)\r\n\
%cB - send a BREAK to the remote system\r\n\
%cC - open a command line\r\n\
%cR - Request rekey (SSH protocol 2 only)\r\n\
%c^Z - suspend ssh\r\n\
%c# - list forwarded connections\r\n\
%c& - background ssh (when waiting for connections to terminate)\r\n\
%c? - this message\r\n\
%c%c - send the escape character by typing it twice\r\n\
(Note that escapes are only recognized immediately after newline.)\r\n",
escape_char, escape_char,
escape_char, escape_char,
escape_char, escape_char,
escape_char, escape_char,
escape_char, escape_char,
escape_char);
}
buffer_append(berr, string, strlen(string));
print_escape_help(berr, escape_char, compat20,
(c && c->ctl_chan != -1),
log_is_on_stderr());
continue;
case '#':
@ -2171,10 +2226,10 @@ client_stop_mux(void)
if (options.control_path != NULL && muxserver_sock != -1)
unlink(options.control_path);
/*
* If we are in persist mode, signal that we should close when all
* active channels are closed.
* If we are in persist mode, or don't have a shell, signal that we
* should close when all active channels are closed.
*/
if (options.control_persist) {
if (options.control_persist || no_shell_flag) {
session_closed = 1;
setproctitle("[stopped mux]");
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.h,v 1.29 2011/09/09 22:46:44 djm Exp $ */
/* $OpenBSD: clientloop.h,v 1.30 2012/08/17 00:45:45 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -76,4 +76,5 @@ void muxserver_listen(void);
void muxclient(const char *);
void mux_exit_message(Channel *, int);
void mux_tty_alloc_failed(Channel *);
void mux_master_session_cleanup_cb(int, void *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: compat.c,v 1.79 2011/09/23 07:45:05 markus Exp $ */
/* $OpenBSD: compat.c,v 1.80 2012/08/17 01:30:00 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@ -43,6 +43,8 @@ int datafellows = 0;
void
enable_compat20(void)
{
if (compat20)
return;
debug("Enabling compatibility mode for protocol 2.0");
compat20 = 1;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.c,v 1.86 2010/09/22 05:01:29 djm Exp $ */
/* $OpenBSD: kex.c,v 1.88 2013/01/08 18:49:04 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@ -231,8 +231,18 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
packet_get_char();
for (i = 0; i < PROPOSAL_MAX; i++)
xfree(packet_get_string(NULL));
(void) packet_get_char();
(void) packet_get_int();
/*
* XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
* KEX method has the server move first, but a server might be using
* a custom method or one that we otherwise don't support. We should
* be prepared to remember first_kex_follows here so we can eat a
* packet later.
* XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means
* for cases where the server *doesn't* go first. I guess we should
* ignore it when it is set for these cases, which is what we do now.
*/
(void) packet_get_char(); /* first_kex_follows */
(void) packet_get_int(); /* reserved */
packet_check_eom();
kex_kexinit_finish(kex);
@ -283,6 +293,7 @@ choose_enc(Enc *enc, char *client, char *server)
enc->name = name;
enc->enabled = 0;
enc->iv = NULL;
enc->iv_len = cipher_ivlen(enc->cipher);
enc->key = NULL;
enc->key_len = cipher_keylen(enc->cipher);
enc->block_size = cipher_blocksize(enc->cipher);
@ -392,7 +403,7 @@ kex_choose_conf(Kex *kex)
char **my, **peer;
char **cprop, **sprop;
int nenc, nmac, ncomp;
u_int mode, ctos, need;
u_int mode, ctos, need, authlen;
int first_kex_follows, type;
my = kex_buf2prop(&kex->my, NULL);
@ -425,13 +436,16 @@ kex_choose_conf(Kex *kex)
nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]);
choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]);
choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc]);
/* ignore mac for authenticated encryption */
authlen = cipher_authlen(newkeys->enc.cipher);
if (authlen == 0)
choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]);
choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
debug("kex: %s %s %s %s",
ctos ? "client->server" : "server->client",
newkeys->enc.name,
newkeys->mac.name,
authlen == 0 ? newkeys->mac.name : "<implicit>",
newkeys->comp.name);
}
choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
@ -444,6 +458,8 @@ kex_choose_conf(Kex *kex)
need = newkeys->enc.key_len;
if (need < newkeys->enc.block_size)
need = newkeys->enc.block_size;
if (need < newkeys->enc.iv_len)
need = newkeys->enc.iv_len;
if (need < newkeys->mac.key_len)
need = newkeys->mac.key_len;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.h,v 1.52 2010/09/22 05:01:29 djm Exp $ */
/* $OpenBSD: kex.h,v 1.54 2013/01/08 18:49:04 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -86,6 +86,7 @@ struct Enc {
Cipher *cipher;
int enabled;
u_int key_len;
u_int iv_len;
u_int block_size;
u_char *key;
u_char *iv;
@ -97,6 +98,7 @@ struct Mac {
u_char *key;
u_int key_len;
int type;
int etm; /* Encrypt-then-MAC */
const EVP_MD *evp_md;
HMAC_CTX evp_ctx;
struct umac_ctx *umac_ctx;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: key.c,v 1.99 2012/05/23 03:28:28 djm Exp $ */
/* $OpenBSD: key.c,v 1.100 2013/01/17 23:00:01 djm Exp $ */
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -51,6 +51,8 @@
#include "misc.h"
#include "ssh2.h"
static int to_blob(const Key *, u_char **, u_int *, int);
static struct KeyCert *
cert_new(void)
{
@ -312,14 +314,15 @@ key_equal(const Key *a, const Key *b)
}
u_char*
key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
u_int *dgst_raw_length)
{
const EVP_MD *md = NULL;
EVP_MD_CTX ctx;
u_char *blob = NULL;
u_char *retval = NULL;
u_int len = 0;
int nlen, elen, otype;
int nlen, elen;
*dgst_raw_length = 0;
@ -357,10 +360,7 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
case KEY_ECDSA_CERT:
case KEY_RSA_CERT:
/* We want a fingerprint of the _key_ not of the cert */
otype = k->type;
k->type = key_type_plain(k->type);
key_to_blob(k, &blob, &len);
k->type = otype;
to_blob(k, &blob, &len, 1);
break;
case KEY_UNSPEC:
return retval;
@ -1530,18 +1530,19 @@ key_from_blob(const u_char *blob, u_int blen)
return key;
}
int
key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
static int
to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain)
{
Buffer b;
int len;
int len, type;
if (key == NULL) {
error("key_to_blob: key == NULL");
return 0;
}
buffer_init(&b);
switch (key->type) {
type = force_plain ? key_type_plain(key->type) : key->type;
switch (type) {
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT:
@ -1552,20 +1553,23 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
buffer_len(&key->cert->certblob));
break;
case KEY_DSA:
buffer_put_cstring(&b, key_ssh_name(key));
buffer_put_cstring(&b,
key_ssh_name_from_type_nid(type, key->ecdsa_nid));
buffer_put_bignum2(&b, key->dsa->p);
buffer_put_bignum2(&b, key->dsa->q);
buffer_put_bignum2(&b, key->dsa->g);
buffer_put_bignum2(&b, key->dsa->pub_key);
break;
case KEY_ECDSA:
buffer_put_cstring(&b, key_ssh_name(key));
buffer_put_cstring(&b,
key_ssh_name_from_type_nid(type, key->ecdsa_nid));
buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid));
buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa),
EC_KEY_get0_public_key(key->ecdsa));
break;
case KEY_RSA:
buffer_put_cstring(&b, key_ssh_name(key));
buffer_put_cstring(&b,
key_ssh_name_from_type_nid(type, key->ecdsa_nid));
buffer_put_bignum2(&b, key->rsa->e);
buffer_put_bignum2(&b, key->rsa->n);
break;
@ -1586,6 +1590,12 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
return len;
}
int
key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
{
return to_blob(key, blobp, lenp, 0);
}
int
key_sign(
const Key *key,
@ -1957,7 +1967,7 @@ key_cert_check_authority(const Key *k, int want_host, int require_principal,
}
int
key_cert_is_legacy(Key *k)
key_cert_is_legacy(const Key *k)
{
switch (k->type) {
case KEY_DSA_CERT_V00:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: key.h,v 1.34 2012/05/23 03:28:28 djm Exp $ */
/* $OpenBSD: key.h,v 1.35 2013/01/17 23:00:01 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -90,7 +90,7 @@ Key *key_demote(const Key *);
int key_equal_public(const Key *, const Key *);
int key_equal(const Key *, const Key *);
char *key_fingerprint(Key *, enum fp_type, enum fp_rep);
u_char *key_fingerprint_raw(Key *, enum fp_type, u_int *);
u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *);
const char *key_type(const Key *);
const char *key_cert_type(const Key *);
int key_write(const Key *, FILE *);
@ -108,7 +108,7 @@ int key_certify(Key *, Key *);
void key_cert_copy(const Key *, struct Key *);
int key_cert_check_authority(const Key *, int, int, const char *,
const char **);
int key_cert_is_legacy(Key *);
int key_cert_is_legacy(const Key *);
int key_ecdsa_nid_from_name(const char *);
int key_curve_name_to_nid(const char *);

1228
crypto/external/bsd/openssh/dist/krl.c vendored Normal file

File diff suppressed because it is too large Load Diff

63
crypto/external/bsd/openssh/dist/krl.h vendored Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $OpenBSD: krl.h,v 1.2 2013/01/18 00:24:58 djm Exp $ */
#ifndef _KRL_H
#define _KRL_H
/* Functions to manage key revocation lists */
#define KRL_MAGIC "SSHKRL\n\0"
#define KRL_FORMAT_VERSION 1
/* KRL section types */
#define KRL_SECTION_CERTIFICATES 1
#define KRL_SECTION_EXPLICIT_KEY 2
#define KRL_SECTION_FINGERPRINT_SHA1 3
#define KRL_SECTION_SIGNATURE 4
/* KRL_SECTION_CERTIFICATES subsection types */
#define KRL_SECTION_CERT_SERIAL_LIST 0x20
#define KRL_SECTION_CERT_SERIAL_RANGE 0x21
#define KRL_SECTION_CERT_SERIAL_BITMAP 0x22
#define KRL_SECTION_CERT_KEY_ID 0x23
struct ssh_krl;
struct ssh_krl *ssh_krl_init(void);
void ssh_krl_free(struct ssh_krl *krl);
void ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version);
void ssh_krl_set_sign_key(struct ssh_krl *krl, const Key *sign_key);
void ssh_krl_set_comment(struct ssh_krl *krl, const char *comment);
int ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const Key *ca_key,
u_int64_t serial);
int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const Key *ca_key,
u_int64_t lo, u_int64_t hi);
int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key,
const char *key_id);
int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key);
int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const Key *key);
int ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key);
int ssh_krl_to_blob(struct ssh_krl *krl, Buffer *buf, const Key **sign_keys,
u_int nsign_keys);
int ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp,
const Key **sign_ca_keys, u_int nsign_ca_keys);
int ssh_krl_check_key(struct ssh_krl *krl, const Key *key);
int ssh_krl_file_contains_key(const char *path, const Key *key);
#endif /* _KRL_H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: log.c,v 1.42 2011/06/17 21:44:30 djm Exp $ */
/* $OpenBSD: log.c,v 1.43 2012/09/06 04:37:39 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -295,6 +295,21 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
}
}
void
log_change_level(LogLevel new_log_level)
{
/* no-op if log_init has not been called */
if (argv0 == NULL)
return;
log_init(argv0, new_log_level, log_facility, log_on_stderr);
}
int
log_is_on_stderr(void)
{
return log_on_stderr;
}
#define MSGBUFSIZ 1024
void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: log.h,v 1.18 2011/06/17 21:44:30 djm Exp $ */
/* $OpenBSD: log.h,v 1.19 2012/09/06 04:37:39 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -46,6 +46,8 @@ typedef enum {
typedef void (log_handler_fn)(LogLevel, const char *, void *);
void log_init(char *, LogLevel, SyslogFacility, int);
void log_change_level(LogLevel);
int log_is_on_stderr(void);
SyslogFacility log_facility_number(char *);
const char * log_facility_name(SyslogFacility);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: mac.c,v 1.18 2012/06/28 05:07:45 dtucker Exp $ */
/* $OpenBSD: mac.c,v 1.21 2012/12/11 22:51:45 sthen Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -43,6 +43,7 @@
#define SSH_EVP 1 /* OpenSSL EVP-based MAC */
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */
#define SSH_UMAC128 3
struct {
char *name;
@ -51,17 +52,32 @@ struct {
int truncatebits; /* truncate digest if != 0 */
int key_len; /* just for UMAC */
int len; /* just for UMAC */
int etm; /* Encrypt-then-MAC */
} macs[] = {
{ "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 },
{ "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 },
{ "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, -1, -1 },
{ "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, -1, -1 },
{ "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1 },
{ "hmac-md5-96", SSH_EVP, EVP_md5, 96, -1, -1 },
{ "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, -1, -1 },
{ "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, -1, -1 },
{ "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64 },
{ NULL, 0, NULL, 0, -1, -1 }
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */
{ "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 },
{ "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 },
{ "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 },
{ "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 },
{ "hmac-md5", SSH_EVP, EVP_md5, 0, 0, 0, 0 },
{ "hmac-md5-96", SSH_EVP, EVP_md5, 96, 0, 0, 0 },
{ "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
{ "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
{ "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 0 },
{ "umac-128@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 0 },
/* Encrypt-then-MAC variants */
{ "hmac-sha1-etm@openssh.com", SSH_EVP, EVP_sha1, 0, 0, 0, 1 },
{ "hmac-sha1-96-etm@openssh.com", SSH_EVP, EVP_sha1, 96, 0, 0, 1 },
{ "hmac-sha2-256-etm@openssh.com", SSH_EVP, EVP_sha256, 0, 0, 0, 1 },
{ "hmac-sha2-512-etm@openssh.com", SSH_EVP, EVP_sha512, 0, 0, 0, 1 },
{ "hmac-md5-etm@openssh.com", SSH_EVP, EVP_md5, 0, 0, 0, 1 },
{ "hmac-md5-96-etm@openssh.com", SSH_EVP, EVP_md5, 96, 0, 0, 1 },
{ "hmac-ripemd160-etm@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 1 },
{ "umac-64-etm@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 1 },
{ "umac-128-etm@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 1 },
{ NULL, 0, NULL, 0, 0, 0, 0 }
};
static void
@ -81,6 +97,7 @@ mac_setup_by_id(Mac *mac, int which)
}
if (macs[which].truncatebits != 0)
mac->mac_len = macs[which].truncatebits / 8;
mac->etm = macs[which].etm;
}
int
@ -115,6 +132,9 @@ mac_init(Mac *mac)
case SSH_UMAC:
mac->umac_ctx = umac_new(mac->key);
return 0;
case SSH_UMAC128:
mac->umac_ctx = umac128_new(mac->key);
return 0;
default:
return -1;
}
@ -144,6 +164,11 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
umac_update(mac->umac_ctx, data, datalen);
umac_final(mac->umac_ctx, m, nonce);
break;
case SSH_UMAC128:
put_u64(nonce, seqno);
umac128_update(mac->umac_ctx, data, datalen);
umac128_final(mac->umac_ctx, m, nonce);
break;
default:
fatal("mac_compute: unknown MAC type");
}
@ -156,6 +181,9 @@ mac_clear(Mac *mac)
if (mac->type == SSH_UMAC) {
if (mac->umac_ctx != NULL)
umac_delete(mac->umac_ctx);
} else if (mac->type == SSH_UMAC128) {
if (mac->umac_ctx != NULL)
umac128_delete(mac->umac_ctx);
} else if (mac->evp_md != NULL)
HMAC_cleanup(&mac->evp_ctx);
mac->evp_md = NULL;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.117 2012/06/22 12:30:26 dtucker Exp $ */
/* $OpenBSD: monitor.c,v 1.120 2012/12/11 22:16:21 markus Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -163,6 +163,7 @@ static int key_blobtype = MM_NOKEY;
static char *hostbased_cuser = NULL;
static char *hostbased_chost = NULL;
static char *auth_method = "unknown";
static char *auth_submethod = NULL;
static u_int session_id2_len = 0;
static u_char *session_id2 = NULL;
static pid_t monitor_child_pid;
@ -274,7 +275,7 @@ void
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
{
struct mon_table *ent;
int authenticated = 0;
int authenticated = 0, partial = 0;
debug3("preauth child monitor started");
@ -299,8 +300,26 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
/* The first few requests do not require asynchronous access */
while (!authenticated) {
partial = 0;
auth_method = "unknown";
auth_submethod = NULL;
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
/* Special handling for multiple required authentications */
if (options.num_auth_methods != 0) {
if (!compat20)
fatal("AuthenticationMethods is not supported"
"with SSH protocol 1");
if (authenticated &&
!auth2_update_methods_lists(authctxt,
auth_method)) {
debug3("%s: method %s: partial", __func__,
auth_method);
authenticated = 0;
partial = 1;
}
}
if (authenticated) {
if (!(ent->flags & MON_AUTHDECIDE))
fatal("%s: unexpected authentication from %d",
@ -309,9 +328,9 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
!auth_root_allowed(auth_method))
authenticated = 0;
}
if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
auth_log(authctxt, authenticated, auth_method,
auth_log(authctxt, authenticated, partial,
auth_method, auth_submethod,
compat20 ? " ssh2" : "");
if (!authenticated)
authctxt->failures++;
@ -327,10 +346,6 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
#endif
}
/* Drain any buffered messages from the child */
while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
;
if (!authctxt->valid)
fatal("%s: authenticated invalid user", __func__);
if (strcmp(auth_method, "unknown") == 0)
@ -341,6 +356,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
mm_get_keystate(pmonitor);
/* Drain any buffered messages from the child */
while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
;
close(pmonitor->m_sendfd);
close(pmonitor->m_log_recvfd);
pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
@ -687,7 +706,17 @@ mm_answer_pwnamallow(int sock, Buffer *m)
COPY_MATCH_STRING_OPTS();
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT
/* Create valid auth method lists */
if (compat20 && auth2_setup_methods_lists(authctxt) != 0) {
/*
* The monitor will continue long enough to let the child
* run to it's packet_disconnect(), but it must not allow any
* authentication to succeed.
*/
debug("%s: no valid authentication method lists", __func__);
}
debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
mm_request_send(sock, MONITOR_ANS_PWNAM, m);
@ -819,7 +848,10 @@ mm_answer_bsdauthrespond(int sock, Buffer *m)
debug3("%s: sending authenticated: %d", __func__, authok);
mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
auth_method = "bsdauth";
if (compat20)
auth_method = "keyboard-interactive"; /* XXX auth_submethod */
else
auth_method = "bsdauth";
return (authok != 0);
}
@ -893,7 +925,8 @@ mm_answer_keyallowed(int sock, Buffer *m)
hostbased_chost = chost;
} else {
/* Log failed attempt */
auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : "");
auth_log(authctxt, 0, 0, auth_method, NULL,
compat20 ? " ssh2" : "");
xfree(blob);
xfree(cuser);
xfree(chost);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.h,v 1.16 2011/06/17 21:44:31 djm Exp $ */
/* $OpenBSD: monitor.h,v 1.17 2012/12/02 20:34:10 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -28,37 +28,39 @@
#ifndef _MONITOR_H_
#define _MONITOR_H_
/* Please keep *_REQ_* values on even numbers and *_ANS_* on odd numbers */
enum monitor_reqtype {
MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
MONITOR_REQ_KEYEXPORT,
MONITOR_REQ_PTY, MONITOR_ANS_PTY,
MONITOR_REQ_PTYCLEANUP,
MONITOR_REQ_SESSKEY, MONITOR_ANS_SESSKEY,
MONITOR_REQ_SESSID,
MONITOR_REQ_RSAKEYALLOWED, MONITOR_ANS_RSAKEYALLOWED,
MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE,
MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE,
MONITOR_REQ_GSSSETUP, MONITOR_ANS_GSSSETUP,
MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
MONITOR_REQ_TERM,
MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
MONITOR_REQ_JPAKE_STEP2, MONITOR_ANS_JPAKE_STEP2,
MONITOR_REQ_JPAKE_KEY_CONFIRM, MONITOR_ANS_JPAKE_KEY_CONFIRM,
MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM,
MONITOR_REQ_MODULI = 0, MONITOR_ANS_MODULI = 1,
MONITOR_REQ_FREE = 2,
MONITOR_REQ_AUTHSERV = 4,
MONITOR_REQ_SIGN = 6, MONITOR_ANS_SIGN = 7,
MONITOR_REQ_PWNAM = 8, MONITOR_ANS_PWNAM = 9,
MONITOR_REQ_AUTH2_READ_BANNER = 10, MONITOR_ANS_AUTH2_READ_BANNER = 11,
MONITOR_REQ_AUTHPASSWORD = 12, MONITOR_ANS_AUTHPASSWORD = 13,
MONITOR_REQ_BSDAUTHQUERY = 14, MONITOR_ANS_BSDAUTHQUERY = 15,
MONITOR_REQ_BSDAUTHRESPOND = 16, MONITOR_ANS_BSDAUTHRESPOND = 17,
MONITOR_REQ_SKEYQUERY = 18, MONITOR_ANS_SKEYQUERY = 19,
MONITOR_REQ_SKEYRESPOND = 20, MONITOR_ANS_SKEYRESPOND = 21,
MONITOR_REQ_KEYALLOWED = 22, MONITOR_ANS_KEYALLOWED = 23,
MONITOR_REQ_KEYVERIFY = 24, MONITOR_ANS_KEYVERIFY = 25,
MONITOR_REQ_KEYEXPORT = 26,
MONITOR_REQ_PTY = 28, MONITOR_ANS_PTY = 29,
MONITOR_REQ_PTYCLEANUP = 30,
MONITOR_REQ_SESSKEY = 32, MONITOR_ANS_SESSKEY = 33,
MONITOR_REQ_SESSID = 34,
MONITOR_REQ_RSAKEYALLOWED = 36, MONITOR_ANS_RSAKEYALLOWED = 37,
MONITOR_REQ_RSACHALLENGE = 38, MONITOR_ANS_RSACHALLENGE = 39,
MONITOR_REQ_RSARESPONSE = 40, MONITOR_ANS_RSARESPONSE = 41,
MONITOR_REQ_GSSSETUP = 42, MONITOR_ANS_GSSSETUP = 43,
MONITOR_REQ_GSSSTEP = 44, MONITOR_ANS_GSSSTEP = 45,
MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
MONITOR_REQ_TERM = 50,
MONITOR_REQ_JPAKE_STEP1 = 52, MONITOR_ANS_JPAKE_STEP1 = 53,
MONITOR_REQ_JPAKE_GET_PWDATA = 54, MONITOR_ANS_JPAKE_GET_PWDATA = 55,
MONITOR_REQ_JPAKE_STEP2 = 56, MONITOR_ANS_JPAKE_STEP2 = 57,
MONITOR_REQ_JPAKE_KEY_CONFIRM = 58, MONITOR_ANS_JPAKE_KEY_CONFIRM = 59,
MONITOR_REQ_JPAKE_CHECK_CONFIRM = 60, MONITOR_ANS_JPAKE_CHECK_CONFIRM = 61,
};
struct mm_master;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.c,v 1.73 2011/06/17 21:44:31 djm Exp $ */
/* $OpenBSD: monitor_wrap.c,v 1.75 2013/01/08 18:49:04 markus Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -480,25 +480,24 @@ mm_newkeys_from_blob(u_char *blob, int blen)
enc->enabled = buffer_get_int(&b);
enc->block_size = buffer_get_int(&b);
enc->key = buffer_get_string(&b, &enc->key_len);
enc->iv = buffer_get_string(&b, &len);
if (len != enc->block_size)
fatal("%s: bad ivlen: expected %u != %u", __func__,
enc->block_size, len);
enc->iv = buffer_get_string(&b, &enc->iv_len);
if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
fatal("%s: bad cipher name %s or pointer %p", __func__,
enc->name, enc->cipher);
/* Mac structure */
mac->name = buffer_get_string(&b, NULL);
if (mac->name == NULL || mac_setup(mac, mac->name) == -1)
fatal("%s: can not setup mac %s", __func__, mac->name);
mac->enabled = buffer_get_int(&b);
mac->key = buffer_get_string(&b, &len);
if (len > mac->key_len)
fatal("%s: bad mac key length: %u > %d", __func__, len,
mac->key_len);
mac->key_len = len;
if (cipher_authlen(enc->cipher) == 0) {
mac->name = buffer_get_string(&b, NULL);
if (mac->name == NULL || mac_setup(mac, mac->name) == -1)
fatal("%s: can not setup mac %s", __func__, mac->name);
mac->enabled = buffer_get_int(&b);
mac->key = buffer_get_string(&b, &len);
if (len > mac->key_len)
fatal("%s: bad mac key length: %u > %d", __func__, len,
mac->key_len);
mac->key_len = len;
}
/* Comp structure */
comp->type = buffer_get_int(&b);
@ -540,13 +539,15 @@ mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
buffer_put_int(&b, enc->enabled);
buffer_put_int(&b, enc->block_size);
buffer_put_string(&b, enc->key, enc->key_len);
packet_get_keyiv(mode, enc->iv, enc->block_size);
buffer_put_string(&b, enc->iv, enc->block_size);
packet_get_keyiv(mode, enc->iv, enc->iv_len);
buffer_put_string(&b, enc->iv, enc->iv_len);
/* Mac structure */
buffer_put_cstring(&b, mac->name);
buffer_put_int(&b, mac->enabled);
buffer_put_string(&b, mac->key, mac->key_len);
if (cipher_authlen(enc->cipher) == 0) {
buffer_put_cstring(&b, mac->name);
buffer_put_int(&b, mac->enabled);
buffer_put_string(&b, mac->key, mac->key_len);
}
/* Comp structure */
buffer_put_int(&b, comp->type);
@ -610,7 +611,7 @@ mm_send_keystate(struct monitor *monitor)
ivlen = packet_get_keyiv_len(MODE_OUT);
packet_get_keyiv(MODE_OUT, iv, ivlen);
buffer_put_string(&m, iv, ivlen);
ivlen = packet_get_keyiv_len(MODE_OUT);
ivlen = packet_get_keyiv_len(MODE_IN);
packet_get_keyiv(MODE_IN, iv, ivlen);
buffer_put_string(&m, iv, ivlen);
goto skip;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: mux.c,v 1.36 2012/07/06 01:37:21 djm Exp $ */
/* $OpenBSD: mux.c,v 1.38 2013/01/02 00:32:07 djm Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@ -171,7 +171,7 @@ static const struct {
/* Cleanup callback fired on closure of mux slave _session_ channel */
/* ARGSUSED */
static void
void
mux_master_session_cleanup_cb(int cid, void *unused)
{
Channel *cc, *c = channel_by_id(cid);
@ -721,9 +721,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
}
if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
if (channel_setup_local_fwd_listener(fwd.listen_host,
if (!channel_setup_local_fwd_listener(fwd.listen_host,
fwd.listen_port, fwd.connect_host, fwd.connect_port,
options.gateway_ports) < 0) {
options.gateway_ports)) {
fail:
logit("slave-requested %s failed", fwd_desc);
buffer_put_int(r, MUX_S_FAILURE);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: myproposal.h,v 1.29 2012/06/28 05:07:45 dtucker Exp $ */
/* $OpenBSD: myproposal.h,v 1.32 2013/01/08 18:49:04 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -50,12 +50,23 @@
#define KEX_DEFAULT_ENCRYPT \
"aes128-ctr,aes192-ctr,aes256-ctr," \
"arcfour256,arcfour128," \
"aes128-gcm@openssh.com,aes256-gcm@openssh.com," \
"aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
"aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"
#define KEX_DEFAULT_MAC \
"hmac-md5-etm@openssh.com," \
"hmac-sha1-etm@openssh.com," \
"umac-64-etm@openssh.com," \
"umac-128-etm@openssh.com," \
"hmac-sha2-256-etm@openssh.com," \
"hmac-sha2-512-etm@openssh.com," \
"hmac-ripemd160-etm@openssh.com," \
"hmac-sha1-96-etm@openssh.com," \
"hmac-md5-96-etm@openssh.com," \
"hmac-md5," \
"hmac-sha1," \
"umac-64@openssh.com," \
"umac-128@openssh.com," \
"hmac-sha2-256," \
"hmac-sha2-512," \
"hmac-ripemd160," \

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.176 2012/01/25 19:40:09 markus Exp $ */
/* $OpenBSD: packet.c,v 1.181 2013/02/10 23:35:24 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -271,7 +271,7 @@ packet_stop_discard(void)
static void
packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard)
{
if (enc == NULL || !cipher_is_cbc(enc->cipher))
if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm))
packet_disconnect("Packet corrupt");
if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled)
active_state->packet_discard_mac = mac;
@ -698,7 +698,7 @@ packet_send1(void)
buffer_len(&active_state->outgoing_packet));
cipher_crypt(&active_state->send_context, cp,
buffer_ptr(&active_state->outgoing_packet),
buffer_len(&active_state->outgoing_packet));
buffer_len(&active_state->outgoing_packet), 0, 0);
#ifdef PACKET_DEBUG
fprintf(stderr, "encrypted: ");
@ -746,6 +746,9 @@ set_newkeys(int mode)
mac = &active_state->newkeys[mode]->mac;
comp = &active_state->newkeys[mode]->comp;
mac_clear(mac);
memset(enc->iv, 0, enc->iv_len);
memset(enc->key, 0, enc->key_len);
memset(mac->key, 0, mac->key_len);
xfree(enc->name);
xfree(enc->iv);
xfree(enc->key);
@ -760,11 +763,11 @@ set_newkeys(int mode)
enc = &active_state->newkeys[mode]->enc;
mac = &active_state->newkeys[mode]->mac;
comp = &active_state->newkeys[mode]->comp;
if (mac_init(mac) == 0)
if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0)
mac->enabled = 1;
DBG(debug("cipher_init_context: %d", mode));
cipher_init(cc, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->block_size, crypt_type);
enc->iv, enc->iv_len, crypt_type);
/* Deleting the keys does not gain extra security */
/* memset(enc->iv, 0, enc->block_size);
memset(enc->key, 0, enc->key_len);
@ -831,9 +834,8 @@ static void
packet_send2_wrapped(void)
{
u_char type, *cp, *macbuf = NULL;
u_char padlen, pad;
u_int packet_length = 0;
u_int i, len;
u_char padlen, pad = 0;
u_int i, len, authlen = 0, aadlen = 0;
u_int32_t rnd = 0;
Enc *enc = NULL;
Mac *mac = NULL;
@ -844,8 +846,12 @@ packet_send2_wrapped(void)
enc = &active_state->newkeys[MODE_OUT]->enc;
mac = &active_state->newkeys[MODE_OUT]->mac;
comp = &active_state->newkeys[MODE_OUT]->comp;
/* disable mac for authenticated encryption */
if ((authlen = cipher_authlen(enc->cipher)) != 0)
mac = NULL;
}
block_size = enc ? enc->block_size : 8;
aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
cp = buffer_ptr(&active_state->outgoing_packet);
type = cp[5];
@ -878,6 +884,7 @@ packet_send2_wrapped(void)
* calc size of padding, alloc space, get random data,
* minimum padding is 4 bytes
*/
len -= aadlen; /* packet length is not encrypted for EtM modes */
padlen = block_size - (len % block_size);
if (padlen < 4)
padlen += block_size;
@ -905,29 +912,37 @@ packet_send2_wrapped(void)
/* clear padding */
memset(cp, 0, padlen);
}
/* packet_length includes payload, padding and padding length field */
packet_length = buffer_len(&active_state->outgoing_packet) - 4;
/* sizeof (packet_len + pad_len + payload + padding) */
len = buffer_len(&active_state->outgoing_packet);
cp = buffer_ptr(&active_state->outgoing_packet);
put_u32(cp, packet_length);
/* packet_length includes payload, padding and padding length field */
put_u32(cp, len - 4);
cp[4] = padlen;
DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
DBG(debug("send: len %d (includes padlen %d, aadlen %d)",
len, padlen, aadlen));
/* compute MAC over seqnr and packet(length fields, payload, padding) */
if (mac && mac->enabled) {
if (mac && mac->enabled && !mac->etm) {
macbuf = mac_compute(mac, active_state->p_send.seqnr,
buffer_ptr(&active_state->outgoing_packet),
buffer_len(&active_state->outgoing_packet));
buffer_ptr(&active_state->outgoing_packet), len);
DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr));
}
/* encrypt packet and append to output buffer. */
cp = buffer_append_space(&active_state->output,
buffer_len(&active_state->outgoing_packet));
cp = buffer_append_space(&active_state->output, len + authlen);
cipher_crypt(&active_state->send_context, cp,
buffer_ptr(&active_state->outgoing_packet),
buffer_len(&active_state->outgoing_packet));
len - aadlen, aadlen, authlen);
/* append unencrypted MAC */
if (mac && mac->enabled)
if (mac && mac->enabled) {
if (mac->etm) {
/* EtM: compute mac over aadlen + cipher text */
macbuf = mac_compute(mac,
active_state->p_send.seqnr, cp, len);
DBG(debug("done calc MAC(EtM) out #%d",
active_state->p_send.seqnr));
}
buffer_append(&active_state->output, macbuf, mac->mac_len);
}
#ifdef PACKET_DEBUG
fprintf(stderr, "encrypted: ");
buffer_dump(&active_state->output);
@ -938,8 +953,8 @@ packet_send2_wrapped(void)
if (++active_state->p_send.packets == 0)
if (!(datafellows & SSH_BUG_NOREKEY))
fatal("XXX too many packets with same key");
active_state->p_send.blocks += (packet_length + 4) / block_size;
active_state->p_send.bytes += packet_length + 4;
active_state->p_send.blocks += len / block_size;
active_state->p_send.bytes += len;
buffer_clear(&active_state->outgoing_packet);
if (type == SSH2_MSG_NEWKEYS)
@ -1175,7 +1190,7 @@ packet_read_poll1(void)
buffer_clear(&active_state->incoming_packet);
cp = buffer_append_space(&active_state->incoming_packet, padded_len);
cipher_crypt(&active_state->receive_context, cp,
buffer_ptr(&active_state->input), padded_len);
buffer_ptr(&active_state->input), padded_len, 0, 0);
buffer_consume(&active_state->input, padded_len);
@ -1223,8 +1238,8 @@ static int
packet_read_poll2(u_int32_t *seqnr_p)
{
u_int padlen, need;
u_char *macbuf, *cp, type;
u_int maclen, block_size;
u_char *macbuf = NULL, *cp, type;
u_int maclen, authlen = 0, aadlen = 0, block_size;
Enc *enc = NULL;
Mac *mac = NULL;
Comp *comp = NULL;
@ -1236,11 +1251,29 @@ packet_read_poll2(u_int32_t *seqnr_p)
enc = &active_state->newkeys[MODE_IN]->enc;
mac = &active_state->newkeys[MODE_IN]->mac;
comp = &active_state->newkeys[MODE_IN]->comp;
/* disable mac for authenticated encryption */
if ((authlen = cipher_authlen(enc->cipher)) != 0)
mac = NULL;
}
maclen = mac && mac->enabled ? mac->mac_len : 0;
block_size = enc ? enc->block_size : 8;
aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
if (active_state->packlen == 0) {
if (aadlen && active_state->packlen == 0) {
if (buffer_len(&active_state->input) < 4)
return SSH_MSG_NONE;
cp = buffer_ptr(&active_state->input);
active_state->packlen = get_u32(cp);
if (active_state->packlen < 1 + 4 ||
active_state->packlen > PACKET_MAX_SIZE) {
#ifdef PACKET_DEBUG
buffer_dump(&active_state->input);
#endif
logit("Bad packet length %u.", active_state->packlen);
packet_disconnect("Packet corrupt");
}
buffer_clear(&active_state->incoming_packet);
} else if (active_state->packlen == 0) {
/*
* check if input size is less than the cipher block size,
* decrypt first block and extract length of incoming packet
@ -1251,7 +1284,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
cp = buffer_append_space(&active_state->incoming_packet,
block_size);
cipher_crypt(&active_state->receive_context, cp,
buffer_ptr(&active_state->input), block_size);
buffer_ptr(&active_state->input), block_size, 0, 0);
cp = buffer_ptr(&active_state->incoming_packet);
active_state->packlen = get_u32(cp);
if (active_state->packlen < 1 + 4 ||
@ -1264,13 +1297,21 @@ packet_read_poll2(u_int32_t *seqnr_p)
PACKET_MAX_SIZE);
return SSH_MSG_NONE;
}
DBG(debug("input: packet len %u", active_state->packlen+4));
buffer_consume(&active_state->input, block_size);
}
/* we have a partial packet of block_size bytes */
need = 4 + active_state->packlen - block_size;
DBG(debug("partial packet %d, need %d, maclen %d", block_size,
need, maclen));
DBG(debug("input: packet len %u", active_state->packlen+4));
if (aadlen) {
/* only the payload is encrypted */
need = active_state->packlen;
} else {
/*
* the payload size and the payload are encrypted, but we
* have a partial packet of block_size bytes
*/
need = 4 + active_state->packlen - block_size;
}
DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d,"
" aadlen %d", block_size, need, maclen, authlen, aadlen));
if (need % block_size != 0) {
logit("padding error: need %d block %d mod %d",
need, block_size, need % block_size);
@ -1280,26 +1321,35 @@ packet_read_poll2(u_int32_t *seqnr_p)
}
/*
* check if the entire packet has been received and
* decrypt into incoming_packet
* decrypt into incoming_packet:
* 'aadlen' bytes are unencrypted, but authenticated.
* 'need' bytes are encrypted, followed by either
* 'authlen' bytes of authentication tag or
* 'maclen' bytes of message authentication code.
*/
if (buffer_len(&active_state->input) < need + maclen)
if (buffer_len(&active_state->input) < aadlen + need + authlen + maclen)
return SSH_MSG_NONE;
#ifdef PACKET_DEBUG
fprintf(stderr, "read_poll enc/full: ");
buffer_dump(&active_state->input);
#endif
cp = buffer_append_space(&active_state->incoming_packet, need);
/* EtM: compute mac over encrypted input */
if (mac && mac->enabled && mac->etm)
macbuf = mac_compute(mac, active_state->p_read.seqnr,
buffer_ptr(&active_state->input), aadlen + need);
cp = buffer_append_space(&active_state->incoming_packet, aadlen + need);
cipher_crypt(&active_state->receive_context, cp,
buffer_ptr(&active_state->input), need);
buffer_consume(&active_state->input, need);
buffer_ptr(&active_state->input), need, aadlen, authlen);
buffer_consume(&active_state->input, aadlen + need + authlen);
/*
* compute MAC over seqnr and packet,
* increment sequence number for incoming packet
*/
if (mac && mac->enabled) {
macbuf = mac_compute(mac, active_state->p_read.seqnr,
buffer_ptr(&active_state->incoming_packet),
buffer_len(&active_state->incoming_packet));
if (!mac->etm)
macbuf = mac_compute(mac, active_state->p_read.seqnr,
buffer_ptr(&active_state->incoming_packet),
buffer_len(&active_state->incoming_packet));
if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input),
mac->mac_len) != 0) {
logit("Corrupted MAC on input.");
@ -1398,7 +1448,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p)
case SSH2_MSG_DISCONNECT:
reason = packet_get_int();
msg = packet_get_string(NULL);
logit("Received disconnect from %s: %u: %.400s",
error("Received disconnect from %s: %u: %.400s",
get_remote_ipaddr(), reason, msg);
xfree(msg);
cleanup_exit(255);
@ -1423,7 +1473,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p)
break;
case SSH_MSG_DISCONNECT:
msg = packet_get_string(NULL);
logit("Received disconnect from %s: %.400s",
error("Received disconnect from %s: %.400s",
get_remote_ipaddr(), msg);
cleanup_exit(255);
break;

View File

@ -1,5 +1,5 @@
/* $OpenBSD: servconf.c,v 1.229 2012/07/13 01:35:21 dtucker Exp $ */
/* $OpenBSD: servconf.c,v 1.234 2013/02/06 00:20:42 dtucker Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -46,6 +46,8 @@
#include "groupaccess.h"
#include "canohost.h"
#include "packet.h"
#include "hostfile.h"
#include "auth.h"
static void add_listen_addr(ServerOptions *, char *, int);
static void add_one_listen_addr(ServerOptions *, char *, int);
@ -128,6 +130,8 @@ initialize_server_options(ServerOptions *options)
options->num_permitted_opens = -1;
options->adm_forced_command = NULL;
options->chroot_directory = NULL;
options->authorized_keys_command = NULL;
options->authorized_keys_command_user = NULL;
options->zero_knowledge_password_authentication = -1;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
@ -232,17 +236,17 @@ fill_default_server_options(ServerOptions *options)
if (options->compression == -1)
options->compression = COMP_DELAYED;
if (options->allow_tcp_forwarding == -1)
options->allow_tcp_forwarding = 1;
options->allow_tcp_forwarding = FORWARD_ALLOW;
if (options->allow_agent_forwarding == -1)
options->allow_agent_forwarding = 1;
if (options->gateway_ports == -1)
options->gateway_ports = 0;
if (options->max_startups == -1)
options->max_startups = 10;
options->max_startups = 100;
if (options->max_startups_rate == -1)
options->max_startups_rate = 100; /* 100% */
options->max_startups_rate = 30; /* 30% */
if (options->max_startups_begin == -1)
options->max_startups_begin = options->max_startups;
options->max_startups_begin = 10;
if (options->max_authtries == -1)
options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
if (options->max_sessions == -1)
@ -302,6 +306,8 @@ typedef enum {
sZeroKnowledgePasswordAuthentication, sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sKexAlgorithms, sIPQoS, sVersionAddendum,
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods,
sDeprecated, sUnsupported
} ServerOpCodes;
@ -414,7 +420,10 @@ static struct {
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
{ "ipqos", sIPQoS, SSHCFG_ALL },
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
@ -579,8 +588,9 @@ out:
}
/*
* All of the attributes on a single Match line are ANDed together, so we need to check every
* attribute and set the result to zero if any attribute does not match.
* All of the attributes on a single Match line are ANDed together, so we need
* to check every * attribute and set the result to zero if any attribute does
* not match.
*/
static int
match_cfg_line(char **condition, int line, struct connection_info *ci)
@ -737,6 +747,14 @@ static const struct multistate multistate_privsep[] = {
{ "no", PRIVSEP_OFF },
{ NULL, -1 }
};
static const struct multistate multistate_tcpfwd[] = {
{ "yes", FORWARD_ALLOW },
{ "all", FORWARD_ALLOW },
{ "no", FORWARD_DENY },
{ "remote", FORWARD_REMOTE },
{ "local", FORWARD_LOCAL },
{ NULL, -1 }
};
int
process_server_config_line(ServerOptions *options, char *line,
@ -1088,7 +1106,8 @@ process_server_config_line(ServerOptions *options, char *line,
case sAllowTcpForwarding:
intptr = &options->allow_tcp_forwarding;
goto parse_flag;
multistate_ptr = multistate_tcpfwd;
goto parse_multistate;
case sAllowAgentForwarding:
intptr = &options->allow_agent_forwarding;
@ -1368,7 +1387,6 @@ process_server_config_line(ServerOptions *options, char *line,
}
if (strcmp(arg, "none") == 0) {
if (*activep && n == -1) {
channel_clear_adm_permitted_opens();
options->num_permitted_opens = 1;
channel_disable_adm_local_opens();
}
@ -1452,6 +1470,43 @@ process_server_config_line(ServerOptions *options, char *line,
}
return 0;
case sAuthorizedKeysCommand:
len = strspn(cp, WHITESPACE);
if (*activep && options->authorized_keys_command == NULL) {
if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
fatal("%.200s line %d: AuthorizedKeysCommand "
"must be an absolute path",
filename, linenum);
options->authorized_keys_command = xstrdup(cp + len);
}
return 0;
case sAuthorizedKeysCommandUser:
charptr = &options->authorized_keys_command_user;
arg = strdelim(&cp);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sAuthenticationMethods:
if (*activep && options->num_auth_methods == 0) {
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_auth_methods >=
MAX_AUTH_METHODS)
fatal("%s line %d: "
"too many authentication methods.",
filename, linenum);
if (auth2_methods_valid(arg, 0) != 0)
fatal("%s line %d: invalid "
"authentication method list.",
filename, linenum);
options->auth_methods[
options->num_auth_methods++] = xstrdup(arg);
}
}
return 0;
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@ -1602,6 +1657,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
M_CP_INTOPT(kbd_interactive_authentication);
M_CP_INTOPT(zero_knowledge_password_authentication);
M_CP_STROPT(authorized_keys_command);
M_CP_STROPT(authorized_keys_command_user);
M_CP_INTOPT(permit_root_login);
M_CP_INTOPT(permit_empty_passwd);
@ -1686,6 +1743,8 @@ fmt_intarg(ServerOpCodes code, int val)
return fmt_multistate_int(val, multistate_compression);
case sUsePrivilegeSeparation:
return fmt_multistate_int(val, multistate_privsep);
case sAllowTcpForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sProtocol:
switch (val) {
case SSH_PROTO_1:
@ -1857,6 +1916,8 @@ dump_config(ServerOptions *o)
dump_cfg_string(sAuthorizedPrincipalsFile,
o->authorized_principals_file);
dump_cfg_string(sVersionAddendum, o->version_addendum);
dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
@ -1874,6 +1935,8 @@ dump_config(ServerOptions *o)
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
dump_cfg_strarray_oneline(sAuthenticationMethods,
o->num_auth_methods, o->auth_methods);
/* other arguments */
for (i = 0; i < o->num_subsystems; i++)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.103 2012/07/10 02:19:15 djm Exp $ */
/* $OpenBSD: servconf.h,v 1.107 2013/01/03 05:49:36 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -28,6 +28,7 @@
#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */
#define MAX_MATCH_GROUPS 256 /* Max # of groups for Match. */
#define MAX_AUTHKEYS_FILES 256 /* Max # of authorized_keys files. */
#define MAX_AUTH_METHODS 256 /* Max # of AuthenticationMethods. */
/* permit_root_login */
#define PERMIT_NOT_SET -1
@ -41,6 +42,12 @@
#define PRIVSEP_ON 1
#define PRIVSEP_NOSANDBOX 2
/* AllowTCPForwarding */
#define FORWARD_DENY 0
#define FORWARD_REMOTE (1)
#define FORWARD_LOCAL (1<<1)
#define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL)
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */
@ -115,7 +122,7 @@ typedef struct {
int permit_user_env; /* If true, read ~/.ssh/environment */
int use_login; /* If true, login(1) is used */
int compression; /* If true, compression is allowed */
int allow_tcp_forwarding;
int allow_tcp_forwarding; /* One of FORWARD_* */
int allow_agent_forwarding;
u_int num_allow_users;
char *allow_users[MAX_ALLOW_USERS];
@ -164,8 +171,13 @@ typedef struct {
char *revoked_keys_file;
char *trusted_user_ca_keys;
char *authorized_principals_file;
char *authorized_keys_command;
char *authorized_keys_command_user;
char *version_addendum; /* Appended to SSH banner */
u_int num_auth_methods;
char *auth_methods[MAX_AUTH_METHODS];
} ServerOptions;
/* Information about the incoming connection as used by Match */
@ -189,12 +201,15 @@ struct connection_info {
M_CP_STROPT(trusted_user_ca_keys); \
M_CP_STROPT(revoked_keys_file); \
M_CP_STROPT(authorized_principals_file); \
M_CP_STROPT(authorized_keys_command); \
M_CP_STROPT(authorized_keys_command_user); \
M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
M_CP_STRARRAYOPT(allow_users, num_allow_users); \
M_CP_STRARRAYOPT(deny_users, num_deny_users); \
M_CP_STRARRAYOPT(allow_groups, num_allow_groups); \
M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
M_CP_STRARRAYOPT(accept_env, num_accept_env); \
M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
} while (0)
struct connection_info *get_connection_info(int, int);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: serverloop.c,v 1.162 2012/06/20 04:42:58 djm Exp $ */
/* $OpenBSD: serverloop.c,v 1.164 2012/12/07 01:51:35 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -676,7 +676,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
&nalloc, max_time_milliseconds);
if (received_sigterm) {
logit("Exiting on signal %d", received_sigterm);
logit("Exiting on signal %d", (int)received_sigterm);
/* Clean up sessions, utmp, etc. */
cleanup_exit(255);
}
@ -826,7 +826,7 @@ server_loop2(Authctxt *authctxt)
&nalloc, 0);
if (received_sigterm) {
logit("Exiting on signal %d", received_sigterm);
logit("Exiting on signal %d", (int)received_sigterm);
/* Clean up sessions, utmp, etc. */
cleanup_exit(255);
}
@ -918,7 +918,7 @@ server_input_window_size(int type, u_int32_t seq, void *ctxt)
static Channel *
server_request_direct_tcpip(void)
{
Channel *c;
Channel *c = NULL;
char *target, *originator;
u_short target_port, originator_port;
@ -931,9 +931,16 @@ server_request_direct_tcpip(void)
debug("server_request_direct_tcpip: originator %s port %d, target %s "
"port %d", originator, originator_port, target, target_port);
/* XXX check permission */
c = channel_connect_to(target, target_port,
"direct-tcpip", "direct-tcpip");
/* XXX fine grained permissions */
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag) {
c = channel_connect_to(target, target_port,
"direct-tcpip", "direct-tcpip");
} else {
logit("refused local port forward: "
"originator %s port %d, target %s port %d",
originator, originator_port, target, target_port);
}
xfree(originator);
xfree(target);
@ -1089,7 +1096,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
listen_address, listen_port);
/* check permissions */
if (!options.allow_tcp_forwarding ||
if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
no_port_forwarding_flag ||
(!want_reply && listen_port == 0) ||
(listen_port != 0 && listen_port < IPPORT_RESERVED &&

View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.260 2012/03/15 03:10:27 guenther Exp $ */
/* $OpenBSD: session.c,v 1.261 2012/12/02 20:46:11 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -256,7 +256,10 @@ do_authenticated(Authctxt *authctxt)
setproctitle("%s", authctxt->pw->pw_name);
/* setup the channel layer */
if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
if (no_port_forwarding_flag ||
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
channel_disable_adm_local_opens();
else
channel_permit_all_opens();
auth_debug_send();
@ -366,7 +369,7 @@ do_authenticated1(Authctxt *authctxt)
debug("Port forwarding not permitted for this authentication.");
break;
}
if (!options.allow_tcp_forwarding) {
if (!(options.allow_tcp_forwarding & FORWARD_REMOTE)) {
debug("Port forwarding not permitted.");
break;
}

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: sftp-server.8,v 1.19 2010/01/09 03:36:00 jmc Exp $
.\" $OpenBSD: sftp-server.8,v 1.21 2013/01/04 19:26:38 jmc Exp $
.\"
.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
.\"
@ -22,7 +22,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: January 9 2010 $
.Dd $Mdocdate: January 4 2013 $
.Dt SFTP-SERVER 8
.Os
.Sh NAME
@ -31,6 +31,7 @@
.Sh SYNOPSIS
.Nm sftp-server
.Op Fl ehR
.Op Fl d Ar start_directory
.Op Fl f Ar log_facility
.Op Fl l Ar log_level
.Op Fl u Ar umask
@ -56,6 +57,17 @@ for more information.
.Pp
Valid options are:
.Bl -tag -width Ds
.It Fl d Ar start_directory
specifies an alternate starting directory for users.
The pathname may contain the following tokens that are expanded at runtime:
%% is replaced by a literal '%',
%h is replaced by the home directory of the user being authenticated,
and %u is replaced by the username of that user.
The default is to use the user's home directory.
This option is useful in conjunction with the
.Xr sshd_config 5
.Cm ChrootDirectory
option.
.It Fl e
Causes
.Nm

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-server.c,v 1.94 2011/06/17 21:46:16 djm Exp $ */
/* $OpenBSD: sftp-server.c,v 1.96 2013/01/04 19:26:38 jmc Exp $ */
/*
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
*
@ -1362,7 +1362,8 @@ sftp_server_usage(void)
extern char *__progname;
fprintf(stderr,
"usage: %s [-ehR] [-f log_facility] [-l log_level] [-u umask]\n",
"usage: %s [-ehR] [-d start_directory] [-f log_facility] "
"[-l log_level]\n\t[-u umask]\n",
__progname);
exit(1);
}
@ -1374,7 +1375,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
int in, out, max, ch, skipargs = 0, log_stderr = 0;
ssize_t len, olen, set_size;
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
char *cp, buf[4*4096];
char *cp, *homedir = NULL, buf[4*4096];
long mask;
extern char *optarg;
@ -1382,7 +1383,9 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
log_init(__progname, log_level, log_facility, log_stderr);
while (!skipargs && (ch = getopt(argc, argv, "f:l:u:cehR")) != -1) {
pw = pwcopy(user_pw);
while (!skipargs && (ch = getopt(argc, argv, "d:f:l:u:cehR")) != -1) {
switch (ch) {
case 'R':
readonly = 1;
@ -1407,6 +1410,12 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
if (log_facility == SYSLOG_FACILITY_NOT_SET)
error("Invalid log facility \"%s\"", optarg);
break;
case 'd':
cp = tilde_expand_filename(optarg, user_pw->pw_uid);
homedir = percent_expand(cp, "d", user_pw->pw_dir,
"u", user_pw->pw_name, (char *)NULL);
free(cp);
break;
case 'u':
errno = 0;
mask = strtol(optarg, &cp, 8);
@ -1434,8 +1443,6 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
} else
client_addr = xstrdup("UNKNOWN");
pw = pwcopy(user_pw);
logit("session opened for local user %s from [%s]",
pw->pw_name, client_addr);
@ -1455,6 +1462,13 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
rset = (fd_set *)xmalloc(set_size);
wset = (fd_set *)xmalloc(set_size);
if (homedir != NULL) {
if (chdir(homedir) != 0) {
error("chdir to \"%s\" failed: %s", homedir,
strerror(errno));
}
}
for (;;) {
memset(rset, 0, set_size);
memset(wset, 0, set_size);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp.c,v 1.136 2012/06/22 14:36:33 dtucker Exp $ */
/* $OpenBSD: sftp.c,v 1.142 2013/02/08 00:41:12 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@ -968,6 +968,10 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
state = MA_START;
i = j = 0;
for (;;) {
if ((size_t)argc >= sizeof(argv) / sizeof(*argv)){
error("Too many arguments.");
return NULL;
}
if (isspace(arg[i])) {
if (state == MA_UNQUOTED) {
/* Terminate current argument */
@ -1118,7 +1122,7 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
/* Figure out which command we have */
for (i = 0; cmds[i].c != NULL; i++) {
if (strcasecmp(cmds[i].c, argv[0]) == 0)
if (argv[0] != NULL && strcasecmp(cmds[i].c, argv[0]) == 0)
break;
}
cmdnum = cmds[i].n;
@ -1671,7 +1675,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
{
glob_t g;
char *tmp, *tmp2, ins[3];
u_int i, hadglob, pwdlen, len, tmplen, filelen;
u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs;
const LineInfo *lf;
/* Glob from "file" location */
@ -1680,6 +1684,9 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
else
xasprintf(&tmp, "%s*", file);
/* Check if the path is absolute. */
isabs = tmp[0] == '/';
memset(&g, 0, sizeof(g));
if (remote != LOCAL) {
tmp = make_absolute(tmp, remote_path);
@ -1714,7 +1721,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
goto out;
tmp2 = complete_ambiguous(file, g.gl_pathv, g.gl_matchc);
tmp = path_strip(tmp2, remote_path);
tmp = path_strip(tmp2, isabs ? NULL : remote_path);
xfree(tmp2);
if (tmp == NULL)
@ -1723,8 +1730,18 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
tmplen = strlen(tmp);
filelen = strlen(file);
if (tmplen > filelen) {
tmp2 = tmp + filelen;
/* Count the number of escaped characters in the input string. */
cesc = isesc = 0;
for (i = 0; i < filelen; i++) {
if (!isesc && file[i] == '\\' && i + 1 < filelen){
isesc = 1;
cesc++;
} else
isesc = 0;
}
if (tmplen > (filelen - cesc)) {
tmp2 = tmp + filelen - cesc;
len = strlen(tmp2);
/* quote argument on way out */
for (i = 0; i < len; i++) {
@ -1738,6 +1755,8 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
case '\t':
case '[':
case ' ':
case '#':
case '*':
if (quote == '\0' || tmp2[i] == quote) {
if (el_insertstr(el, ins) == -1)
fatal("el_insertstr "
@ -1890,6 +1909,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
return (-1);
}
} else {
/* XXX this is wrong wrt quoting */
if (file2 == NULL)
snprintf(cmd, sizeof cmd, "get %s", dir);
else

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-add.1,v 1.56 2011/10/18 05:00:48 djm Exp $
.\" $OpenBSD: ssh-add.1,v 1.58 2012/12/03 08:33:02 jmc Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: October 18 2011 $
.Dd $Mdocdate: December 3 2012 $
.Dt SSH-ADD 1
.Os
.Sh NAME
@ -98,10 +98,10 @@ Deletes all identities from the agent.
Instead of adding identities, removes identities from the agent.
If
.Nm
has been run without arguments, the keys for the default identities will
be removed.
has been run without arguments, the keys for the default identities and
their corresponding certificates will be removed.
Otherwise, the argument list will be interpreted as a list of paths to
public key files and matching keys will be removed from the agent.
public key files to specify keys and certificates to be removed from the agent.
If no public key is found at a given path,
.Nm
will append
@ -111,8 +111,8 @@ and retry.
Remove keys provided by the PKCS#11 shared library
.Ar pkcs11 .
.It Fl k
When loading keys into the agent, load plain private keys only and skip
certificates.
When loading keys into or deleting keys from the agent, process plain private
keys only and skip certificates.
.It Fl L
Lists public key parameters of all identities currently represented
by the agent.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-add.c,v 1.103 2011/10/18 23:37:42 djm Exp $ */
/* $OpenBSD: ssh-add.c,v 1.105 2012/12/05 15:42:52 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -90,10 +90,10 @@ clear_pass(void)
}
static int
delete_file(AuthenticationConnection *ac, const char *filename)
delete_file(AuthenticationConnection *ac, const char *filename, int key_only)
{
Key *public;
char *comment = NULL;
Key *public = NULL, *cert = NULL;
char *certpath = NULL, *comment = NULL;
int ret = -1;
public = key_load_public(filename, &comment);
@ -107,8 +107,33 @@ delete_file(AuthenticationConnection *ac, const char *filename)
} else
fprintf(stderr, "Could not remove identity: %s\n", filename);
key_free(public);
xfree(comment);
if (key_only)
goto out;
/* Now try to delete the corresponding certificate too */
free(comment);
comment = NULL;
xasprintf(&certpath, "%s-cert.pub", filename);
if ((cert = key_load_public(certpath, &comment)) == NULL)
goto out;
if (!key_equal_public(cert, public))
fatal("Certificate %s does not match private key %s",
certpath, filename);
if (ssh_remove_identity(ac, cert)) {
fprintf(stderr, "Identity removed: %s (%s)\n", certpath,
comment);
ret = 0;
} else
fprintf(stderr, "Could not remove identity: %s\n", certpath);
out:
if (cert != NULL)
key_free(cert);
if (public != NULL)
key_free(public);
free(certpath);
free(comment);
return ret;
}
@ -348,7 +373,7 @@ static int
do_file(AuthenticationConnection *ac, int deleting, int key_only, char *file)
{
if (deleting) {
if (delete_file(ac, file) == -1)
if (delete_file(ac, file, key_only) == -1)
return -1;
} else {
if (add_file(ac, file, key_only) == -1)

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-keygen.1,v 1.109 2012/07/06 00:41:59 dtucker Exp $
.\" $OpenBSD: ssh-keygen.1,v 1.115 2013/01/19 07:13:25 jmc Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: July 6 2012 $
.Dd $Mdocdate: January 19 2013 $
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
@ -122,6 +122,17 @@
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl A
.Nm ssh-keygen
.Fl k
.Fl f Ar krl_file
.Op Fl u
.Op Fl s Ar ca_public
.Op Fl z Ar version_number
.Ar
.Nm ssh-keygen
.Fl Q
.Fl f Ar krl_file
.Ar
.Ek
.Sh DESCRIPTION
.Nm
@ -144,6 +155,14 @@ See the
.Sx MODULI GENERATION
section for details.
.Pp
Finally,
.Nm
can be used to generate and update Key Revocation Lists, and to test whether
given keys have been revoked by one.
See the
.Sx KEY REVOCATION LISTS
section for details.
.Pp
Normally each user wishing to use SSH
with public key authentication runs this once to create the authentication
key in
@ -321,6 +340,17 @@ This option allows importing keys from other software, including several
commercial SSH implementations.
The default import format is
.Dq RFC4716 .
.It Fl k
Generate a KRL file.
In this mode,
.Nm
will generate a KRL file at the location specified via the
.Fl f
flag that revokes every key or certificate presented on the command line.
Keys/certificates to be revoked may be specified by public key file or
using the format described in the
.Sx KEY REVOCATION LISTS
section.
.It Fl L
Prints the contents of a certificate.
.It Fl l
@ -425,6 +455,8 @@ creating a new private key.
The program will prompt for the file
containing the private key, for the old passphrase, and twice for the
new passphrase.
.It Fl Q
Test whether keys have been revoked in a KRL.
.It Fl q
Silence
.Nm ssh-keygen .
@ -448,6 +480,14 @@ Certify (sign) a public key using the specified CA key.
Please see the
.Sx CERTIFICATES
section for details.
.Pp
When generating a KRL,
.Fl s
specifies a path to a CA public key file used to revoke certificates directly
by key ID or serial number.
See the
.Sx KEY REVOCATION LISTS
section for details.
.It Fl T Ar output_file
Test DH group exchange candidate primes (generated using the
.Fl G
@ -462,6 +502,12 @@ for protocol version 1 and
or
.Dq rsa
for protocol version 2.
.It Fl u
Update a KRL.
When specified with
.Fl k ,
keys listed via the command line are added to the existing KRL rather than
a new KRL being created.
.It Fl V Ar validity_interval
Specify a validity interval when signing a certificate.
A validity interval may consist of a single time, indicating that the
@ -504,6 +550,10 @@ OpenSSH format file and print an OpenSSH public key to stdout.
Specifies a serial number to be embedded in the certificate to distinguish
this certificate from others from the same CA.
The default serial number is zero.
.Pp
When generating a KRL, the
.Fl z
flag is used to specify a KRL version number.
.El
.Sh MODULI GENERATION
.Nm
@ -628,7 +678,9 @@ The
option allows specification of certificate start and end times.
A certificate that is presented at a time outside this range will not be
considered valid.
By default, certificates have a maximum validity interval.
By default, certificates are valid from
.Ux
Epoch to the distant future.
.Pp
For certificates to be used for user or host authentication, the CA
public key must be trusted by
@ -636,6 +688,73 @@ public key must be trusted by
or
.Xr ssh 1 .
Please refer to those manual pages for details.
.Sh KEY REVOCATION LISTS
.Nm
is able to manage OpenSSH format Key Revocation Lists (KRLs).
These binary files specify keys or certificates to be revoked using a
compact format, taking as little a one bit per certificate if they are being
revoked by serial number.
.Pp
KRLs may be generated using the
.Fl k
flag.
This option reads one or more files from the command line and generates a new
KRL.
The files may either contain a KRL specification (see below) or public keys,
listed one per line.
Plain public keys are revoked by listing their hash or contents in the KRL and
certificates revoked by serial number or key ID (if the serial is zero or
not available).
.Pp
Revoking keys using a KRL specification offers explicit control over the
types of record used to revoke keys and may be used to directly revoke
certificates by serial number or key ID without having the complete original
certificate on hand.
A KRL specification consists of lines containing one of the following directives
followed by a colon and some directive-specific information.
.Bl -tag -width Ds
.It Cm serial : Ar serial_number Ns Op - Ns Ar serial_number
Revokes a certificate with the specified serial number.
Serial numbers are 64-bit values, not including zero and may be expressed
in decimal, hex or octal.
If two serial numbers are specified separated by a hyphen, then the range
of serial numbers including and between each is revoked.
The CA key must have been specified on the
.Nm
command line using the
.Fl s
option.
.It Cm id : Ar key_id
Revokes a certificate with the specified key ID string.
The CA key must have been specified on the
.Nm
command line using the
.Fl s
option.
.It Cm key : Ar public_key
Revokes the specified key.
If a certificate is listed, then it is revoked as a plain public key.
.It Cm sha1 : Ar public_key
Revokes the specified key by its SHA1 hash.
.El
.Pp
KRLs may be updated using the
.Fl u
flag in addition to
.Fl k .
When this option is specified, keys listed via the command line are merged into
the KRL, adding to those already there.
.Pp
It is also possible, given a KRL, to test whether it revokes a particular key
(or keys).
The
.Fl Q
flag will query an existing KRL, testing each key specified on the commandline.
If any key listed on the command line has been revoked (or an error encountered)
then
.Nm
will exit with a non-zero exit status.
A zero exit status will only be returned if no key was revoked.
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.ssh/identity

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keygen.c,v 1.216 2012/07/06 06:38:03 jmc Exp $ */
/* $OpenBSD: ssh-keygen.c,v 1.225 2013/02/10 23:32:10 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -40,7 +40,10 @@
#include "match.h"
#include "hostfile.h"
#include "dns.h"
#include "ssh.h"
#include "ssh2.h"
#include "atomicio.h"
#include "krl.h"
#ifdef ENABLE_PKCS11
#include "ssh-pkcs11.h"
@ -99,7 +102,7 @@ char *identity_comment = NULL;
char *ca_key_path = NULL;
/* Certificate serial number */
long long cert_serial = 0;
unsigned long long cert_serial = 0;
/* Key type when certifying */
u_int cert_key_type = SSH2_CERT_TYPE_USER;
@ -710,15 +713,33 @@ do_download(struct passwd *pw)
#ifdef ENABLE_PKCS11
Key **keys = NULL;
int i, nkeys;
enum fp_rep rep;
enum fp_type fptype;
char *fp, *ra;
fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
pkcs11_init(0);
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
if (nkeys <= 0)
fatal("cannot read public key from pkcs11");
for (i = 0; i < nkeys; i++) {
key_write(keys[i], stdout);
if (print_fingerprint) {
fp = key_fingerprint(keys[i], fptype, rep);
ra = key_fingerprint(keys[i], SSH_FP_MD5,
SSH_FP_RANDOMART);
printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]),
fp, key_type(keys[i]));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
xfree(ra);
xfree(fp);
} else {
key_write(keys[i], stdout);
fprintf(stdout, "\n");
}
key_free(keys[i]);
fprintf(stdout, "\n");
}
xfree(keys);
pkcs11_terminate();
@ -1073,8 +1094,14 @@ do_known_hosts(struct passwd *pw, const char *name)
ca ? " (CA key)" : "");
printhost(out, cp, pub, ca, 0);
}
if (delete_host && !c && !ca)
printhost(out, cp, pub, ca, 0);
if (delete_host) {
if (!c && !ca)
printhost(out, cp, pub, ca, 0);
else
printf("# Host %s found: "
"line %d type %s\n", name,
num, key_type(pub));
}
} else if (hash_hosts)
printhost(out, cp, pub, ca, 0);
} else {
@ -1089,8 +1116,14 @@ do_known_hosts(struct passwd *pw, const char *name)
printhost(out, name, pub,
ca, hash_hosts && !ca);
}
if (delete_host && !c && !ca)
printhost(out, cp, pub, ca, 0);
if (delete_host) {
if (!c && !ca)
printhost(out, cp, pub, ca, 0);
else
printf("# Host %s found: "
"line %d type %s\n", name,
num, key_type(pub));
}
} else if (hash_hosts) {
for (cp2 = strsep(&cp, ",");
cp2 != NULL && *cp2 != '\0';
@ -1851,6 +1884,226 @@ do_show_cert(struct passwd *pw)
exit(0);
}
static void
load_krl(const char *path, struct ssh_krl **krlp)
{
Buffer krlbuf;
int fd;
buffer_init(&krlbuf);
if ((fd = open(path, O_RDONLY)) == -1)
fatal("open %s: %s", path, strerror(errno));
if (!key_load_file(fd, path, &krlbuf))
fatal("Unable to load KRL");
close(fd);
/* XXX check sigs */
if (ssh_krl_from_blob(&krlbuf, krlp, NULL, 0) != 0 ||
*krlp == NULL)
fatal("Invalid KRL file");
buffer_free(&krlbuf);
}
static void
update_krl_from_file(struct passwd *pw, const char *file, const Key *ca,
struct ssh_krl *krl)
{
Key *key = NULL;
u_long lnum = 0;
char *path, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES];
unsigned long long serial, serial2;
int i, was_explicit_key, was_sha1, r;
FILE *krl_spec;
path = tilde_expand_filename(file, pw->pw_uid);
if (strcmp(path, "-") == 0) {
krl_spec = stdin;
free(path);
path = xstrdup("(standard input)");
} else if ((krl_spec = fopen(path, "r")) == NULL)
fatal("fopen %s: %s", path, strerror(errno));
if (!quiet)
printf("Revoking from %s\n", path);
while (read_keyfile_line(krl_spec, path, line, sizeof(line),
&lnum) == 0) {
was_explicit_key = was_sha1 = 0;
cp = line + strspn(line, " \t");
/* Trim trailing space, comments and strip \n */
for (i = 0, r = -1; cp[i] != '\0'; i++) {
if (cp[i] == '#' || cp[i] == '\n') {
cp[i] = '\0';
break;
}
if (cp[i] == ' ' || cp[i] == '\t') {
/* Remember the start of a span of whitespace */
if (r == -1)
r = i;
} else
r = -1;
}
if (r != -1)
cp[r] = '\0';
if (*cp == '\0')
continue;
if (strncasecmp(cp, "serial:", 7) == 0) {
if (ca == NULL) {
fatal("revoking certificated by serial number "
"requires specification of a CA key");
}
cp += 7;
cp = cp + strspn(cp, " \t");
errno = 0;
serial = strtoull(cp, &ep, 0);
if (*cp == '\0' || (*ep != '\0' && *ep != '-'))
fatal("%s:%lu: invalid serial \"%s\"",
path, lnum, cp);
if (errno == ERANGE && serial == ULLONG_MAX)
fatal("%s:%lu: serial out of range",
path, lnum);
serial2 = serial;
if (*ep == '-') {
cp = ep + 1;
errno = 0;
serial2 = strtoull(cp, &ep, 0);
if (*cp == '\0' || *ep != '\0')
fatal("%s:%lu: invalid serial \"%s\"",
path, lnum, cp);
if (errno == ERANGE && serial2 == ULLONG_MAX)
fatal("%s:%lu: serial out of range",
path, lnum);
if (serial2 <= serial)
fatal("%s:%lu: invalid serial range "
"%llu:%llu", path, lnum,
(unsigned long long)serial,
(unsigned long long)serial2);
}
if (ssh_krl_revoke_cert_by_serial_range(krl,
ca, serial, serial2) != 0) {
fatal("%s: revoke serial failed",
__func__);
}
} else if (strncasecmp(cp, "id:", 3) == 0) {
if (ca == NULL) {
fatal("revoking certificated by key ID "
"requires specification of a CA key");
}
cp += 3;
cp = cp + strspn(cp, " \t");
if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
fatal("%s: revoke key ID failed", __func__);
} else {
if (strncasecmp(cp, "key:", 4) == 0) {
cp += 4;
cp = cp + strspn(cp, " \t");
was_explicit_key = 1;
} else if (strncasecmp(cp, "sha1:", 5) == 0) {
cp += 5;
cp = cp + strspn(cp, " \t");
was_sha1 = 1;
} else {
/*
* Just try to process the line as a key.
* Parsing will fail if it isn't.
*/
}
if ((key = key_new(KEY_UNSPEC)) == NULL)
fatal("key_new");
if (key_read(key, &cp) != 1)
fatal("%s:%lu: invalid key", path, lnum);
if (was_explicit_key)
r = ssh_krl_revoke_key_explicit(krl, key);
else if (was_sha1)
r = ssh_krl_revoke_key_sha1(krl, key);
else
r = ssh_krl_revoke_key(krl, key);
if (r != 0)
fatal("%s: revoke key failed", __func__);
key_free(key);
}
}
if (strcmp(path, "-") != 0)
fclose(krl_spec);
}
static void
do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
{
struct ssh_krl *krl;
struct stat sb;
Key *ca = NULL;
int fd, i;
char *tmp;
Buffer kbuf;
if (*identity_file == '\0')
fatal("KRL generation requires an output file");
if (stat(identity_file, &sb) == -1) {
if (errno != ENOENT)
fatal("Cannot access KRL \"%s\": %s",
identity_file, strerror(errno));
if (updating)
fatal("KRL \"%s\" does not exist", identity_file);
}
if (ca_key_path != NULL) {
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
if ((ca = key_load_public(tmp, NULL)) == NULL)
fatal("Cannot load CA public key %s", tmp);
xfree(tmp);
}
if (updating)
load_krl(identity_file, &krl);
else if ((krl = ssh_krl_init()) == NULL)
fatal("couldn't create KRL");
if (cert_serial != 0)
ssh_krl_set_version(krl, cert_serial);
if (identity_comment != NULL)
ssh_krl_set_comment(krl, identity_comment);
for (i = 0; i < argc; i++)
update_krl_from_file(pw, argv[i], ca, krl);
buffer_init(&kbuf);
if (ssh_krl_to_blob(krl, &kbuf, NULL, 0) != 0)
fatal("Couldn't generate KRL");
if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
fatal("open %s: %s", identity_file, strerror(errno));
if (atomicio(vwrite, fd, buffer_ptr(&kbuf), buffer_len(&kbuf)) !=
buffer_len(&kbuf))
fatal("write %s: %s", identity_file, strerror(errno));
close(fd);
buffer_free(&kbuf);
ssh_krl_free(krl);
}
static void
do_check_krl(struct passwd *pw, int argc, char **argv)
{
int i, r, ret = 0;
char *comment;
struct ssh_krl *krl;
Key *k;
if (*identity_file == '\0')
fatal("KRL checking requires an input file");
load_krl(identity_file, &krl);
for (i = 0; i < argc; i++) {
if ((k = key_load_public(argv[i], &comment)) == NULL)
fatal("Cannot load public key %s", argv[i]);
r = ssh_krl_check_key(krl, k);
printf("%s%s%s%s: %s\n", argv[i],
*comment ? " (" : "", comment, *comment ? ")" : "",
r == 0 ? "ok" : "REVOKED");
if (r != 0)
ret = 1;
key_free(k);
free(comment);
}
ssh_krl_free(krl);
exit(ret);
}
static void
usage(void)
{
@ -1877,6 +2130,7 @@ usage(void)
fprintf(stderr, " -J number Screen this number of moduli lines.\n");
fprintf(stderr, " -j number Start screening moduli at specified line.\n");
fprintf(stderr, " -K checkpt Write checkpoints to this file.\n");
fprintf(stderr, " -k Generate a KRL file.\n");
fprintf(stderr, " -L Print the contents of a certificate.\n");
fprintf(stderr, " -l Show fingerprint of key file.\n");
fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
@ -1886,6 +2140,7 @@ usage(void)
fprintf(stderr, " -O option Specify a certificate option.\n");
fprintf(stderr, " -P phrase Provide old passphrase.\n");
fprintf(stderr, " -p Change passphrase of private key file.\n");
fprintf(stderr, " -Q Test whether key(s) are revoked in KRL.\n");
fprintf(stderr, " -q Quiet.\n");
fprintf(stderr, " -R hostname Remove host from known_hosts file.\n");
fprintf(stderr, " -r hostname Print DNS resource record.\n");
@ -1893,6 +2148,7 @@ usage(void)
fprintf(stderr, " -s ca_key Certify keys with CA key.\n");
fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n");
fprintf(stderr, " -t type Specify type of key to create.\n");
fprintf(stderr, " -u Update KRL rather than creating a new one.\n");
fprintf(stderr, " -V from:to Specify certificate validity interval.\n");
fprintf(stderr, " -v Verbose.\n");
fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
@ -1910,14 +2166,14 @@ main(int argc, char **argv)
{
char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
char *checkpoint = NULL;
char out_file[MAXPATHLEN], *rr_hostname = NULL;
char out_file[MAXPATHLEN], *ep, *rr_hostname = NULL;
Key *private, *public;
struct passwd *pw;
struct stat st;
int opt, type, fd;
u_int32_t memory = 0, generator_wanted = 0, trials = 100;
int do_gen_candidates = 0, do_screen_candidates = 0;
int gen_all_hostkeys = 0;
int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
unsigned long start_lineno = 0, lines_to_process = 0;
BIGNUM *start = NULL;
FILE *f;
@ -1943,8 +2199,8 @@ main(int argc, char **argv)
exit(1);
}
while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:J:j:K:P:"
"m:N:n:O:C:r:g:R:T:G:M:S:s:a:V:W:z")) != -1) {
while ((opt = getopt(argc, argv, "ABHLQXceghiklpquvxy"
"C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
switch (opt) {
case 'A':
gen_all_hostkeys = 1;
@ -2023,6 +2279,9 @@ main(int argc, char **argv)
case 'N':
identity_new_passphrase = optarg;
break;
case 'Q':
check_krl = 1;
break;
case 'O':
add_cert_option(optarg);
break;
@ -2041,6 +2300,9 @@ main(int argc, char **argv)
cert_key_type = SSH2_CERT_TYPE_HOST;
certflags_flags = 0;
break;
case 'k':
gen_krl = 1;
break;
case 'i':
case 'X':
/* import key */
@ -2058,6 +2320,9 @@ main(int argc, char **argv)
case 'D':
pkcs11provider = optarg;
break;
case 'u':
update_krl = 1;
break;
case 'v':
if (log_level == SYSLOG_LEVEL_INFO)
log_level = SYSLOG_LEVEL_DEBUG1;
@ -2114,9 +2379,11 @@ main(int argc, char **argv)
parse_cert_times(optarg);
break;
case 'z':
cert_serial = strtonum(optarg, 0, LLONG_MAX, &errstr);
if (errstr)
fatal("Invalid serial number: %s", errstr);
errno = 0;
cert_serial = strtoull(optarg, &ep, 10);
if (*optarg < '0' || *optarg > '9' || *ep != '\0' ||
(errno == ERANGE && cert_serial == ULLONG_MAX))
fatal("Invalid serial number \"%s\"", optarg);
break;
case '?':
default:
@ -2131,11 +2398,11 @@ main(int argc, char **argv)
argc -= optind;
if (ca_key_path != NULL) {
if (argc < 1) {
if (argc < 1 && !gen_krl) {
printf("Too few arguments.\n");
usage();
}
} else if (argc > 0) {
} else if (argc > 0 && !gen_krl && !check_krl) {
printf("Too many arguments.\n");
usage();
}
@ -2144,9 +2411,17 @@ main(int argc, char **argv)
usage();
}
if (print_fingerprint && (delete_host || hash_hosts)) {
printf("Cannot use -l with -D or -R.\n");
printf("Cannot use -l with -H or -R.\n");
usage();
}
if (gen_krl) {
do_gen_krl(pw, update_krl, argc, argv);
return (0);
}
if (check_krl) {
do_check_krl(pw, argc, argv);
return (0);
}
if (ca_key_path != NULL) {
if (cert_key_id == NULL)
fatal("Must specify key id (-I) when certifying");
@ -2156,6 +2431,8 @@ main(int argc, char **argv)
do_show_cert(pw);
if (delete_host || hash_hosts || find_host)
do_known_hosts(pw, rr_hostname);
if (pkcs11provider != NULL)
do_download(pw);
if (print_fingerprint || print_bubblebabble)
do_fingerprint(pw);
if (change_passphrase)
@ -2193,8 +2470,6 @@ main(int argc, char **argv)
exit(0);
}
}
if (pkcs11provider != NULL)
do_download(pw);
if (do_gen_candidates) {
FILE *out = fopen(out_file, "w");
@ -2214,7 +2489,7 @@ main(int argc, char **argv)
if (do_screen_candidates) {
FILE *in;
FILE *out = fopen(out_file, "w");
FILE *out = fopen(out_file, "a");
if (have_identity && strcmp(identity_file, "-") != 0) {
if ((in = fopen(identity_file, "r")) == NULL) {

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh.1,v 1.326 2012/06/18 12:17:18 dtucker Exp $
.Dd $Mdocdate: June 18 2012 $
.\" $OpenBSD: ssh.1,v 1.330 2012/10/04 13:21:50 markus Exp $
.Dd $Mdocdate: October 4 2012 $
.Dt SSH 1
.Os
.Sh NAME
@ -674,7 +674,7 @@ it provides additional mechanisms for confidentiality
(the traffic is encrypted using AES, 3DES, Blowfish, CAST128, or Arcfour)
and integrity (hmac-md5, hmac-sha1,
hmac-sha2-256, hmac-sha2-512,
umac-64, hmac-ripemd160).
umac-64, umac-128, hmac-ripemd160).
Protocol 1 lacks a strong mechanism for ensuring the
integrity of the connection.
.Pp
@ -926,6 +926,14 @@ option.
.It Cm ~R
Request rekeying of the connection
(only useful for SSH protocol version 2 and if the peer supports it).
.It Cm ~V
Decrease the verbosity
.Pq Ic LogLevel
when errors are being written to stderr.
.It Cm ~v
Increase the verbosity
.Pq Ic LogLevel
when errors are being written to stderr.
.El
.Sh TCP FORWARDING
Forwarding of arbitrary TCP connections over the secure channel can
@ -1426,77 +1434,118 @@ if an error occurred.
.Xr ssh_config 5 ,
.Xr ssh-keysign 8 ,
.Xr sshd 8
.Sh STANDARDS
.Rs
.%A S. Lehtinen
.%A C. Lonvick
.%D January 2006
.%R RFC 4250
.%T "The Secure Shell (SSH) Protocol Assigned Numbers"
.%D 2006
.%T The Secure Shell (SSH) Protocol Assigned Numbers
.Re
.Pp
.Rs
.%A T. Ylonen
.%A C. Lonvick
.%D January 2006
.%R RFC 4251
.%T "The Secure Shell (SSH) Protocol Architecture"
.%D 2006
.%T The Secure Shell (SSH) Protocol Architecture
.Re
.Pp
.Rs
.%A T. Ylonen
.%A C. Lonvick
.%D January 2006
.%R RFC 4252
.%T "The Secure Shell (SSH) Authentication Protocol"
.%D 2006
.%T The Secure Shell (SSH) Authentication Protocol
.Re
.Pp
.Rs
.%A T. Ylonen
.%A C. Lonvick
.%D January 2006
.%R RFC 4253
.%T "The Secure Shell (SSH) Transport Layer Protocol"
.%D 2006
.%T The Secure Shell (SSH) Transport Layer Protocol
.Re
.Pp
.Rs
.%A T. Ylonen
.%A C. Lonvick
.%D January 2006
.%R RFC 4254
.%T "The Secure Shell (SSH) Connection Protocol"
.%D 2006
.%T The Secure Shell (SSH) Connection Protocol
.Re
.Pp
.Rs
.%A J. Schlyter
.%A W. Griffin
.%D January 2006
.%R RFC 4255
.%T "Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints"
.%D 2006
.%T Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
.Re
.Pp
.Rs
.%A F. Cusack
.%A M. Forssen
.%D January 2006
.%R RFC 4256
.%T "Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)"
.%D 2006
.%T Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)
.Re
.Pp
.Rs
.%A J. Galbraith
.%A P. Remaker
.%D January 2006
.%R RFC 4335
.%T "The Secure Shell (SSH) Session Channel Break Extension"
.%D 2006
.%T The Secure Shell (SSH) Session Channel Break Extension
.Re
.Pp
.Rs
.%A M. Bellare
.%A T. Kohno
.%A C. Namprempre
.%D January 2006
.%R RFC 4344
.%T "The Secure Shell (SSH) Transport Layer Encryption Modes"
.%D 2006
.%T The Secure Shell (SSH) Transport Layer Encryption Modes
.Re
.Pp
.Rs
.%A B. Harris
.%D January 2006
.%R RFC 4345
.%T "Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol"
.%D 2006
.%T Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol
.Re
.Pp
.Rs
.%A M. Friedl
.%A N. Provos
.%A W. Simpson
.%D March 2006
.%R RFC 4419
.%T "Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol"
.%D 2006
.%T Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol
.Re
.Pp
.Rs
.%A J. Galbraith
.%A R. Thayer
.%D November 2006
.%R RFC 4716
.%T "The Secure Shell (SSH) Public Key File Format"
.%D 2006
.%T The Secure Shell (SSH) Public Key File Format
.Re
.Pp
.Rs
.%A D. Stebila
.%A J. Green
.%D December 2009
.%R RFC 5656
.%T "Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer"
.%D 2009
.%T Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
.Re
.Pp
.Rs
.%T "Hash Visualization: a New Technique to improve Real-World Security"
.%A A. Perrig
.%A D. Song
.%D 1999
.%O "International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)"
.%O International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)
.%T Hash Visualization: a New Technique to improve Real-World Security
.Re
.Sh AUTHORS
OpenSSH is a derivative of the original and free

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh_config.5,v 1.157 2012/06/29 13:57:25 naddy Exp $
.Dd $Mdocdate: June 29 2012 $
.\" $OpenBSD: ssh_config.5,v 1.161 2013/01/08 18:49:04 markus Exp $
.Dd $Mdocdate: January 8 2013 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@ -204,6 +204,8 @@ The supported ciphers are
.Dq aes128-ctr ,
.Dq aes192-ctr ,
.Dq aes256-ctr ,
.Dq aes128-gcm@openssh.com ,
.Dq aes256-gcm@openssh.com ,
.Dq arcfour128 ,
.Dq arcfour256 ,
.Dq arcfour ,
@ -213,6 +215,7 @@ and
The default is:
.Bd -literal -offset 3n
aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
aes128-gcm@openssh.com,aes256-gcm@openssh.com,
aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
aes256-cbc,arcfour
.Ed
@ -602,6 +605,8 @@ should only use the authentication identity files configured in the
files,
even if
.Xr ssh-agent 1
or a
.Cm PKCS11Provider
offers more identities.
The argument to this keyword must be
.Dq yes
@ -790,9 +795,18 @@ in order of preference.
The MAC algorithm is used in protocol version 2
for data integrity protection.
Multiple algorithms must be comma-separated.
The algorithms that contain
.Dq -etm
calculate the MAC after encryption (encrypt-then-mac).
These are considered safer and their use recommended.
The default is:
.Bd -literal -offset indent
hmac-md5,hmac-sha1,umac-64@openssh.com,
hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
umac-64-etm@openssh.com,umac-128-etm@openssh.com,
hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,
hmac-md5-96-etm@openssh.com,
hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,
hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,
hmac-sha1-96,hmac-md5-96
.Ed

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.c,v 1.234 2011/05/24 07:15:47 djm Exp $ */
/* $OpenBSD: sshconnect.c,v 1.236 2012/09/14 16:51:34 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -419,6 +419,24 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
return 0;
}
static void
send_client_banner(int connection_out, int minor1)
{
/* Send our own protocol version identification. */
if (compat20) {
xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n",
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION);
} else {
xasprintf(&client_version_string, "SSH-%d.%d-%.100s\n",
PROTOCOL_MAJOR_1, minor1, SSH_VERSION);
}
if (roaming_atomicio(vwrite, connection_out, client_version_string,
strlen(client_version_string)) != strlen(client_version_string))
fatal("write: %.100s", strerror(errno));
chop(client_version_string);
debug("Local version string %.100s", client_version_string);
}
/*
* Waits for the server identification string, and sends our own
* identification string.
@ -430,7 +448,7 @@ ssh_exchange_identification(int timeout_ms)
int remote_major, remote_minor, mismatch;
int connection_in = packet_get_connection_in();
int connection_out = packet_get_connection_out();
int minor1 = PROTOCOL_MINOR_1;
int minor1 = PROTOCOL_MINOR_1, client_banner_sent = 0;
u_int i, n;
size_t len;
int fdsetsz, remaining, rc;
@ -440,6 +458,16 @@ ssh_exchange_identification(int timeout_ms)
fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
fdset = xcalloc(1, fdsetsz);
/*
* If we are SSH2-only then we can send the banner immediately and
* save a round-trip.
*/
if (options.protocol == SSH_PROTO_2) {
enable_compat20();
send_client_banner(connection_out, 0);
client_banner_sent = 1;
}
/* Read other side's version identification. */
remaining = timeout_ms;
for (n = 0;;) {
@ -542,18 +570,9 @@ ssh_exchange_identification(int timeout_ms)
fatal("Protocol major versions differ: %d vs. %d",
(options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
remote_major);
/* Send our own protocol version identification. */
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
compat20 ? PROTOCOL_MINOR_2 : minor1,
SSH_VERSION, compat20 ? "\r\n" : "\n");
if (roaming_atomicio(vwrite, connection_out, buf, strlen(buf))
!= strlen(buf))
fatal("write: %.100s", strerror(errno));
client_version_string = xstrdup(buf);
chop(client_version_string);
if (!client_banner_sent)
send_client_banner(connection_out, minor1);
chop(server_version_string);
debug("Local version string %.100s", client_version_string);
}
/* defaults to 'no' */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect2.c,v 1.189 2012/06/22 12:30:26 dtucker Exp $ */
/* $OpenBSD: sshconnect2.c,v 1.191 2013/02/15 00:21:01 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@ -242,6 +242,7 @@ struct identity {
char *filename; /* comment for agent-only keys */
int tried;
int isprivate; /* key points to the private key */
int userprovided;
};
TAILQ_HEAD(idlist, identity);
@ -306,7 +307,7 @@ void userauth(Authctxt *, char *);
static int sign_and_send_pubkey(Authctxt *, Identity *);
static void pubkey_prepare(Authctxt *);
static void pubkey_cleanup(Authctxt *);
static Key *load_identity_file(char *);
static Key *load_identity_file(char *, int);
static Authmethod *authmethod_get(char *authlist);
static Authmethod *authmethod_lookup(const char *name);
@ -1180,7 +1181,7 @@ identity_sign(Identity *id, u_char **sigp, u_int *lenp,
if (id->isprivate || (id->key->flags & KEY_FLAG_EXT))
return (key_sign(id->key, sigp, lenp, data, datalen));
/* load the private key from the file */
if ((prv = load_identity_file(id->filename)) == NULL)
if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL)
return (-1);
ret = key_sign(prv, sigp, lenp, data, datalen);
key_free(prv);
@ -1305,7 +1306,7 @@ send_pubkey_test(Authctxt *authctxt, Identity *id)
}
static Key *
load_identity_file(char *filename)
load_identity_file(char *filename, int userprovided)
{
Key *private;
char prompt[300], *passphrase;
@ -1313,7 +1314,8 @@ load_identity_file(char *filename)
struct stat st;
if (stat(filename, &st) < 0) {
debug3("no such identity: %s", filename);
(userprovided ? logit : debug3)("no such identity: %s: %s",
filename, strerror(errno));
return NULL;
}
private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok);
@ -1353,7 +1355,7 @@ load_identity_file(char *filename)
static void
pubkey_prepare(Authctxt *authctxt)
{
Identity *id;
Identity *id, *id2, *tmp;
Idlist agent, files, *preferred;
Key *key;
AuthenticationConnection *ac;
@ -1365,7 +1367,7 @@ pubkey_prepare(Authctxt *authctxt)
preferred = &authctxt->keys;
TAILQ_INIT(preferred); /* preferred order of keys */
/* list of keys stored in the filesystem */
/* list of keys stored in the filesystem and PKCS#11 */
for (i = 0; i < options.num_identity_files; i++) {
key = options.identity_keys[i];
if (key && key->type == KEY_RSA1)
@ -1376,8 +1378,32 @@ pubkey_prepare(Authctxt *authctxt)
id = xcalloc(1, sizeof(*id));
id->key = key;
id->filename = xstrdup(options.identity_files[i]);
id->userprovided = 1;
TAILQ_INSERT_TAIL(&files, id, next);
}
/* Prefer PKCS11 keys that are explicitly listed */
TAILQ_FOREACH_SAFE(id, &files, next, tmp) {
if (id->key == NULL || (id->key->flags & KEY_FLAG_EXT) == 0)
continue;
found = 0;
TAILQ_FOREACH(id2, &files, next) {
if (id2->key == NULL ||
(id2->key->flags & KEY_FLAG_EXT) != 0)
continue;
if (key_equal(id->key, id2->key)) {
TAILQ_REMOVE(&files, id, next);
TAILQ_INSERT_TAIL(preferred, id, next);
found = 1;
break;
}
}
/* If IdentitiesOnly set and key not found then don't use it */
if (!found && options.identities_only) {
TAILQ_REMOVE(&files, id, next);
bzero(id, sizeof(id));
free(id);
}
}
/* list of keys supported by the agent */
if ((ac = ssh_get_authentication_connection())) {
for (key = ssh_get_first_identity(ac, &comment, 2);
@ -1417,7 +1443,8 @@ pubkey_prepare(Authctxt *authctxt)
TAILQ_INSERT_TAIL(preferred, id, next);
}
TAILQ_FOREACH(id, preferred, next) {
debug2("key: %s (%p)", id->filename, id->key);
debug2("key: %s (%p),%s", id->filename, id->key,
id->userprovided ? " explicit" : "");
}
}
@ -1462,7 +1489,8 @@ userauth_pubkey(Authctxt *authctxt)
sent = send_pubkey_test(authctxt, id);
} else if (id->key == NULL) {
debug("Trying private key: %s", id->filename);
id->key = load_identity_file(id->filename);
id->key = load_identity_file(id->filename,
id->userprovided);
if (id->key != NULL) {
id->isprivate = 1;
sent = sign_and_send_pubkey(authctxt, id);

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: sshd.8,v 1.266 2012/06/18 12:07:07 dtucker Exp $
.Dd $Mdocdate: June 18 2012 $
.\" $OpenBSD: sshd.8,v 1.267 2012/10/04 13:21:50 markus Exp $
.Dd $Mdocdate: October 4 2012 $
.Dt SSHD 8
.Os
.Sh NAME
@ -316,7 +316,7 @@ The client selects the encryption algorithm
to use from those offered by the server.
Additionally, session integrity is provided
through a cryptographic message authentication code
(hmac-md5, hmac-sha1, umac-64, hmac-ripemd160,
(hmac-md5, hmac-sha1, umac-64, umac-128, hmac-ripemd160,
hmac-sha2-256 or hmac-sha2-512).
.Pp
Finally, the server and the client enter an authentication dialog.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.393 2012/07/10 02:19:15 djm Exp $ */
/* $OpenBSD: sshd.c,v 1.397 2013/02/11 21:21:58 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -339,6 +339,15 @@ grace_alarm_handler(int sig)
if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
kill(pmonitor->m_pid, SIGALRM);
/*
* Try to kill any processes that we have spawned, E.g. authorized
* keys command helpers.
*/
if (getpgid(0) == getpid()) {
signal(SIGTERM, SIG_IGN);
killpg(0, SIGTERM);
}
/* Log error and exit. */
sigdie("Timeout before authentication for %s", get_remote_ipaddr());
}
@ -1293,6 +1302,7 @@ main(int ac, char **av)
int remote_port;
char *line;
int config_s[2] = { -1 , -1 };
u_int n;
u_int64_t ibytes, obytes;
mode_t new_umask;
Key *key;
@ -1481,6 +1491,33 @@ main(int ac, char **av)
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
/* Check that options are sensible */
if (options.authorized_keys_command_user == NULL &&
(options.authorized_keys_command != NULL &&
strcasecmp(options.authorized_keys_command, "none") != 0))
fatal("AuthorizedKeysCommand set without "
"AuthorizedKeysCommandUser");
/*
* Check whether there is any path through configured auth methods.
* Unfortunately it is not possible to verify this generally before
* daemonisation in the presence of Match block, but this catches
* and warns for trivial misconfigurations that could break login.
*/
if (options.num_auth_methods != 0) {
if ((options.protocol & SSH_PROTO_1))
fatal("AuthenticationMethods is not supported with "
"SSH protocol 1");
for (n = 0; n < options.num_auth_methods; n++) {
if (auth2_methods_valid(options.auth_methods[n],
1) == 0)
break;
}
if (n >= options.num_auth_methods)
fatal("AuthenticationMethods cannot be satisfied by "
"enabled authentication methods");
}
/* set default channel AF */
channel_set_af(options.address_family);
@ -1490,7 +1527,8 @@ main(int ac, char **av)
exit(1);
}
debug("sshd version %.100s", SSH_VERSION);
debug("sshd version %s, %s", SSH_VERSION,
SSLeay_version(SSLEAY_VERSION));
/* load private host keys */
sensitive_data.host_keys = xcalloc(options.num_host_key_files,

View File

@ -1,4 +1,4 @@
# $OpenBSD: sshd_config,v 1.87 2012/07/10 02:19:15 djm Exp $
# $OpenBSD: sshd_config,v 1.89 2013/02/06 00:20:42 dtucker Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
@ -49,6 +49,9 @@ AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
@ -93,7 +96,7 @@ UsePrivilegeSeparation sandbox # Default for new installations.
#ClientAliveCountMax 3
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: sshd_config.5,v 1.144 2012/06/29 13:57:25 naddy Exp $
.Dd $Mdocdate: June 29 2012 $
.\" $OpenBSD: sshd_config.5,v 1.156 2013/02/06 00:20:42 dtucker Exp $
.Dd $Mdocdate: February 6 2013 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@ -124,6 +124,19 @@ in
for more information on patterns.
.It Cm AllowTcpForwarding
Specifies whether TCP forwarding is permitted.
The available options are
.Dq yes
or
.Dq all
to allow TCP forwarding,
.Dq no
to prevent all TCP forwarding,
.Dq local
to allow local (from the perspective of
.Xr ssh 1 )
forwarding only or
.Dq remote
to allow remote forwarding only.
The default is
.Dq yes .
Note that disabling TCP forwarding does not improve security unless
@ -151,6 +164,45 @@ See
in
.Xr ssh_config 5
for more information on patterns.
.It Cm AuthenticationMethods
Specifies the authentication methods that must be successfully completed
for a user to be granted access.
This option must be followed by one or more comma-separated lists of
authentication method names.
Successful authentication requires completion of every method in at least
one of these lists.
.Pp
For example, an argument of
.Dq publickey,password publickey,keyboard-interactive
would require the user to complete public key authentication, followed by
either password or keyboard interactive authentication.
Only methods that are next in one or more lists are offered at each stage,
so for this example, it would not be possible to attempt password or
keyboard-interactive authentication before public key.
.Pp
This option is only available for SSH protocol 2 and will yield a fatal
error if enabled if protocol 1 is also enabled.
Note that each authentication method listed should also be explicitly enabled
in the configuration.
The default is not to require multiple authentication; successful completion
of a single authentication method is sufficient.
.It Cm AuthorizedKeysCommand
Specifies a program to be used to look up the user's public keys.
The program will be invoked with a single argument of the username
being authenticated, and should produce on standard output zero or
more lines of authorized_keys output (see
.Sx AUTHORIZED_KEYS
in
.Xr sshd 8 ) .
If a key supplied by AuthorizedKeysCommand does not successfully authenticate
and authorize the user then public key authentication continues using the usual
.Cm AuthorizedKeysFile
files.
By default, no AuthorizedKeysCommand is run.
.It Cm AuthorizedKeysCommandUser
Specifies the user under whose account the AuthorizedKeysCommand is run.
It is recommended to use a dedicated user that has no other role on the host
than running authorized keys commands.
.It Cm AuthorizedKeysFile
Specifies the file that contains the public keys that can be used
for user authentication.
@ -285,6 +337,8 @@ The supported ciphers are
.Dq aes128-ctr ,
.Dq aes192-ctr ,
.Dq aes256-ctr ,
.Dq aes128-gcm@openssh.com ,
.Dq aes256-gcm@openssh.com ,
.Dq arcfour128 ,
.Dq arcfour256 ,
.Dq arcfour ,
@ -294,6 +348,7 @@ and
The default is:
.Bd -literal -offset 3n
aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
aes128-gcm@openssh.com,aes256-gcm@openssh.com,
aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
aes256-cbc,arcfour
.Ed
@ -655,9 +710,18 @@ Specifies the available MAC (message authentication code) algorithms.
The MAC algorithm is used in protocol version 2
for data integrity protection.
Multiple algorithms must be comma-separated.
The algorithms that contain
.Dq -etm
calculate the MAC after encryption (encrypt-then-mac).
These are considered safer and their use recommended.
The default is:
.Bd -literal -offset indent
hmac-md5,hmac-sha1,umac-64@openssh.com,
hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
umac-64-etm@openssh.com,umac-128-etm@openssh.com,
hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,
hmac-md5-96-etm@openssh.com,
hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,
hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,
hmac-sha1-96,hmac-md5-96
.Ed
@ -712,6 +776,9 @@ Available keywords are
.Cm AllowGroups ,
.Cm AllowTcpForwarding ,
.Cm AllowUsers ,
.Cm AuthenticationMethods ,
.Cm AuthorizedKeysCommand ,
.Cm AuthorizedKeysCommandUser ,
.Cm AuthorizedKeysFile ,
.Cm AuthorizedPrincipalsFile ,
.Cm Banner ,
@ -754,7 +821,7 @@ SSH daemon.
Additional connections will be dropped until authentication succeeds or the
.Cm LoginGraceTime
expires for a connection.
The default is 10.
The default is 10:30:100.
.Pp
Alternatively, random early drop can be enabled by specifying
the three colon separated values
@ -928,10 +995,17 @@ The default is
.Dq yes .
Note that this option applies to protocol version 2 only.
.It Cm RevokedKeys
Specifies a list of revoked public keys.
Specifies revoked public keys.
Keys listed in this file will be refused for public key authentication.
Note that if this file is not readable, then public key authentication will
be refused for all users.
Keys may be specified as a text file, listing one public key per line, or as
an OpenSSH Key Revocation List (KRL) as generated by
.Xr ssh-keygen 1 .
For more information on KRLs, see the
.Sx KEY REVOCATION LISTS
section in
.Xr ssh-keygen 1 .
.It Cm RhostsRSAAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication together
with successful RSA host authentication is allowed.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: umac.h,v 1.1 2007/06/07 19:37:34 pvalchev Exp $ */
/* $OpenBSD: umac.h,v 1.2 2012/10/04 13:21:50 markus Exp $ */
/* -----------------------------------------------------------------------
*
* umac.h -- C Implementation UMAC Message Authentication
@ -116,6 +116,12 @@ int uhash(uhash_ctx_t ctx,
#endif
/* matching umac-128 API, we reuse umac_ctx, since it's opaque */
struct umac_ctx *umac128_new(u_char key[]);
int umac128_update(struct umac_ctx *ctx, u_char *input, long len);
int umac128_final(struct umac_ctx *ctx, u_char tag[], u_char nonce[8]);
int umac128_delete(struct umac_ctx *ctx);
#ifdef __cplusplus
}
#endif

View File

@ -1,3 +1,3 @@
/* $OpenBSD: version.h,v 1.65 2012/07/22 18:19:21 markus Exp $ */
/* $OpenBSD: version.h,v 1.66 2013/02/10 21:19:34 markus Exp $ */
#define SSH_VERSION "OpenSSH_6.1"
#define SSH_VERSION "OpenSSH_6.2"