Import of OpenSSH 2.3.0 (virgin OpenBSD source release).
This commit is contained in:
@@ -36,7 +36,7 @@ OpenSSH contains no GPL code.
|
||||
- The make-ssh-known-hosts script is no longer included
|
||||
- TSS has been removed
|
||||
- MD5 is now external, in the OpenSSL library
|
||||
- RC4 support has been removed
|
||||
- RC4 support has been replaced with ARC4 support from OpenSSL
|
||||
- Blowfish is now external, in the OpenSSL library
|
||||
|
||||
[The licence continues]
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
CFLAGS+= -I${.CURDIR}/..
|
||||
|
||||
CFLAGS+= -Wall
|
||||
|
||||
.include <bsd.obj.mk>
|
||||
|
||||
.if exists(${.CURDIR}/../lib/${__objdir})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" -*- nroff -*-
|
||||
.\"
|
||||
.\" $Id: RFC.nroff,v 1.1 1999/09/26 20:53:32 deraadt Exp $
|
||||
.\" $OpenBSD: RFC.nroff,v 1.2 2000/10/16 09:38:44 djm Exp $
|
||||
.\"
|
||||
.pl 10.0i
|
||||
.po 0
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: atomicio.c,v 1.5 2000/09/07 20:27:49 deraadt Exp $");
|
||||
RCSID("$OpenBSD: atomicio.c,v 1.7 2000/10/18 18:04:02 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "ssh.h"
|
||||
#include "servconf.h"
|
||||
|
||||
RCSID("$OpenBSD: auth-krb4.c,v 1.18 2000/09/07 20:27:49 deraadt Exp $");
|
||||
RCSID("$OpenBSD: auth-krb4.c,v 1.19 2000/10/03 18:03:02 markus Exp $");
|
||||
|
||||
#ifdef KRB4
|
||||
char *ticket = NULL;
|
||||
@@ -280,6 +280,8 @@ auth_kerberos_tgt(struct passwd *pw, const char *string)
|
||||
{
|
||||
CREDENTIALS creds;
|
||||
|
||||
if (pw == NULL)
|
||||
goto auth_kerberos_tgt_failure;
|
||||
if (!radix_to_creds(string, &creds)) {
|
||||
log("Protocol error decoding Kerberos V4 tgt");
|
||||
packet_send_debug("Protocol error decoding Kerberos V4 tgt");
|
||||
@@ -334,8 +336,16 @@ int
|
||||
auth_afs_token(struct passwd *pw, const char *token_string)
|
||||
{
|
||||
CREDENTIALS creds;
|
||||
uid_t uid = pw->pw_uid;
|
||||
uid_t uid;
|
||||
|
||||
if (pw == NULL) {
|
||||
/* XXX fake protocol error */
|
||||
packet_send_debug("Protocol error decoding AFS token");
|
||||
packet_start(SSH_SMSG_FAILURE);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
return 0;
|
||||
}
|
||||
if (!radix_to_creds(token_string, &creds)) {
|
||||
log("Protocol error decoding AFS token");
|
||||
packet_send_debug("Protocol error decoding AFS token");
|
||||
@@ -349,6 +359,8 @@ auth_afs_token(struct passwd *pw, const char *token_string)
|
||||
|
||||
if (strncmp(creds.pname, "AFS ID ", 7) == 0)
|
||||
uid = atoi(creds.pname + 7);
|
||||
else
|
||||
uid = pw->pw_uid;
|
||||
|
||||
if (kafs_settoken(creds.realm, uid, &creds)) {
|
||||
log("AFS token (%s@%s) rejected for %s", creds.pname, creds.realm,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth-options.c,v 1.4 2000/09/07 21:13:36 markus Exp $");
|
||||
RCSID("$OpenBSD: auth-options.c,v 1.5 2000/10/09 21:32:34 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
@@ -33,6 +33,25 @@ char *forced_command = NULL;
|
||||
/* "environment=" options. */
|
||||
struct envstring *custom_environment = NULL;
|
||||
|
||||
void
|
||||
auth_clear_options(void)
|
||||
{
|
||||
no_agent_forwarding_flag = 0;
|
||||
no_port_forwarding_flag = 0;
|
||||
no_pty_flag = 0;
|
||||
no_x11_forwarding_flag = 0;
|
||||
while (custom_environment) {
|
||||
struct envstring *ce = custom_environment;
|
||||
custom_environment = ce->next;
|
||||
xfree(ce->s);
|
||||
xfree(ce);
|
||||
}
|
||||
if (forced_command) {
|
||||
xfree(forced_command);
|
||||
forced_command = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* return 1 if access is granted, 0 if not. side effect: sets key option flags */
|
||||
int
|
||||
auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
|
||||
@@ -40,6 +59,10 @@ auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
|
||||
const char *cp;
|
||||
if (!options)
|
||||
return 1;
|
||||
|
||||
/* reset options */
|
||||
auth_clear_options();
|
||||
|
||||
while (*options && *options != ' ' && *options != '\t') {
|
||||
cp = "no-port-forwarding";
|
||||
if (strncmp(options, cp, strlen(cp)) == 0) {
|
||||
@@ -87,9 +110,9 @@ auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
|
||||
}
|
||||
if (!*options) {
|
||||
debug("%.100s, line %lu: missing end quote",
|
||||
SSH_USER_PERMITTED_KEYS, linenum);
|
||||
SSH_USER_PERMITTED_KEYS, linenum);
|
||||
packet_send_debug("%.100s, line %lu: missing end quote",
|
||||
SSH_USER_PERMITTED_KEYS, linenum);
|
||||
SSH_USER_PERMITTED_KEYS, linenum);
|
||||
continue;
|
||||
}
|
||||
forced_command[i] = 0;
|
||||
@@ -117,9 +140,9 @@ auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
|
||||
}
|
||||
if (!*options) {
|
||||
debug("%.100s, line %lu: missing end quote",
|
||||
SSH_USER_PERMITTED_KEYS, linenum);
|
||||
SSH_USER_PERMITTED_KEYS, linenum);
|
||||
packet_send_debug("%.100s, line %lu: missing end quote",
|
||||
SSH_USER_PERMITTED_KEYS, linenum);
|
||||
SSH_USER_PERMITTED_KEYS, linenum);
|
||||
continue;
|
||||
}
|
||||
s[i] = 0;
|
||||
@@ -175,21 +198,6 @@ auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
|
||||
get_remote_ipaddr());
|
||||
packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
|
||||
get_canonical_hostname());
|
||||
/* key invalid for this host, reset flags */
|
||||
no_agent_forwarding_flag = 0;
|
||||
no_port_forwarding_flag = 0;
|
||||
no_pty_flag = 0;
|
||||
no_x11_forwarding_flag = 0;
|
||||
while (custom_environment) {
|
||||
struct envstring *ce = custom_environment;
|
||||
custom_environment = ce->next;
|
||||
xfree(ce->s);
|
||||
xfree(ce);
|
||||
}
|
||||
if (forced_command) {
|
||||
xfree(forced_command);
|
||||
forced_command = NULL;
|
||||
}
|
||||
/* deny access */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* $OpenBSD: auth-options.h,v 1.5 2000/10/16 09:38:44 djm Exp $ */
|
||||
|
||||
#ifndef AUTH_OPTIONS_H
|
||||
#define AUTH_OPTIONS_H
|
||||
/* Flags that may be set in authorized_keys options. */
|
||||
@@ -22,4 +25,7 @@ extern struct envstring *custom_environment;
|
||||
|
||||
/* return 1 if access is granted, 0 if not. side effect: sets key option flags */
|
||||
int auth_parse_options(struct passwd *pw, char *options, unsigned long linenum);
|
||||
/* reset options flags */
|
||||
void auth_clear_options(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth-passwd.c,v 1.17 2000/09/07 20:27:49 deraadt Exp $");
|
||||
RCSID("$OpenBSD: auth-passwd.c,v 1.18 2000/10/03 18:03:03 markus Exp $");
|
||||
|
||||
#include "packet.h"
|
||||
#include "ssh.h"
|
||||
@@ -84,7 +84,7 @@ auth_password(struct passwd * pw, const char *password)
|
||||
if (*password == '\0' && options.permit_empty_passwd == 0)
|
||||
return 0;
|
||||
|
||||
#ifdef SKEY
|
||||
#ifdef SKEY_VIA_PASSWD_IS_DISABLED
|
||||
if (options.skey_authentication == 1) {
|
||||
int ret = auth_skey_password(pw, password);
|
||||
if (ret == 1 || ret == 0)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.16 2000/09/07 21:13:36 markus Exp $");
|
||||
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.17 2000/10/03 18:03:03 markus Exp $");
|
||||
|
||||
#include "packet.h"
|
||||
#include "ssh.h"
|
||||
@@ -39,9 +39,9 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key
|
||||
HostStatus host_status;
|
||||
Key *client_key, *found;
|
||||
|
||||
debug("Trying rhosts with RSA host authentication for %.100s", client_user);
|
||||
debug("Trying rhosts with RSA host authentication for client user %.100s", client_user);
|
||||
|
||||
if (client_host_key == NULL)
|
||||
if (pw == NULL || client_host_key == NULL)
|
||||
return 0;
|
||||
|
||||
/* Check if we would accept it using rhosts authentication. */
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth-rhosts.c,v 1.15 2000/09/07 20:27:49 deraadt Exp $");
|
||||
RCSID("$OpenBSD: auth-rhosts.c,v 1.16 2000/10/03 18:03:03 markus Exp $");
|
||||
|
||||
#include "packet.h"
|
||||
#include "ssh.h"
|
||||
@@ -154,6 +154,9 @@ auth_rhosts(struct passwd *pw, const char *client_user)
|
||||
static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
|
||||
unsigned int rhosts_file_index;
|
||||
|
||||
/* no user given */
|
||||
if (pw == NULL)
|
||||
return 0;
|
||||
/* Switch to the user's uid. */
|
||||
temporarily_use_uid(pw->pw_uid);
|
||||
/*
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth-rsa.c,v 1.29 2000/09/07 21:13:36 markus Exp $");
|
||||
RCSID("$OpenBSD: auth-rsa.c,v 1.32 2000/10/14 12:19:45 markus Exp $");
|
||||
|
||||
#include "rsa.h"
|
||||
#include "packet.h"
|
||||
@@ -29,6 +29,10 @@ RCSID("$OpenBSD: auth-rsa.c,v 1.29 2000/09/07 21:13:36 markus Exp $");
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/md5.h>
|
||||
|
||||
|
||||
/* import */
|
||||
extern ServerOptions options;
|
||||
|
||||
/*
|
||||
* Session identifier that is used to bind key exchange and authentication
|
||||
* responses to a particular session.
|
||||
@@ -116,7 +120,6 @@ auth_rsa_challenge_dialog(RSA *pk)
|
||||
int
|
||||
auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
||||
{
|
||||
extern ServerOptions options;
|
||||
char line[8192], file[1024];
|
||||
int authenticated;
|
||||
unsigned int bits;
|
||||
@@ -125,6 +128,10 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
||||
struct stat st;
|
||||
RSA *pk;
|
||||
|
||||
/* no user given */
|
||||
if (pw == NULL)
|
||||
return 0;
|
||||
|
||||
/* Temporarily use the user's uid. */
|
||||
temporarily_use_uid(pw->pw_uid);
|
||||
|
||||
@@ -224,6 +231,12 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
||||
}
|
||||
} else
|
||||
options = NULL;
|
||||
/*
|
||||
* If our options do not allow this key to be used,
|
||||
* do not send challenge.
|
||||
*/
|
||||
if (!auth_parse_options(pw, options, linenum))
|
||||
continue;
|
||||
|
||||
/* Parse the key from the line. */
|
||||
if (!auth_rsa_read_key(&cp, &bits, pk->e, pk->n)) {
|
||||
@@ -262,9 +275,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
||||
* Break out of the loop if authentication was successful;
|
||||
* otherwise continue searching.
|
||||
*/
|
||||
authenticated = auth_parse_options(pw, options, linenum);
|
||||
if (authenticated)
|
||||
break;
|
||||
authenticated = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Restore the privileged uid. */
|
||||
@@ -277,6 +289,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
||||
|
||||
if (authenticated)
|
||||
packet_send_debug("RSA authentication accepted.");
|
||||
else
|
||||
auth_clear_options();
|
||||
|
||||
/* Return authentication result. */
|
||||
return authenticated;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth-skey.c,v 1.8 2000/09/07 20:27:49 deraadt Exp $");
|
||||
RCSID("$OpenBSD: auth-skey.c,v 1.9 2000/10/19 16:41:13 deraadt Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
@@ -45,7 +45,7 @@ auth_skey_password(struct passwd * pw, const char *password)
|
||||
skeyinfo = skey_fake_keyinfo(pw->pw_name);
|
||||
}
|
||||
if (skeyinfo != NULL)
|
||||
packet_send_debug(skeyinfo);
|
||||
packet_send_debug("%s", skeyinfo);
|
||||
/* Try again. */
|
||||
return 0;
|
||||
} else if (skey_haskey(pw->pw_name) == 0 &&
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth.c,v 1.10 2000/09/07 21:13:36 markus Exp $");
|
||||
RCSID("$OpenBSD: auth.c,v 1.11 2000/10/11 20:27:23 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "rsa.h"
|
||||
@@ -41,7 +41,6 @@ RCSID("$OpenBSD: auth.c,v 1.10 2000/09/07 21:13:36 markus Exp $");
|
||||
#include "pty.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
#include "cipher.h"
|
||||
#include "mpaux.h"
|
||||
#include "servconf.h"
|
||||
#include "compat.h"
|
||||
|
||||
+18
-4
@@ -20,21 +20,35 @@
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $OpenBSD: auth.h,v 1.7 2000/10/16 09:38:44 djm Exp $
|
||||
*/
|
||||
#ifndef AUTH_H
|
||||
#define AUTH_H
|
||||
|
||||
typedef struct Authctxt Authctxt;
|
||||
struct Authctxt {
|
||||
int success;
|
||||
int valid;
|
||||
int attempt;
|
||||
char *user;
|
||||
char *service;
|
||||
struct passwd *pw;
|
||||
};
|
||||
|
||||
void do_authentication(void);
|
||||
void do_authentication2(void);
|
||||
|
||||
struct passwd *
|
||||
auth_get_user(void);
|
||||
void userauth_log(Authctxt *authctxt, int authenticated, char *method);
|
||||
void userauth_reply(Authctxt *authctxt, int authenticated);
|
||||
|
||||
int allowed_user(struct passwd * pw);
|
||||
int auth2_skey(Authctxt *authctxt);
|
||||
|
||||
int allowed_user(struct passwd * pw);
|
||||
struct passwd * auth_get_user(void);
|
||||
|
||||
#define AUTH_FAIL_MAX 6
|
||||
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
|
||||
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+57
-112
@@ -10,14 +10,13 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth1.c,v 1.4 2000/09/07 20:27:49 deraadt Exp $");
|
||||
RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "rsa.h"
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
#include "cipher.h"
|
||||
#include "mpaux.h"
|
||||
#include "servconf.h"
|
||||
#include "compat.h"
|
||||
@@ -58,78 +57,16 @@ get_authname(int type)
|
||||
}
|
||||
|
||||
/*
|
||||
* The user does not exist or access is denied,
|
||||
* but fake indication that authentication is needed.
|
||||
* read packets and try to authenticate local user 'luser'.
|
||||
* return if authentication is successfull. not that pw == NULL
|
||||
* if the user does not exists or is not allowed to login.
|
||||
* each auth method has to 'fake' authentication for nonexisting
|
||||
* users.
|
||||
*/
|
||||
void
|
||||
do_fake_authloop1(char *user)
|
||||
{
|
||||
int attempt = 0;
|
||||
|
||||
log("Faking authloop for illegal user %.200s from %.200s port %d",
|
||||
user,
|
||||
get_remote_ipaddr(),
|
||||
get_remote_port());
|
||||
|
||||
/* Indicate that authentication is needed. */
|
||||
packet_start(SSH_SMSG_FAILURE);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
/*
|
||||
* Keep reading packets, and always respond with a failure. This is
|
||||
* to avoid disclosing whether such a user really exists.
|
||||
*/
|
||||
for (attempt = 1;; attempt++) {
|
||||
/* Read a packet. This will not return if the client disconnects. */
|
||||
int plen;
|
||||
int type = packet_read(&plen);
|
||||
#ifdef SKEY
|
||||
unsigned int dlen;
|
||||
char *password, *skeyinfo;
|
||||
password = NULL;
|
||||
/* Try to send a fake s/key challenge. */
|
||||
if (options.skey_authentication == 1 &&
|
||||
(skeyinfo = skey_fake_keyinfo(user)) != NULL) {
|
||||
if (type == SSH_CMSG_AUTH_TIS) {
|
||||
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
|
||||
packet_put_string(skeyinfo, strlen(skeyinfo));
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
continue;
|
||||
} else if (type == SSH_CMSG_AUTH_PASSWORD &&
|
||||
options.password_authentication &&
|
||||
(password = packet_get_string(&dlen)) != NULL &&
|
||||
dlen == 5 &&
|
||||
strncasecmp(password, "s/key", 5) == 0 ) {
|
||||
packet_send_debug(skeyinfo);
|
||||
}
|
||||
}
|
||||
if (password != NULL)
|
||||
xfree(password);
|
||||
#endif
|
||||
if (attempt > AUTH_FAIL_MAX)
|
||||
packet_disconnect(AUTH_FAIL_MSG, user);
|
||||
|
||||
/*
|
||||
* Send failure. This should be indistinguishable from a
|
||||
* failed authentication.
|
||||
*/
|
||||
packet_start(SSH_SMSG_FAILURE);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
}
|
||||
/* NOTREACHED */
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* read packets and try to authenticate local user *pw.
|
||||
* return if authentication is successfull
|
||||
*/
|
||||
void
|
||||
do_authloop(struct passwd * pw)
|
||||
do_authloop(struct passwd * pw, char *luser)
|
||||
{
|
||||
int authenticated = 0;
|
||||
int attempt = 0;
|
||||
unsigned int bits;
|
||||
RSA *client_host_key;
|
||||
@@ -148,7 +85,9 @@ do_authloop(struct passwd * pw)
|
||||
packet_write_wait();
|
||||
|
||||
for (attempt = 1;; attempt++) {
|
||||
int authenticated = 0;
|
||||
/* default to fail */
|
||||
authenticated = 0;
|
||||
|
||||
strlcpy(user, "", sizeof user);
|
||||
|
||||
/* Get a packet from the client. */
|
||||
@@ -159,7 +98,6 @@ do_authloop(struct passwd * pw)
|
||||
#ifdef AFS
|
||||
case SSH_CMSG_HAVE_KERBEROS_TGT:
|
||||
if (!options.kerberos_tgt_passing) {
|
||||
/* packet_get_all(); */
|
||||
verbose("Kerberos tgt passing disabled.");
|
||||
break;
|
||||
} else {
|
||||
@@ -167,14 +105,13 @@ do_authloop(struct passwd * pw)
|
||||
char *tgt = packet_get_string(&dlen);
|
||||
packet_integrity_check(plen, 4 + dlen, type);
|
||||
if (!auth_kerberos_tgt(pw, tgt))
|
||||
verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
|
||||
verbose("Kerberos tgt REFUSED for %.100s", luser);
|
||||
xfree(tgt);
|
||||
}
|
||||
continue;
|
||||
|
||||
case SSH_CMSG_HAVE_AFS_TOKEN:
|
||||
if (!options.afs_token_passing || !k_hasafs()) {
|
||||
/* packet_get_all(); */
|
||||
verbose("AFS token passing disabled.");
|
||||
break;
|
||||
} else {
|
||||
@@ -182,7 +119,7 @@ do_authloop(struct passwd * pw)
|
||||
char *token_string = packet_get_string(&dlen);
|
||||
packet_integrity_check(plen, 4 + dlen, type);
|
||||
if (!auth_afs_token(pw, token_string))
|
||||
verbose("AFS token REFUSED for %s", pw->pw_name);
|
||||
verbose("AFS token REFUSED for %.100s", luser);
|
||||
xfree(token_string);
|
||||
}
|
||||
continue;
|
||||
@@ -204,11 +141,12 @@ do_authloop(struct passwd * pw)
|
||||
memcpy(auth.dat, kdata, auth.length);
|
||||
xfree(kdata);
|
||||
|
||||
authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
|
||||
|
||||
if (authenticated) {
|
||||
snprintf(user, sizeof user, " tktuser %s", tkt_user);
|
||||
xfree(tkt_user);
|
||||
if (pw != NULL) {
|
||||
authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
|
||||
if (authenticated) {
|
||||
snprintf(user, sizeof user, " tktuser %s", tkt_user);
|
||||
xfree(tkt_user);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -228,8 +166,7 @@ do_authloop(struct passwd * pw)
|
||||
client_user = packet_get_string(&ulen);
|
||||
packet_integrity_check(plen, 4 + ulen, type);
|
||||
|
||||
/* Try to authenticate using /etc/hosts.equiv and
|
||||
.rhosts. */
|
||||
/* Try to authenticate using /etc/hosts.equiv and .rhosts. */
|
||||
authenticated = auth_rhosts(pw, client_user);
|
||||
|
||||
snprintf(user, sizeof user, " ruser %s", client_user);
|
||||
@@ -261,7 +198,7 @@ do_authloop(struct passwd * pw)
|
||||
packet_get_bignum(client_host_key->n, &nlen);
|
||||
|
||||
if (bits != BN_num_bits(client_host_key->n))
|
||||
log("Warning: keysize mismatch for client_host_key: "
|
||||
verbose("Warning: keysize mismatch for client_host_key: "
|
||||
"actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
|
||||
packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
|
||||
|
||||
@@ -309,16 +246,18 @@ do_authloop(struct passwd * pw)
|
||||
case SSH_CMSG_AUTH_TIS:
|
||||
debug("rcvd SSH_CMSG_AUTH_TIS");
|
||||
if (options.skey_authentication == 1) {
|
||||
char *skeyinfo = skey_keyinfo(pw->pw_name);
|
||||
char *skeyinfo = NULL;
|
||||
if (pw != NULL)
|
||||
skey_keyinfo(pw->pw_name);
|
||||
if (skeyinfo == NULL) {
|
||||
debug("generating fake skeyinfo for %.100s.", pw->pw_name);
|
||||
skeyinfo = skey_fake_keyinfo(pw->pw_name);
|
||||
debug("generating fake skeyinfo for %.100s.", luser);
|
||||
skeyinfo = skey_fake_keyinfo(luser);
|
||||
}
|
||||
if (skeyinfo != NULL) {
|
||||
/* we send our s/key- in tis-challenge messages */
|
||||
debug("sending challenge '%s'", skeyinfo);
|
||||
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
|
||||
packet_put_string(skeyinfo, strlen(skeyinfo));
|
||||
packet_put_cstring(skeyinfo);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
continue;
|
||||
@@ -331,8 +270,9 @@ do_authloop(struct passwd * pw)
|
||||
char *response = packet_get_string(&dlen);
|
||||
debug("skey response == '%s'", response);
|
||||
packet_integrity_check(plen, 4 + dlen, type);
|
||||
authenticated = (skey_haskey(pw->pw_name) == 0 &&
|
||||
skey_passcheck(pw->pw_name, response) != -1);
|
||||
authenticated = (pw != NULL &&
|
||||
skey_haskey(pw->pw_name) == 0 &&
|
||||
skey_passcheck(pw->pw_name, response) != -1);
|
||||
xfree(response);
|
||||
}
|
||||
break;
|
||||
@@ -351,13 +291,15 @@ do_authloop(struct passwd * pw)
|
||||
log("Unknown message during authentication: type %d", type);
|
||||
break;
|
||||
}
|
||||
if (authenticated && pw == NULL)
|
||||
fatal("internal error: authenticated for pw == NULL");
|
||||
|
||||
/*
|
||||
* Check if the user is logging in as root and root logins
|
||||
* are disallowed.
|
||||
* Note that root login is allowed for forced commands.
|
||||
*/
|
||||
if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
|
||||
if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
|
||||
if (forced_command) {
|
||||
log("Root login accepted for forced command.");
|
||||
} else {
|
||||
@@ -373,10 +315,11 @@ do_authloop(struct passwd * pw)
|
||||
type == SSH_CMSG_AUTH_PASSWORD)
|
||||
authlog = log;
|
||||
|
||||
authlog("%s %s for %.200s from %.200s port %d%s",
|
||||
authlog("%s %s for %s%.100s from %.200s port %d%s",
|
||||
authenticated ? "Accepted" : "Failed",
|
||||
get_authname(type),
|
||||
pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
|
||||
pw ? "" : "illegal user ",
|
||||
pw && pw->pw_uid == 0 ? "ROOT" : luser,
|
||||
get_remote_ipaddr(),
|
||||
get_remote_port(),
|
||||
user);
|
||||
@@ -385,7 +328,7 @@ do_authloop(struct passwd * pw)
|
||||
return;
|
||||
|
||||
if (attempt > AUTH_FAIL_MAX)
|
||||
packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
|
||||
packet_disconnect(AUTH_FAIL_MSG, luser);
|
||||
|
||||
/* Send a message indicating that the authentication attempt failed. */
|
||||
packet_start(SSH_SMSG_FAILURE);
|
||||
@@ -425,29 +368,29 @@ do_authentication()
|
||||
|
||||
/* Verify that the user is a valid user. */
|
||||
pw = getpwnam(user);
|
||||
if (!pw || !allowed_user(pw))
|
||||
do_fake_authloop1(user);
|
||||
xfree(user);
|
||||
|
||||
/* Take a copy of the returned structure. */
|
||||
memset(&pwcopy, 0, sizeof(pwcopy));
|
||||
pwcopy.pw_name = xstrdup(pw->pw_name);
|
||||
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
||||
pwcopy.pw_uid = pw->pw_uid;
|
||||
pwcopy.pw_gid = pw->pw_gid;
|
||||
pwcopy.pw_class = xstrdup(pw->pw_class);
|
||||
pwcopy.pw_dir = xstrdup(pw->pw_dir);
|
||||
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
||||
pw = &pwcopy;
|
||||
if (pw && allowed_user(pw)) {
|
||||
/* Take a copy of the returned structure. */
|
||||
memset(&pwcopy, 0, sizeof(pwcopy));
|
||||
pwcopy.pw_name = xstrdup(pw->pw_name);
|
||||
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
||||
pwcopy.pw_uid = pw->pw_uid;
|
||||
pwcopy.pw_gid = pw->pw_gid;
|
||||
pwcopy.pw_class = xstrdup(pw->pw_class);
|
||||
pwcopy.pw_dir = xstrdup(pw->pw_dir);
|
||||
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
||||
pw = &pwcopy;
|
||||
} else {
|
||||
pw = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are not running as root, the user must have the same uid as
|
||||
* the server.
|
||||
*/
|
||||
if (getuid() != 0 && pw->pw_uid != getuid())
|
||||
if (getuid() != 0 && pw && pw->pw_uid != getuid())
|
||||
packet_disconnect("Cannot change user when server not running as root.");
|
||||
|
||||
debug("Attempting authentication for %.100s.", pw->pw_name);
|
||||
debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user);
|
||||
|
||||
/* If the user has no password, accept authentication immediately. */
|
||||
if (options.password_authentication &&
|
||||
@@ -457,13 +400,15 @@ do_authentication()
|
||||
auth_password(pw, "")) {
|
||||
/* Authentication with empty password succeeded. */
|
||||
log("Login for user %s from %.100s, accepted without authentication.",
|
||||
pw->pw_name, get_remote_ipaddr());
|
||||
user, get_remote_ipaddr());
|
||||
} else {
|
||||
/* Loop until the user has been authenticated or the
|
||||
connection is closed, do_authloop() returns only if
|
||||
authentication is successfull */
|
||||
do_authloop(pw);
|
||||
do_authloop(pw, user);
|
||||
}
|
||||
if (pw == NULL)
|
||||
fatal("internal error, authentication successfull for user '%.100s'", user);
|
||||
|
||||
/* The user has been authenticated and accepted. */
|
||||
packet_start(SSH_SMSG_SUCCESS);
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth2-skey.c,v 1.1 2000/10/11 20:14:38 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "ssh2.h"
|
||||
#include "auth.h"
|
||||
#include "packet.h"
|
||||
#include "xmalloc.h"
|
||||
#include "dispatch.h"
|
||||
|
||||
void send_userauth_into_request(Authctxt *authctxt, int echo);
|
||||
void input_userauth_info_response(int type, int plen, void *ctxt);
|
||||
|
||||
/*
|
||||
* try skey authentication, always return -1 (= postponed) since we have to
|
||||
* wait for the s/key response.
|
||||
*/
|
||||
int
|
||||
auth2_skey(Authctxt *authctxt)
|
||||
{
|
||||
send_userauth_into_request(authctxt, 0);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &input_userauth_info_response);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
send_userauth_into_request(Authctxt *authctxt, int echo)
|
||||
{
|
||||
int retval = -1;
|
||||
struct skey skey;
|
||||
char challenge[SKEY_MAX_CHALLENGE];
|
||||
char *fake;
|
||||
|
||||
if (authctxt->user == NULL)
|
||||
fatal("send_userauth_into_request: internal error: no user");
|
||||
|
||||
/* get skey challenge */
|
||||
if (authctxt->valid)
|
||||
retval = skeychallenge(&skey, authctxt->user, challenge);
|
||||
|
||||
if (retval == -1) {
|
||||
fake = skey_fake_keyinfo(authctxt->user);
|
||||
strlcpy(challenge, fake, sizeof challenge);
|
||||
}
|
||||
/* send our info request */
|
||||
packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
|
||||
packet_put_cstring("S/Key Authentication"); /* Name */
|
||||
packet_put_cstring(challenge); /* Instruction */
|
||||
packet_put_cstring(""); /* Language */
|
||||
packet_put_int(1); /* Number of prompts */
|
||||
packet_put_cstring(echo ?
|
||||
"Response [Echo]: ": "Response: "); /* Prompt */
|
||||
packet_put_char(echo); /* Echo */
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
memset(challenge, 'c', sizeof challenge);
|
||||
}
|
||||
|
||||
void
|
||||
input_userauth_info_response(int type, int plen, void *ctxt)
|
||||
{
|
||||
Authctxt *authctxt = ctxt;
|
||||
int authenticated = 0;
|
||||
unsigned int nresp, rlen;
|
||||
char *resp, *method;
|
||||
|
||||
if (authctxt == NULL)
|
||||
fatal("input_userauth_info_response: no authentication context");
|
||||
|
||||
if (authctxt->attempt++ >= AUTH_FAIL_MAX)
|
||||
packet_disconnect("too many failed userauth_requests");
|
||||
|
||||
nresp = packet_get_int();
|
||||
if (nresp == 1) {
|
||||
/* we only support s/key and assume s/key for nresp == 1 */
|
||||
method = "s/key";
|
||||
resp = packet_get_string(&rlen);
|
||||
packet_done();
|
||||
if (strlen(resp) == 0) {
|
||||
/*
|
||||
* if we received a null response, resend prompt with
|
||||
* echo enabled
|
||||
*/
|
||||
authenticated = -1;
|
||||
userauth_log(authctxt, authenticated, method);
|
||||
send_userauth_into_request(authctxt, 1);
|
||||
} else {
|
||||
/* verify skey response */
|
||||
if (authctxt->valid &&
|
||||
skey_haskey(authctxt->pw->pw_name) == 0 &&
|
||||
skey_passcheck(authctxt->pw->pw_name, resp) != -1) {
|
||||
authenticated = 1;
|
||||
} else {
|
||||
authenticated = 0;
|
||||
}
|
||||
memset(resp, 'r', rlen);
|
||||
/* unregister callback */
|
||||
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
|
||||
userauth_log(authctxt, authenticated, method);
|
||||
userauth_reply(authctxt, authenticated);
|
||||
}
|
||||
xfree(resp);
|
||||
}
|
||||
}
|
||||
+263
-123
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth2.c,v 1.14 2000/09/07 20:27:49 deraadt Exp $");
|
||||
RCSID("$OpenBSD: auth2.c,v 1.20 2000/10/14 12:16:56 markus Exp $");
|
||||
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
@@ -35,7 +35,6 @@ RCSID("$OpenBSD: auth2.c,v 1.14 2000/09/07 20:27:49 deraadt Exp $");
|
||||
#include "pty.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
#include "cipher.h"
|
||||
#include "servconf.h"
|
||||
#include "compat.h"
|
||||
#include "channels.h"
|
||||
@@ -57,54 +56,77 @@ extern ServerOptions options;
|
||||
extern unsigned char *session_id2;
|
||||
extern int session_id2_len;
|
||||
|
||||
static Authctxt *x_authctxt = NULL;
|
||||
static int one = 1;
|
||||
|
||||
typedef struct Authmethod Authmethod;
|
||||
struct Authmethod {
|
||||
char *name;
|
||||
int (*userauth)(Authctxt *authctxt);
|
||||
int *enabled;
|
||||
};
|
||||
|
||||
/* protocol */
|
||||
|
||||
void input_service_request(int type, int plen);
|
||||
void input_userauth_request(int type, int plen);
|
||||
void protocol_error(int type, int plen);
|
||||
void input_service_request(int type, int plen, void *ctxt);
|
||||
void input_userauth_request(int type, int plen, void *ctxt);
|
||||
void protocol_error(int type, int plen, void *ctxt);
|
||||
|
||||
/* auth */
|
||||
int ssh2_auth_none(struct passwd *pw);
|
||||
int ssh2_auth_password(struct passwd *pw);
|
||||
int ssh2_auth_pubkey(struct passwd *pw, char *service);
|
||||
|
||||
/* helper */
|
||||
struct passwd* auth_set_user(char *u, char *s);
|
||||
Authmethod *authmethod_lookup(const char *name);
|
||||
struct passwd *pwcopy(struct passwd *pw);
|
||||
int user_dsa_key_allowed(struct passwd *pw, Key *key);
|
||||
char *authmethods_get(void);
|
||||
|
||||
typedef struct Authctxt Authctxt;
|
||||
struct Authctxt {
|
||||
char *user;
|
||||
char *service;
|
||||
struct passwd pw;
|
||||
int valid;
|
||||
/* auth */
|
||||
int userauth_none(Authctxt *authctxt);
|
||||
int userauth_passwd(Authctxt *authctxt);
|
||||
int userauth_pubkey(Authctxt *authctxt);
|
||||
int userauth_kbdint(Authctxt *authctxt);
|
||||
|
||||
Authmethod authmethods[] = {
|
||||
{"none",
|
||||
userauth_none,
|
||||
&one},
|
||||
{"publickey",
|
||||
userauth_pubkey,
|
||||
&options.dsa_authentication},
|
||||
{"keyboard-interactive",
|
||||
userauth_kbdint,
|
||||
&options.kbd_interactive_authentication},
|
||||
{"password",
|
||||
userauth_passwd,
|
||||
&options.password_authentication},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
static Authctxt *authctxt = NULL;
|
||||
static int userauth_success = 0;
|
||||
|
||||
/*
|
||||
* loop until userauth_success == TRUE
|
||||
* loop until authctxt->success == TRUE
|
||||
*/
|
||||
|
||||
void
|
||||
do_authentication2()
|
||||
{
|
||||
/* turn off skey/kerberos, not supported by SSH2 */
|
||||
#ifdef SKEY
|
||||
options.skey_authentication = 0;
|
||||
#endif
|
||||
Authctxt *authctxt = xmalloc(sizeof(*authctxt));
|
||||
memset(authctxt, 'a', sizeof(*authctxt));
|
||||
authctxt->valid = 0;
|
||||
authctxt->attempt = 0;
|
||||
authctxt->success = 0;
|
||||
x_authctxt = authctxt; /*XXX*/
|
||||
|
||||
#ifdef KRB4
|
||||
/* turn off kerberos, not supported by SSH2 */
|
||||
options.kerberos_authentication = 0;
|
||||
#endif
|
||||
|
||||
dispatch_init(&protocol_error);
|
||||
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
|
||||
dispatch_run(DISPATCH_BLOCK, &userauth_success);
|
||||
dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
|
||||
do_authenticated2();
|
||||
}
|
||||
|
||||
void
|
||||
protocol_error(int type, int plen)
|
||||
protocol_error(int type, int plen, void *ctxt)
|
||||
{
|
||||
log("auth: protocol error: type %d plen %d", type, plen);
|
||||
packet_start(SSH2_MSG_UNIMPLEMENTED);
|
||||
@@ -114,15 +136,19 @@ protocol_error(int type, int plen)
|
||||
}
|
||||
|
||||
void
|
||||
input_service_request(int type, int plen)
|
||||
input_service_request(int type, int plen, void *ctxt)
|
||||
{
|
||||
Authctxt *authctxt = ctxt;
|
||||
unsigned int len;
|
||||
int accept = 0;
|
||||
char *service = packet_get_string(&len);
|
||||
packet_done();
|
||||
|
||||
if (authctxt == NULL)
|
||||
fatal("input_service_request: no authctxt");
|
||||
|
||||
if (strcmp(service, "ssh-userauth") == 0) {
|
||||
if (!userauth_success) {
|
||||
if (!authctxt->success) {
|
||||
accept = 1;
|
||||
/* now we can handle user-auth requests */
|
||||
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
|
||||
@@ -143,47 +169,89 @@ input_service_request(int type, int plen)
|
||||
}
|
||||
|
||||
void
|
||||
input_userauth_request(int type, int plen)
|
||||
input_userauth_request(int type, int plen, void *ctxt)
|
||||
{
|
||||
static void (*authlog) (const char *fmt,...) = verbose;
|
||||
static int attempt = 0;
|
||||
unsigned int len;
|
||||
Authctxt *authctxt = ctxt;
|
||||
Authmethod *m = NULL;
|
||||
char *user, *service, *method;
|
||||
int authenticated = 0;
|
||||
char *user, *service, *method, *authmsg = NULL;
|
||||
struct passwd *pw;
|
||||
|
||||
if (++attempt == AUTH_FAIL_MAX)
|
||||
if (authctxt == NULL)
|
||||
fatal("input_userauth_request: no authctxt");
|
||||
if (authctxt->attempt++ >= AUTH_FAIL_MAX)
|
||||
packet_disconnect("too many failed userauth_requests");
|
||||
|
||||
user = packet_get_string(&len);
|
||||
service = packet_get_string(&len);
|
||||
method = packet_get_string(&len);
|
||||
user = packet_get_string(NULL);
|
||||
service = packet_get_string(NULL);
|
||||
method = packet_get_string(NULL);
|
||||
debug("userauth-request for user %s service %s method %s", user, service, method);
|
||||
debug("attempt #%d", authctxt->attempt);
|
||||
|
||||
/* XXX we only allow the ssh-connection service */
|
||||
pw = auth_set_user(user, service);
|
||||
if (pw && strcmp(service, "ssh-connection")==0) {
|
||||
if (strcmp(method, "none") == 0) {
|
||||
authenticated = ssh2_auth_none(pw);
|
||||
} else if (strcmp(method, "password") == 0) {
|
||||
authenticated = ssh2_auth_password(pw);
|
||||
} else if (strcmp(method, "publickey") == 0) {
|
||||
authenticated = ssh2_auth_pubkey(pw, service);
|
||||
if (authctxt->attempt == 1) {
|
||||
/* setup auth context */
|
||||
struct passwd *pw = NULL;
|
||||
setproctitle("%s", user);
|
||||
pw = getpwnam(user);
|
||||
if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
|
||||
authctxt->pw = pwcopy(pw);
|
||||
authctxt->valid = 1;
|
||||
debug2("input_userauth_request: setting up authctxt for %s", user);
|
||||
} else {
|
||||
log("input_userauth_request: illegal user %s", user);
|
||||
}
|
||||
authctxt->user = xstrdup(user);
|
||||
authctxt->service = xstrdup(service);
|
||||
} else if (authctxt->valid) {
|
||||
if (strcmp(user, authctxt->user) != 0 ||
|
||||
strcmp(service, authctxt->service) != 0) {
|
||||
log("input_userauth_request: missmatch: (%s,%s)!=(%s,%s)",
|
||||
user, service, authctxt->user, authctxt->service);
|
||||
authctxt->valid = 0;
|
||||
}
|
||||
}
|
||||
if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
|
||||
authenticated = 0;
|
||||
log("ROOT LOGIN REFUSED FROM %.200s",
|
||||
get_canonical_hostname());
|
||||
|
||||
m = authmethod_lookup(method);
|
||||
if (m != NULL) {
|
||||
debug2("input_userauth_request: try method %s", method);
|
||||
authenticated = m->userauth(authctxt);
|
||||
} else {
|
||||
debug2("input_userauth_request: unsupported method %s", method);
|
||||
}
|
||||
if (!authctxt->valid && authenticated == 1) {
|
||||
log("input_userauth_request: INTERNAL ERROR: authenticated invalid user %s service %s", user, method);
|
||||
authenticated = 0;
|
||||
}
|
||||
|
||||
/* Special handling for root */
|
||||
if (authenticated == 1 &&
|
||||
authctxt->valid && authctxt->pw->pw_uid == 0 && !options.permit_root_login) {
|
||||
authenticated = 0;
|
||||
log("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname());
|
||||
}
|
||||
|
||||
/* Log before sending the reply */
|
||||
userauth_log(authctxt, authenticated, method);
|
||||
userauth_reply(authctxt, authenticated);
|
||||
|
||||
xfree(service);
|
||||
xfree(user);
|
||||
xfree(method);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
userauth_log(Authctxt *authctxt, int authenticated, char *method)
|
||||
{
|
||||
void (*authlog) (const char *fmt,...) = verbose;
|
||||
char *user = NULL, *authmsg = NULL;
|
||||
|
||||
/* Raise logging level */
|
||||
if (authenticated == 1 ||
|
||||
attempt == AUTH_FAIL_LOG ||
|
||||
!authctxt->valid ||
|
||||
authctxt->attempt >= AUTH_FAIL_LOG ||
|
||||
strcmp(method, "password") == 0)
|
||||
authlog = log;
|
||||
|
||||
/* Log before sending the reply */
|
||||
if (authenticated == 1) {
|
||||
authmsg = "Accepted";
|
||||
} else if (authenticated == 0) {
|
||||
@@ -191,13 +259,24 @@ input_userauth_request(int type, int plen)
|
||||
} else {
|
||||
authmsg = "Postponed";
|
||||
}
|
||||
authlog("%s %s for %.200s from %.200s port %d ssh2",
|
||||
authmsg,
|
||||
method,
|
||||
pw && pw->pw_uid == 0 ? "ROOT" : user,
|
||||
get_remote_ipaddr(),
|
||||
get_remote_port());
|
||||
|
||||
if (authctxt->valid) {
|
||||
user = authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user;
|
||||
} else {
|
||||
user = "NOUSER";
|
||||
}
|
||||
|
||||
authlog("%s %s for %.200s from %.200s port %d ssh2",
|
||||
authmsg,
|
||||
method,
|
||||
user,
|
||||
get_remote_ipaddr(),
|
||||
get_remote_port());
|
||||
}
|
||||
|
||||
void
|
||||
userauth_reply(Authctxt *authctxt, int authenticated)
|
||||
{
|
||||
/* XXX todo: check if multiple auth methods are needed */
|
||||
if (authenticated == 1) {
|
||||
/* turn off userauth */
|
||||
@@ -206,28 +285,33 @@ input_userauth_request(int type, int plen)
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
/* now we can break out */
|
||||
userauth_success = 1;
|
||||
authctxt->success = 1;
|
||||
} else if (authenticated == 0) {
|
||||
char *methods = authmethods_get();
|
||||
packet_start(SSH2_MSG_USERAUTH_FAILURE);
|
||||
packet_put_cstring("publickey,password"); /* XXX dynamic */
|
||||
packet_put_char(0); /* XXX partial success, unused */
|
||||
packet_put_cstring(methods);
|
||||
packet_put_char(0); /* XXX partial success, unused */
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
xfree(methods);
|
||||
} else {
|
||||
/* do nothing, we did already send a reply */
|
||||
}
|
||||
|
||||
xfree(service);
|
||||
xfree(user);
|
||||
xfree(method);
|
||||
}
|
||||
|
||||
int
|
||||
ssh2_auth_none(struct passwd *pw)
|
||||
userauth_none(Authctxt *authctxt)
|
||||
{
|
||||
/* disable method "none", only allowed one time */
|
||||
Authmethod *m = authmethod_lookup("none");
|
||||
if (m != NULL)
|
||||
m->enabled = NULL;
|
||||
packet_done();
|
||||
return auth_password(pw, "");
|
||||
return authctxt->valid ? auth_password(authctxt->pw, "") : 0;
|
||||
}
|
||||
|
||||
int
|
||||
ssh2_auth_password(struct passwd *pw)
|
||||
userauth_passwd(Authctxt *authctxt)
|
||||
{
|
||||
char *password;
|
||||
int authenticated = 0;
|
||||
@@ -238,15 +322,38 @@ ssh2_auth_password(struct passwd *pw)
|
||||
log("password change not supported");
|
||||
password = packet_get_string(&len);
|
||||
packet_done();
|
||||
if (options.password_authentication &&
|
||||
auth_password(pw, password) == 1)
|
||||
if (authctxt->valid &&
|
||||
auth_password(authctxt->pw, password) == 1)
|
||||
authenticated = 1;
|
||||
memset(password, 0, len);
|
||||
xfree(password);
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
int
|
||||
ssh2_auth_pubkey(struct passwd *pw, char *service)
|
||||
userauth_kbdint(Authctxt *authctxt)
|
||||
{
|
||||
int authenticated = 0;
|
||||
char *lang = NULL;
|
||||
char *devs = NULL;
|
||||
|
||||
lang = packet_get_string(NULL);
|
||||
devs = packet_get_string(NULL);
|
||||
packet_done();
|
||||
|
||||
debug("keyboard-interactive language %s devs %s", lang, devs);
|
||||
#ifdef SKEY
|
||||
/* XXX hardcoded, we should look at devs */
|
||||
if (options.skey_authentication != 0)
|
||||
authenticated = auth2_skey(authctxt);
|
||||
#endif
|
||||
xfree(lang);
|
||||
xfree(devs);
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
int
|
||||
userauth_pubkey(Authctxt *authctxt)
|
||||
{
|
||||
Buffer b;
|
||||
Key *key;
|
||||
@@ -255,15 +362,15 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
|
||||
int have_sig;
|
||||
int authenticated = 0;
|
||||
|
||||
if (options.dsa_authentication == 0) {
|
||||
debug("pubkey auth disabled");
|
||||
if (!authctxt->valid) {
|
||||
debug2("userauth_pubkey: disabled because of invalid user");
|
||||
return 0;
|
||||
}
|
||||
have_sig = packet_get_char();
|
||||
pkalg = packet_get_string(&alen);
|
||||
if (strcmp(pkalg, KEX_DSS) != 0) {
|
||||
xfree(pkalg);
|
||||
log("bad pkalg %s", pkalg); /*XXX*/
|
||||
xfree(pkalg);
|
||||
return 0;
|
||||
}
|
||||
pkblob = packet_get_string(&blen);
|
||||
@@ -273,18 +380,18 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
|
||||
sig = packet_get_string(&slen);
|
||||
packet_done();
|
||||
buffer_init(&b);
|
||||
if (datafellows & SSH_COMPAT_SESSIONID_ENCODING) {
|
||||
buffer_put_string(&b, session_id2, session_id2_len);
|
||||
} else {
|
||||
if (datafellows & SSH_OLD_SESSIONID) {
|
||||
buffer_append(&b, session_id2, session_id2_len);
|
||||
} else {
|
||||
buffer_put_string(&b, session_id2, session_id2_len);
|
||||
}
|
||||
/* reconstruct packet */
|
||||
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
|
||||
buffer_put_cstring(&b, pw->pw_name);
|
||||
buffer_put_cstring(&b, authctxt->user);
|
||||
buffer_put_cstring(&b,
|
||||
datafellows & SSH_BUG_PUBKEYAUTH ?
|
||||
"ssh-userauth" :
|
||||
service);
|
||||
authctxt->service);
|
||||
buffer_put_cstring(&b, "publickey");
|
||||
buffer_put_char(&b, have_sig);
|
||||
buffer_put_cstring(&b, KEX_DSS);
|
||||
@@ -293,15 +400,15 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
|
||||
buffer_dump(&b);
|
||||
#endif
|
||||
/* test for correct signature */
|
||||
if (user_dsa_key_allowed(pw, key) &&
|
||||
if (user_dsa_key_allowed(authctxt->pw, key) &&
|
||||
dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
|
||||
authenticated = 1;
|
||||
buffer_clear(&b);
|
||||
xfree(sig);
|
||||
} else {
|
||||
debug("test whether pkalg/pkblob are acceptable");
|
||||
packet_done();
|
||||
debug("test key...");
|
||||
/* test whether pkalg/pkblob are acceptable */
|
||||
|
||||
/* XXX fake reply and always send PK_OK ? */
|
||||
/*
|
||||
* XXX this allows testing whether a user is allowed
|
||||
@@ -310,7 +417,7 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
|
||||
* if a user is not allowed to login. is this an
|
||||
* issue? -markus
|
||||
*/
|
||||
if (user_dsa_key_allowed(pw, key)) {
|
||||
if (user_dsa_key_allowed(authctxt->pw, key)) {
|
||||
packet_start(SSH2_MSG_USERAUTH_PK_OK);
|
||||
packet_put_string(pkalg, alen);
|
||||
packet_put_string(pkblob, blen);
|
||||
@@ -319,6 +426,8 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
|
||||
authenticated = -1;
|
||||
}
|
||||
}
|
||||
if (authenticated != 1)
|
||||
auth_clear_options();
|
||||
key_free(key);
|
||||
}
|
||||
xfree(pkalg);
|
||||
@@ -326,49 +435,60 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
/* set and get current user */
|
||||
/* get current user */
|
||||
|
||||
struct passwd*
|
||||
auth_get_user(void)
|
||||
{
|
||||
return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL;
|
||||
return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL;
|
||||
}
|
||||
|
||||
struct passwd*
|
||||
auth_set_user(char *u, char *s)
|
||||
{
|
||||
struct passwd *pw, *copy;
|
||||
#define DELIM ","
|
||||
|
||||
if (authctxt == NULL) {
|
||||
authctxt = xmalloc(sizeof(*authctxt));
|
||||
authctxt->valid = 0;
|
||||
authctxt->user = xstrdup(u);
|
||||
authctxt->service = xstrdup(s);
|
||||
setproctitle("%s", u);
|
||||
pw = getpwnam(u);
|
||||
if (!pw || !allowed_user(pw)) {
|
||||
log("auth_set_user: illegal user %s", u);
|
||||
return NULL;
|
||||
}
|
||||
copy = &authctxt->pw;
|
||||
memset(copy, 0, sizeof(*copy));
|
||||
copy->pw_name = xstrdup(pw->pw_name);
|
||||
copy->pw_passwd = xstrdup(pw->pw_passwd);
|
||||
copy->pw_uid = pw->pw_uid;
|
||||
copy->pw_gid = pw->pw_gid;
|
||||
copy->pw_class = xstrdup(pw->pw_class);
|
||||
copy->pw_dir = xstrdup(pw->pw_dir);
|
||||
copy->pw_shell = xstrdup(pw->pw_shell);
|
||||
authctxt->valid = 1;
|
||||
} else {
|
||||
if (strcmp(u, authctxt->user) != 0 ||
|
||||
strcmp(s, authctxt->service) != 0) {
|
||||
log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)",
|
||||
u, s, authctxt->user, authctxt->service);
|
||||
return NULL;
|
||||
char *
|
||||
authmethods_get(void)
|
||||
{
|
||||
Authmethod *method = NULL;
|
||||
unsigned int size = 0;
|
||||
char *list;
|
||||
|
||||
for (method = authmethods; method->name != NULL; method++) {
|
||||
if (strcmp(method->name, "none") == 0)
|
||||
continue;
|
||||
if (method->enabled != NULL && *(method->enabled) != 0) {
|
||||
if (size != 0)
|
||||
size += strlen(DELIM);
|
||||
size += strlen(method->name);
|
||||
}
|
||||
}
|
||||
return auth_get_user();
|
||||
size++; /* trailing '\0' */
|
||||
list = xmalloc(size);
|
||||
list[0] = '\0';
|
||||
|
||||
for (method = authmethods; method->name != NULL; method++) {
|
||||
if (strcmp(method->name, "none") == 0)
|
||||
continue;
|
||||
if (method->enabled != NULL && *(method->enabled) != 0) {
|
||||
if (list[0] != '\0')
|
||||
strlcat(list, DELIM, size);
|
||||
strlcat(list, method->name, size);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
Authmethod *
|
||||
authmethod_lookup(const char *name)
|
||||
{
|
||||
Authmethod *method = NULL;
|
||||
if (name != NULL)
|
||||
for (method = authmethods; method->name != NULL; method++)
|
||||
if (method->enabled != NULL &&
|
||||
*(method->enabled) != 0 &&
|
||||
strcmp(name, method->name) == 0)
|
||||
return method;
|
||||
debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* return 1 if user allows given key */
|
||||
@@ -383,6 +503,9 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
||||
struct stat st;
|
||||
Key *found;
|
||||
|
||||
if (pw == NULL)
|
||||
return 0;
|
||||
|
||||
/* Temporarily use the user's uid. */
|
||||
temporarily_use_uid(pw->pw_uid);
|
||||
|
||||
@@ -410,8 +533,10 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
||||
if (fstat(fileno(f), &st) < 0 ||
|
||||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
|
||||
(st.st_mode & 022) != 0) {
|
||||
snprintf(buf, sizeof buf, "DSA authentication refused for %.100s: "
|
||||
"bad ownership or modes for '%s'.", pw->pw_name, file);
|
||||
snprintf(buf, sizeof buf,
|
||||
"%s authentication refused for %.100s: "
|
||||
"bad ownership or modes for '%s'.",
|
||||
key_type(key), pw->pw_name, file);
|
||||
fail = 1;
|
||||
} else {
|
||||
/* Check path to SSH_USER_PERMITTED_KEYS */
|
||||
@@ -426,9 +551,9 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
||||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
|
||||
(st.st_mode & 022) != 0) {
|
||||
snprintf(buf, sizeof buf,
|
||||
"DSA authentication refused for %.100s: "
|
||||
"%s authentication refused for %.100s: "
|
||||
"bad ownership or modes for '%s'.",
|
||||
pw->pw_name, line);
|
||||
key_type(key), pw->pw_name, line);
|
||||
fail = 1;
|
||||
break;
|
||||
}
|
||||
@@ -442,7 +567,7 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
||||
}
|
||||
}
|
||||
found_key = 0;
|
||||
found = key_new(KEY_DSA);
|
||||
found = key_new(key->type);
|
||||
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
char *cp, *options = NULL;
|
||||
@@ -486,3 +611,18 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
||||
key_free(found);
|
||||
return found_key;
|
||||
}
|
||||
|
||||
struct passwd *
|
||||
pwcopy(struct passwd *pw)
|
||||
{
|
||||
struct passwd *copy = xmalloc(sizeof(*copy));
|
||||
memset(copy, 0, sizeof(*copy));
|
||||
copy->pw_name = xstrdup(pw->pw_name);
|
||||
copy->pw_passwd = xstrdup(pw->pw_passwd);
|
||||
copy->pw_uid = pw->pw_uid;
|
||||
copy->pw_gid = pw->pw_gid;
|
||||
copy->pw_class = xstrdup(pw->pw_class);
|
||||
copy->pw_dir = xstrdup(pw->pw_dir);
|
||||
copy->pw_shell = xstrdup(pw->pw_shell);
|
||||
return copy;
|
||||
}
|
||||
|
||||
+16
-6
@@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: authfd.c,v 1.27 2000/09/07 20:27:49 deraadt Exp $");
|
||||
RCSID("$OpenBSD: authfd.c,v 1.29 2000/10/09 21:51:00 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "rsa.h"
|
||||
@@ -51,10 +51,15 @@ RCSID("$OpenBSD: authfd.c,v 1.27 2000/09/07 20:27:49 deraadt Exp $");
|
||||
#include "authfd.h"
|
||||
#include "kex.h"
|
||||
#include "dsa.h"
|
||||
#include "compat.h"
|
||||
|
||||
/* helper */
|
||||
int decode_reply(int type);
|
||||
|
||||
/* macro to check for "agent failure" message */
|
||||
#define agent_failed(x) \
|
||||
((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE))
|
||||
|
||||
/* Returns the number of the authentication fd, or -1 if there is none. */
|
||||
|
||||
int
|
||||
@@ -237,7 +242,7 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
|
||||
|
||||
/* Get message type, and verify that we got a proper answer. */
|
||||
type = buffer_get_char(&auth->identities);
|
||||
if (type == SSH_AGENT_FAILURE) {
|
||||
if (agent_failed(type)) {
|
||||
return NULL;
|
||||
} else if (type != code2) {
|
||||
fatal("Bad authentication reply message type: %d", type);
|
||||
@@ -336,7 +341,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
|
||||
}
|
||||
type = buffer_get_char(&buffer);
|
||||
|
||||
if (type == SSH_AGENT_FAILURE) {
|
||||
if (agent_failed(type)) {
|
||||
log("Agent admitted failure to authenticate using the key.");
|
||||
} else if (type != SSH_AGENT_RSA_RESPONSE) {
|
||||
fatal("Bad authentication response: %d", type);
|
||||
@@ -360,20 +365,24 @@ ssh_agent_sign(AuthenticationConnection *auth,
|
||||
unsigned char **sigp, int *lenp,
|
||||
unsigned char *data, int datalen)
|
||||
{
|
||||
extern int datafellows;
|
||||
Buffer msg;
|
||||
unsigned char *blob;
|
||||
unsigned int blen;
|
||||
int type;
|
||||
int type, flags = 0;
|
||||
int ret = -1;
|
||||
|
||||
if (dsa_make_key_blob(key, &blob, &blen) == 0)
|
||||
return -1;
|
||||
|
||||
if (datafellows & SSH_BUG_SIGBLOB)
|
||||
flags = SSH_AGENT_OLD_SIGNATURE;
|
||||
|
||||
buffer_init(&msg);
|
||||
buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
|
||||
buffer_put_string(&msg, blob, blen);
|
||||
buffer_put_string(&msg, data, datalen);
|
||||
buffer_put_int(&msg, 0); /* flags, unused */
|
||||
buffer_put_int(&msg, flags);
|
||||
xfree(blob);
|
||||
|
||||
if (ssh_request_reply(auth, &msg, &msg) == 0) {
|
||||
@@ -381,7 +390,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
|
||||
return -1;
|
||||
}
|
||||
type = buffer_get_char(&msg);
|
||||
if (type == SSH_AGENT_FAILURE) {
|
||||
if (agent_failed(type)) {
|
||||
log("Agent admitted failure to sign using the key.");
|
||||
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
|
||||
fatal("Bad authentication response: %d", type);
|
||||
@@ -528,6 +537,7 @@ decode_reply(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case SSH_AGENT_FAILURE:
|
||||
case SSH_COM_AGENT2_FAILURE:
|
||||
log("SSH_AGENT_FAILURE");
|
||||
return 0;
|
||||
case SSH_AGENT_SUCCESS:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: authfd.h,v 1.11 2000/09/07 20:27:49 deraadt Exp $"); */
|
||||
/* RCSID("$OpenBSD: authfd.h,v 1.13 2000/10/09 21:51:00 markus Exp $"); */
|
||||
|
||||
#ifndef AUTHFD_H
|
||||
#define AUTHFD_H
|
||||
@@ -29,6 +29,7 @@
|
||||
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
|
||||
#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
|
||||
|
||||
/* private OpenSSH extensions for SSH2 */
|
||||
#define SSH2_AGENTC_REQUEST_IDENTITIES 11
|
||||
#define SSH2_AGENT_IDENTITIES_ANSWER 12
|
||||
#define SSH2_AGENTC_SIGN_REQUEST 13
|
||||
@@ -37,6 +38,12 @@
|
||||
#define SSH2_AGENTC_REMOVE_IDENTITY 18
|
||||
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
|
||||
|
||||
/* additional error code for ssh.com's ssh-agent2 */
|
||||
#define SSH_COM_AGENT2_FAILURE 102
|
||||
|
||||
#define SSH_AGENT_OLD_SIGNATURE 0x01
|
||||
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
Buffer identities;
|
||||
|
||||
+22
-22
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp $");
|
||||
RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $");
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
@@ -47,7 +47,6 @@ RCSID("$OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp $");
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
#include "cipher.h"
|
||||
#include "ssh.h"
|
||||
#include "key.h"
|
||||
|
||||
@@ -68,8 +67,8 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
||||
Buffer buffer, encrypted;
|
||||
char buf[100], *cp;
|
||||
int fd, i;
|
||||
CipherContext cipher;
|
||||
int cipher_type;
|
||||
CipherContext ciphercontext;
|
||||
Cipher *cipher;
|
||||
u_int32_t rand;
|
||||
|
||||
/*
|
||||
@@ -77,9 +76,11 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
||||
* to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
|
||||
*/
|
||||
if (strcmp(passphrase, "") == 0)
|
||||
cipher_type = SSH_CIPHER_NONE;
|
||||
cipher = cipher_by_number(SSH_CIPHER_NONE);
|
||||
else
|
||||
cipher_type = SSH_AUTHFILE_CIPHER;
|
||||
cipher = cipher_by_number(SSH_AUTHFILE_CIPHER);
|
||||
if (cipher == NULL)
|
||||
fatal("save_private_key_rsa: bad cipher");
|
||||
|
||||
/* This buffer is used to built the secret part of the private key. */
|
||||
buffer_init(&buffer);
|
||||
@@ -116,7 +117,7 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
||||
buffer_put_char(&encrypted, 0);
|
||||
|
||||
/* Store cipher type. */
|
||||
buffer_put_char(&encrypted, cipher_type);
|
||||
buffer_put_char(&encrypted, cipher->number);
|
||||
buffer_put_int(&encrypted, 0); /* For future extension */
|
||||
|
||||
/* Store public key. This will be in plain text. */
|
||||
@@ -128,11 +129,10 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
||||
/* Allocate space for the private part of the key in the buffer. */
|
||||
buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
|
||||
|
||||
cipher_set_key_string(&cipher, cipher_type, passphrase);
|
||||
cipher_encrypt(&cipher, (unsigned char *) cp,
|
||||
(unsigned char *) buffer_ptr(&buffer),
|
||||
buffer_len(&buffer));
|
||||
memset(&cipher, 0, sizeof(cipher));
|
||||
cipher_set_key_string(&ciphercontext, cipher, passphrase);
|
||||
cipher_encrypt(&ciphercontext, (unsigned char *) cp,
|
||||
(unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
|
||||
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
||||
|
||||
/* Destroy temporary data. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
@@ -313,7 +313,8 @@ load_private_key_rsa(int fd, const char *filename,
|
||||
off_t len;
|
||||
Buffer buffer, decrypted;
|
||||
char *cp;
|
||||
CipherContext cipher;
|
||||
CipherContext ciphercontext;
|
||||
Cipher *cipher;
|
||||
BN_CTX *ctx;
|
||||
BIGNUM *aux;
|
||||
|
||||
@@ -364,10 +365,10 @@ load_private_key_rsa(int fd, const char *filename,
|
||||
xfree(buffer_get_string(&buffer, NULL));
|
||||
|
||||
/* Check that it is a supported cipher. */
|
||||
if (((cipher_mask1() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
|
||||
(1 << cipher_type)) == 0) {
|
||||
debug("Unsupported cipher %.100s used in key file %.200s.",
|
||||
cipher_name(cipher_type), filename);
|
||||
cipher = cipher_by_number(cipher_type);
|
||||
if (cipher == NULL) {
|
||||
debug("Unsupported cipher %d used in key file %.200s.",
|
||||
cipher_type, filename);
|
||||
buffer_free(&buffer);
|
||||
goto fail;
|
||||
}
|
||||
@@ -376,11 +377,10 @@ load_private_key_rsa(int fd, const char *filename,
|
||||
buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
|
||||
|
||||
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
|
||||
cipher_set_key_string(&cipher, cipher_type, passphrase);
|
||||
cipher_decrypt(&cipher, (unsigned char *) cp,
|
||||
(unsigned char *) buffer_ptr(&buffer),
|
||||
buffer_len(&buffer));
|
||||
|
||||
cipher_set_key_string(&ciphercontext, cipher, passphrase);
|
||||
cipher_decrypt(&ciphercontext, (unsigned char *) cp,
|
||||
(unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
|
||||
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
||||
buffer_free(&buffer);
|
||||
|
||||
check1 = buffer_get_char(&decrypted);
|
||||
|
||||
@@ -10,9 +10,13 @@
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* $OpenBSD: authfile.h,v 1.5 2000/10/16 09:38:44 djm Exp $ */
|
||||
|
||||
#ifndef AUTHFILE_H
|
||||
#define AUTHFILE_H
|
||||
|
||||
|
||||
/*
|
||||
* Saves the authentication (private) key in a file, encrypting it with
|
||||
* passphrase.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: canohost.c,v 1.15 2000/09/07 21:13:37 markus Exp $");
|
||||
RCSID("$OpenBSD: canohost.c,v 1.16 2000/10/21 17:04:22 markus Exp $");
|
||||
|
||||
#include "packet.h"
|
||||
#include "xmalloc.h"
|
||||
@@ -123,7 +123,7 @@ get_remote_hostname(int socket)
|
||||
else
|
||||
ipproto = IPPROTO_IP;
|
||||
option_size = sizeof(options);
|
||||
if (getsockopt(0, ipproto, IP_OPTIONS, (char *) options,
|
||||
if (getsockopt(socket, ipproto, IP_OPTIONS, (char *) options,
|
||||
&option_size) >= 0 && option_size != 0) {
|
||||
cp = text;
|
||||
/* Note: "text" buffer must be at least 3x as big as options. */
|
||||
|
||||
+69
-42
@@ -40,7 +40,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: channels.c,v 1.68 2000/09/07 20:40:29 markus Exp $");
|
||||
RCSID("$OpenBSD: channels.c,v 1.72 2000/10/27 07:48:22 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
@@ -174,7 +174,8 @@ channel_lookup(int id)
|
||||
*/
|
||||
|
||||
void
|
||||
channel_register_fds(Channel *c, int rfd, int wfd, int efd, int extusage)
|
||||
channel_register_fds(Channel *c, int rfd, int wfd, int efd,
|
||||
int extusage, int nonblock)
|
||||
{
|
||||
/* Update the maximum file descriptor value. */
|
||||
if (rfd > channel_max_fd_value)
|
||||
@@ -190,12 +191,16 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd, int extusage)
|
||||
c->sock = (rfd == wfd) ? rfd : -1;
|
||||
c->efd = efd;
|
||||
c->extended_usage = extusage;
|
||||
if (rfd != -1)
|
||||
set_nonblock(rfd);
|
||||
if (wfd != -1)
|
||||
set_nonblock(wfd);
|
||||
if (efd != -1)
|
||||
set_nonblock(efd);
|
||||
|
||||
/* enable nonblocking mode */
|
||||
if (nonblock) {
|
||||
if (rfd != -1)
|
||||
set_nonblock(rfd);
|
||||
if (wfd != -1)
|
||||
set_nonblock(wfd);
|
||||
if (efd != -1)
|
||||
set_nonblock(efd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -205,7 +210,7 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd, int extusage)
|
||||
|
||||
int
|
||||
channel_new(char *ctype, int type, int rfd, int wfd, int efd,
|
||||
int window, int maxpack, int extusage, char *remote_name)
|
||||
int window, int maxpack, int extusage, char *remote_name, int nonblock)
|
||||
{
|
||||
int i, found;
|
||||
Channel *c;
|
||||
@@ -234,7 +239,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
|
||||
/* There are no free slots. Take last+1 slot and expand the array. */
|
||||
found = channels_alloc;
|
||||
channels_alloc += 10;
|
||||
debug("channel: expanding %d", channels_alloc);
|
||||
debug2("channel: expanding %d", channels_alloc);
|
||||
channels = xrealloc(channels, channels_alloc * sizeof(Channel));
|
||||
for (i = found; i < channels_alloc; i++)
|
||||
channels[i].type = SSH_CHANNEL_FREE;
|
||||
@@ -245,7 +250,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
|
||||
buffer_init(&c->output);
|
||||
buffer_init(&c->extended);
|
||||
chan_init_iostates(c);
|
||||
channel_register_fds(c, rfd, wfd, efd, extusage);
|
||||
channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
|
||||
c->self = found;
|
||||
c->type = type;
|
||||
c->ctype = ctype;
|
||||
@@ -269,7 +274,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
|
||||
int
|
||||
channel_allocate(int type, int sock, char *remote_name)
|
||||
{
|
||||
return channel_new("", type, sock, sock, -1, 0, 0, 0, remote_name);
|
||||
return channel_new("", type, sock, sock, -1, 0, 0, 0, remote_name, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -548,7 +553,7 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
newch = channel_new("x11",
|
||||
SSH_CHANNEL_OPENING, newsock, newsock, -1,
|
||||
c->local_window_max, c->local_maxpacket,
|
||||
0, xstrdup(buf));
|
||||
0, xstrdup(buf), 1);
|
||||
if (compat20) {
|
||||
packet_start(SSH2_MSG_CHANNEL_OPEN);
|
||||
packet_put_cstring("x11");
|
||||
@@ -606,7 +611,7 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
newch = channel_new("direct-tcpip",
|
||||
SSH_CHANNEL_OPENING, newsock, newsock, -1,
|
||||
c->local_window_max, c->local_maxpacket,
|
||||
0, xstrdup(buf));
|
||||
0, xstrdup(buf), 1);
|
||||
if (compat20) {
|
||||
packet_start(SSH2_MSG_CHANNEL_OPEN);
|
||||
packet_put_cstring("direct-tcpip");
|
||||
@@ -737,7 +742,7 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
buffer_len(&c->extended) > 0) {
|
||||
len = write(c->efd, buffer_ptr(&c->extended),
|
||||
buffer_len(&c->extended));
|
||||
debug("channel %d: written %d to efd %d",
|
||||
debug2("channel %d: written %d to efd %d",
|
||||
c->self, len, c->efd);
|
||||
if (len > 0) {
|
||||
buffer_consume(&c->extended, len);
|
||||
@@ -746,7 +751,7 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
} else if (c->extended_usage == CHAN_EXTENDED_READ &&
|
||||
FD_ISSET(c->efd, readset)) {
|
||||
len = read(c->efd, buf, sizeof(buf));
|
||||
debug("channel %d: read %d from efd %d",
|
||||
debug2("channel %d: read %d from efd %d",
|
||||
c->self, len, c->efd);
|
||||
if (len == 0) {
|
||||
debug("channel %d: closing efd %d",
|
||||
@@ -769,7 +774,7 @@ channel_check_window(Channel *c, fd_set * readset, fd_set * writeset)
|
||||
packet_put_int(c->remote_id);
|
||||
packet_put_int(c->local_consumed);
|
||||
packet_send();
|
||||
debug("channel %d: window %d sent adjust %d",
|
||||
debug2("channel %d: window %d sent adjust %d",
|
||||
c->self, c->local_window,
|
||||
c->local_consumed);
|
||||
c->local_window += c->local_consumed;
|
||||
@@ -998,7 +1003,7 @@ channel_output_poll()
|
||||
*/
|
||||
|
||||
void
|
||||
channel_input_data(int type, int plen)
|
||||
channel_input_data(int type, int plen, void *ctxt)
|
||||
{
|
||||
int id;
|
||||
char *data;
|
||||
@@ -1043,7 +1048,7 @@ channel_input_data(int type, int plen)
|
||||
xfree(data);
|
||||
}
|
||||
void
|
||||
channel_input_extended_data(int type, int plen)
|
||||
channel_input_extended_data(int type, int plen, void *ctxt)
|
||||
{
|
||||
int id;
|
||||
int tcode;
|
||||
@@ -1076,7 +1081,7 @@ channel_input_extended_data(int type, int plen)
|
||||
xfree(data);
|
||||
return;
|
||||
}
|
||||
debug("channel %d: rcvd ext data %d", c->self, data_len);
|
||||
debug2("channel %d: rcvd ext data %d", c->self, data_len);
|
||||
c->local_window -= data_len;
|
||||
buffer_append(&c->extended, data, data_len);
|
||||
xfree(data);
|
||||
@@ -1113,7 +1118,7 @@ channel_not_very_much_buffered_data()
|
||||
}
|
||||
|
||||
void
|
||||
channel_input_ieof(int type, int plen)
|
||||
channel_input_ieof(int type, int plen, void *ctxt)
|
||||
{
|
||||
int id;
|
||||
Channel *c;
|
||||
@@ -1128,7 +1133,7 @@ channel_input_ieof(int type, int plen)
|
||||
}
|
||||
|
||||
void
|
||||
channel_input_close(int type, int plen)
|
||||
channel_input_close(int type, int plen, void *ctxt)
|
||||
{
|
||||
int id;
|
||||
Channel *c;
|
||||
@@ -1167,7 +1172,7 @@ channel_input_close(int type, int plen)
|
||||
|
||||
/* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
|
||||
void
|
||||
channel_input_oclose(int type, int plen)
|
||||
channel_input_oclose(int type, int plen, void *ctxt)
|
||||
{
|
||||
int id = packet_get_int();
|
||||
Channel *c = channel_lookup(id);
|
||||
@@ -1178,7 +1183,7 @@ channel_input_oclose(int type, int plen)
|
||||
}
|
||||
|
||||
void
|
||||
channel_input_close_confirmation(int type, int plen)
|
||||
channel_input_close_confirmation(int type, int plen, void *ctxt)
|
||||
{
|
||||
int id = packet_get_int();
|
||||
Channel *c = channel_lookup(id);
|
||||
@@ -1194,7 +1199,7 @@ channel_input_close_confirmation(int type, int plen)
|
||||
}
|
||||
|
||||
void
|
||||
channel_input_open_confirmation(int type, int plen)
|
||||
channel_input_open_confirmation(int type, int plen, void *ctxt)
|
||||
{
|
||||
int id, remote_id;
|
||||
Channel *c;
|
||||
@@ -1218,9 +1223,9 @@ channel_input_open_confirmation(int type, int plen)
|
||||
c->remote_maxpacket = packet_get_int();
|
||||
packet_done();
|
||||
if (c->cb_fn != NULL && c->cb_event == type) {
|
||||
debug("callback start");
|
||||
debug2("callback start");
|
||||
c->cb_fn(c->self, c->cb_arg);
|
||||
debug("callback done");
|
||||
debug2("callback done");
|
||||
}
|
||||
debug("channel %d: open confirm rwindow %d rmax %d", c->self,
|
||||
c->remote_window, c->remote_maxpacket);
|
||||
@@ -1228,7 +1233,7 @@ channel_input_open_confirmation(int type, int plen)
|
||||
}
|
||||
|
||||
void
|
||||
channel_input_open_failure(int type, int plen)
|
||||
channel_input_open_failure(int type, int plen, void *ctxt)
|
||||
{
|
||||
int id;
|
||||
Channel *c;
|
||||
@@ -1256,7 +1261,7 @@ channel_input_open_failure(int type, int plen)
|
||||
}
|
||||
|
||||
void
|
||||
channel_input_channel_request(int type, int plen)
|
||||
channel_input_channel_request(int type, int plen, void *ctxt)
|
||||
{
|
||||
int id;
|
||||
Channel *c;
|
||||
@@ -1269,19 +1274,19 @@ channel_input_channel_request(int type, int plen)
|
||||
packet_disconnect("Received request for "
|
||||
"non-open channel %d.", id);
|
||||
if (c->cb_fn != NULL && c->cb_event == type) {
|
||||
debug("callback start");
|
||||
debug2("callback start");
|
||||
c->cb_fn(c->self, c->cb_arg);
|
||||
debug("callback done");
|
||||
debug2("callback done");
|
||||
} else {
|
||||
char *service = packet_get_string(NULL);
|
||||
debug("channel: %d rcvd request for %s", c->self, service);
|
||||
debug("cb_fn %p cb_event %d", c->cb_fn , c->cb_event);
|
||||
debug("cb_fn %p cb_event %d", c->cb_fn , c->cb_event);
|
||||
xfree(service);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
channel_input_window_adjust(int type, int plen)
|
||||
channel_input_window_adjust(int type, int plen, void *ctxt)
|
||||
{
|
||||
Channel *c;
|
||||
int id, adjust;
|
||||
@@ -1300,7 +1305,7 @@ channel_input_window_adjust(int type, int plen)
|
||||
}
|
||||
adjust = packet_get_int();
|
||||
packet_done();
|
||||
debug("channel %d: rcvd adjust %d", id, adjust);
|
||||
debug2("channel %d: rcvd adjust %d", id, adjust);
|
||||
c->remote_window += adjust;
|
||||
}
|
||||
|
||||
@@ -1510,7 +1515,7 @@ channel_request_local_forwarding(u_short port, const char *host,
|
||||
"port listener", SSH_CHANNEL_PORT_LISTENER,
|
||||
sock, sock, -1,
|
||||
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
|
||||
0, xstrdup("port listener"));
|
||||
0, xstrdup("port listener"), 1);
|
||||
strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
|
||||
channels[ch].host_port = host_port;
|
||||
channels[ch].listening_port = port;
|
||||
@@ -1652,7 +1657,7 @@ channel_connect_to(const char *host, u_short host_port)
|
||||
*/
|
||||
|
||||
void
|
||||
channel_input_port_open(int type, int plen)
|
||||
channel_input_port_open(int type, int plen, void *ctxt)
|
||||
{
|
||||
u_short host_port;
|
||||
char *host, *originator_string;
|
||||
@@ -1800,7 +1805,7 @@ x11_create_display_inet(int screen_number, int x11_display_offset)
|
||||
(void) channel_new("x11 listener",
|
||||
SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
|
||||
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
|
||||
0, xstrdup("X11 inet listener"));
|
||||
0, xstrdup("X11 inet listener"), 1);
|
||||
}
|
||||
|
||||
/* Return a suitable value for the DISPLAY environment variable. */
|
||||
@@ -1942,7 +1947,7 @@ x11_connect_display(void)
|
||||
*/
|
||||
|
||||
void
|
||||
x11_input_open(int type, int plen)
|
||||
x11_input_open(int type, int plen, void *ctxt)
|
||||
{
|
||||
int remote_channel, sock = 0, newch;
|
||||
char *remote_host;
|
||||
@@ -1986,6 +1991,28 @@ x11_input_open(int type, int plen)
|
||||
}
|
||||
}
|
||||
|
||||
/* dummy protocol handler that denies SSH-1 requests (agent/x11) */
|
||||
void
|
||||
deny_input_open(int type, int plen, void *ctxt)
|
||||
{
|
||||
int rchan = packet_get_int();
|
||||
switch(type){
|
||||
case SSH_SMSG_AGENT_OPEN:
|
||||
error("Warning: ssh server tried agent forwarding.");
|
||||
break;
|
||||
case SSH_SMSG_X11_OPEN:
|
||||
error("Warning: ssh server tried X11 forwarding.");
|
||||
break;
|
||||
default:
|
||||
error("deny_input_open: type %d plen %d", type, plen);
|
||||
break;
|
||||
}
|
||||
error("Warning: this is probably a break in attempt by a malicious server.");
|
||||
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
|
||||
packet_put_int(rchan);
|
||||
packet_send();
|
||||
}
|
||||
|
||||
/*
|
||||
* Requests forwarding of X11 connections, generates fake authentication
|
||||
* data, and enables authentication spoofing.
|
||||
@@ -2157,7 +2184,7 @@ auth_input_request_forwarding(struct passwd * pw)
|
||||
/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
|
||||
|
||||
void
|
||||
auth_input_open_request(int type, int plen)
|
||||
auth_input_open_request(int type, int plen, void *ctxt)
|
||||
{
|
||||
int remch, sock, newch;
|
||||
char *dummyname;
|
||||
@@ -2290,13 +2317,13 @@ channel_register_filter(int id, channel_filter_fn *fn)
|
||||
}
|
||||
|
||||
void
|
||||
channel_set_fds(int id, int rfd, int wfd, int efd, int extusage)
|
||||
channel_set_fds(int id, int rfd, int wfd, int efd,
|
||||
int extusage, int nonblock)
|
||||
{
|
||||
Channel *c = channel_lookup(id);
|
||||
if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
|
||||
fatal("channel_activate for non-larval channel %d.", id);
|
||||
|
||||
channel_register_fds(c, rfd, wfd, efd, extusage);
|
||||
channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
|
||||
c->type = SSH_CHANNEL_OPEN;
|
||||
/* XXX window size? */
|
||||
c->local_window = c->local_window_max = c->local_maxpacket * 2;
|
||||
|
||||
+22
-17
@@ -32,7 +32,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.
|
||||
*/
|
||||
/* RCSID("$OpenBSD: channels.h,v 1.19 2000/09/07 21:13:37 markus Exp $"); */
|
||||
/* RCSID("$OpenBSD: channels.h,v 1.22 2000/10/27 07:48:22 markus Exp $"); */
|
||||
|
||||
#ifndef CHANNELS_H
|
||||
#define CHANNELS_H
|
||||
@@ -117,7 +117,6 @@ struct Channel {
|
||||
#define CHAN_X11_PACKET_DEFAULT (CHAN_X11_WINDOW_DEFAULT/2)
|
||||
|
||||
|
||||
void channel_set_fds(int id, int rfd, int wfd, int efd, int extusage);
|
||||
void channel_open(int id);
|
||||
void channel_request(int id, char *service, int wantconfirm);
|
||||
void channel_request_start(int id, char *service, int wantconfirm);
|
||||
@@ -129,20 +128,26 @@ Channel *channel_lookup(int id);
|
||||
|
||||
int
|
||||
channel_new(char *ctype, int type, int rfd, int wfd, int efd,
|
||||
int window, int maxpack, int extended_usage, char *remote_name);
|
||||
int window, int maxpack, int extended_usage, char *remote_name,
|
||||
int nonblock);
|
||||
void
|
||||
channel_set_fds(int id, int rfd, int wfd, int efd,
|
||||
int extusage, int nonblock);
|
||||
|
||||
void channel_input_channel_request(int type, int plen);
|
||||
void channel_input_close(int type, int plen);
|
||||
void channel_input_close_confirmation(int type, int plen);
|
||||
void channel_input_data(int type, int plen);
|
||||
void channel_input_extended_data(int type, int plen);
|
||||
void channel_input_ieof(int type, int plen);
|
||||
void channel_input_oclose(int type, int plen);
|
||||
void channel_input_open_confirmation(int type, int plen);
|
||||
void channel_input_open_failure(int type, int plen);
|
||||
void channel_input_port_open(int type, int plen);
|
||||
void channel_input_window_adjust(int type, int plen);
|
||||
void channel_input_open(int type, int plen);
|
||||
void deny_input_open(int type, int plen, void *ctxt);
|
||||
|
||||
void channel_input_channel_request(int type, int plen, void *ctxt);
|
||||
void channel_input_close(int type, int plen, void *ctxt);
|
||||
void channel_input_close_confirmation(int type, int plen, void *ctxt);
|
||||
void channel_input_data(int type, int plen, void *ctxt);
|
||||
void channel_input_extended_data(int type, int plen, void *ctxt);
|
||||
void channel_input_ieof(int type, int plen, void *ctxt);
|
||||
void channel_input_oclose(int type, int plen, void *ctxt);
|
||||
void channel_input_open_confirmation(int type, int plen, void *ctxt);
|
||||
void channel_input_open_failure(int type, int plen, void *ctxt);
|
||||
void channel_input_port_open(int type, int plen, void *ctxt);
|
||||
void channel_input_window_adjust(int type, int plen, void *ctxt);
|
||||
void channel_input_open(int type, int plen, void *ctxt);
|
||||
|
||||
/* Sets specific protocol options. */
|
||||
void channel_set_options(int hostname_in_open);
|
||||
@@ -246,7 +251,7 @@ char *x11_create_display_inet(int screen, int x11_display_offset);
|
||||
* the remote channel number. We should do whatever we want, and respond
|
||||
* with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE.
|
||||
*/
|
||||
void x11_input_open(int type, int plen);
|
||||
void x11_input_open(int type, int plen, void *ctxt);
|
||||
|
||||
/*
|
||||
* Requests forwarding of X11 connections. This should be called on the
|
||||
@@ -279,7 +284,7 @@ char *auth_get_socket_name(void);
|
||||
int auth_input_request_forwarding(struct passwd * pw);
|
||||
|
||||
/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
|
||||
void auth_input_open_request(int type, int plen);
|
||||
void auth_input_open_request(int type, int plen, void *ctxt);
|
||||
|
||||
/* XXX */
|
||||
int channel_connect_to(const char *host, u_short host_port);
|
||||
|
||||
+407
-329
@@ -35,14 +35,91 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: cipher.c,v 1.30 2000/09/07 20:27:50 deraadt Exp $");
|
||||
RCSID("$OpenBSD: cipher.c,v 1.37 2000/10/23 19:31:54 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "cipher.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#include <openssl/md5.h>
|
||||
|
||||
|
||||
/* no encryption */
|
||||
void
|
||||
none_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||
{
|
||||
}
|
||||
void
|
||||
none_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
||||
{
|
||||
}
|
||||
void
|
||||
none_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
memcpy(dest, src, len);
|
||||
}
|
||||
|
||||
/* DES */
|
||||
void
|
||||
des_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||
{
|
||||
static int dowarn = 1;
|
||||
if (dowarn) {
|
||||
error("Warning: use of DES is strongly discouraged "
|
||||
"due to cryptographic weaknesses");
|
||||
dowarn = 0;
|
||||
}
|
||||
des_set_key((void *)key, cc->u.des.key);
|
||||
}
|
||||
void
|
||||
des_ssh1_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
||||
{
|
||||
memset(cc->u.des.iv, 0, sizeof(cc->u.des.iv));
|
||||
}
|
||||
void
|
||||
des_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
|
||||
DES_ENCRYPT);
|
||||
}
|
||||
void
|
||||
des_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
|
||||
DES_DECRYPT);
|
||||
}
|
||||
|
||||
/* 3DES */
|
||||
void
|
||||
des3_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||
{
|
||||
des_set_key((void *) key, cc->u.des3.key1);
|
||||
des_set_key((void *) (key+8), cc->u.des3.key2);
|
||||
des_set_key((void *) (key+16), cc->u.des3.key3);
|
||||
}
|
||||
void
|
||||
des3_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
||||
{
|
||||
memset(cc->u.des3.iv2, 0, sizeof(cc->u.des3.iv2));
|
||||
memset(cc->u.des3.iv3, 0, sizeof(cc->u.des3.iv3));
|
||||
if (iv == NULL)
|
||||
return;
|
||||
memcpy(cc->u.des3.iv3, (char *)iv, 8);
|
||||
}
|
||||
void
|
||||
des3_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
des_ede3_cbc_encrypt(src, dest, len,
|
||||
cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,
|
||||
&cc->u.des3.iv3, DES_ENCRYPT);
|
||||
}
|
||||
void
|
||||
des3_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
des_ede3_cbc_encrypt(src, dest, len,
|
||||
cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,
|
||||
&cc->u.des3.iv3, DES_DECRYPT);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is used by SSH1:
|
||||
*
|
||||
@@ -58,160 +135,356 @@ RCSID("$OpenBSD: cipher.c,v 1.30 2000/09/07 20:27:50 deraadt Exp $");
|
||||
* choosing the X block.
|
||||
*/
|
||||
void
|
||||
SSH_3CBC_ENCRYPT(des_key_schedule ks1,
|
||||
des_key_schedule ks2, des_cblock * iv2,
|
||||
des_key_schedule ks3, des_cblock * iv3,
|
||||
unsigned char *dest, unsigned char *src,
|
||||
unsigned int len)
|
||||
des3_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||
{
|
||||
des_set_key((void *) key, cc->u.des3.key1);
|
||||
des_set_key((void *) (key+8), cc->u.des3.key2);
|
||||
if (keylen <= 16)
|
||||
des_set_key((void *) key, cc->u.des3.key3);
|
||||
else
|
||||
des_set_key((void *) (key+16), cc->u.des3.key3);
|
||||
}
|
||||
void
|
||||
des3_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
||||
u_int len)
|
||||
{
|
||||
des_cblock iv1;
|
||||
des_cblock *iv2 = &cc->u.des3.iv2;
|
||||
des_cblock *iv3 = &cc->u.des3.iv3;
|
||||
|
||||
memcpy(&iv1, iv2, 8);
|
||||
|
||||
des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT);
|
||||
des_cbc_encrypt(src, dest, len, cc->u.des3.key1, &iv1, DES_ENCRYPT);
|
||||
memcpy(&iv1, dest + len - 8, 8);
|
||||
|
||||
des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT);
|
||||
des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_DECRYPT);
|
||||
memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */
|
||||
|
||||
des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT);
|
||||
des_cbc_encrypt(dest, dest, len, cc->u.des3.key3, iv3, DES_ENCRYPT);
|
||||
memcpy(iv3, dest + len - 8, 8);
|
||||
}
|
||||
|
||||
void
|
||||
SSH_3CBC_DECRYPT(des_key_schedule ks1,
|
||||
des_key_schedule ks2, des_cblock * iv2,
|
||||
des_key_schedule ks3, des_cblock * iv3,
|
||||
unsigned char *dest, unsigned char *src,
|
||||
unsigned int len)
|
||||
des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
||||
u_int len)
|
||||
{
|
||||
des_cblock iv1;
|
||||
des_cblock *iv2 = &cc->u.des3.iv2;
|
||||
des_cblock *iv3 = &cc->u.des3.iv3;
|
||||
|
||||
memcpy(&iv1, iv2, 8);
|
||||
|
||||
des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT);
|
||||
des_cbc_encrypt(src, dest, len, cc->u.des3.key3, iv3, DES_DECRYPT);
|
||||
memcpy(iv3, src + len - 8, 8);
|
||||
|
||||
des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT);
|
||||
des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_ENCRYPT);
|
||||
memcpy(iv2, dest + len - 8, 8);
|
||||
|
||||
des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT);
|
||||
des_cbc_encrypt(dest, dest, len, cc->u.des3.key1, &iv1, DES_DECRYPT);
|
||||
/* memcpy(&iv1, iv2, 8); */
|
||||
/* Note how iv1 == iv2 on entry and exit. */
|
||||
}
|
||||
|
||||
/* Blowfish */
|
||||
void
|
||||
blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||
{
|
||||
BF_set_key(&cc->u.bf.key, keylen, (unsigned char *)key);
|
||||
}
|
||||
void
|
||||
blowfish_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
||||
{
|
||||
if (iv == NULL)
|
||||
memset(cc->u.bf.iv, 0, 8);
|
||||
else
|
||||
memcpy(cc->u.bf.iv, (char *)iv, 8);
|
||||
}
|
||||
void
|
||||
blowfish_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
||||
u_int len)
|
||||
{
|
||||
BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,
|
||||
BF_ENCRYPT);
|
||||
}
|
||||
void
|
||||
blowfish_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
||||
u_int len)
|
||||
{
|
||||
BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,
|
||||
BF_DECRYPT);
|
||||
}
|
||||
|
||||
/*
|
||||
* SSH1 uses a variation on Blowfish, all bytes must be swapped before
|
||||
* and after encryption/decryption. Thus the swap_bytes stuff (yuk).
|
||||
*/
|
||||
static void
|
||||
swap_bytes(const unsigned char *src, unsigned char *dst_, int n)
|
||||
swap_bytes(const unsigned char *src, unsigned char *dst, int n)
|
||||
{
|
||||
/* dst must be properly aligned. */
|
||||
u_int32_t *dst = (u_int32_t *) dst_;
|
||||
union {
|
||||
u_int32_t i;
|
||||
char c[4];
|
||||
} t;
|
||||
char c[4];
|
||||
|
||||
/* Process 8 bytes every lap. */
|
||||
for (n = n / 8; n > 0; n--) {
|
||||
t.c[3] = *src++;
|
||||
t.c[2] = *src++;
|
||||
t.c[1] = *src++;
|
||||
t.c[0] = *src++;
|
||||
*dst++ = t.i;
|
||||
/* Process 4 bytes every lap. */
|
||||
for (n = n / 4; n > 0; n--) {
|
||||
c[3] = *src++;
|
||||
c[2] = *src++;
|
||||
c[1] = *src++;
|
||||
c[0] = *src++;
|
||||
|
||||
t.c[3] = *src++;
|
||||
t.c[2] = *src++;
|
||||
t.c[1] = *src++;
|
||||
t.c[0] = *src++;
|
||||
*dst++ = t.i;
|
||||
*dst++ = c[0];
|
||||
*dst++ = c[1];
|
||||
*dst++ = c[2];
|
||||
*dst++ = c[3];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Names of all encryption algorithms.
|
||||
* These must match the numbers defined in cipher.h.
|
||||
*/
|
||||
static char *cipher_names[] =
|
||||
void
|
||||
blowfish_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
||||
u_int len)
|
||||
{
|
||||
"none",
|
||||
"idea",
|
||||
"des",
|
||||
"3des",
|
||||
"tss",
|
||||
"rc4",
|
||||
"blowfish",
|
||||
"reserved",
|
||||
"blowfish-cbc",
|
||||
"3des-cbc",
|
||||
"arcfour",
|
||||
"cast128-cbc"
|
||||
swap_bytes(src, dest, len);
|
||||
BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv,
|
||||
BF_ENCRYPT);
|
||||
swap_bytes(dest, dest, len);
|
||||
}
|
||||
void
|
||||
blowfish_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
||||
u_int len)
|
||||
{
|
||||
swap_bytes(src, dest, len);
|
||||
BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv,
|
||||
BF_DECRYPT);
|
||||
swap_bytes(dest, dest, len);
|
||||
}
|
||||
|
||||
/* alleged rc4 */
|
||||
void
|
||||
arcfour_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||
{
|
||||
RC4_set_key(&cc->u.rc4, keylen, (u_char *)key);
|
||||
}
|
||||
void
|
||||
arcfour_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
RC4(&cc->u.rc4, len, (u_char *)src, dest);
|
||||
}
|
||||
|
||||
/* CAST */
|
||||
void
|
||||
cast_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||
{
|
||||
CAST_set_key(&cc->u.cast.key, keylen, (unsigned char *) key);
|
||||
}
|
||||
void
|
||||
cast_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
||||
{
|
||||
if (iv == NULL)
|
||||
fatal("no IV for %s.", cc->cipher->name);
|
||||
memcpy(cc->u.cast.iv, (char *)iv, 8);
|
||||
}
|
||||
void
|
||||
cast_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
|
||||
CAST_ENCRYPT);
|
||||
}
|
||||
void
|
||||
cast_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
|
||||
CAST_DECRYPT);
|
||||
}
|
||||
|
||||
/* RIJNDAEL */
|
||||
|
||||
#define RIJNDAEL_BLOCKSIZE 16
|
||||
void
|
||||
rijndael_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||
{
|
||||
rijndael_set_key(&cc->u.rijndael.enc, (u4byte *)key, 8*keylen, 1);
|
||||
rijndael_set_key(&cc->u.rijndael.dec, (u4byte *)key, 8*keylen, 0);
|
||||
}
|
||||
void
|
||||
rijndael_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
||||
{
|
||||
if (iv == NULL)
|
||||
fatal("no IV for %s.", cc->cipher->name);
|
||||
memcpy((u_char *)cc->u.rijndael.iv, iv, RIJNDAEL_BLOCKSIZE);
|
||||
}
|
||||
void
|
||||
rijndael_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
||||
u_int len)
|
||||
{
|
||||
rijndael_ctx *ctx = &cc->u.rijndael.enc;
|
||||
u4byte *iv = cc->u.rijndael.iv;
|
||||
u4byte in[4];
|
||||
u4byte *cprev, *cnow, *plain;
|
||||
int i, blocks = len / RIJNDAEL_BLOCKSIZE;
|
||||
if (len == 0)
|
||||
return;
|
||||
if (len % RIJNDAEL_BLOCKSIZE)
|
||||
fatal("rijndael_cbc_encrypt: bad len %d", len);
|
||||
cnow = (u4byte*) dest;
|
||||
plain = (u4byte*) src;
|
||||
cprev = iv;
|
||||
for(i = 0; i < blocks; i++, plain+=4, cnow+=4) {
|
||||
in[0] = plain[0] ^ cprev[0];
|
||||
in[1] = plain[1] ^ cprev[1];
|
||||
in[2] = plain[2] ^ cprev[2];
|
||||
in[3] = plain[3] ^ cprev[3];
|
||||
rijndael_encrypt(ctx, in, cnow);
|
||||
cprev = cnow;
|
||||
}
|
||||
memcpy(iv, cprev, RIJNDAEL_BLOCKSIZE);
|
||||
}
|
||||
|
||||
void
|
||||
rijndael_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
||||
u_int len)
|
||||
{
|
||||
rijndael_ctx *ctx = &cc->u.rijndael.dec;
|
||||
u4byte *iv = cc->u.rijndael.iv;
|
||||
u4byte ivsaved[4];
|
||||
u4byte *cnow = (u4byte*) (src+len-RIJNDAEL_BLOCKSIZE);
|
||||
u4byte *plain = (u4byte*) (dest+len-RIJNDAEL_BLOCKSIZE);
|
||||
u4byte *ivp;
|
||||
int i, blocks = len / RIJNDAEL_BLOCKSIZE;
|
||||
if (len == 0)
|
||||
return;
|
||||
if (len % RIJNDAEL_BLOCKSIZE)
|
||||
fatal("rijndael_cbc_decrypt: bad len %d", len);
|
||||
memcpy(ivsaved, cnow, RIJNDAEL_BLOCKSIZE);
|
||||
for(i = blocks; i > 0; i--, cnow-=4, plain-=4) {
|
||||
rijndael_decrypt(ctx, cnow, plain);
|
||||
ivp = (i == 1) ? iv : cnow-4;
|
||||
plain[0] ^= ivp[0];
|
||||
plain[1] ^= ivp[1];
|
||||
plain[2] ^= ivp[2];
|
||||
plain[3] ^= ivp[3];
|
||||
}
|
||||
memcpy(iv, ivsaved, RIJNDAEL_BLOCKSIZE);
|
||||
}
|
||||
|
||||
Cipher ciphers[] = {
|
||||
{ "none",
|
||||
SSH_CIPHER_NONE, 8, 0,
|
||||
none_setkey, none_setiv,
|
||||
none_crypt, none_crypt },
|
||||
{ "des",
|
||||
SSH_CIPHER_DES, 8, 8,
|
||||
des_ssh1_setkey, des_ssh1_setiv,
|
||||
des_ssh1_encrypt, des_ssh1_decrypt },
|
||||
{ "3des",
|
||||
SSH_CIPHER_3DES, 8, 16,
|
||||
des3_ssh1_setkey, des3_setiv,
|
||||
des3_ssh1_encrypt, des3_ssh1_decrypt },
|
||||
{ "blowfish",
|
||||
SSH_CIPHER_BLOWFISH, 8, 16,
|
||||
blowfish_setkey, blowfish_setiv,
|
||||
blowfish_ssh1_encrypt, blowfish_ssh1_decrypt },
|
||||
|
||||
{ "3des-cbc",
|
||||
SSH_CIPHER_SSH2, 8, 24,
|
||||
des3_setkey, des3_setiv,
|
||||
des3_cbc_encrypt, des3_cbc_decrypt },
|
||||
{ "blowfish-cbc",
|
||||
SSH_CIPHER_SSH2, 8, 16,
|
||||
blowfish_setkey, blowfish_setiv,
|
||||
blowfish_cbc_encrypt, blowfish_cbc_decrypt },
|
||||
{ "cast128-cbc",
|
||||
SSH_CIPHER_SSH2, 8, 16,
|
||||
cast_setkey, cast_setiv,
|
||||
cast_cbc_encrypt, cast_cbc_decrypt },
|
||||
{ "arcfour",
|
||||
SSH_CIPHER_SSH2, 8, 16,
|
||||
arcfour_setkey, none_setiv,
|
||||
arcfour_crypt, arcfour_crypt },
|
||||
{ "aes128-cbc",
|
||||
SSH_CIPHER_SSH2, 16, 16,
|
||||
rijndael_setkey, rijndael_setiv,
|
||||
rijndael_cbc_encrypt, rijndael_cbc_decrypt },
|
||||
{ "aes192-cbc",
|
||||
SSH_CIPHER_SSH2, 16, 24,
|
||||
rijndael_setkey, rijndael_setiv,
|
||||
rijndael_cbc_encrypt, rijndael_cbc_decrypt },
|
||||
{ "aes256-cbc",
|
||||
SSH_CIPHER_SSH2, 16, 32,
|
||||
rijndael_setkey, rijndael_setiv,
|
||||
rijndael_cbc_encrypt, rijndael_cbc_decrypt },
|
||||
{ "rijndael128-cbc",
|
||||
SSH_CIPHER_SSH2, 16, 16,
|
||||
rijndael_setkey, rijndael_setiv,
|
||||
rijndael_cbc_encrypt, rijndael_cbc_decrypt },
|
||||
{ "rijndael192-cbc",
|
||||
SSH_CIPHER_SSH2, 16, 24,
|
||||
rijndael_setkey, rijndael_setiv,
|
||||
rijndael_cbc_encrypt, rijndael_cbc_decrypt },
|
||||
{ "rijndael256-cbc",
|
||||
SSH_CIPHER_SSH2, 16, 32,
|
||||
rijndael_setkey, rijndael_setiv,
|
||||
rijndael_cbc_encrypt, rijndael_cbc_decrypt },
|
||||
{ "rijndael-cbc@lysator.liu.se",
|
||||
SSH_CIPHER_SSH2, 16, 32,
|
||||
rijndael_setkey, rijndael_setiv,
|
||||
rijndael_cbc_encrypt, rijndael_cbc_decrypt },
|
||||
{ NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns a bit mask indicating which ciphers are supported by this
|
||||
* implementation. The bit mask has the corresponding bit set of each
|
||||
* supported cipher.
|
||||
*/
|
||||
/*--*/
|
||||
|
||||
unsigned int
|
||||
cipher_mask1()
|
||||
cipher_mask_ssh1(int client)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
|
||||
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
|
||||
mask |= 1 << SSH_CIPHER_BLOWFISH;
|
||||
if (client) {
|
||||
mask |= 1 << SSH_CIPHER_DES;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
unsigned int
|
||||
cipher_mask2()
|
||||
|
||||
Cipher *
|
||||
cipher_by_name(const char *name)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
mask |= 1 << SSH_CIPHER_BLOWFISH_CBC;
|
||||
mask |= 1 << SSH_CIPHER_3DES_CBC;
|
||||
mask |= 1 << SSH_CIPHER_ARCFOUR;
|
||||
mask |= 1 << SSH_CIPHER_CAST128_CBC;
|
||||
return mask;
|
||||
}
|
||||
unsigned int
|
||||
cipher_mask()
|
||||
{
|
||||
return cipher_mask1() | cipher_mask2();
|
||||
Cipher *c;
|
||||
for (c = ciphers; c->name != NULL; c++)
|
||||
if (strcasecmp(c->name, name) == 0)
|
||||
return c;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns the name of the cipher. */
|
||||
|
||||
const char *
|
||||
cipher_name(int cipher)
|
||||
Cipher *
|
||||
cipher_by_number(int id)
|
||||
{
|
||||
if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) ||
|
||||
cipher_names[cipher] == NULL)
|
||||
fatal("cipher_name: bad cipher name: %d", cipher);
|
||||
return cipher_names[cipher];
|
||||
Cipher *c;
|
||||
for (c = ciphers; c->name != NULL; c++)
|
||||
if (c->number == id)
|
||||
return c;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns 1 if the name of the ciphers are valid. */
|
||||
|
||||
#define CIPHER_SEP ","
|
||||
int
|
||||
ciphers_valid(const char *names)
|
||||
{
|
||||
Cipher *c;
|
||||
char *ciphers, *cp;
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
if (names == NULL || strcmp(names, "") == 0)
|
||||
return 0;
|
||||
ciphers = cp = xstrdup(names);
|
||||
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
|
||||
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
|
||||
(p = strsep(&cp, CIPHER_SEP))) {
|
||||
i = cipher_number(p);
|
||||
if (i == -1 || !(cipher_mask2() & (1 << i))) {
|
||||
c = cipher_by_name(p);
|
||||
if (c == NULL || c->number != SSH_CIPHER_SSH2) {
|
||||
debug("bad cipher %s [%s]", p, names);
|
||||
xfree(ciphers);
|
||||
return 0;
|
||||
} else {
|
||||
debug3("cipher ok: %s [%s]", p, names);
|
||||
}
|
||||
}
|
||||
debug3("ciphers ok: [%s]", names);
|
||||
xfree(ciphers);
|
||||
return 1;
|
||||
}
|
||||
@@ -224,14 +497,49 @@ ciphers_valid(const char *names)
|
||||
int
|
||||
cipher_number(const char *name)
|
||||
{
|
||||
int i;
|
||||
Cipher *c;
|
||||
if (name == NULL)
|
||||
return -1;
|
||||
for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++)
|
||||
if (strcmp(cipher_names[i], name) == 0 &&
|
||||
(cipher_mask() & (1 << i)))
|
||||
return i;
|
||||
return -1;
|
||||
c = cipher_by_name(name);
|
||||
return (c==NULL) ? -1 : c->number;
|
||||
}
|
||||
|
||||
char *
|
||||
cipher_name(int id)
|
||||
{
|
||||
Cipher *c = cipher_by_number(id);
|
||||
return (c==NULL) ? "<unknown>" : c->name;
|
||||
}
|
||||
|
||||
void
|
||||
cipher_init(CipherContext *cc, Cipher *cipher,
|
||||
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen)
|
||||
{
|
||||
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)
|
||||
fatal("cipher_init: iv length %d is insufficient for %s.",
|
||||
ivlen, cipher->name);
|
||||
cc->cipher = cipher;
|
||||
cipher->setkey(cc, key, keylen);
|
||||
cipher->setiv(cc, iv, ivlen);
|
||||
}
|
||||
|
||||
void
|
||||
cipher_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
if (len % cc->cipher->block_size)
|
||||
fatal("cipher_encrypt: bad plaintext length %d", len);
|
||||
cc->cipher->encrypt(cc, dest, src, len);
|
||||
}
|
||||
|
||||
void
|
||||
cipher_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
||||
{
|
||||
if (len % cc->cipher->block_size)
|
||||
fatal("cipher_decrypt: bad ciphertext length %d", len);
|
||||
cc->cipher->decrypt(cc, dest, src, len);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -240,248 +548,18 @@ cipher_number(const char *name)
|
||||
*/
|
||||
|
||||
void
|
||||
cipher_set_key_string(CipherContext *context, int cipher, const char *passphrase)
|
||||
cipher_set_key_string(CipherContext *cc, Cipher *cipher,
|
||||
const char *passphrase)
|
||||
{
|
||||
MD5_CTX md;
|
||||
unsigned char digest[16];
|
||||
|
||||
MD5_Init(&md);
|
||||
MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase));
|
||||
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
|
||||
MD5_Final(digest, &md);
|
||||
|
||||
cipher_set_key(context, cipher, digest, 16);
|
||||
cipher_init(cc, cipher, digest, 16, NULL, 0);
|
||||
|
||||
memset(digest, 0, sizeof(digest));
|
||||
memset(&md, 0, sizeof(md));
|
||||
}
|
||||
|
||||
/* Selects the cipher to use and sets the key. */
|
||||
|
||||
void
|
||||
cipher_set_key(CipherContext *context, int cipher, const unsigned char *key,
|
||||
int keylen)
|
||||
{
|
||||
unsigned char padded[32];
|
||||
|
||||
/* Set cipher type. */
|
||||
context->type = cipher;
|
||||
|
||||
/* Get 32 bytes of key data. Pad if necessary. (So that code
|
||||
below does not need to worry about key size). */
|
||||
memset(padded, 0, sizeof(padded));
|
||||
memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));
|
||||
|
||||
/* Initialize the initialization vector. */
|
||||
switch (cipher) {
|
||||
case SSH_CIPHER_NONE:
|
||||
/*
|
||||
* Has to stay for authfile saving of private key with no
|
||||
* passphrase
|
||||
*/
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_3DES:
|
||||
/*
|
||||
* Note: the least significant bit of each byte of key is
|
||||
* parity, and must be ignored by the implementation. 16
|
||||
* bytes of key are used (first and last keys are the same).
|
||||
*/
|
||||
if (keylen < 16)
|
||||
error("Key length %d is insufficient for 3DES.", keylen);
|
||||
des_set_key((void *) padded, context->u.des3.key1);
|
||||
des_set_key((void *) (padded + 8), context->u.des3.key2);
|
||||
if (keylen <= 16)
|
||||
des_set_key((void *) padded, context->u.des3.key3);
|
||||
else
|
||||
des_set_key((void *) (padded + 16), context->u.des3.key3);
|
||||
memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
|
||||
memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_BLOWFISH:
|
||||
if (keylen < 16)
|
||||
error("Key length %d is insufficient for blowfish.", keylen);
|
||||
BF_set_key(&context->u.bf.key, keylen, padded);
|
||||
memset(context->u.bf.iv, 0, 8);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_3DES_CBC:
|
||||
case SSH_CIPHER_BLOWFISH_CBC:
|
||||
case SSH_CIPHER_ARCFOUR:
|
||||
case SSH_CIPHER_CAST128_CBC:
|
||||
fatal("cipher_set_key: illegal cipher: %s", cipher_name(cipher));
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
|
||||
}
|
||||
memset(padded, 0, sizeof(padded));
|
||||
}
|
||||
|
||||
void
|
||||
cipher_set_key_iv(CipherContext * context, int cipher,
|
||||
const unsigned char *key, int keylen,
|
||||
const unsigned char *iv, int ivlen)
|
||||
{
|
||||
/* Set cipher type. */
|
||||
context->type = cipher;
|
||||
|
||||
/* Initialize the initialization vector. */
|
||||
switch (cipher) {
|
||||
case SSH_CIPHER_NONE:
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_3DES:
|
||||
case SSH_CIPHER_BLOWFISH:
|
||||
fatal("cipher_set_key_iv: illegal cipher: %s", cipher_name(cipher));
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_3DES_CBC:
|
||||
if (keylen < 24)
|
||||
error("Key length %d is insufficient for 3des-cbc.", keylen);
|
||||
des_set_key((void *) key, context->u.des3.key1);
|
||||
des_set_key((void *) (key+8), context->u.des3.key2);
|
||||
des_set_key((void *) (key+16), context->u.des3.key3);
|
||||
if (ivlen < 8)
|
||||
error("IV length %d is insufficient for 3des-cbc.", ivlen);
|
||||
memcpy(context->u.des3.iv3, (char *)iv, 8);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_BLOWFISH_CBC:
|
||||
if (keylen < 16)
|
||||
error("Key length %d is insufficient for blowfish.", keylen);
|
||||
if (ivlen < 8)
|
||||
error("IV length %d is insufficient for blowfish.", ivlen);
|
||||
BF_set_key(&context->u.bf.key, keylen, (unsigned char *)key);
|
||||
memcpy(context->u.bf.iv, (char *)iv, 8);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_ARCFOUR:
|
||||
if (keylen < 16)
|
||||
error("Key length %d is insufficient for arcfour.", keylen);
|
||||
RC4_set_key(&context->u.rc4, keylen, (unsigned char *)key);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_CAST128_CBC:
|
||||
if (keylen < 16)
|
||||
error("Key length %d is insufficient for cast128.", keylen);
|
||||
if (ivlen < 8)
|
||||
error("IV length %d is insufficient for cast128.", ivlen);
|
||||
CAST_set_key(&context->u.cast.key, keylen, (unsigned char *) key);
|
||||
memcpy(context->u.cast.iv, (char *)iv, 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
|
||||
}
|
||||
}
|
||||
|
||||
/* Encrypts data using the cipher. */
|
||||
|
||||
void
|
||||
cipher_encrypt(CipherContext *context, unsigned char *dest,
|
||||
const unsigned char *src, unsigned int len)
|
||||
{
|
||||
if ((len & 7) != 0)
|
||||
fatal("cipher_encrypt: bad plaintext length %d", len);
|
||||
|
||||
switch (context->type) {
|
||||
case SSH_CIPHER_NONE:
|
||||
memcpy(dest, src, len);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_3DES:
|
||||
SSH_3CBC_ENCRYPT(context->u.des3.key1,
|
||||
context->u.des3.key2, &context->u.des3.iv2,
|
||||
context->u.des3.key3, &context->u.des3.iv3,
|
||||
dest, (unsigned char *) src, len);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_BLOWFISH:
|
||||
swap_bytes(src, dest, len);
|
||||
BF_cbc_encrypt(dest, dest, len,
|
||||
&context->u.bf.key, context->u.bf.iv,
|
||||
BF_ENCRYPT);
|
||||
swap_bytes(dest, dest, len);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_BLOWFISH_CBC:
|
||||
BF_cbc_encrypt((void *)src, dest, len,
|
||||
&context->u.bf.key, context->u.bf.iv,
|
||||
BF_ENCRYPT);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_3DES_CBC:
|
||||
des_ede3_cbc_encrypt(src, dest, len,
|
||||
context->u.des3.key1, context->u.des3.key2,
|
||||
context->u.des3.key3, &context->u.des3.iv3, DES_ENCRYPT);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_ARCFOUR:
|
||||
RC4(&context->u.rc4, len, (unsigned char *)src, dest);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_CAST128_CBC:
|
||||
CAST_cbc_encrypt(src, dest, len,
|
||||
&context->u.cast.key, context->u.cast.iv, CAST_ENCRYPT);
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type));
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrypts data using the cipher. */
|
||||
|
||||
void
|
||||
cipher_decrypt(CipherContext *context, unsigned char *dest,
|
||||
const unsigned char *src, unsigned int len)
|
||||
{
|
||||
if ((len & 7) != 0)
|
||||
fatal("cipher_decrypt: bad ciphertext length %d", len);
|
||||
|
||||
switch (context->type) {
|
||||
case SSH_CIPHER_NONE:
|
||||
memcpy(dest, src, len);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_3DES:
|
||||
SSH_3CBC_DECRYPT(context->u.des3.key1,
|
||||
context->u.des3.key2, &context->u.des3.iv2,
|
||||
context->u.des3.key3, &context->u.des3.iv3,
|
||||
dest, (unsigned char *) src, len);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_BLOWFISH:
|
||||
swap_bytes(src, dest, len);
|
||||
BF_cbc_encrypt((void *) dest, dest, len,
|
||||
&context->u.bf.key, context->u.bf.iv,
|
||||
BF_DECRYPT);
|
||||
swap_bytes(dest, dest, len);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_BLOWFISH_CBC:
|
||||
BF_cbc_encrypt((void *) src, dest, len,
|
||||
&context->u.bf.key, context->u.bf.iv,
|
||||
BF_DECRYPT);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_3DES_CBC:
|
||||
des_ede3_cbc_encrypt(src, dest, len,
|
||||
context->u.des3.key1, context->u.des3.key2,
|
||||
context->u.des3.key3, &context->u.des3.iv3, DES_DECRYPT);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_ARCFOUR:
|
||||
RC4(&context->u.rc4, len, (unsigned char *)src, dest);
|
||||
break;
|
||||
|
||||
case SSH_CIPHER_CAST128_CBC:
|
||||
CAST_cbc_encrypt(src, dest, len,
|
||||
&context->u.cast.key, context->u.cast.iv, CAST_DECRYPT);
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type));
|
||||
}
|
||||
}
|
||||
|
||||
+66
-63
@@ -8,9 +8,31 @@
|
||||
* software must be clearly marked as such, and if the derived work is
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: cipher.h,v 1.19 2000/09/07 20:27:50 deraadt Exp $"); */
|
||||
/* RCSID("$OpenBSD: cipher.h,v 1.22 2000/10/13 18:59:14 markus Exp $"); */
|
||||
|
||||
#ifndef CIPHER_H
|
||||
#define CIPHER_H
|
||||
@@ -19,9 +41,12 @@
|
||||
#include <openssl/blowfish.h>
|
||||
#include <openssl/rc4.h>
|
||||
#include <openssl/cast.h>
|
||||
|
||||
/* Cipher types. New types can be added, but old types should not be removed
|
||||
for compatibility. The maximum allowed value is 31. */
|
||||
#include "rijndael.h"
|
||||
/*
|
||||
* Cipher types for SSH-1. New types can be added, but old types should not
|
||||
* be removed for compatibility. The maximum allowed value is 31.
|
||||
*/
|
||||
#define SSH_CIPHER_SSH2 -3
|
||||
#define SSH_CIPHER_ILLEGAL -2 /* No valid cipher selected. */
|
||||
#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
|
||||
#define SSH_CIPHER_NONE 0 /* no encryption */
|
||||
@@ -32,16 +57,17 @@
|
||||
#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
|
||||
#define SSH_CIPHER_BLOWFISH 6
|
||||
#define SSH_CIPHER_RESERVED 7
|
||||
#define SSH_CIPHER_MAX 31
|
||||
|
||||
/* these ciphers are used in SSH2: */
|
||||
#define SSH_CIPHER_BLOWFISH_CBC 8
|
||||
#define SSH_CIPHER_3DES_CBC 9
|
||||
#define SSH_CIPHER_ARCFOUR 10 /* Alleged RC4 */
|
||||
#define SSH_CIPHER_CAST128_CBC 11
|
||||
typedef struct Cipher Cipher;
|
||||
typedef struct CipherContext CipherContext;
|
||||
|
||||
typedef struct {
|
||||
unsigned int type;
|
||||
struct CipherContext {
|
||||
union {
|
||||
struct {
|
||||
des_key_schedule key;
|
||||
des_cblock iv;
|
||||
} des;
|
||||
struct {
|
||||
des_key_schedule key1;
|
||||
des_key_schedule key2;
|
||||
@@ -51,64 +77,41 @@ typedef struct {
|
||||
} des3;
|
||||
struct {
|
||||
struct bf_key_st key;
|
||||
unsigned char iv[8];
|
||||
u_char iv[8];
|
||||
} bf;
|
||||
struct {
|
||||
CAST_KEY key;
|
||||
unsigned char iv[8];
|
||||
u_char iv[8];
|
||||
} cast;
|
||||
struct {
|
||||
u4byte iv[4];
|
||||
rijndael_ctx enc;
|
||||
rijndael_ctx dec;
|
||||
} rijndael;
|
||||
RC4_KEY rc4;
|
||||
} u;
|
||||
} CipherContext;
|
||||
/*
|
||||
* Returns a bit mask indicating which ciphers are supported by this
|
||||
* implementation. The bit mask has the corresponding bit set of each
|
||||
* supported cipher.
|
||||
*/
|
||||
unsigned int cipher_mask();
|
||||
unsigned int cipher_mask1();
|
||||
unsigned int cipher_mask2();
|
||||
Cipher *cipher;
|
||||
};
|
||||
struct Cipher {
|
||||
char *name;
|
||||
int number; /* for ssh1 only */
|
||||
u_int block_size;
|
||||
u_int key_len;
|
||||
void (*setkey)(CipherContext *, const u_char *, u_int);
|
||||
void (*setiv)(CipherContext *, const u_char *, u_int);
|
||||
void (*encrypt)(CipherContext *, u_char *, const u_char *, u_int);
|
||||
void (*decrypt)(CipherContext *, u_char *, const u_char *, u_int);
|
||||
};
|
||||
|
||||
/* Returns the name of the cipher. */
|
||||
const char *cipher_name(int cipher);
|
||||
|
||||
/*
|
||||
* Parses the name of the cipher. Returns the number of the corresponding
|
||||
* cipher, or -1 on error.
|
||||
*/
|
||||
int cipher_number(const char *name);
|
||||
|
||||
/* returns 1 if all ciphers are supported (ssh2 only) */
|
||||
int ciphers_valid(const char *names);
|
||||
|
||||
/*
|
||||
* Selects the cipher to use and sets the key. If for_encryption is true,
|
||||
* the key is setup for encryption; otherwise it is setup for decryption.
|
||||
*/
|
||||
void
|
||||
cipher_set_key(CipherContext * context, int cipher,
|
||||
const unsigned char *key, int keylen);
|
||||
void
|
||||
cipher_set_key_iv(CipherContext * context, int cipher,
|
||||
const unsigned char *key, int keylen,
|
||||
const unsigned char *iv, int ivlen);
|
||||
|
||||
/*
|
||||
* Sets key for the cipher by computing the MD5 checksum of the passphrase,
|
||||
* and using the resulting 16 bytes as the key.
|
||||
*/
|
||||
void
|
||||
cipher_set_key_string(CipherContext * context, int cipher,
|
||||
const char *passphrase);
|
||||
|
||||
/* Encrypts data using the cipher. */
|
||||
void
|
||||
cipher_encrypt(CipherContext * context, unsigned char *dest,
|
||||
const unsigned char *src, unsigned int len);
|
||||
|
||||
/* Decrypts data using the cipher. */
|
||||
void
|
||||
cipher_decrypt(CipherContext * context, unsigned char *dest,
|
||||
const unsigned char *src, unsigned int len);
|
||||
unsigned int cipher_mask_ssh1(int client);
|
||||
Cipher *cipher_by_name(const char *name);
|
||||
Cipher *cipher_by_number(int id);
|
||||
int cipher_number(const char *name);
|
||||
char *cipher_name(int id);
|
||||
int ciphers_valid(const char *names);
|
||||
void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, const u_char *, u_int);
|
||||
void cipher_encrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len);
|
||||
void cipher_decrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len);
|
||||
void cipher_set_key_string(CipherContext *context, Cipher *cipher, const char *passphrase);
|
||||
|
||||
#endif /* CIPHER_H */
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: cli.c,v 1.2 2000/10/16 09:38:44 djm Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include <vis.h>
|
||||
|
||||
static int cli_input = -1;
|
||||
static int cli_output = -1;
|
||||
static int cli_from_stdin = 0;
|
||||
|
||||
sigset_t oset;
|
||||
sigset_t nset;
|
||||
struct sigaction nsa;
|
||||
struct sigaction osa;
|
||||
struct termios ntio;
|
||||
struct termios otio;
|
||||
int echo_modified;
|
||||
|
||||
volatile int intr;
|
||||
|
||||
static int
|
||||
cli_open(int from_stdin)
|
||||
{
|
||||
if (cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin)
|
||||
return 1;
|
||||
|
||||
if (from_stdin) {
|
||||
if (!cli_from_stdin && cli_input >= 0) {
|
||||
(void)close(cli_input);
|
||||
}
|
||||
cli_input = STDIN_FILENO;
|
||||
cli_output = STDERR_FILENO;
|
||||
} else {
|
||||
cli_input = cli_output = open("/dev/tty", O_RDWR);
|
||||
if (cli_input < 0)
|
||||
fatal("You have no controlling tty. Cannot read passphrase.");
|
||||
}
|
||||
|
||||
cli_from_stdin = from_stdin;
|
||||
|
||||
return cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin;
|
||||
}
|
||||
|
||||
static void
|
||||
cli_close()
|
||||
{
|
||||
if (!cli_from_stdin && cli_input >= 0)
|
||||
close(cli_input);
|
||||
cli_input = -1;
|
||||
cli_output = -1;
|
||||
cli_from_stdin = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
intrcatch()
|
||||
{
|
||||
intr = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
cli_echo_disable()
|
||||
{
|
||||
sigemptyset(&nset);
|
||||
sigaddset(&nset, SIGTSTP);
|
||||
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
|
||||
|
||||
intr = 0;
|
||||
|
||||
memset(&nsa, 0, sizeof(nsa));
|
||||
nsa.sa_handler = intrcatch;
|
||||
(void) sigaction(SIGINT, &nsa, &osa);
|
||||
|
||||
echo_modified = 0;
|
||||
if (tcgetattr(cli_input, &otio) == 0 && (otio.c_lflag & ECHO)) {
|
||||
echo_modified = 1;
|
||||
ntio = otio;
|
||||
ntio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
|
||||
(void) tcsetattr(cli_input, TCSANOW, &ntio);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
cli_echo_restore()
|
||||
{
|
||||
if (echo_modified != 0) {
|
||||
tcsetattr(cli_input, TCSANOW, &otio);
|
||||
echo_modified = 0;
|
||||
}
|
||||
|
||||
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
|
||||
(void) sigaction(SIGINT, &osa, NULL);
|
||||
|
||||
if (intr != 0) {
|
||||
kill(getpid(), SIGINT);
|
||||
sigemptyset(&nset);
|
||||
/* XXX tty has not neccessarily drained by now? */
|
||||
sigsuspend(&nset);
|
||||
intr = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
cli_read(char* buf, int size, int echo)
|
||||
{
|
||||
char ch = 0;
|
||||
int i = 0;
|
||||
|
||||
if (!echo)
|
||||
cli_echo_disable();
|
||||
|
||||
while (ch != '\n') {
|
||||
if (read(cli_input, &ch, 1) != 1)
|
||||
break;
|
||||
if (ch == '\n' || intr != 0)
|
||||
break;
|
||||
if (i < size)
|
||||
buf[i++] = ch;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
|
||||
if (!echo)
|
||||
cli_echo_restore();
|
||||
if (!intr && !echo)
|
||||
(void) write(cli_output, "\n", 1);
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
cli_write(char* buf, int size)
|
||||
{
|
||||
int i, len, pos, ret = 0;
|
||||
char *output, *p;
|
||||
|
||||
output = xmalloc(4*size);
|
||||
for (p = output, i = 0; i < size; i++) {
|
||||
if (buf[i] == '\n')
|
||||
*p++ = buf[i];
|
||||
else
|
||||
p = vis(p, buf[i], 0, 0);
|
||||
}
|
||||
len = p - output;
|
||||
|
||||
for (pos = 0; pos < len; pos += ret) {
|
||||
ret = write(cli_output, output + pos, len - pos);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Presents a prompt and returns the response allocated with xmalloc().
|
||||
* Uses /dev/tty or stdin/out depending on arg. Optionally disables echo
|
||||
* of response depending on arg. Tries to ensure that no other userland
|
||||
* buffer is storing the response.
|
||||
*/
|
||||
char*
|
||||
cli_read_passphrase(char* prompt, int from_stdin, int echo_enable)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
char* p;
|
||||
|
||||
if (!cli_open(from_stdin))
|
||||
fatal("Cannot read passphrase.");
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
cli_write(prompt, strlen(prompt));
|
||||
cli_read(buf, sizeof buf, echo_enable);
|
||||
|
||||
cli_close();
|
||||
|
||||
p = xstrdup(buf);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
return (p);
|
||||
}
|
||||
|
||||
char*
|
||||
cli_prompt(char* prompt, int echo_enable)
|
||||
{
|
||||
return cli_read_passphrase(prompt, 0, echo_enable);
|
||||
}
|
||||
|
||||
void
|
||||
cli_mesg(char* mesg)
|
||||
{
|
||||
cli_open(0);
|
||||
cli_write(mesg, strlen(mesg));
|
||||
cli_write("\n", strlen("\n"));
|
||||
cli_close();
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* $OpenBSD: cli.h,v 1.2 2000/10/16 09:38:44 djm Exp $ */
|
||||
|
||||
#ifndef CLI_H
|
||||
#define CLI_H
|
||||
|
||||
/*
|
||||
* Presents a prompt and returns the response allocated with xmalloc().
|
||||
* Uses /dev/tty or stdin/out depending on arg. Optionally disables echo
|
||||
* of response depending on arg. Tries to ensure that no other userland
|
||||
* buffer is storing the response.
|
||||
*/
|
||||
char* cli_read_passphrase(char* prompt, int from_stdin, int echo_enable);
|
||||
char* cli_prompt(char* prompt, int echo_enable);
|
||||
void cli_mesg(char* mesg);
|
||||
|
||||
#endif /* CLI_H */
|
||||
+16
-17
@@ -59,7 +59,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: clientloop.c,v 1.34 2000/09/07 20:40:30 markus Exp $");
|
||||
RCSID("$OpenBSD: clientloop.c,v 1.39 2000/10/27 07:48:22 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
@@ -75,6 +75,8 @@ RCSID("$OpenBSD: clientloop.c,v 1.34 2000/09/07 20:40:30 markus Exp $");
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
|
||||
|
||||
/* import options */
|
||||
extern Options options;
|
||||
|
||||
/* Flag indicating that stdin should be redirected from /dev/null. */
|
||||
@@ -335,7 +337,7 @@ client_check_window_change()
|
||||
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
|
||||
return;
|
||||
|
||||
debug("client_check_window_change: changed");
|
||||
debug2("client_check_window_change: changed");
|
||||
|
||||
if (compat20) {
|
||||
channel_request_start(session_ident, "window-change", 0);
|
||||
@@ -362,8 +364,6 @@ client_check_window_change()
|
||||
void
|
||||
client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
|
||||
{
|
||||
/*debug("client_wait_until_can_do_something"); */
|
||||
|
||||
/* Initialize select masks. */
|
||||
FD_ZERO(readset);
|
||||
FD_ZERO(writeset);
|
||||
@@ -482,7 +482,6 @@ client_process_net_input(fd_set * readset)
|
||||
if (FD_ISSET(connection_in, readset)) {
|
||||
/* Read as much as possible. */
|
||||
len = read(connection_in, buf, sizeof(buf));
|
||||
/*debug("read connection_in len %d", len); XXX */
|
||||
if (len == 0) {
|
||||
/* Received EOF. The remote host has closed the connection. */
|
||||
snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
|
||||
@@ -773,7 +772,7 @@ client_process_output(fd_set * writeset)
|
||||
void
|
||||
client_process_buffered_input_packets()
|
||||
{
|
||||
dispatch_run(DISPATCH_NONBLOCK, &quit_pending);
|
||||
dispatch_run(DISPATCH_NONBLOCK, &quit_pending, NULL);
|
||||
}
|
||||
|
||||
/* scan buf[] for '~' before sending data to the peer */
|
||||
@@ -853,7 +852,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
||||
client_process_buffered_input_packets();
|
||||
|
||||
if (compat20 && !channel_still_open()) {
|
||||
debug("!channel_still_open.");
|
||||
debug2("!channel_still_open.");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -979,7 +978,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
|
||||
/*********/
|
||||
|
||||
void
|
||||
client_input_stdout_data(int type, int plen)
|
||||
client_input_stdout_data(int type, int plen, void *ctxt)
|
||||
{
|
||||
unsigned int data_len;
|
||||
char *data = packet_get_string(&data_len);
|
||||
@@ -990,7 +989,7 @@ client_input_stdout_data(int type, int plen)
|
||||
xfree(data);
|
||||
}
|
||||
void
|
||||
client_input_stderr_data(int type, int plen)
|
||||
client_input_stderr_data(int type, int plen, void *ctxt)
|
||||
{
|
||||
unsigned int data_len;
|
||||
char *data = packet_get_string(&data_len);
|
||||
@@ -1001,7 +1000,7 @@ client_input_stderr_data(int type, int plen)
|
||||
xfree(data);
|
||||
}
|
||||
void
|
||||
client_input_exit_status(int type, int plen)
|
||||
client_input_exit_status(int type, int plen, void *ctxt)
|
||||
{
|
||||
packet_integrity_check(plen, 4, type);
|
||||
exit_status = packet_get_int();
|
||||
@@ -1019,7 +1018,7 @@ client_input_exit_status(int type, int plen)
|
||||
|
||||
/* XXXX move to generic input handler */
|
||||
void
|
||||
client_input_channel_open(int type, int plen)
|
||||
client_input_channel_open(int type, int plen, void *ctxt)
|
||||
{
|
||||
Channel *c = NULL;
|
||||
char *ctype;
|
||||
@@ -1043,7 +1042,7 @@ client_input_channel_open(int type, int plen)
|
||||
int originator_port;
|
||||
originator = packet_get_string(NULL);
|
||||
if (datafellows & SSH_BUG_X11FWD) {
|
||||
debug("buggy server: x11 request w/o originator_port");
|
||||
debug2("buggy server: x11 request w/o originator_port");
|
||||
originator_port = 0;
|
||||
} else {
|
||||
originator_port = packet_get_int();
|
||||
@@ -1056,7 +1055,7 @@ client_input_channel_open(int type, int plen)
|
||||
if (sock >= 0) {
|
||||
id = channel_new("x11", SSH_CHANNEL_X11_OPEN,
|
||||
sock, sock, -1, CHAN_X11_WINDOW_DEFAULT,
|
||||
CHAN_X11_PACKET_DEFAULT, 0, xstrdup("x11"));
|
||||
CHAN_X11_PACKET_DEFAULT, 0, xstrdup("x11"), 1);
|
||||
c = channel_lookup(id);
|
||||
}
|
||||
}
|
||||
@@ -1114,9 +1113,9 @@ client_init_dispatch_13()
|
||||
dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
|
||||
|
||||
dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
|
||||
&auth_input_open_request : NULL);
|
||||
&auth_input_open_request : &deny_input_open);
|
||||
dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
|
||||
&x11_input_open : NULL);
|
||||
&x11_input_open : &deny_input_open);
|
||||
}
|
||||
void
|
||||
client_init_dispatch_15()
|
||||
@@ -1152,7 +1151,7 @@ client_input_channel_req(int id, void *arg)
|
||||
|
||||
c = channel_lookup(id);
|
||||
if (c == NULL)
|
||||
fatal("session_input_channel_req: channel %d: bad channel", id);
|
||||
fatal("client_input_channel_req: channel %d: bad channel", id);
|
||||
|
||||
if (session_ident == -1) {
|
||||
error("client_input_channel_req: no channel %d", id);
|
||||
@@ -1176,7 +1175,7 @@ client_input_channel_req(int id, void *arg)
|
||||
void
|
||||
client_set_session_ident(int id)
|
||||
{
|
||||
debug("client_set_session_ident: id %d", id);
|
||||
debug2("client_set_session_ident: id %d", id);
|
||||
session_ident = id;
|
||||
channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
|
||||
client_input_channel_req, (void *)0);
|
||||
|
||||
+34
-14
@@ -23,12 +23,13 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: compat.c,v 1.23 2000/09/07 21:13:37 markus Exp $");
|
||||
RCSID("$OpenBSD: compat.c,v 1.27 2000/10/31 09:31:58 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
#include "xmalloc.h"
|
||||
#include "compat.h"
|
||||
#include <regex.h>
|
||||
|
||||
int compat13 = 0;
|
||||
int compat20 = 0;
|
||||
@@ -50,27 +51,46 @@ enable_compat13(void)
|
||||
void
|
||||
compat_datafellows(const char *version)
|
||||
{
|
||||
int i;
|
||||
size_t len;
|
||||
struct {
|
||||
char *version;
|
||||
int i, ret;
|
||||
char ebuf[1024];
|
||||
regex_t reg;
|
||||
static struct {
|
||||
char *pat;
|
||||
int bugs;
|
||||
} check[] = {
|
||||
{"2.1.0", SSH_BUG_SIGBLOB|SSH_BUG_HMAC},
|
||||
{"2.0.1", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|SSH_BUG_PUBKEYAUTH|SSH_BUG_X11FWD},
|
||||
{"2.", SSH_BUG_HMAC|SSH_COMPAT_SESSIONID_ENCODING},
|
||||
{NULL, 0}
|
||||
{ "^OpenSSH[-_]2\\.[012]", SSH_OLD_SESSIONID },
|
||||
{ "MindTerm", 0 },
|
||||
{ "^2\\.1\\.0 ", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
|
||||
SSH_OLD_SESSIONID },
|
||||
{ "^2\\.0\\.", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
|
||||
SSH_OLD_SESSIONID|
|
||||
SSH_BUG_PUBKEYAUTH|SSH_BUG_X11FWD },
|
||||
{ "^2\\.[23]\\.0 ", SSH_BUG_HMAC},
|
||||
{ "^2\\.[2-9]\\.", 0 },
|
||||
{ "^2\\.4$", SSH_OLD_SESSIONID}, /* Van Dyke */
|
||||
{ "^3\\.0 SecureCRT", SSH_OLD_SESSIONID},
|
||||
{ "^1\\.7 SecureFX", SSH_OLD_SESSIONID},
|
||||
{ "^2\\.", SSH_BUG_HMAC}, /* XXX fallback */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
/* process table, return first match */
|
||||
for (i = 0; check[i].version; i++) {
|
||||
len = strlen(check[i].version);
|
||||
if (strlen(version) >= len &&
|
||||
(strncmp(version, check[i].version, len) == 0)) {
|
||||
verbose("datafellows: %.200s", version);
|
||||
for (i = 0; check[i].pat; i++) {
|
||||
ret = regcomp(®, check[i].pat, REG_EXTENDED|REG_NOSUB);
|
||||
if (ret != 0) {
|
||||
regerror(ret, ®, ebuf, sizeof(ebuf));
|
||||
ebuf[sizeof(ebuf)-1] = '\0';
|
||||
error("regerror: %s", ebuf);
|
||||
continue;
|
||||
}
|
||||
ret = regexec(®, version, 0, NULL, 0);
|
||||
regfree(®);
|
||||
if (ret == 0) {
|
||||
debug("match: %s pat %s\n", version, check[i].pat);
|
||||
datafellows = check[i].bugs;
|
||||
return;
|
||||
}
|
||||
}
|
||||
debug("no match: %s", version);
|
||||
}
|
||||
|
||||
#define SEP ","
|
||||
|
||||
@@ -21,7 +21,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.
|
||||
*/
|
||||
/* RCSID("$OpenBSD: compat.h,v 1.10 2000/09/07 20:27:50 deraadt Exp $"); */
|
||||
/* RCSID("$OpenBSD: compat.h,v 1.11 2000/10/14 12:16:56 markus Exp $"); */
|
||||
|
||||
#ifndef COMPAT_H
|
||||
#define COMPAT_H
|
||||
@@ -35,7 +35,7 @@
|
||||
#define SSH_BUG_PUBKEYAUTH 0x02
|
||||
#define SSH_BUG_HMAC 0x04
|
||||
#define SSH_BUG_X11FWD 0x08
|
||||
#define SSH_COMPAT_SESSIONID_ENCODING 0x10
|
||||
#define SSH_OLD_SESSIONID 0x10
|
||||
|
||||
void enable_compat13(void);
|
||||
void enable_compat20(void);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: deattack.c,v 1.9 2000/09/07 20:27:51 deraadt Exp $ */
|
||||
/* $OpenBSD: deattack.c,v 1.10 2000/10/31 13:18:53 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Cryptographic attack detector for ssh - source code
|
||||
@@ -85,7 +85,7 @@ int
|
||||
detect_attack(unsigned char *buf, u_int32_t len, unsigned char *IV)
|
||||
{
|
||||
static u_int16_t *h = (u_int16_t *) NULL;
|
||||
static u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
|
||||
static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
|
||||
register u_int32_t i, j;
|
||||
u_int32_t l;
|
||||
register unsigned char *c;
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: dh.c,v 1.2 2000/10/11 20:11:35 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "ssh.h"
|
||||
#include "buffer.h"
|
||||
#include "kex.h"
|
||||
#include "dh.h"
|
||||
|
||||
int
|
||||
parse_prime(int linenum, char *line, struct dhgroup *dhg)
|
||||
{
|
||||
char *cp, *arg;
|
||||
char *strsize, *gen, *prime;
|
||||
|
||||
cp = line;
|
||||
arg = strdelim(&cp);
|
||||
/* Ignore leading whitespace */
|
||||
if (*arg == '\0')
|
||||
arg = strdelim(&cp);
|
||||
if (!*arg || *arg == '#')
|
||||
return 0;
|
||||
|
||||
/* time */
|
||||
if (cp == NULL || *arg == '\0')
|
||||
goto fail;
|
||||
arg = strsep(&cp, " "); /* type */
|
||||
if (cp == NULL || *arg == '\0')
|
||||
goto fail;
|
||||
arg = strsep(&cp, " "); /* tests */
|
||||
if (cp == NULL || *arg == '\0')
|
||||
goto fail;
|
||||
arg = strsep(&cp, " "); /* tries */
|
||||
if (cp == NULL || *arg == '\0')
|
||||
goto fail;
|
||||
strsize = strsep(&cp, " "); /* size */
|
||||
if (cp == NULL || *strsize == '\0' ||
|
||||
(dhg->size = atoi(strsize)) == 0)
|
||||
goto fail;
|
||||
gen = strsep(&cp, " "); /* gen */
|
||||
if (cp == NULL || *gen == '\0')
|
||||
goto fail;
|
||||
prime = strsep(&cp, " "); /* prime */
|
||||
if (cp != NULL || *prime == '\0')
|
||||
goto fail;
|
||||
|
||||
dhg->g = BN_new();
|
||||
if (BN_hex2bn(&dhg->g, gen) < 0) {
|
||||
BN_free(dhg->g);
|
||||
goto fail;
|
||||
}
|
||||
dhg->p = BN_new();
|
||||
if (BN_hex2bn(&dhg->p, prime) < 0) {
|
||||
BN_free(dhg->g);
|
||||
BN_free(dhg->p);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return (1);
|
||||
fail:
|
||||
fprintf(stderr, "Bad prime description in line %d\n", linenum);
|
||||
return (0);
|
||||
}
|
||||
|
||||
DH *
|
||||
choose_dh(int minbits)
|
||||
{
|
||||
FILE *f;
|
||||
char line[1024];
|
||||
int best, bestcount, which;
|
||||
int linenum;
|
||||
struct dhgroup dhg;
|
||||
|
||||
f = fopen(DH_PRIMES, "r");
|
||||
if (!f) {
|
||||
perror(DH_PRIMES);
|
||||
log("WARNING: %s does not exist, using old prime", DH_PRIMES);
|
||||
return (dh_new_group1());
|
||||
}
|
||||
|
||||
linenum = 0;
|
||||
best = bestcount = 0;
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
linenum++;
|
||||
if (!parse_prime(linenum, line, &dhg))
|
||||
continue;
|
||||
BN_free(dhg.g);
|
||||
BN_free(dhg.p);
|
||||
|
||||
if ((dhg.size > minbits && dhg.size < best) ||
|
||||
(dhg.size > best && best < minbits)) {
|
||||
best = dhg.size;
|
||||
bestcount = 0;
|
||||
}
|
||||
if (dhg.size == best)
|
||||
bestcount++;
|
||||
}
|
||||
fclose (f);
|
||||
|
||||
if (bestcount == 0) {
|
||||
log("WARNING: no primes in %s, using old prime", DH_PRIMES);
|
||||
return (dh_new_group1());
|
||||
}
|
||||
|
||||
f = fopen(DH_PRIMES, "r");
|
||||
if (!f) {
|
||||
perror(DH_PRIMES);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
linenum = 0;
|
||||
which = arc4random() % bestcount;
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
if (!parse_prime(linenum, line, &dhg))
|
||||
continue;
|
||||
if (dhg.size != best)
|
||||
continue;
|
||||
if (linenum++ != which) {
|
||||
BN_free(dhg.g);
|
||||
BN_free(dhg.p);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return (dh_new_group(dhg.g, dhg.p));
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef DH_H
|
||||
#define DH_H
|
||||
|
||||
struct dhgroup {
|
||||
int size;
|
||||
BIGNUM *g;
|
||||
BIGNUM *p;
|
||||
};
|
||||
|
||||
DH *choose_dh(int minbits);
|
||||
|
||||
#endif
|
||||
@@ -22,7 +22,7 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: dispatch.c,v 1.4 2000/09/07 20:27:51 deraadt Exp $");
|
||||
RCSID("$OpenBSD: dispatch.c,v 1.5 2000/09/21 11:25:34 markus Exp $");
|
||||
#include "ssh.h"
|
||||
#include "dispatch.h"
|
||||
#include "packet.h"
|
||||
@@ -33,7 +33,7 @@ RCSID("$OpenBSD: dispatch.c,v 1.4 2000/09/07 20:27:51 deraadt Exp $");
|
||||
dispatch_fn *dispatch[DISPATCH_MAX];
|
||||
|
||||
void
|
||||
dispatch_protocol_error(int type, int plen)
|
||||
dispatch_protocol_error(int type, int plen, void *ctxt)
|
||||
{
|
||||
error("Hm, dispatch protocol error: type %d plen %d", type, plen);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ dispatch_set(int type, dispatch_fn *fn)
|
||||
dispatch[type] = fn;
|
||||
}
|
||||
void
|
||||
dispatch_run(int mode, int *done)
|
||||
dispatch_run(int mode, int *done, void *ctxt)
|
||||
{
|
||||
for (;;) {
|
||||
int plen;
|
||||
@@ -64,7 +64,7 @@ dispatch_run(int mode, int *done)
|
||||
return;
|
||||
}
|
||||
if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL)
|
||||
(*dispatch[type])(type, plen);
|
||||
(*dispatch[type])(type, plen, ctxt);
|
||||
else
|
||||
packet_disconnect("protocol error: rcvd type %d", type);
|
||||
if (done != NULL && *done)
|
||||
|
||||
@@ -26,9 +26,9 @@ enum {
|
||||
DISPATCH_NONBLOCK
|
||||
};
|
||||
|
||||
typedef void dispatch_fn(int type, int plen);
|
||||
typedef void dispatch_fn(int type, int plen, void *ctxt);
|
||||
|
||||
void dispatch_init(dispatch_fn *dflt);
|
||||
void dispatch_set(int type, dispatch_fn *fn);
|
||||
void dispatch_run(int mode, int *done);
|
||||
void dispatch_protocol_error(int type, int plen);
|
||||
void dispatch_run(int mode, int *done, void *ctxt);
|
||||
void dispatch_protocol_error(int type, int plen, void *ctxt);
|
||||
|
||||
+115
-54
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: kex.c,v 1.10 2000/09/07 20:27:51 deraadt Exp $");
|
||||
RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "ssh2.h"
|
||||
@@ -31,7 +31,6 @@ RCSID("$OpenBSD: kex.c,v 1.10 2000/09/07 20:27:51 deraadt Exp $");
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
#include "packet.h"
|
||||
#include "cipher.h"
|
||||
#include "compat.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
@@ -123,11 +122,6 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
|
||||
int n = BN_num_bits(dh_pub);
|
||||
int bits_set = 0;
|
||||
|
||||
/* we only accept g==2 */
|
||||
if (!BN_is_word(dh->g, 2)) {
|
||||
log("invalid DH base != 2");
|
||||
return 0;
|
||||
}
|
||||
if (dh_pub->neg) {
|
||||
log("invalid public DH value: negativ");
|
||||
return 0;
|
||||
@@ -145,27 +139,10 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
|
||||
}
|
||||
|
||||
DH *
|
||||
dh_new_group1()
|
||||
dh_gen_key(DH *dh)
|
||||
{
|
||||
static char *group1 =
|
||||
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
|
||||
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
|
||||
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
|
||||
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
|
||||
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
|
||||
"FFFFFFFF" "FFFFFFFF";
|
||||
DH *dh;
|
||||
int ret, tries = 0;
|
||||
dh = DH_new();
|
||||
if(dh == NULL)
|
||||
fatal("DH_new");
|
||||
ret = BN_hex2bn(&dh->p, group1);
|
||||
if(ret<0)
|
||||
fatal("BN_hex2bn");
|
||||
dh->g = BN_new();
|
||||
if(dh->g == NULL)
|
||||
fatal("DH_new g");
|
||||
BN_set_word(dh->g, 2);
|
||||
int tries = 0;
|
||||
|
||||
do {
|
||||
if (DH_generate_key(dh) == 0)
|
||||
fatal("DH_generate_key");
|
||||
@@ -175,6 +152,52 @@ dh_new_group1()
|
||||
return dh;
|
||||
}
|
||||
|
||||
DH *
|
||||
dh_new_group_asc(const char *gen, const char *modulus)
|
||||
{
|
||||
DH *dh;
|
||||
int ret;
|
||||
|
||||
dh = DH_new();
|
||||
if (dh == NULL)
|
||||
fatal("DH_new");
|
||||
|
||||
if ((ret = BN_hex2bn(&dh->p, modulus)) < 0)
|
||||
fatal("BN_hex2bn p");
|
||||
if ((ret = BN_hex2bn(&dh->g, gen)) < 0)
|
||||
fatal("BN_hex2bn g");
|
||||
|
||||
return (dh_gen_key(dh));
|
||||
}
|
||||
|
||||
DH *
|
||||
dh_new_group(BIGNUM *gen, BIGNUM *modulus)
|
||||
{
|
||||
DH *dh;
|
||||
|
||||
dh = DH_new();
|
||||
if (dh == NULL)
|
||||
fatal("DH_new");
|
||||
dh->p = modulus;
|
||||
dh->g = gen;
|
||||
|
||||
return (dh_gen_key(dh));
|
||||
}
|
||||
|
||||
DH *
|
||||
dh_new_group1()
|
||||
{
|
||||
static char *gen = "2", *group1 =
|
||||
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
|
||||
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
|
||||
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
|
||||
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
|
||||
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
|
||||
"FFFFFFFF" "FFFFFFFF";
|
||||
|
||||
return (dh_new_group_asc(gen, group1));
|
||||
}
|
||||
|
||||
void
|
||||
dump_digest(unsigned char *digest, int len)
|
||||
{
|
||||
@@ -236,6 +259,59 @@ kex_hash(
|
||||
return digest;
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
kex_hash_gex(
|
||||
char *client_version_string,
|
||||
char *server_version_string,
|
||||
char *ckexinit, int ckexinitlen,
|
||||
char *skexinit, int skexinitlen,
|
||||
char *serverhostkeyblob, int sbloblen,
|
||||
int minbits, BIGNUM *prime, BIGNUM *gen,
|
||||
BIGNUM *client_dh_pub,
|
||||
BIGNUM *server_dh_pub,
|
||||
BIGNUM *shared_secret)
|
||||
{
|
||||
Buffer b;
|
||||
static unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
EVP_MD *evp_md = EVP_sha1();
|
||||
EVP_MD_CTX md;
|
||||
|
||||
buffer_init(&b);
|
||||
buffer_put_string(&b, client_version_string, strlen(client_version_string));
|
||||
buffer_put_string(&b, server_version_string, strlen(server_version_string));
|
||||
|
||||
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
|
||||
buffer_put_int(&b, ckexinitlen+1);
|
||||
buffer_put_char(&b, SSH2_MSG_KEXINIT);
|
||||
buffer_append(&b, ckexinit, ckexinitlen);
|
||||
buffer_put_int(&b, skexinitlen+1);
|
||||
buffer_put_char(&b, SSH2_MSG_KEXINIT);
|
||||
buffer_append(&b, skexinit, skexinitlen);
|
||||
|
||||
buffer_put_string(&b, serverhostkeyblob, sbloblen);
|
||||
buffer_put_int(&b, minbits);
|
||||
buffer_put_bignum2(&b, prime);
|
||||
buffer_put_bignum2(&b, gen);
|
||||
buffer_put_bignum2(&b, client_dh_pub);
|
||||
buffer_put_bignum2(&b, server_dh_pub);
|
||||
buffer_put_bignum2(&b, shared_secret);
|
||||
|
||||
#ifdef DEBUG_KEX
|
||||
buffer_dump(&b);
|
||||
#endif
|
||||
|
||||
EVP_DigestInit(&md, evp_md);
|
||||
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
|
||||
EVP_DigestFinal(&md, digest, NULL);
|
||||
|
||||
buffer_free(&b);
|
||||
|
||||
#ifdef DEBUG_KEX
|
||||
dump_digest(digest, evp_md->md_size);
|
||||
#endif
|
||||
return digest;
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret)
|
||||
{
|
||||
@@ -318,28 +394,9 @@ choose_enc(Enc *enc, char *client, char *server)
|
||||
char *name = get_match(client, server);
|
||||
if (name == NULL)
|
||||
fatal("no matching cipher found: client %s server %s", client, server);
|
||||
enc->type = cipher_number(name);
|
||||
|
||||
switch (enc->type) {
|
||||
case SSH_CIPHER_3DES_CBC:
|
||||
enc->key_len = 24;
|
||||
enc->iv_len = 8;
|
||||
enc->block_size = 8;
|
||||
break;
|
||||
case SSH_CIPHER_BLOWFISH_CBC:
|
||||
case SSH_CIPHER_CAST128_CBC:
|
||||
enc->key_len = 16;
|
||||
enc->iv_len = 8;
|
||||
enc->block_size = 8;
|
||||
break;
|
||||
case SSH_CIPHER_ARCFOUR:
|
||||
enc->key_len = 16;
|
||||
enc->iv_len = 0;
|
||||
enc->block_size = 8;
|
||||
break;
|
||||
default:
|
||||
fatal("unsupported cipher %s", name);
|
||||
}
|
||||
enc->cipher = cipher_by_name(name);
|
||||
if (enc->cipher == NULL)
|
||||
fatal("matching cipher is not supported: %s", name);
|
||||
enc->name = name;
|
||||
enc->enabled = 0;
|
||||
enc->iv = NULL;
|
||||
@@ -387,7 +444,11 @@ choose_kex(Kex *k, char *client, char *server)
|
||||
k->name = get_match(client, server);
|
||||
if (k->name == NULL)
|
||||
fatal("no kex alg");
|
||||
if (strcmp(k->name, KEX_DH1) != 0)
|
||||
if (strcmp(k->name, KEX_DH1) == 0) {
|
||||
k->kex_type = DH_GRP1_SHA1;
|
||||
} else if (strcmp(k->name, KEX_DHGEX) == 0) {
|
||||
k->kex_type = DH_GEX_SHA1;
|
||||
} else
|
||||
fatal("bad kex alg %s", k->name);
|
||||
}
|
||||
void
|
||||
@@ -432,10 +493,10 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server
|
||||
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
|
||||
need = 0;
|
||||
for (mode = 0; mode < MODE_MAX; mode++) {
|
||||
if (need < k->enc[mode].key_len)
|
||||
need = k->enc[mode].key_len;
|
||||
if (need < k->enc[mode].iv_len)
|
||||
need = k->enc[mode].iv_len;
|
||||
if (need < k->enc[mode].cipher->key_len)
|
||||
need = k->enc[mode].cipher->key_len;
|
||||
if (need < k->enc[mode].cipher->block_size)
|
||||
need = k->enc[mode].cipher->block_size;
|
||||
if (need < k->mac[mode].key_len)
|
||||
need = k->mac[mode].key_len;
|
||||
}
|
||||
|
||||
+26
-9
@@ -24,8 +24,9 @@
|
||||
#ifndef KEX_H
|
||||
#define KEX_H
|
||||
|
||||
#define KEX_DH1 "diffie-hellman-group1-sha1"
|
||||
#define KEX_DSS "ssh-dss"
|
||||
#define KEX_DH1 "diffie-hellman-group1-sha1"
|
||||
#define KEX_DHGEX "diffie-hellman-group-exchange-sha1"
|
||||
#define KEX_DSS "ssh-dss"
|
||||
|
||||
enum kex_init_proposals {
|
||||
PROPOSAL_KEX_ALGS,
|
||||
@@ -47,28 +48,30 @@ enum kex_modes {
|
||||
MODE_MAX
|
||||
};
|
||||
|
||||
enum kex_exchange {
|
||||
DH_GRP1_SHA1,
|
||||
DH_GEX_SHA1
|
||||
};
|
||||
|
||||
typedef struct Kex Kex;
|
||||
typedef struct Mac Mac;
|
||||
typedef struct Comp Comp;
|
||||
typedef struct Enc Enc;
|
||||
|
||||
struct Enc {
|
||||
int type;
|
||||
char *name;
|
||||
Cipher *cipher;
|
||||
int enabled;
|
||||
int block_size;
|
||||
unsigned char *key;
|
||||
unsigned char *iv;
|
||||
int key_len;
|
||||
int iv_len;
|
||||
char *name;
|
||||
};
|
||||
struct Mac {
|
||||
EVP_MD *md;
|
||||
char *name;
|
||||
int enabled;
|
||||
EVP_MD *md;
|
||||
int mac_len;
|
||||
unsigned char *key;
|
||||
int key_len;
|
||||
char *name;
|
||||
};
|
||||
struct Comp {
|
||||
int type;
|
||||
@@ -83,6 +86,7 @@ struct Kex {
|
||||
int server;
|
||||
char *name;
|
||||
char *hostkeyalg;
|
||||
int kex_type;
|
||||
};
|
||||
|
||||
Buffer *kex_init(char *myproposal[PROPOSAL_MAX]);
|
||||
@@ -96,6 +100,8 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX],
|
||||
int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret);
|
||||
void packet_set_kex(Kex *k);
|
||||
int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
|
||||
DH *dh_new_group_asc(const char *, const char *);
|
||||
DH *dh_new_group(BIGNUM *, BIGNUM *);
|
||||
DH *dh_new_group1();
|
||||
|
||||
unsigned char *
|
||||
@@ -109,4 +115,15 @@ kex_hash(
|
||||
BIGNUM *server_dh_pub,
|
||||
BIGNUM *shared_secret);
|
||||
|
||||
unsigned char *
|
||||
kex_hash_gex(
|
||||
char *client_version_string,
|
||||
char *server_version_string,
|
||||
char *ckexinit, int ckexinitlen,
|
||||
char *skexinit, int skexinitlen,
|
||||
char *serverhostkeyblob, int sbloblen,
|
||||
int minbits, BIGNUM *prime, BIGNUM *gen,
|
||||
BIGNUM *client_dh_pub,
|
||||
BIGNUM *server_dh_pub,
|
||||
BIGNUM *shared_secret);
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,8 @@ SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \
|
||||
cipher.c compat.c compress.c crc32.c deattack.c \
|
||||
hostfile.c log.c match.c mpaux.c nchan.c packet.c readpass.c \
|
||||
rsa.c tildexpand.c ttymodes.c uidswap.c xmalloc.c atomicio.c \
|
||||
key.c dispatch.c dsa.c kex.c hmac.c uuencode.c util.c
|
||||
key.c dispatch.c dsa.c kex.c hmac.c uuencode.c util.c \
|
||||
cli.c rijndael.c
|
||||
|
||||
NOPROFILE= yes
|
||||
NOPIC= yes
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: log-client.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $");
|
||||
RCSID("$OpenBSD: log-client.c,v 1.12 2000/09/12 20:53:10 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
@@ -57,7 +57,9 @@ log_init(char *av0, LogLevel level, SyslogFacility ignored1, int ignored2)
|
||||
case SYSLOG_LEVEL_FATAL:
|
||||
case SYSLOG_LEVEL_INFO:
|
||||
case SYSLOG_LEVEL_VERBOSE:
|
||||
case SYSLOG_LEVEL_DEBUG:
|
||||
case SYSLOG_LEVEL_DEBUG1:
|
||||
case SYSLOG_LEVEL_DEBUG2:
|
||||
case SYSLOG_LEVEL_DEBUG3:
|
||||
log_level = level;
|
||||
break;
|
||||
default:
|
||||
@@ -75,7 +77,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
|
||||
|
||||
if (level > log_level)
|
||||
return;
|
||||
if (level == SYSLOG_LEVEL_DEBUG)
|
||||
if (level >= SYSLOG_LEVEL_DEBUG1)
|
||||
fprintf(stderr, "debug: ");
|
||||
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
|
||||
fprintf(stderr, "%s\r\n", msgbuf);
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: log-server.c,v 1.16 2000/09/07 20:27:52 deraadt Exp $");
|
||||
RCSID("$OpenBSD: log-server.c,v 1.17 2000/09/12 20:53:10 markus Exp $");
|
||||
|
||||
#include <syslog.h>
|
||||
#include "packet.h"
|
||||
@@ -62,7 +62,9 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
|
||||
case SYSLOG_LEVEL_FATAL:
|
||||
case SYSLOG_LEVEL_INFO:
|
||||
case SYSLOG_LEVEL_VERBOSE:
|
||||
case SYSLOG_LEVEL_DEBUG:
|
||||
case SYSLOG_LEVEL_DEBUG1:
|
||||
case SYSLOG_LEVEL_DEBUG2:
|
||||
case SYSLOG_LEVEL_DEBUG3:
|
||||
log_level = level;
|
||||
break;
|
||||
default:
|
||||
@@ -138,8 +140,16 @@ do_log(LogLevel level, const char *fmt, va_list args)
|
||||
case SYSLOG_LEVEL_VERBOSE:
|
||||
pri = LOG_INFO;
|
||||
break;
|
||||
case SYSLOG_LEVEL_DEBUG:
|
||||
txt = "debug";
|
||||
case SYSLOG_LEVEL_DEBUG1:
|
||||
txt = "debug1";
|
||||
pri = LOG_DEBUG;
|
||||
break;
|
||||
case SYSLOG_LEVEL_DEBUG2:
|
||||
txt = "debug2";
|
||||
pri = LOG_DEBUG;
|
||||
break;
|
||||
case SYSLOG_LEVEL_DEBUG3:
|
||||
txt = "debug3";
|
||||
pri = LOG_DEBUG;
|
||||
break;
|
||||
default:
|
||||
|
||||
+24
-3
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: log.c,v 1.9 2000/09/07 21:13:37 markus Exp $");
|
||||
RCSID("$OpenBSD: log.c,v 1.11 2000/09/30 16:27:43 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "xmalloc.h"
|
||||
@@ -93,7 +93,25 @@ debug(const char *fmt,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
do_log(SYSLOG_LEVEL_DEBUG, fmt, args);
|
||||
do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
debug2(const char *fmt,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
debug3(const char *fmt,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -190,7 +208,10 @@ static struct {
|
||||
{ "ERROR", SYSLOG_LEVEL_ERROR },
|
||||
{ "INFO", SYSLOG_LEVEL_INFO },
|
||||
{ "VERBOSE", SYSLOG_LEVEL_VERBOSE },
|
||||
{ "DEBUG", SYSLOG_LEVEL_DEBUG },
|
||||
{ "DEBUG", SYSLOG_LEVEL_DEBUG1 },
|
||||
{ "DEBUG1", SYSLOG_LEVEL_DEBUG1 },
|
||||
{ "DEBUG2", SYSLOG_LEVEL_DEBUG2 },
|
||||
{ "DEBUG3", SYSLOG_LEVEL_DEBUG3 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -21,11 +21,15 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#define KEX_DEFAULT_KEX "diffie-hellman-group1-sha1"
|
||||
#define KEX_DEFAULT_KEX "diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1"
|
||||
#define KEX_DEFAULT_PK_ALG "ssh-dss"
|
||||
#define KEX_DEFAULT_ENCRYPT "3des-cbc,blowfish-cbc,arcfour,cast128-cbc"
|
||||
#define KEX_DEFAULT_ENCRYPT \
|
||||
"3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \
|
||||
"aes128-cbc,aes192-cbc,aes256-cbc," \
|
||||
"rijndael128-cbc,rijndael192-cbc,rijndael256-cbc," \
|
||||
"rijndael-cbc@lysator.liu.se"
|
||||
#define KEX_DEFAULT_MAC "hmac-sha1,hmac-md5,hmac-ripemd160@openssh.com"
|
||||
#define KEX_DEFAULT_COMP "zlib,none"
|
||||
#define KEX_DEFAULT_COMP "none,zlib"
|
||||
#define KEX_DEFAULT_LANG ""
|
||||
|
||||
|
||||
|
||||
+33
-39
@@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: packet.c,v 1.35 2000/09/07 20:27:52 deraadt Exp $");
|
||||
RCSID("$OpenBSD: packet.c,v 1.38 2000/10/12 14:21:12 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
@@ -45,7 +45,6 @@ RCSID("$OpenBSD: packet.c,v 1.35 2000/09/07 20:27:52 deraadt Exp $");
|
||||
#include "bufaux.h"
|
||||
#include "ssh.h"
|
||||
#include "crc32.h"
|
||||
#include "cipher.h"
|
||||
#include "getput.h"
|
||||
|
||||
#include "compress.h"
|
||||
@@ -59,6 +58,7 @@ RCSID("$OpenBSD: packet.c,v 1.35 2000/09/07 20:27:52 deraadt Exp $");
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include "buffer.h"
|
||||
#include "cipher.h"
|
||||
#include "kex.h"
|
||||
#include "hmac.h"
|
||||
|
||||
@@ -161,11 +161,14 @@ packet_set_ssh2_format(void)
|
||||
void
|
||||
packet_set_connection(int fd_in, int fd_out)
|
||||
{
|
||||
Cipher *none = cipher_by_name("none");
|
||||
if (none == NULL)
|
||||
fatal("packet_set_connection: cannot load cipher 'none'");
|
||||
connection_in = fd_in;
|
||||
connection_out = fd_out;
|
||||
cipher_type = SSH_CIPHER_NONE;
|
||||
cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *) "", 0);
|
||||
cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *) "", 0);
|
||||
cipher_init(&send_context, none, (unsigned char *) "", 0, NULL, 0);
|
||||
cipher_init(&receive_context, none, (unsigned char *) "", 0, NULL, 0);
|
||||
if (!initialized) {
|
||||
initialized = 1;
|
||||
buffer_init(&input);
|
||||
@@ -326,28 +329,18 @@ packet_encrypt(CipherContext * cc, void *dest, void *src,
|
||||
*/
|
||||
|
||||
void
|
||||
packet_decrypt(CipherContext * cc, void *dest, void *src,
|
||||
unsigned int bytes)
|
||||
packet_decrypt(CipherContext *context, void *dest, void *src, unsigned int bytes)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((bytes % 8) != 0)
|
||||
fatal("packet_decrypt: bad ciphertext length %d", bytes);
|
||||
|
||||
/*
|
||||
* Cryptographic attack detector for ssh - Modifications for packet.c
|
||||
* (C)1998 CORE-SDI, Buenos Aires Argentina Ariel Futoransky(futo@core-sdi.com)
|
||||
*/
|
||||
|
||||
if (cc->type == SSH_CIPHER_NONE || compat20) {
|
||||
i = DEATTACK_OK;
|
||||
} else {
|
||||
i = detect_attack(src, bytes, NULL);
|
||||
}
|
||||
if (i == DEATTACK_DETECTED)
|
||||
if (!compat20 &&
|
||||
context->cipher->number != SSH_CIPHER_NONE &&
|
||||
detect_attack(src, bytes, NULL) == DEATTACK_DETECTED)
|
||||
packet_disconnect("crc32 compensation attack: network attack detected");
|
||||
|
||||
cipher_decrypt(cc, dest, src, bytes);
|
||||
cipher_decrypt(context, dest, src, bytes);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -358,14 +351,15 @@ packet_decrypt(CipherContext * cc, void *dest, void *src,
|
||||
|
||||
void
|
||||
packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
|
||||
int cipher)
|
||||
int number)
|
||||
{
|
||||
Cipher *cipher = cipher_by_number(number);
|
||||
if (cipher == NULL)
|
||||
fatal("packet_set_encryption_key: unknown cipher number %d", number);
|
||||
if (keylen < 20)
|
||||
fatal("keylen too small: %d", keylen);
|
||||
|
||||
/* All other ciphers use the same key in both directions for now. */
|
||||
cipher_set_key(&receive_context, cipher, key, keylen);
|
||||
cipher_set_key(&send_context, cipher, key, keylen);
|
||||
fatal("packet_set_encryption_key: keylen too small: %d", keylen);
|
||||
cipher_init(&receive_context, cipher, key, keylen, NULL, 0);
|
||||
cipher_init(&send_context, cipher, key, keylen, NULL, 0);
|
||||
}
|
||||
|
||||
/* Starts constructing a packet to send. */
|
||||
@@ -553,7 +547,7 @@ packet_send2()
|
||||
mac = &kex->mac[MODE_OUT];
|
||||
comp = &kex->comp[MODE_OUT];
|
||||
}
|
||||
block_size = enc ? enc->block_size : 8;
|
||||
block_size = enc ? enc->cipher->block_size : 8;
|
||||
|
||||
cp = buffer_ptr(&outgoing_packet);
|
||||
type = cp[5] & 0xff;
|
||||
@@ -588,7 +582,7 @@ packet_send2()
|
||||
if (padlen < 4)
|
||||
padlen += block_size;
|
||||
buffer_append_space(&outgoing_packet, &cp, padlen);
|
||||
if (enc && enc->type != SSH_CIPHER_NONE) {
|
||||
if (enc && enc->cipher->number != SSH_CIPHER_NONE) {
|
||||
/* random padding */
|
||||
for (i = 0; i < padlen; i++) {
|
||||
if (i % 4 == 0)
|
||||
@@ -614,7 +608,7 @@ packet_send2()
|
||||
buffer_len(&outgoing_packet),
|
||||
mac->key, mac->key_len
|
||||
);
|
||||
DBG(debug("done calc HMAC out #%d", seqnr));
|
||||
DBG(debug("done calc MAC out #%d", seqnr));
|
||||
}
|
||||
/* encrypt packet and append to output buffer. */
|
||||
buffer_append_space(&output, &cp, buffer_len(&outgoing_packet));
|
||||
@@ -637,10 +631,10 @@ packet_send2()
|
||||
fatal("packet_send2: no KEX");
|
||||
if (mac->md != NULL)
|
||||
mac->enabled = 1;
|
||||
DBG(debug("cipher_set_key_iv send_context"));
|
||||
cipher_set_key_iv(&send_context, enc->type,
|
||||
enc->key, enc->key_len,
|
||||
enc->iv, enc->iv_len);
|
||||
DBG(debug("cipher_init send_context"));
|
||||
cipher_init(&send_context, enc->cipher,
|
||||
enc->key, enc->cipher->key_len,
|
||||
enc->iv, enc->cipher->block_size);
|
||||
clear_enc_keys(enc, kex->we_need);
|
||||
if (comp->type != 0 && comp->enabled == 0) {
|
||||
comp->enabled = 1;
|
||||
@@ -841,7 +835,7 @@ packet_read_poll2(int *payload_len_ptr)
|
||||
comp = &kex->comp[MODE_IN];
|
||||
}
|
||||
maclen = mac && mac->enabled ? mac->mac_len : 0;
|
||||
block_size = enc ? enc->block_size : 8;
|
||||
block_size = enc ? enc->cipher->block_size : 8;
|
||||
|
||||
if (packet_length == 0) {
|
||||
/*
|
||||
@@ -894,8 +888,8 @@ packet_read_poll2(int *payload_len_ptr)
|
||||
mac->key, mac->key_len
|
||||
);
|
||||
if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
|
||||
packet_disconnect("Corrupted HMAC on input.");
|
||||
DBG(debug("HMAC #%d ok", seqnr));
|
||||
packet_disconnect("Corrupted MAC on input.");
|
||||
DBG(debug("MAC #%d ok", seqnr));
|
||||
buffer_consume(&input, mac->mac_len);
|
||||
}
|
||||
if (++seqnr == 0)
|
||||
@@ -939,10 +933,10 @@ packet_read_poll2(int *payload_len_ptr)
|
||||
fatal("packet_read_poll2: no KEX");
|
||||
if (mac->md != NULL)
|
||||
mac->enabled = 1;
|
||||
DBG(debug("cipher_set_key_iv receive_context"));
|
||||
cipher_set_key_iv(&receive_context, enc->type,
|
||||
enc->key, enc->key_len,
|
||||
enc->iv, enc->iv_len);
|
||||
DBG(debug("cipher_init receive_context"));
|
||||
cipher_init(&receive_context, enc->cipher,
|
||||
enc->key, enc->cipher->key_len,
|
||||
enc->iv, enc->cipher->block_size);
|
||||
clear_enc_keys(enc, kex->we_need);
|
||||
if (comp->type != 0 && comp->enabled == 0) {
|
||||
comp->enabled = 1;
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: readconf.c,v 1.47 2000/09/07 21:13:37 markus Exp $");
|
||||
RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "cipher.h"
|
||||
#include "readconf.h"
|
||||
#include "match.h"
|
||||
#include "xmalloc.h"
|
||||
@@ -103,7 +102,8 @@ typedef enum {
|
||||
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
|
||||
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
|
||||
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2,
|
||||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication
|
||||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication,
|
||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices
|
||||
} OpCodes;
|
||||
|
||||
/* Textual representations of the tokens. */
|
||||
@@ -119,6 +119,8 @@ static struct {
|
||||
{ "useprivilegedport", oUsePrivilegedPort },
|
||||
{ "rhostsauthentication", oRhostsAuthentication },
|
||||
{ "passwordauthentication", oPasswordAuthentication },
|
||||
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
|
||||
{ "kbdinteractivedevices", oKbdInteractiveDevices },
|
||||
{ "rsaauthentication", oRSAAuthentication },
|
||||
{ "dsaauthentication", oDSAAuthentication },
|
||||
{ "skeyauthentication", oSkeyAuthentication },
|
||||
@@ -288,6 +290,14 @@ process_config_line(Options *options, const char *host,
|
||||
intptr = &options->password_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
case oKbdInteractiveAuthentication:
|
||||
intptr = &options->kbd_interactive_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
case oKbdInteractiveDevices:
|
||||
charptr = &options->kbd_interactive_devices;
|
||||
goto parse_string;
|
||||
|
||||
case oDSAAuthentication:
|
||||
intptr = &options->dsa_authentication;
|
||||
goto parse_flag;
|
||||
@@ -662,6 +672,8 @@ initialize_options(Options * options)
|
||||
options->afs_token_passing = -1;
|
||||
#endif
|
||||
options->password_authentication = -1;
|
||||
options->kbd_interactive_authentication = -1;
|
||||
options->kbd_interactive_devices = NULL;
|
||||
options->rhosts_rsa_authentication = -1;
|
||||
options->fallback_to_rsh = -1;
|
||||
options->use_rsh = -1;
|
||||
@@ -732,6 +744,8 @@ fill_default_options(Options * options)
|
||||
#endif /* AFS */
|
||||
if (options->password_authentication == -1)
|
||||
options->password_authentication = 1;
|
||||
if (options->kbd_interactive_authentication == -1)
|
||||
options->kbd_interactive_authentication = 0;
|
||||
if (options->rhosts_rsa_authentication == -1)
|
||||
options->rhosts_rsa_authentication = 1;
|
||||
if (options->fallback_to_rsh == -1)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: readconf.h,v 1.21 2000/09/07 20:27:53 deraadt Exp $"); */
|
||||
/* RCSID("$OpenBSD: readconf.h,v 1.22 2000/10/11 20:14:39 markus Exp $"); */
|
||||
|
||||
#ifndef READCONF_H
|
||||
#define READCONF_H
|
||||
@@ -47,6 +47,8 @@ typedef struct {
|
||||
#endif
|
||||
int password_authentication; /* Try password
|
||||
* authentication. */
|
||||
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
|
||||
char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
|
||||
int fallback_to_rsh;/* Use rsh if cannot connect with ssh. */
|
||||
int use_rsh; /* Always use rsh (don\'t try ssh). */
|
||||
int batch_mode; /* Batch mode: do not ask for passwords. */
|
||||
|
||||
@@ -32,88 +32,24 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: readpass.c,v 1.11 2000/06/20 01:39:44 markus Exp $");
|
||||
RCSID("$OpenBSD: readpass.c,v 1.12 2000/10/11 20:14:39 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
|
||||
volatile int intr;
|
||||
|
||||
void
|
||||
intcatch()
|
||||
{
|
||||
intr = 1;
|
||||
}
|
||||
#include "cli.h"
|
||||
|
||||
/*
|
||||
* Reads a passphrase from /dev/tty with echo turned off. Returns the
|
||||
* passphrase (allocated with xmalloc), being very careful to ensure that
|
||||
* no other userland buffer is storing the password.
|
||||
*/
|
||||
/*
|
||||
* Note: the funcationallity of this routing has been moved to
|
||||
* cli_read_passphrase(). This routing remains to maintain
|
||||
* compatibility with existing code.
|
||||
*/
|
||||
char *
|
||||
read_passphrase(const char *prompt, int from_stdin)
|
||||
read_passphrase(char *prompt, int from_stdin)
|
||||
{
|
||||
char buf[1024], *p, ch;
|
||||
struct termios tio, saved_tio;
|
||||
sigset_t oset, nset;
|
||||
struct sigaction sa, osa;
|
||||
int input, output, echo = 0;
|
||||
|
||||
if (from_stdin) {
|
||||
input = STDIN_FILENO;
|
||||
output = STDERR_FILENO;
|
||||
} else
|
||||
input = output = open("/dev/tty", O_RDWR);
|
||||
|
||||
if (input == -1)
|
||||
fatal("You have no controlling tty. Cannot read passphrase.\n");
|
||||
|
||||
/* block signals, get terminal modes and turn off echo */
|
||||
sigemptyset(&nset);
|
||||
sigaddset(&nset, SIGTSTP);
|
||||
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = intcatch;
|
||||
(void) sigaction(SIGINT, &sa, &osa);
|
||||
|
||||
intr = 0;
|
||||
|
||||
if (tcgetattr(input, &saved_tio) == 0 && (saved_tio.c_lflag & ECHO)) {
|
||||
echo = 1;
|
||||
tio = saved_tio;
|
||||
tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
|
||||
(void) tcsetattr(input, TCSANOW, &tio);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
(void)write(output, prompt, strlen(prompt));
|
||||
for (p = buf; read(input, &ch, 1) == 1 && ch != '\n';) {
|
||||
if (intr)
|
||||
break;
|
||||
if (p < buf + sizeof(buf) - 1)
|
||||
*p++ = ch;
|
||||
}
|
||||
*p = '\0';
|
||||
if (!intr)
|
||||
(void)write(output, "\n", 1);
|
||||
|
||||
/* restore terminal modes and allow signals */
|
||||
if (echo)
|
||||
tcsetattr(input, TCSANOW, &saved_tio);
|
||||
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
|
||||
(void) sigaction(SIGINT, &osa, NULL);
|
||||
|
||||
if (intr) {
|
||||
kill(getpid(), SIGINT);
|
||||
sigemptyset(&nset);
|
||||
/* XXX tty has not neccessarily drained by now? */
|
||||
sigsuspend(&nset);
|
||||
}
|
||||
|
||||
if (!from_stdin)
|
||||
(void)close(input);
|
||||
p = xstrdup(buf);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
return (p);
|
||||
return cli_read_passphrase(prompt, from_stdin, 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,493 @@
|
||||
/* $OpenBSD: rijndael.c,v 1.2 2000/10/15 14:14:01 markus Exp $ */
|
||||
|
||||
/* This is an independent implementation of the encryption algorithm: */
|
||||
/* */
|
||||
/* RIJNDAEL by Joan Daemen and Vincent Rijmen */
|
||||
/* */
|
||||
/* which is a candidate algorithm in the Advanced Encryption Standard */
|
||||
/* programme of the US National Institute of Standards and Technology. */
|
||||
/* */
|
||||
/* Copyright in this implementation is held by Dr B R Gladman but I */
|
||||
/* hereby give permission for its free direct or derivative use subject */
|
||||
/* to acknowledgment of its origin and compliance with any conditions */
|
||||
/* that the originators of the algorithm place on its exploitation. */
|
||||
/* */
|
||||
/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */
|
||||
|
||||
/* Timing data for Rijndael (rijndael.c)
|
||||
|
||||
Algorithm: rijndael (rijndael.c)
|
||||
|
||||
128 bit key:
|
||||
Key Setup: 305/1389 cycles (encrypt/decrypt)
|
||||
Encrypt: 374 cycles = 68.4 mbits/sec
|
||||
Decrypt: 352 cycles = 72.7 mbits/sec
|
||||
Mean: 363 cycles = 70.5 mbits/sec
|
||||
|
||||
192 bit key:
|
||||
Key Setup: 277/1595 cycles (encrypt/decrypt)
|
||||
Encrypt: 439 cycles = 58.3 mbits/sec
|
||||
Decrypt: 425 cycles = 60.2 mbits/sec
|
||||
Mean: 432 cycles = 59.3 mbits/sec
|
||||
|
||||
256 bit key:
|
||||
Key Setup: 374/1960 cycles (encrypt/decrypt)
|
||||
Encrypt: 502 cycles = 51.0 mbits/sec
|
||||
Decrypt: 498 cycles = 51.4 mbits/sec
|
||||
Mean: 500 cycles = 51.2 mbits/sec
|
||||
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "rijndael.h"
|
||||
|
||||
void gen_tabs __P((void));
|
||||
|
||||
/* 3. Basic macros for speeding up generic operations */
|
||||
|
||||
/* Circular rotate of 32 bit values */
|
||||
|
||||
#define rotr(x,n) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n))))
|
||||
#define rotl(x,n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n))))
|
||||
|
||||
/* Invert byte order in a 32 bit variable */
|
||||
|
||||
#define bswap(x) (rotl(x, 8) & 0x00ff00ff | rotr(x, 8) & 0xff00ff00)
|
||||
|
||||
/* Extract byte from a 32 bit quantity (little endian notation) */
|
||||
|
||||
#define byte(x,n) ((u1byte)((x) >> (8 * n)))
|
||||
|
||||
#if BYTE_ORDER != LITTLE_ENDIAN
|
||||
#define BLOCK_SWAP
|
||||
#endif
|
||||
|
||||
/* For inverting byte order in input/output 32 bit words if needed */
|
||||
|
||||
#ifdef BLOCK_SWAP
|
||||
#define BYTE_SWAP
|
||||
#define WORD_SWAP
|
||||
#endif
|
||||
|
||||
#ifdef BYTE_SWAP
|
||||
#define io_swap(x) bswap(x)
|
||||
#else
|
||||
#define io_swap(x) (x)
|
||||
#endif
|
||||
|
||||
/* For inverting the byte order of input/output blocks if needed */
|
||||
|
||||
#ifdef WORD_SWAP
|
||||
|
||||
#define get_block(x) \
|
||||
((u4byte*)(x))[0] = io_swap(in_blk[3]); \
|
||||
((u4byte*)(x))[1] = io_swap(in_blk[2]); \
|
||||
((u4byte*)(x))[2] = io_swap(in_blk[1]); \
|
||||
((u4byte*)(x))[3] = io_swap(in_blk[0])
|
||||
|
||||
#define put_block(x) \
|
||||
out_blk[3] = io_swap(((u4byte*)(x))[0]); \
|
||||
out_blk[2] = io_swap(((u4byte*)(x))[1]); \
|
||||
out_blk[1] = io_swap(((u4byte*)(x))[2]); \
|
||||
out_blk[0] = io_swap(((u4byte*)(x))[3])
|
||||
|
||||
#define get_key(x,len) \
|
||||
((u4byte*)(x))[4] = ((u4byte*)(x))[5] = \
|
||||
((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0; \
|
||||
switch((((len) + 63) / 64)) { \
|
||||
case 2: \
|
||||
((u4byte*)(x))[0] = io_swap(in_key[3]); \
|
||||
((u4byte*)(x))[1] = io_swap(in_key[2]); \
|
||||
((u4byte*)(x))[2] = io_swap(in_key[1]); \
|
||||
((u4byte*)(x))[3] = io_swap(in_key[0]); \
|
||||
break; \
|
||||
case 3: \
|
||||
((u4byte*)(x))[0] = io_swap(in_key[5]); \
|
||||
((u4byte*)(x))[1] = io_swap(in_key[4]); \
|
||||
((u4byte*)(x))[2] = io_swap(in_key[3]); \
|
||||
((u4byte*)(x))[3] = io_swap(in_key[2]); \
|
||||
((u4byte*)(x))[4] = io_swap(in_key[1]); \
|
||||
((u4byte*)(x))[5] = io_swap(in_key[0]); \
|
||||
break; \
|
||||
case 4: \
|
||||
((u4byte*)(x))[0] = io_swap(in_key[7]); \
|
||||
((u4byte*)(x))[1] = io_swap(in_key[6]); \
|
||||
((u4byte*)(x))[2] = io_swap(in_key[5]); \
|
||||
((u4byte*)(x))[3] = io_swap(in_key[4]); \
|
||||
((u4byte*)(x))[4] = io_swap(in_key[3]); \
|
||||
((u4byte*)(x))[5] = io_swap(in_key[2]); \
|
||||
((u4byte*)(x))[6] = io_swap(in_key[1]); \
|
||||
((u4byte*)(x))[7] = io_swap(in_key[0]); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define get_block(x) \
|
||||
((u4byte*)(x))[0] = io_swap(in_blk[0]); \
|
||||
((u4byte*)(x))[1] = io_swap(in_blk[1]); \
|
||||
((u4byte*)(x))[2] = io_swap(in_blk[2]); \
|
||||
((u4byte*)(x))[3] = io_swap(in_blk[3])
|
||||
|
||||
#define put_block(x) \
|
||||
out_blk[0] = io_swap(((u4byte*)(x))[0]); \
|
||||
out_blk[1] = io_swap(((u4byte*)(x))[1]); \
|
||||
out_blk[2] = io_swap(((u4byte*)(x))[2]); \
|
||||
out_blk[3] = io_swap(((u4byte*)(x))[3])
|
||||
|
||||
#define get_key(x,len) \
|
||||
((u4byte*)(x))[4] = ((u4byte*)(x))[5] = \
|
||||
((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0; \
|
||||
switch((((len) + 63) / 64)) { \
|
||||
case 4: \
|
||||
((u4byte*)(x))[6] = io_swap(in_key[6]); \
|
||||
((u4byte*)(x))[7] = io_swap(in_key[7]); \
|
||||
case 3: \
|
||||
((u4byte*)(x))[4] = io_swap(in_key[4]); \
|
||||
((u4byte*)(x))[5] = io_swap(in_key[5]); \
|
||||
case 2: \
|
||||
((u4byte*)(x))[0] = io_swap(in_key[0]); \
|
||||
((u4byte*)(x))[1] = io_swap(in_key[1]); \
|
||||
((u4byte*)(x))[2] = io_swap(in_key[2]); \
|
||||
((u4byte*)(x))[3] = io_swap(in_key[3]); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define LARGE_TABLES
|
||||
|
||||
u1byte pow_tab[256];
|
||||
u1byte log_tab[256];
|
||||
u1byte sbx_tab[256];
|
||||
u1byte isb_tab[256];
|
||||
u4byte rco_tab[ 10];
|
||||
u4byte ft_tab[4][256];
|
||||
u4byte it_tab[4][256];
|
||||
|
||||
#ifdef LARGE_TABLES
|
||||
u4byte fl_tab[4][256];
|
||||
u4byte il_tab[4][256];
|
||||
#endif
|
||||
|
||||
u4byte tab_gen = 0;
|
||||
|
||||
#define ff_mult(a,b) (a && b ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0)
|
||||
|
||||
#define f_rn(bo, bi, n, k) \
|
||||
bo[n] = ft_tab[0][byte(bi[n],0)] ^ \
|
||||
ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
|
||||
ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
|
||||
ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
|
||||
|
||||
#define i_rn(bo, bi, n, k) \
|
||||
bo[n] = it_tab[0][byte(bi[n],0)] ^ \
|
||||
it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
|
||||
it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
|
||||
it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
|
||||
|
||||
#ifdef LARGE_TABLES
|
||||
|
||||
#define ls_box(x) \
|
||||
( fl_tab[0][byte(x, 0)] ^ \
|
||||
fl_tab[1][byte(x, 1)] ^ \
|
||||
fl_tab[2][byte(x, 2)] ^ \
|
||||
fl_tab[3][byte(x, 3)] )
|
||||
|
||||
#define f_rl(bo, bi, n, k) \
|
||||
bo[n] = fl_tab[0][byte(bi[n],0)] ^ \
|
||||
fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
|
||||
fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
|
||||
fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
|
||||
|
||||
#define i_rl(bo, bi, n, k) \
|
||||
bo[n] = il_tab[0][byte(bi[n],0)] ^ \
|
||||
il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
|
||||
il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
|
||||
il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
|
||||
|
||||
#else
|
||||
|
||||
#define ls_box(x) \
|
||||
((u4byte)sbx_tab[byte(x, 0)] << 0) ^ \
|
||||
((u4byte)sbx_tab[byte(x, 1)] << 8) ^ \
|
||||
((u4byte)sbx_tab[byte(x, 2)] << 16) ^ \
|
||||
((u4byte)sbx_tab[byte(x, 3)] << 24)
|
||||
|
||||
#define f_rl(bo, bi, n, k) \
|
||||
bo[n] = (u4byte)sbx_tab[byte(bi[n],0)] ^ \
|
||||
rotl(((u4byte)sbx_tab[byte(bi[(n + 1) & 3],1)]), 8) ^ \
|
||||
rotl(((u4byte)sbx_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \
|
||||
rotl(((u4byte)sbx_tab[byte(bi[(n + 3) & 3],3)]), 24) ^ *(k + n)
|
||||
|
||||
#define i_rl(bo, bi, n, k) \
|
||||
bo[n] = (u4byte)isb_tab[byte(bi[n],0)] ^ \
|
||||
rotl(((u4byte)isb_tab[byte(bi[(n + 3) & 3],1)]), 8) ^ \
|
||||
rotl(((u4byte)isb_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \
|
||||
rotl(((u4byte)isb_tab[byte(bi[(n + 1) & 3],3)]), 24) ^ *(k + n)
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
gen_tabs(void)
|
||||
{
|
||||
u4byte i, t;
|
||||
u1byte p, q;
|
||||
|
||||
/* log and power tables for GF(2**8) finite field with */
|
||||
/* 0x11b as modular polynomial - the simplest prmitive */
|
||||
/* root is 0x11, used here to generate the tables */
|
||||
|
||||
for(i = 0,p = 1; i < 256; ++i) {
|
||||
pow_tab[i] = (u1byte)p; log_tab[p] = (u1byte)i;
|
||||
|
||||
p = p ^ (p << 1) ^ (p & 0x80 ? 0x01b : 0);
|
||||
}
|
||||
|
||||
log_tab[1] = 0; p = 1;
|
||||
|
||||
for(i = 0; i < 10; ++i) {
|
||||
rco_tab[i] = p;
|
||||
|
||||
p = (p << 1) ^ (p & 0x80 ? 0x1b : 0);
|
||||
}
|
||||
|
||||
/* note that the affine byte transformation matrix in */
|
||||
/* rijndael specification is in big endian format with */
|
||||
/* bit 0 as the most significant bit. In the remainder */
|
||||
/* of the specification the bits are numbered from the */
|
||||
/* least significant end of a byte. */
|
||||
|
||||
for(i = 0; i < 256; ++i) {
|
||||
p = (i ? pow_tab[255 - log_tab[i]] : 0); q = p;
|
||||
q = (q >> 7) | (q << 1); p ^= q;
|
||||
q = (q >> 7) | (q << 1); p ^= q;
|
||||
q = (q >> 7) | (q << 1); p ^= q;
|
||||
q = (q >> 7) | (q << 1); p ^= q ^ 0x63;
|
||||
sbx_tab[i] = (u1byte)p; isb_tab[p] = (u1byte)i;
|
||||
}
|
||||
|
||||
for(i = 0; i < 256; ++i) {
|
||||
p = sbx_tab[i];
|
||||
|
||||
#ifdef LARGE_TABLES
|
||||
|
||||
t = p; fl_tab[0][i] = t;
|
||||
fl_tab[1][i] = rotl(t, 8);
|
||||
fl_tab[2][i] = rotl(t, 16);
|
||||
fl_tab[3][i] = rotl(t, 24);
|
||||
#endif
|
||||
t = ((u4byte)ff_mult(2, p)) |
|
||||
((u4byte)p << 8) |
|
||||
((u4byte)p << 16) |
|
||||
((u4byte)ff_mult(3, p) << 24);
|
||||
|
||||
ft_tab[0][i] = t;
|
||||
ft_tab[1][i] = rotl(t, 8);
|
||||
ft_tab[2][i] = rotl(t, 16);
|
||||
ft_tab[3][i] = rotl(t, 24);
|
||||
|
||||
p = isb_tab[i];
|
||||
|
||||
#ifdef LARGE_TABLES
|
||||
|
||||
t = p; il_tab[0][i] = t;
|
||||
il_tab[1][i] = rotl(t, 8);
|
||||
il_tab[2][i] = rotl(t, 16);
|
||||
il_tab[3][i] = rotl(t, 24);
|
||||
#endif
|
||||
t = ((u4byte)ff_mult(14, p)) |
|
||||
((u4byte)ff_mult( 9, p) << 8) |
|
||||
((u4byte)ff_mult(13, p) << 16) |
|
||||
((u4byte)ff_mult(11, p) << 24);
|
||||
|
||||
it_tab[0][i] = t;
|
||||
it_tab[1][i] = rotl(t, 8);
|
||||
it_tab[2][i] = rotl(t, 16);
|
||||
it_tab[3][i] = rotl(t, 24);
|
||||
}
|
||||
|
||||
tab_gen = 1;
|
||||
}
|
||||
|
||||
#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
|
||||
|
||||
#define imix_col(y,x) \
|
||||
u = star_x(x); \
|
||||
v = star_x(u); \
|
||||
w = star_x(v); \
|
||||
t = w ^ (x); \
|
||||
(y) = u ^ v ^ w; \
|
||||
(y) ^= rotr(u ^ t, 8) ^ \
|
||||
rotr(v ^ t, 16) ^ \
|
||||
rotr(t,24)
|
||||
|
||||
/* initialise the key schedule from the user supplied key */
|
||||
|
||||
#define loop4(i) \
|
||||
{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \
|
||||
t ^= e_key[4 * i]; e_key[4 * i + 4] = t; \
|
||||
t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t; \
|
||||
t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t; \
|
||||
t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t; \
|
||||
}
|
||||
|
||||
#define loop6(i) \
|
||||
{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \
|
||||
t ^= e_key[6 * i]; e_key[6 * i + 6] = t; \
|
||||
t ^= e_key[6 * i + 1]; e_key[6 * i + 7] = t; \
|
||||
t ^= e_key[6 * i + 2]; e_key[6 * i + 8] = t; \
|
||||
t ^= e_key[6 * i + 3]; e_key[6 * i + 9] = t; \
|
||||
t ^= e_key[6 * i + 4]; e_key[6 * i + 10] = t; \
|
||||
t ^= e_key[6 * i + 5]; e_key[6 * i + 11] = t; \
|
||||
}
|
||||
|
||||
#define loop8(i) \
|
||||
{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \
|
||||
t ^= e_key[8 * i]; e_key[8 * i + 8] = t; \
|
||||
t ^= e_key[8 * i + 1]; e_key[8 * i + 9] = t; \
|
||||
t ^= e_key[8 * i + 2]; e_key[8 * i + 10] = t; \
|
||||
t ^= e_key[8 * i + 3]; e_key[8 * i + 11] = t; \
|
||||
t = e_key[8 * i + 4] ^ ls_box(t); \
|
||||
e_key[8 * i + 12] = t; \
|
||||
t ^= e_key[8 * i + 5]; e_key[8 * i + 13] = t; \
|
||||
t ^= e_key[8 * i + 6]; e_key[8 * i + 14] = t; \
|
||||
t ^= e_key[8 * i + 7]; e_key[8 * i + 15] = t; \
|
||||
}
|
||||
|
||||
rijndael_ctx *
|
||||
rijndael_set_key(rijndael_ctx *ctx, const u4byte *in_key, const u4byte key_len,
|
||||
int encrypt)
|
||||
{
|
||||
u4byte i, t, u, v, w;
|
||||
u4byte *e_key = ctx->e_key;
|
||||
u4byte *d_key = ctx->d_key;
|
||||
|
||||
ctx->decrypt = !encrypt;
|
||||
|
||||
if(!tab_gen)
|
||||
gen_tabs();
|
||||
|
||||
ctx->k_len = (key_len + 31) / 32;
|
||||
|
||||
e_key[0] = in_key[0]; e_key[1] = in_key[1];
|
||||
e_key[2] = in_key[2]; e_key[3] = in_key[3];
|
||||
|
||||
switch(ctx->k_len) {
|
||||
case 4: t = e_key[3];
|
||||
for(i = 0; i < 10; ++i)
|
||||
loop4(i);
|
||||
break;
|
||||
|
||||
case 6: e_key[4] = in_key[4]; t = e_key[5] = in_key[5];
|
||||
for(i = 0; i < 8; ++i)
|
||||
loop6(i);
|
||||
break;
|
||||
|
||||
case 8: e_key[4] = in_key[4]; e_key[5] = in_key[5];
|
||||
e_key[6] = in_key[6]; t = e_key[7] = in_key[7];
|
||||
for(i = 0; i < 7; ++i)
|
||||
loop8(i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!encrypt) {
|
||||
d_key[0] = e_key[0]; d_key[1] = e_key[1];
|
||||
d_key[2] = e_key[2]; d_key[3] = e_key[3];
|
||||
|
||||
for(i = 4; i < 4 * ctx->k_len + 24; ++i) {
|
||||
imix_col(d_key[i], e_key[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/* encrypt a block of text */
|
||||
|
||||
#define f_nround(bo, bi, k) \
|
||||
f_rn(bo, bi, 0, k); \
|
||||
f_rn(bo, bi, 1, k); \
|
||||
f_rn(bo, bi, 2, k); \
|
||||
f_rn(bo, bi, 3, k); \
|
||||
k += 4
|
||||
|
||||
#define f_lround(bo, bi, k) \
|
||||
f_rl(bo, bi, 0, k); \
|
||||
f_rl(bo, bi, 1, k); \
|
||||
f_rl(bo, bi, 2, k); \
|
||||
f_rl(bo, bi, 3, k)
|
||||
|
||||
void
|
||||
rijndael_encrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk)
|
||||
{
|
||||
u4byte k_len = ctx->k_len;
|
||||
u4byte *e_key = ctx->e_key;
|
||||
u4byte b0[4], b1[4], *kp;
|
||||
|
||||
b0[0] = in_blk[0] ^ e_key[0]; b0[1] = in_blk[1] ^ e_key[1];
|
||||
b0[2] = in_blk[2] ^ e_key[2]; b0[3] = in_blk[3] ^ e_key[3];
|
||||
|
||||
kp = e_key + 4;
|
||||
|
||||
if(k_len > 6) {
|
||||
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
|
||||
}
|
||||
|
||||
if(k_len > 4) {
|
||||
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
|
||||
}
|
||||
|
||||
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
|
||||
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
|
||||
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
|
||||
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
|
||||
f_nround(b1, b0, kp); f_lround(b0, b1, kp);
|
||||
|
||||
out_blk[0] = b0[0]; out_blk[1] = b0[1];
|
||||
out_blk[2] = b0[2]; out_blk[3] = b0[3];
|
||||
}
|
||||
|
||||
/* decrypt a block of text */
|
||||
|
||||
#define i_nround(bo, bi, k) \
|
||||
i_rn(bo, bi, 0, k); \
|
||||
i_rn(bo, bi, 1, k); \
|
||||
i_rn(bo, bi, 2, k); \
|
||||
i_rn(bo, bi, 3, k); \
|
||||
k -= 4
|
||||
|
||||
#define i_lround(bo, bi, k) \
|
||||
i_rl(bo, bi, 0, k); \
|
||||
i_rl(bo, bi, 1, k); \
|
||||
i_rl(bo, bi, 2, k); \
|
||||
i_rl(bo, bi, 3, k)
|
||||
|
||||
void
|
||||
rijndael_decrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk)
|
||||
{
|
||||
u4byte b0[4], b1[4], *kp;
|
||||
u4byte k_len = ctx->k_len;
|
||||
u4byte *e_key = ctx->e_key;
|
||||
u4byte *d_key = ctx->d_key;
|
||||
|
||||
b0[0] = in_blk[0] ^ e_key[4 * k_len + 24]; b0[1] = in_blk[1] ^ e_key[4 * k_len + 25];
|
||||
b0[2] = in_blk[2] ^ e_key[4 * k_len + 26]; b0[3] = in_blk[3] ^ e_key[4 * k_len + 27];
|
||||
|
||||
kp = d_key + 4 * (k_len + 5);
|
||||
|
||||
if(k_len > 6) {
|
||||
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
|
||||
}
|
||||
|
||||
if(k_len > 4) {
|
||||
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
|
||||
}
|
||||
|
||||
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
|
||||
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
|
||||
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
|
||||
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
|
||||
i_nround(b1, b0, kp); i_lround(b0, b1, kp);
|
||||
|
||||
out_blk[0] = b0[0]; out_blk[1] = b0[1];
|
||||
out_blk[2] = b0[2]; out_blk[3] = b0[3];
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef _RIJNDAEL_H_
|
||||
#define _RIJNDAEL_H_
|
||||
|
||||
/* 1. Standard types for AES cryptography source code */
|
||||
|
||||
typedef u_int8_t u1byte; /* an 8 bit unsigned character type */
|
||||
typedef u_int16_t u2byte; /* a 16 bit unsigned integer type */
|
||||
typedef u_int32_t u4byte; /* a 32 bit unsigned integer type */
|
||||
|
||||
typedef int8_t s1byte; /* an 8 bit signed character type */
|
||||
typedef int16_t s2byte; /* a 16 bit signed integer type */
|
||||
typedef int32_t s4byte; /* a 32 bit signed integer type */
|
||||
|
||||
typedef struct _rijndael_ctx {
|
||||
u4byte k_len;
|
||||
int decrypt;
|
||||
u4byte e_key[64];
|
||||
u4byte d_key[64];
|
||||
} rijndael_ctx;
|
||||
|
||||
|
||||
/* 2. Standard interface for AES cryptographic routines */
|
||||
|
||||
/* These are all based on 32 bit unsigned values and will therefore */
|
||||
/* require endian conversions for big-endian architectures */
|
||||
|
||||
rijndael_ctx *rijndael_set_key __P((rijndael_ctx *, const u4byte *, u4byte, int));
|
||||
void rijndael_encrypt __P((rijndael_ctx *, const u4byte *, u4byte *));
|
||||
void rijndael_decrypt __P((rijndael_ctx *, const u4byte *, u4byte *));
|
||||
|
||||
#endif /* _RIJNDAEL_H_ */
|
||||
@@ -9,7 +9,7 @@
|
||||
.\"
|
||||
.\" Created: Sun May 7 00:14:37 1995 ylo
|
||||
.\"
|
||||
.\" $Id: scp.1,v 1.10 2000/09/01 15:25:13 deraadt Exp $
|
||||
.\" $OpenBSD: scp.1,v 1.13 2000/10/16 09:38:44 djm Exp $
|
||||
.\"
|
||||
.Dd September 25, 1999
|
||||
.Dt SCP 1
|
||||
@@ -24,6 +24,7 @@
|
||||
.Op Fl P Ar port
|
||||
.Op Fl c Ar cipher
|
||||
.Op Fl i Ar identity_file
|
||||
.Op Fl o Ar option
|
||||
.Sm off
|
||||
.Oo
|
||||
.Op Ar user@
|
||||
@@ -102,9 +103,13 @@ is already reserved for preserving the times and modes of the file in
|
||||
.It Fl S Ar program
|
||||
Name of
|
||||
.Ar program
|
||||
to use for the encrypted connection. The program must understand
|
||||
to use for the encrypted connection.
|
||||
The program must understand
|
||||
.Xr ssh 1
|
||||
options.
|
||||
.It Fl o Ar option
|
||||
The given option is directly passed to
|
||||
.Xr ssh 1 .
|
||||
.It Fl 4
|
||||
Forces
|
||||
.Nm
|
||||
|
||||
+79
-95
@@ -75,11 +75,10 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: scp.c,v 1.39 2000/09/07 20:53:00 markus Exp $");
|
||||
RCSID("$OpenBSD: scp.c,v 1.43 2000/10/18 18:23:02 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "xmalloc.h"
|
||||
#include <utime.h>
|
||||
|
||||
#define _PATH_CP "cp"
|
||||
|
||||
@@ -93,6 +92,9 @@ void progressmeter(int);
|
||||
int getttywidth(void);
|
||||
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
|
||||
|
||||
/* setup arguments for the call to ssh */
|
||||
void addargs(char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
/* Time a transfer started. */
|
||||
static struct timeval start;
|
||||
|
||||
@@ -105,12 +107,6 @@ off_t totalbytes = 0;
|
||||
/* Name of current file being transferred. */
|
||||
char *curfile;
|
||||
|
||||
/* This is set to non-zero if IPv4 is desired. */
|
||||
int IPv4 = 0;
|
||||
|
||||
/* This is set to non-zero if IPv6 is desired. */
|
||||
int IPv6 = 0;
|
||||
|
||||
/* This is set to non-zero to enable verbose mode. */
|
||||
int verbose_mode = 0;
|
||||
|
||||
@@ -120,23 +116,16 @@ int compress = 0;
|
||||
/* This is set to zero if the progressmeter is not desired. */
|
||||
int showprogress = 1;
|
||||
|
||||
/* This is set to non-zero if running in batch mode (that is, password
|
||||
and passphrase queries are not allowed). */
|
||||
int batchmode = 0;
|
||||
|
||||
/* This is set to the cipher type string if given on the command line. */
|
||||
char *cipher = NULL;
|
||||
|
||||
/* This is set to the RSA authentication identity file name if given on
|
||||
the command line. */
|
||||
char *identity = NULL;
|
||||
|
||||
/* This is the port to use in contacting the remote site (is non-NULL). */
|
||||
char *port = NULL;
|
||||
|
||||
/* This is the program to execute for the secured connection. ("ssh" or -S) */
|
||||
char *ssh_program = SSH_PROGRAM;
|
||||
|
||||
/* This is the list of arguments that scp passes to ssh */
|
||||
struct {
|
||||
char **list;
|
||||
int num;
|
||||
int nalloc;
|
||||
} args;
|
||||
|
||||
/*
|
||||
* This function executes the given command as the specified user on the
|
||||
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This
|
||||
@@ -149,8 +138,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
|
||||
int pin[2], pout[2], reserved[2];
|
||||
|
||||
if (verbose_mode)
|
||||
fprintf(stderr, "Executing: host %s, user %s, command %s\n",
|
||||
host, remuser ? remuser : "(unspecified)", cmd);
|
||||
fprintf(stderr, "Executing: program %s host %s, user %s, command %s\n",
|
||||
ssh_program, host, remuser ? remuser : "(unspecified)", cmd);
|
||||
|
||||
/*
|
||||
* Reserve two descriptors so that the real pipes won't get
|
||||
@@ -169,10 +158,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
|
||||
close(reserved[1]);
|
||||
|
||||
/* For a child to execute the command on the remote host using ssh. */
|
||||
if (fork() == 0) {
|
||||
char *args[100]; /* XXX careful */
|
||||
unsigned int i;
|
||||
|
||||
if (fork() == 0) {
|
||||
/* Child. */
|
||||
close(pin[1]);
|
||||
close(pout[0]);
|
||||
@@ -181,41 +167,13 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
|
||||
close(pin[0]);
|
||||
close(pout[1]);
|
||||
|
||||
i = 0;
|
||||
args[i++] = ssh_program;
|
||||
args[i++] = "-x";
|
||||
args[i++] = "-oFallBackToRsh no";
|
||||
if (IPv4)
|
||||
args[i++] = "-4";
|
||||
if (IPv6)
|
||||
args[i++] = "-6";
|
||||
if (verbose_mode)
|
||||
args[i++] = "-v";
|
||||
if (compress)
|
||||
args[i++] = "-C";
|
||||
if (batchmode)
|
||||
args[i++] = "-oBatchMode yes";
|
||||
if (cipher != NULL) {
|
||||
args[i++] = "-c";
|
||||
args[i++] = cipher;
|
||||
}
|
||||
if (identity != NULL) {
|
||||
args[i++] = "-i";
|
||||
args[i++] = identity;
|
||||
}
|
||||
if (port != NULL) {
|
||||
args[i++] = "-p";
|
||||
args[i++] = port;
|
||||
}
|
||||
if (remuser != NULL) {
|
||||
args[i++] = "-l";
|
||||
args[i++] = remuser;
|
||||
}
|
||||
args[i++] = host;
|
||||
args[i++] = cmd;
|
||||
args[i++] = NULL;
|
||||
args.list[0] = ssh_program;
|
||||
if (remuser != NULL)
|
||||
addargs("-l%s", remuser);
|
||||
addargs("%s", host);
|
||||
addargs("%s", cmd);
|
||||
|
||||
execvp(ssh_program, args);
|
||||
execvp(ssh_program, args.list);
|
||||
perror(ssh_program);
|
||||
exit(1);
|
||||
}
|
||||
@@ -281,27 +239,45 @@ main(argc, argv)
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
args.list = NULL;
|
||||
addargs("ssh"); /* overwritten with ssh_program */
|
||||
addargs("-x");
|
||||
addargs("-oFallBackToRsh no");
|
||||
|
||||
fflag = tflag = 0;
|
||||
while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:")) != EOF)
|
||||
while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:")) != EOF)
|
||||
switch (ch) {
|
||||
/* User-visible flags. */
|
||||
case '4':
|
||||
IPv4 = 1;
|
||||
break;
|
||||
case '6':
|
||||
IPv6 = 1;
|
||||
case 'C':
|
||||
addargs("-%c", ch);
|
||||
break;
|
||||
case 'o':
|
||||
case 'c':
|
||||
case 'i':
|
||||
addargs("-%c%s", ch, optarg);
|
||||
break;
|
||||
case 'P':
|
||||
addargs("-p%s", optarg);
|
||||
break;
|
||||
case 'B':
|
||||
addargs("-oBatchmode yes");
|
||||
break;
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
break;
|
||||
case 'P':
|
||||
port = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
iamrecursive = 1;
|
||||
break;
|
||||
case 'S':
|
||||
ssh_program = optarg;
|
||||
ssh_program = xstrdup(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
verbose_mode = 1;
|
||||
break;
|
||||
case 'q':
|
||||
showprogress = 0;
|
||||
break;
|
||||
|
||||
/* Server options. */
|
||||
@@ -316,24 +292,6 @@ main(argc, argv)
|
||||
iamremote = 1;
|
||||
tflag = 1;
|
||||
break;
|
||||
case 'c':
|
||||
cipher = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
identity = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose_mode = 1;
|
||||
break;
|
||||
case 'B':
|
||||
batchmode = 1;
|
||||
break;
|
||||
case 'C':
|
||||
compress = 1;
|
||||
break;
|
||||
case 'q':
|
||||
showprogress = 0;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@@ -703,8 +661,8 @@ sink(argc, argv)
|
||||
off_t size;
|
||||
int setimes, targisdir, wrerrno = 0;
|
||||
char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
|
||||
struct utimbuf ut;
|
||||
int dummy_usec;
|
||||
struct timeval tv[2];
|
||||
|
||||
#define SCREWUP(str) { why = str; goto screwup; }
|
||||
|
||||
@@ -758,16 +716,18 @@ sink(argc, argv)
|
||||
if (*cp == 'T') {
|
||||
setimes++;
|
||||
cp++;
|
||||
getnum(ut.modtime);
|
||||
getnum(tv[1].tv_sec);
|
||||
if (*cp++ != ' ')
|
||||
SCREWUP("mtime.sec not delimited");
|
||||
getnum(dummy_usec);
|
||||
tv[1].tv_usec = 0;
|
||||
if (*cp++ != ' ')
|
||||
SCREWUP("mtime.usec not delimited");
|
||||
getnum(ut.actime);
|
||||
getnum(tv[0].tv_sec);
|
||||
if (*cp++ != ' ')
|
||||
SCREWUP("atime.sec not delimited");
|
||||
getnum(dummy_usec);
|
||||
tv[0].tv_usec = 0;
|
||||
if (*cp++ != '\0')
|
||||
SCREWUP("atime.usec not delimited");
|
||||
(void) atomicio(write, remout, "", 1);
|
||||
@@ -835,7 +795,7 @@ sink(argc, argv)
|
||||
sink(1, vect);
|
||||
if (setimes) {
|
||||
setimes = 0;
|
||||
if (utime(np, &ut) < 0)
|
||||
if (utimes(np, tv) < 0)
|
||||
run_err("%s: set times: %s",
|
||||
np, strerror(errno));
|
||||
}
|
||||
@@ -868,8 +828,10 @@ bad: run_err("%s: %s", np, strerror(errno));
|
||||
amt = size - i;
|
||||
count += amt;
|
||||
do {
|
||||
j = atomicio(read, remin, cp, amt);
|
||||
if (j <= 0) {
|
||||
j = read(remin, cp, amt);
|
||||
if (j == -1 && (errno == EINTR || errno == EAGAIN)) {
|
||||
continue;
|
||||
} else if (j <= 0) {
|
||||
run_err("%s", j ? strerror(errno) :
|
||||
"dropped connection");
|
||||
exit(1);
|
||||
@@ -922,7 +884,7 @@ bad: run_err("%s: %s", np, strerror(errno));
|
||||
(void) response();
|
||||
if (setimes && wrerr == NO) {
|
||||
setimes = 0;
|
||||
if (utime(np, &ut) < 0) {
|
||||
if (utimes(np, tv) < 0) {
|
||||
run_err("%s: set times: %s",
|
||||
np, strerror(errno));
|
||||
wrerr = DISPLAYED;
|
||||
@@ -1249,3 +1211,25 @@ getttywidth(void)
|
||||
else
|
||||
return (80);
|
||||
}
|
||||
|
||||
void
|
||||
addargs(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (args.list == NULL) {
|
||||
args.nalloc = 32;
|
||||
args.num = 0;
|
||||
args.list = xmalloc(args.nalloc * sizeof(char *));
|
||||
} else if (args.num+2 >= args.nalloc) {
|
||||
args.nalloc *= 2;
|
||||
args.list = xrealloc(args.list, args.nalloc * sizeof(char *));
|
||||
}
|
||||
args.list[args.num++] = xstrdup(buf);
|
||||
args.list[args.num] = NULL;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: servconf.c,v 1.51 2000/09/07 20:27:53 deraadt Exp $");
|
||||
RCSID("$OpenBSD: servconf.c,v 1.53 2000/10/14 12:12:09 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "servconf.h"
|
||||
@@ -61,11 +61,13 @@ initialize_server_options(ServerOptions *options)
|
||||
options->afs_token_passing = -1;
|
||||
#endif
|
||||
options->password_authentication = -1;
|
||||
options->kbd_interactive_authentication = -1;
|
||||
#ifdef SKEY
|
||||
options->skey_authentication = -1;
|
||||
#endif
|
||||
options->permit_empty_passwd = -1;
|
||||
options->use_login = -1;
|
||||
options->allow_tcp_forwarding = -1;
|
||||
options->num_allow_users = 0;
|
||||
options->num_deny_users = 0;
|
||||
options->num_allow_groups = 0;
|
||||
@@ -148,6 +150,8 @@ fill_default_server_options(ServerOptions *options)
|
||||
#endif /* AFS */
|
||||
if (options->password_authentication == -1)
|
||||
options->password_authentication = 1;
|
||||
if (options->kbd_interactive_authentication == -1)
|
||||
options->kbd_interactive_authentication = 0;
|
||||
#ifdef SKEY
|
||||
if (options->skey_authentication == -1)
|
||||
options->skey_authentication = 1;
|
||||
@@ -156,6 +160,8 @@ fill_default_server_options(ServerOptions *options)
|
||||
options->permit_empty_passwd = 0;
|
||||
if (options->use_login == -1)
|
||||
options->use_login = 0;
|
||||
if (options->allow_tcp_forwarding == -1)
|
||||
options->allow_tcp_forwarding = 1;
|
||||
if (options->protocol == SSH_PROTO_UNKNOWN)
|
||||
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
|
||||
if (options->gateway_ports == -1)
|
||||
@@ -183,10 +189,11 @@ typedef enum {
|
||||
#ifdef SKEY
|
||||
sSkeyAuthentication,
|
||||
#endif
|
||||
sPasswordAuthentication, sListenAddress,
|
||||
sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
|
||||
sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
|
||||
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
|
||||
sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
|
||||
sUseLogin, sAllowTcpForwarding,
|
||||
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
|
||||
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
|
||||
sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem, sMaxStartups
|
||||
} ServerOpCodes;
|
||||
@@ -220,6 +227,7 @@ static struct {
|
||||
{ "afstokenpassing", sAFSTokenPassing },
|
||||
#endif
|
||||
{ "passwordauthentication", sPasswordAuthentication },
|
||||
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
|
||||
#ifdef SKEY
|
||||
{ "skeyauthentication", sSkeyAuthentication },
|
||||
#endif
|
||||
@@ -236,6 +244,7 @@ static struct {
|
||||
{ "uselogin", sUseLogin },
|
||||
{ "randomseed", sRandomSeedFile },
|
||||
{ "keepalive", sKeepAlives },
|
||||
{ "allowtcpforwarding", sAllowTcpForwarding },
|
||||
{ "allowusers", sAllowUsers },
|
||||
{ "denyusers", sDenyUsers },
|
||||
{ "allowgroups", sAllowGroups },
|
||||
@@ -497,6 +506,10 @@ read_server_config(ServerOptions *options, const char *filename)
|
||||
intptr = &options->password_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
case sKbdInteractiveAuthentication:
|
||||
intptr = &options->kbd_interactive_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
case sCheckMail:
|
||||
intptr = &options->check_mail;
|
||||
goto parse_flag;
|
||||
@@ -565,6 +578,10 @@ read_server_config(ServerOptions *options, const char *filename)
|
||||
*intptr = (LogLevel) value;
|
||||
break;
|
||||
|
||||
case sAllowTcpForwarding:
|
||||
intptr = &options->allow_tcp_forwarding;
|
||||
goto parse_flag;
|
||||
|
||||
case sAllowUsers:
|
||||
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||
if (options->num_allow_users >= MAX_ALLOW_USERS)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: servconf.h,v 1.28 2000/09/07 20:27:53 deraadt Exp $"); */
|
||||
/* RCSID("$OpenBSD: servconf.h,v 1.30 2000/10/14 12:12:09 markus Exp $"); */
|
||||
|
||||
#ifndef SERVCONF_H
|
||||
#define SERVCONF_H
|
||||
@@ -78,6 +78,7 @@ typedef struct {
|
||||
#endif
|
||||
int password_authentication; /* If true, permit password
|
||||
* authentication. */
|
||||
int kbd_interactive_authentication; /* If true, permit */
|
||||
#ifdef SKEY
|
||||
int skey_authentication; /* If true, permit s/key
|
||||
* authentication. */
|
||||
@@ -85,6 +86,7 @@ typedef struct {
|
||||
int permit_empty_passwd; /* If false, do not permit empty
|
||||
* passwords. */
|
||||
int use_login; /* If true, login(1) is used */
|
||||
int allow_tcp_forwarding;
|
||||
unsigned int num_allow_users;
|
||||
char *allow_users[MAX_ALLOW_USERS];
|
||||
unsigned int num_deny_users;
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
@@ -49,6 +51,8 @@
|
||||
#include "dispatch.h"
|
||||
#include "auth-options.h"
|
||||
|
||||
extern ServerOptions options;
|
||||
|
||||
static Buffer stdin_buffer; /* Buffer for stdin data. */
|
||||
static Buffer stdout_buffer; /* Buffer for stdout data. */
|
||||
static Buffer stderr_buffer; /* Buffer for stderr data. */
|
||||
@@ -380,7 +384,7 @@ drain_output()
|
||||
void
|
||||
process_buffered_input_packets()
|
||||
{
|
||||
dispatch_run(DISPATCH_NONBLOCK, NULL);
|
||||
dispatch_run(DISPATCH_NONBLOCK, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -673,7 +677,7 @@ server_loop2(void)
|
||||
}
|
||||
|
||||
void
|
||||
server_input_stdin_data(int type, int plen)
|
||||
server_input_stdin_data(int type, int plen, void *ctxt)
|
||||
{
|
||||
char *data;
|
||||
unsigned int data_len;
|
||||
@@ -690,7 +694,7 @@ server_input_stdin_data(int type, int plen)
|
||||
}
|
||||
|
||||
void
|
||||
server_input_eof(int type, int plen)
|
||||
server_input_eof(int type, int plen, void *ctxt)
|
||||
{
|
||||
/*
|
||||
* Eof from the client. The stdin descriptor to the
|
||||
@@ -703,7 +707,7 @@ server_input_eof(int type, int plen)
|
||||
}
|
||||
|
||||
void
|
||||
server_input_window_size(int type, int plen)
|
||||
server_input_window_size(int type, int plen, void *ctxt)
|
||||
{
|
||||
int row = packet_get_int();
|
||||
int col = packet_get_int();
|
||||
@@ -733,7 +737,7 @@ input_direct_tcpip(void)
|
||||
originator, originator_port, target, target_port);
|
||||
|
||||
/* XXX check permission */
|
||||
if (no_port_forwarding_flag) {
|
||||
if (no_port_forwarding_flag || !options.allow_tcp_forwarding) {
|
||||
xfree(target);
|
||||
xfree(originator);
|
||||
return -1;
|
||||
@@ -745,11 +749,11 @@ input_direct_tcpip(void)
|
||||
return -1;
|
||||
return channel_new("direct-tcpip", SSH_CHANNEL_OPEN,
|
||||
sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
|
||||
CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"));
|
||||
CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1);
|
||||
}
|
||||
|
||||
void
|
||||
server_input_channel_open(int type, int plen)
|
||||
server_input_channel_open(int type, int plen, void *ctxt)
|
||||
{
|
||||
Channel *c = NULL;
|
||||
char *ctype;
|
||||
@@ -764,7 +768,7 @@ server_input_channel_open(int type, int plen)
|
||||
rwindow = packet_get_int();
|
||||
rmaxpack = packet_get_int();
|
||||
|
||||
debug("channel_input_open: ctype %s rchan %d win %d max %d",
|
||||
debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
|
||||
ctype, rchan, rwindow, rmaxpack);
|
||||
|
||||
if (strcmp(ctype, "session") == 0) {
|
||||
@@ -779,7 +783,7 @@ server_input_channel_open(int type, int plen)
|
||||
*/
|
||||
id = channel_new(ctype, SSH_CHANNEL_LARVAL,
|
||||
-1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT,
|
||||
0, xstrdup("server-session"));
|
||||
0, xstrdup("server-session"), 1);
|
||||
if (session_open(id) == 1) {
|
||||
channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
|
||||
session_input_channel_req, (void *)0);
|
||||
|
||||
+16
-10
@@ -33,14 +33,13 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: session.c,v 1.37 2000/09/07 20:27:53 deraadt Exp $");
|
||||
RCSID("$OpenBSD: session.c,v 1.42 2000/10/27 07:32:18 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include "pty.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
#include "cipher.h"
|
||||
#include "mpaux.h"
|
||||
#include "servconf.h"
|
||||
#include "uidswap.h"
|
||||
@@ -90,7 +89,7 @@ void session_pty_cleanup(Session *s);
|
||||
void session_proctitle(Session *s);
|
||||
void do_exec_pty(Session *s, const char *command, struct passwd * pw);
|
||||
void do_exec_no_pty(Session *s, const char *command, struct passwd * pw);
|
||||
void do_login(Session *s);
|
||||
void do_login(Session *s, const char *command);
|
||||
|
||||
void
|
||||
do_child(const char *command, struct passwd * pw, const char *term,
|
||||
@@ -197,7 +196,7 @@ do_authenticated(struct passwd * pw)
|
||||
* by the client telling us, so we can equally well trust the client
|
||||
* not to request anything bogus.)
|
||||
*/
|
||||
if (!no_port_forwarding_flag)
|
||||
if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
|
||||
channel_permit_all_opens();
|
||||
|
||||
s = session_new();
|
||||
@@ -349,6 +348,10 @@ do_authenticated(struct passwd * pw)
|
||||
debug("Port forwarding not permitted for this authentication.");
|
||||
break;
|
||||
}
|
||||
if (!options.allow_tcp_forwarding) {
|
||||
debug("Port forwarding not permitted.");
|
||||
break;
|
||||
}
|
||||
debug("Received TCP/IP port forwarding request.");
|
||||
channel_input_port_forward_request(pw->pw_uid == 0, options.gateway_ports);
|
||||
success = 1;
|
||||
@@ -569,8 +572,8 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
|
||||
close(ttyfd);
|
||||
|
||||
/* record login, etc. similar to login(1) */
|
||||
if (command == NULL && !options.use_login)
|
||||
do_login(s);
|
||||
if (!(options.use_login && command == NULL))
|
||||
do_login(s, command);
|
||||
|
||||
/* Do common processing for the child, such as execing the command. */
|
||||
do_child(command, pw, s->term, s->display, s->auth_proto,
|
||||
@@ -622,7 +625,7 @@ get_remote_name_or_ip(void)
|
||||
|
||||
/* administrative, login(1)-like work */
|
||||
void
|
||||
do_login(Session *s)
|
||||
do_login(Session *s, const char *command)
|
||||
{
|
||||
FILE *f;
|
||||
char *time_string;
|
||||
@@ -658,7 +661,9 @@ do_login(Session *s)
|
||||
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
|
||||
get_remote_name_or_ip(), (struct sockaddr *)&from);
|
||||
|
||||
/* Done if .hushlogin exists. */
|
||||
/* Done if .hushlogin exists or a command given. */
|
||||
if (command != NULL)
|
||||
return;
|
||||
snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
|
||||
#ifdef HAVE_LOGIN_CAP
|
||||
if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
|
||||
@@ -670,7 +675,7 @@ do_login(Session *s)
|
||||
time_string = ctime(&last_login_time);
|
||||
if (strchr(time_string, '\n'))
|
||||
*strchr(time_string, '\n') = 0;
|
||||
if (strcmp(buf, "") == 0)
|
||||
if (strcmp(hostname, "") == 0)
|
||||
printf("Last login: %s\r\n", time_string);
|
||||
else
|
||||
printf("Last login: %s from %s\r\n", time_string, hostname);
|
||||
@@ -1477,7 +1482,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
|
||||
fatal("no channel for session %d", s->self);
|
||||
channel_set_fds(s->chanid,
|
||||
fdout, fdin, fderr,
|
||||
fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ);
|
||||
fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
|
||||
1);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: sftp-server.8,v 1.2 2000/09/07 20:27:53 deraadt Exp $
|
||||
.\" $OpenBSD: sftp-server.8,v 1.3 2000/10/13 17:20:44 aaron Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
.\"
|
||||
@@ -36,21 +36,21 @@ is a program that speaks the server side of SFTP protocol
|
||||
to stdout and expects client requests from stdin.
|
||||
.Nm
|
||||
is not intended to be called directly, but from
|
||||
.Xr sshd 8
|
||||
.Xr sshd 8
|
||||
using the
|
||||
.Cm Subsystem
|
||||
option.
|
||||
See
|
||||
.Xr sshd 8
|
||||
.Xr sshd 8
|
||||
for more information.
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
first appeared in
|
||||
.Ox 2.8 .
|
||||
.Sh AUTHOR
|
||||
Markus Friedl <markus@openbsd.org>
|
||||
.Sh SEE ALSO
|
||||
.Xr ssh 1 ,
|
||||
.Xr ssh-add 1 ,
|
||||
.Xr ssh-keygen 1 ,
|
||||
.Xr sshd 8 ,
|
||||
.Xr sshd 8
|
||||
.Sh AUTHOR
|
||||
Markus Friedl <markus@openbsd.org>
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
first appeared in
|
||||
.Ox 2.8 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-agent.c,v 1.35 2000/09/07 20:27:54 deraadt Exp $ */
|
||||
/* $OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: ssh-agent.c,v 1.35 2000/09/07 20:27:54 deraadt Exp $");
|
||||
RCSID("$OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "rsa.h"
|
||||
@@ -56,6 +56,7 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.35 2000/09/07 20:27:54 deraadt Exp $");
|
||||
#include "authfd.h"
|
||||
#include "dsa.h"
|
||||
#include "kex.h"
|
||||
#include "compat.h"
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
@@ -233,6 +234,7 @@ process_sign_request2(SocketEntry *e)
|
||||
Key *key, *private;
|
||||
unsigned char *blob, *data, *signature = NULL;
|
||||
unsigned int blen, dlen, slen = 0;
|
||||
int flags;
|
||||
Buffer msg;
|
||||
int ok = -1;
|
||||
|
||||
@@ -240,7 +242,10 @@ process_sign_request2(SocketEntry *e)
|
||||
|
||||
blob = buffer_get_string(&e->input, &blen);
|
||||
data = buffer_get_string(&e->input, &dlen);
|
||||
buffer_get_int(&e->input); /* flags, unused */
|
||||
|
||||
flags = buffer_get_int(&e->input);
|
||||
if (flags & SSH_AGENT_OLD_SIGNATURE)
|
||||
datafellows = SSH_BUG_SIGBLOB;
|
||||
|
||||
key = dsa_key_from_blob(blob, blen);
|
||||
if (key != NULL) {
|
||||
@@ -771,8 +776,11 @@ main(int ac, char **av)
|
||||
printf("echo Agent pid %d;\n", pid);
|
||||
exit(0);
|
||||
}
|
||||
setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1);
|
||||
setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1);
|
||||
if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
|
||||
setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
|
||||
perror("setenv");
|
||||
exit(1);
|
||||
}
|
||||
execvp(av[0], av);
|
||||
perror(av[0]);
|
||||
exit(1);
|
||||
|
||||
@@ -168,8 +168,9 @@ removed once the RSA patent expires.
|
||||
This option will read a private
|
||||
OpenSSH DSA format file and print a SSH2-compatible public key to stdout.
|
||||
.It Fl X
|
||||
This option will read a
|
||||
SSH2-compatible public key file and print an OpenSSH DSA compatible public key to stdout.
|
||||
This option will read a unencrypted
|
||||
SSH2-compatible private (or public) key file and
|
||||
print an OpenSSH compatible private (or public) key to stdout.
|
||||
.It Fl y
|
||||
This option will read a private
|
||||
OpenSSH DSA format file and print an OpenSSH DSA public key to stdout.
|
||||
|
||||
+94
-11
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: ssh-keygen.c,v 1.31 2000/09/07 20:27:54 deraadt Exp $");
|
||||
RCSID("$OpenBSD: ssh-keygen.c,v 1.32 2000/10/09 21:30:44 markus Exp $");
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
@@ -27,6 +27,9 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.31 2000/09/07 20:27:54 deraadt Exp $");
|
||||
#include "authfile.h"
|
||||
#include "uuencode.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
|
||||
/* Number of bits in the RSA/DSA key. This value can be changed on the command line. */
|
||||
int bits = 1024;
|
||||
|
||||
@@ -104,8 +107,10 @@ try_load_key(char *filename, Key *k)
|
||||
return success;
|
||||
}
|
||||
|
||||
#define SSH_COM_MAGIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
|
||||
#define SSH_COM_MAGIC_END "---- END SSH2 PUBLIC KEY ----"
|
||||
#define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
|
||||
#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
|
||||
#define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
|
||||
#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
|
||||
|
||||
void
|
||||
do_convert_to_ssh2(struct passwd *pw)
|
||||
@@ -127,18 +132,83 @@ do_convert_to_ssh2(struct passwd *pw)
|
||||
exit(1);
|
||||
}
|
||||
dsa_make_key_blob(k, &blob, &len);
|
||||
fprintf(stdout, "%s\n", SSH_COM_MAGIC_BEGIN);
|
||||
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
|
||||
fprintf(stdout,
|
||||
"Comment: \"%d-bit DSA, converted from openssh by %s@%s\"\n",
|
||||
BN_num_bits(k->dsa->p),
|
||||
"Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n",
|
||||
key_size(k), key_type(k),
|
||||
pw->pw_name, hostname);
|
||||
dump_base64(stdout, blob, len);
|
||||
fprintf(stdout, "%s\n", SSH_COM_MAGIC_END);
|
||||
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
|
||||
key_free(k);
|
||||
xfree(blob);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
|
||||
{
|
||||
int bits = buffer_get_int(b);
|
||||
int bytes = (bits + 7) / 8;
|
||||
if (buffer_len(b) < bytes)
|
||||
fatal("buffer_get_bignum_bits: input buffer too small");
|
||||
BN_bin2bn((unsigned char *)buffer_ptr(b), bytes, value);
|
||||
buffer_consume(b, bytes);
|
||||
}
|
||||
|
||||
Key *
|
||||
do_convert_private_ssh2_from_blob(char *blob, int blen)
|
||||
{
|
||||
Buffer b;
|
||||
DSA *dsa;
|
||||
Key *key = NULL;
|
||||
int ignore, magic, rlen;
|
||||
char *type, *cipher;
|
||||
|
||||
buffer_init(&b);
|
||||
buffer_append(&b, blob, blen);
|
||||
|
||||
magic = buffer_get_int(&b);
|
||||
if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
|
||||
error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
|
||||
buffer_free(&b);
|
||||
return NULL;
|
||||
}
|
||||
ignore = buffer_get_int(&b);
|
||||
type = buffer_get_string(&b, NULL);
|
||||
cipher = buffer_get_string(&b, NULL);
|
||||
ignore = buffer_get_int(&b);
|
||||
ignore = buffer_get_int(&b);
|
||||
ignore = buffer_get_int(&b);
|
||||
xfree(type);
|
||||
|
||||
if (strcmp(cipher, "none") != 0) {
|
||||
error("unsupported cipher %s", cipher);
|
||||
xfree(cipher);
|
||||
buffer_free(&b);
|
||||
return NULL;
|
||||
}
|
||||
xfree(cipher);
|
||||
|
||||
key = key_new(KEY_DSA);
|
||||
dsa = key->dsa;
|
||||
dsa->priv_key = BN_new();
|
||||
if (dsa->priv_key == NULL) {
|
||||
error("alloc priv_key failed");
|
||||
key_free(key);
|
||||
return NULL;
|
||||
}
|
||||
buffer_get_bignum_bits(&b, dsa->p);
|
||||
buffer_get_bignum_bits(&b, dsa->g);
|
||||
buffer_get_bignum_bits(&b, dsa->q);
|
||||
buffer_get_bignum_bits(&b, dsa->pub_key);
|
||||
buffer_get_bignum_bits(&b, dsa->priv_key);
|
||||
rlen = buffer_len(&b);
|
||||
if(rlen != 0)
|
||||
error("do_convert_private_ssh2_from_blob: remaining bytes in key blob %d", rlen);
|
||||
buffer_free(&b);
|
||||
return key;
|
||||
}
|
||||
|
||||
void
|
||||
do_convert_from_ssh2(struct passwd *pw)
|
||||
{
|
||||
@@ -148,7 +218,7 @@ do_convert_from_ssh2(struct passwd *pw)
|
||||
char blob[8096];
|
||||
char encoded[8096];
|
||||
struct stat st;
|
||||
int escaped = 0;
|
||||
int escaped = 0, private = 0, ok;
|
||||
FILE *fp;
|
||||
|
||||
if (!have_identity)
|
||||
@@ -172,6 +242,8 @@ do_convert_from_ssh2(struct passwd *pw)
|
||||
escaped++;
|
||||
if (strncmp(line, "----", 4) == 0 ||
|
||||
strstr(line, ": ") != NULL) {
|
||||
if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
|
||||
private = 1;
|
||||
fprintf(stderr, "ignore: %s", line);
|
||||
continue;
|
||||
}
|
||||
@@ -188,9 +260,20 @@ do_convert_from_ssh2(struct passwd *pw)
|
||||
fprintf(stderr, "uudecode failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
k = dsa_key_from_blob(blob, blen);
|
||||
if (!key_write(k, stdout))
|
||||
fprintf(stderr, "key_write failed");
|
||||
k = private ?
|
||||
do_convert_private_ssh2_from_blob(blob, blen) :
|
||||
dsa_key_from_blob(blob, blen);
|
||||
if (k == NULL) {
|
||||
fprintf(stderr, "decode blob failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
ok = private ?
|
||||
PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
|
||||
key_write(k, stdout);
|
||||
if (!ok) {
|
||||
fprintf(stderr, "key write failed");
|
||||
exit(1);
|
||||
}
|
||||
key_free(k);
|
||||
fprintf(stdout, "\n");
|
||||
fclose(fp);
|
||||
|
||||
+11
-6
@@ -34,6 +34,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.
|
||||
.\"
|
||||
.\" $OpenBSD: ssh.1,v 1.64 2000/10/16 21:46:31 markus Exp $
|
||||
.Dd September 25, 1999
|
||||
.Dt SSH 1
|
||||
.Os
|
||||
@@ -367,15 +368,16 @@ It is believed to be secure.
|
||||
(triple-des) is an encrypt-decrypt-encrypt triple with three different keys.
|
||||
It is presumably more secure than the
|
||||
.Ar des
|
||||
cipher which is no longer supported in
|
||||
cipher which is no longer fully supported in
|
||||
.Nm ssh .
|
||||
.Ar blowfish
|
||||
is a fast block cipher, it appears very secure and is much faster than
|
||||
.Ar 3des .
|
||||
.It Fl c Ar "3des-cbc,blowfish-cbc,arcfour,cast128-cbc"
|
||||
Additionally, for protocol version 2 a comma-separated list of ciphers can
|
||||
be specified in order of preference. Protocol version 2 supports
|
||||
3DES, Blowfish and CAST128 in CBC mode and Arcfour.
|
||||
be specified in order of preference.
|
||||
Protocol version 2 supports 3DES, Blowfish, and CAST128 in CBC mode
|
||||
and Arcfour.
|
||||
.It Fl e Ar ch|^ch|none
|
||||
Sets the escape character for sessions with a pty (default:
|
||||
.Ql ~ ) .
|
||||
@@ -483,6 +485,8 @@ debugging connection, authentication, and configuration problems.
|
||||
The verbose mode is also used to display
|
||||
.Xr skey 1
|
||||
challenges, if the user entered "s/key" as password.
|
||||
Multiple -v options increases the verbosity.
|
||||
Maximum is 3.
|
||||
.It Fl x
|
||||
Disables X11 forwarding.
|
||||
.It Fl X
|
||||
@@ -624,9 +628,10 @@ If the option is set to
|
||||
.Dq no ,
|
||||
the check will not be executed.
|
||||
.It Cm Cipher
|
||||
Specifies the cipher to use for encrypting the session.
|
||||
Specifies the cipher to use for encrypting the session
|
||||
in protocol version 1.
|
||||
Currently,
|
||||
.Dq blowfish ,
|
||||
.Dq blowfish
|
||||
and
|
||||
.Dq 3des
|
||||
are supported.
|
||||
@@ -637,7 +642,7 @@ Specifies the ciphers allowed for protocol version 2
|
||||
in order of preference.
|
||||
Multiple ciphers must be comma-separated.
|
||||
The default is
|
||||
.Dq 3des-cbc,blowfish-cbc,arcfour,cast128-cbc .
|
||||
.Dq 3des-cbc,blowfish-cbc,cast128-cbc,arcfour .
|
||||
.It Cm Compression
|
||||
Specifies whether to use compression.
|
||||
The argument must be
|
||||
|
||||
+24
-22
@@ -39,7 +39,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: ssh.c,v 1.65 2000/09/07 20:40:30 markus Exp $");
|
||||
RCSID("$OpenBSD: ssh.c,v 1.69 2000/10/27 07:32:19 markus Exp $");
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/dsa.h>
|
||||
@@ -147,6 +147,7 @@ usage()
|
||||
fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n");
|
||||
fprintf(stderr, " -T Do not allocate a tty.\n");
|
||||
fprintf(stderr, " -v Verbose; display verbose debugging messages.\n");
|
||||
fprintf(stderr, " Multiple -v increases verbosity.\n");
|
||||
fprintf(stderr, " -V Display version number only.\n");
|
||||
fprintf(stderr, " -P Don't allocate a privileged port.\n");
|
||||
fprintf(stderr, " -q Quiet; don't display any warning messages.\n");
|
||||
@@ -361,6 +362,16 @@ main(int ac, char **av)
|
||||
tty_flag = 1;
|
||||
break;
|
||||
case 'v':
|
||||
if (0 == debug_flag) {
|
||||
debug_flag = 1;
|
||||
options.log_level = SYSLOG_LEVEL_DEBUG1;
|
||||
} else if (options.log_level < SYSLOG_LEVEL_DEBUG3) {
|
||||
options.log_level++;
|
||||
break;
|
||||
} else {
|
||||
fatal("Too high debugging level.\n");
|
||||
}
|
||||
/* fallthrough */
|
||||
case 'V':
|
||||
fprintf(stderr, "SSH Version %s, protocol versions %d.%d/%d.%d.\n",
|
||||
SSH_VERSION,
|
||||
@@ -369,8 +380,6 @@ main(int ac, char **av)
|
||||
fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay());
|
||||
if (opt == 'V')
|
||||
exit(0);
|
||||
debug_flag = 1;
|
||||
options.log_level = SYSLOG_LEVEL_DEBUG;
|
||||
break;
|
||||
case 'q':
|
||||
options.log_level = SYSLOG_LEVEL_QUIET;
|
||||
@@ -395,11 +404,12 @@ main(int ac, char **av)
|
||||
options.cipher = SSH_CIPHER_ILLEGAL;
|
||||
} else {
|
||||
/* SSH1 only */
|
||||
options.cipher = cipher_number(optarg);
|
||||
if (options.cipher == -1) {
|
||||
Cipher *c = cipher_by_name(optarg);
|
||||
if (c == NULL || c->number < 0) {
|
||||
fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
options.cipher = c->number;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
@@ -550,22 +560,6 @@ main(int ac, char **av)
|
||||
if (options.hostname != NULL)
|
||||
host = options.hostname;
|
||||
|
||||
/* Find canonic host name. */
|
||||
if (strchr(host, '.') == 0) {
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *ai = NULL;
|
||||
int errgai;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = IPv4or6;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
errgai = getaddrinfo(host, NULL, &hints, &ai);
|
||||
if (errgai == 0) {
|
||||
if (ai->ai_canonname != NULL)
|
||||
host = xstrdup(ai->ai_canonname);
|
||||
freeaddrinfo(ai);
|
||||
}
|
||||
}
|
||||
/* Disable rhosts authentication if not running as root. */
|
||||
if (original_effective_uid != 0 || !options.use_privileged_port) {
|
||||
options.rhosts_authentication = 0;
|
||||
@@ -986,6 +980,14 @@ ssh_session2(void)
|
||||
if (in < 0 || out < 0 || err < 0)
|
||||
fatal("dup() in/out/err failed");
|
||||
|
||||
/* enable nonblocking unless tty */
|
||||
if (!isatty(in))
|
||||
set_nonblock(in);
|
||||
if (!isatty(out))
|
||||
set_nonblock(out);
|
||||
if (!isatty(err))
|
||||
set_nonblock(err);
|
||||
|
||||
/* should be pre-session */
|
||||
init_local_fwd();
|
||||
|
||||
@@ -1003,7 +1005,7 @@ ssh_session2(void)
|
||||
id = channel_new(
|
||||
"session", SSH_CHANNEL_OPENING, in, out, err,
|
||||
window, packetmax, CHAN_EXTENDED_WRITE,
|
||||
xstrdup("client-session"));
|
||||
xstrdup("client-session"), /*nonblock*/0);
|
||||
|
||||
channel_open(id);
|
||||
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
|
||||
|
||||
+8
-11
@@ -12,7 +12,7 @@
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: ssh.h,v 1.50 2000/09/07 20:27:54 deraadt Exp $"); */
|
||||
/* RCSID("$OpenBSD: ssh.h,v 1.54 2000/10/11 20:27:24 markus Exp $"); */
|
||||
|
||||
#ifndef SSH_H
|
||||
#define SSH_H
|
||||
@@ -20,14 +20,6 @@
|
||||
#include "rsa.h"
|
||||
#include "cipher.h"
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* The default cipher used if IDEA is not supported by the remote host. It is
|
||||
* recommended that this be one of the mandatory ciphers (DES, 3DES), though
|
||||
* that is not required.
|
||||
*/
|
||||
#define SSH_FALLBACK_CIPHER SSH_CIPHER_3DES
|
||||
|
||||
/* Cipher used for encrypting authentication files. */
|
||||
#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES
|
||||
|
||||
@@ -81,6 +73,7 @@
|
||||
#define SERVER_CONFIG_FILE ETCDIR "/sshd_config"
|
||||
#define HOST_CONFIG_FILE ETCDIR "/ssh_config"
|
||||
#define HOST_DSA_KEY_FILE ETCDIR "/ssh_host_dsa_key"
|
||||
#define DH_PRIMES ETCDIR "/primes"
|
||||
|
||||
#define SSH_PROGRAM "/usr/bin/ssh"
|
||||
|
||||
@@ -380,7 +373,7 @@ int auth_rsa_challenge_dialog(RSA *pk);
|
||||
* passphrase (allocated with xmalloc). Exits if EOF is encountered. If
|
||||
* from_stdin is true, the passphrase will be read from stdin instead.
|
||||
*/
|
||||
char *read_passphrase(const char *prompt, int from_stdin);
|
||||
char *read_passphrase(char *prompt, int from_stdin);
|
||||
|
||||
|
||||
/*------------ Definitions for logging. -----------------------*/
|
||||
@@ -406,7 +399,9 @@ typedef enum {
|
||||
SYSLOG_LEVEL_ERROR,
|
||||
SYSLOG_LEVEL_INFO,
|
||||
SYSLOG_LEVEL_VERBOSE,
|
||||
SYSLOG_LEVEL_DEBUG
|
||||
SYSLOG_LEVEL_DEBUG1,
|
||||
SYSLOG_LEVEL_DEBUG2,
|
||||
SYSLOG_LEVEL_DEBUG3
|
||||
} LogLevel;
|
||||
/* Initializes logging. */
|
||||
void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr);
|
||||
@@ -424,6 +419,8 @@ void error(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
||||
void log(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
||||
void verbose(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
||||
void debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
||||
void debug2(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
||||
void debug3(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
/* same as fatal() but w/o logging */
|
||||
void fatal_cleanup(void);
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
*
|
||||
* 192-255 Local extensions
|
||||
*/
|
||||
/* RCSID("$OpenBSD: ssh2.h,v 1.4 2000/09/07 20:27:54 deraadt Exp $"); */
|
||||
/* RCSID("$OpenBSD: ssh2.h,v 1.5 2000/10/11 04:02:17 provos Exp $"); */
|
||||
|
||||
/* transport layer: generic */
|
||||
|
||||
@@ -73,6 +73,12 @@
|
||||
#define SSH2_MSG_KEXDH_INIT 30
|
||||
#define SSH2_MSG_KEXDH_REPLY 31
|
||||
|
||||
/* dh-group-exchange */
|
||||
#define SSH2_MSG_KEX_DH_GEX_REQUEST 30
|
||||
#define SSH2_MSG_KEX_DH_GEX_GROUP 31
|
||||
#define SSH2_MSG_KEX_DH_GEX_INIT 32
|
||||
#define SSH2_MSG_KEX_DH_GEX_REPLY 33
|
||||
|
||||
/* user authentication: generic */
|
||||
|
||||
#define SSH2_MSG_USERAUTH_REQUEST 50
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sshconnect.c,v 1.78 2000/09/07 20:27:54 deraadt Exp $");
|
||||
RCSID("$OpenBSD: sshconnect.c,v 1.79 2000/09/17 15:52:51 markus Exp $");
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
@@ -436,8 +436,10 @@ read_yes_or_no(const char *prompt, int defval)
|
||||
retval = defval;
|
||||
if (strcmp(buf, "yes") == 0)
|
||||
retval = 1;
|
||||
if (strcmp(buf, "no") == 0)
|
||||
else if (strcmp(buf, "no") == 0)
|
||||
retval = 0;
|
||||
else
|
||||
fprintf(stderr, "Please type 'yes' or 'no'.\n");
|
||||
|
||||
if (retval != -1) {
|
||||
if (f != stdin)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sshconnect1.c,v 1.6 2000/09/07 20:27:54 deraadt Exp $");
|
||||
RCSID("$OpenBSD: sshconnect1.c,v 1.8 2000/10/12 09:59:19 markus Exp $");
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
@@ -25,7 +25,6 @@ RCSID("$OpenBSD: sshconnect1.c,v 1.6 2000/09/07 20:27:54 deraadt Exp $");
|
||||
#include "ssh.h"
|
||||
#include "buffer.h"
|
||||
#include "packet.h"
|
||||
#include "cipher.h"
|
||||
#include "mpaux.h"
|
||||
#include "uidswap.h"
|
||||
#include "readconf.h"
|
||||
@@ -836,17 +835,11 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
|
||||
|
||||
if (options.cipher == SSH_CIPHER_ILLEGAL) {
|
||||
log("No valid SSH1 cipher, using %.100s instead.",
|
||||
cipher_name(SSH_FALLBACK_CIPHER));
|
||||
options.cipher = SSH_FALLBACK_CIPHER;
|
||||
cipher_name(ssh_cipher_default));
|
||||
options.cipher = ssh_cipher_default;
|
||||
} else if (options.cipher == SSH_CIPHER_NOT_SET) {
|
||||
if (cipher_mask1() & supported_ciphers & (1 << ssh_cipher_default))
|
||||
if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default))
|
||||
options.cipher = ssh_cipher_default;
|
||||
else {
|
||||
debug("Cipher %s not supported, using %.100s instead.",
|
||||
cipher_name(ssh_cipher_default),
|
||||
cipher_name(SSH_FALLBACK_CIPHER));
|
||||
options.cipher = SSH_FALLBACK_CIPHER;
|
||||
}
|
||||
}
|
||||
/* Check that the selected cipher is supported. */
|
||||
if (!(supported_ciphers & (1 << options.cipher)))
|
||||
|
||||
+705
-201
File diff suppressed because it is too large
Load Diff
+20
-7
@@ -34,6 +34,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.
|
||||
.\"
|
||||
.\" $OpenBSD: sshd.8,v 1.70 2000/10/16 09:38:44 djm Exp $
|
||||
.Dd September 25, 1999
|
||||
.Dt SSHD 8
|
||||
.Os
|
||||
@@ -186,6 +187,8 @@ The server sends verbose debug output to the system
|
||||
log, and does not put itself in the background.
|
||||
The server also will not fork and will only process one connection.
|
||||
This option is only intended for debugging for the server.
|
||||
Multiple -d options increases the debugging level.
|
||||
Maximum is 3.
|
||||
.It Fl f Ar configuration_file
|
||||
Specifies the name of the configuration file.
|
||||
The default is
|
||||
@@ -254,12 +257,13 @@ file.
|
||||
.It Fl Q
|
||||
Do not print an error message if RSA support is missing.
|
||||
.It Fl V Ar client_protocol_id
|
||||
SSH2 compatibility mode.
|
||||
SSH-2 compatibility mode.
|
||||
When this option is specified
|
||||
.Nm
|
||||
assumes the client has sent the supplied version string
|
||||
and skips the
|
||||
Protocol Version Identification Exchange.
|
||||
This option is not intended to be called directly.
|
||||
.It Fl 4
|
||||
Forces
|
||||
.Nm
|
||||
@@ -300,6 +304,14 @@ wildcards in the patterns.
|
||||
Only group names are valid; a numerical group ID isn't recognized.
|
||||
By default login is allowed regardless of the primary group.
|
||||
.Pp
|
||||
.It Cm AllowTcpForwarding
|
||||
Specifies whether TCP forwarding is permitted.
|
||||
The default is
|
||||
.Dq yes .
|
||||
Note that disabling TCP forwarding does not improve security unless
|
||||
users are also denied shell access, as they can always install their
|
||||
own forwarders.
|
||||
.Pp
|
||||
.It Cm AllowUsers
|
||||
This keyword can be followed by a number of user names, separated
|
||||
by spaces.
|
||||
@@ -423,7 +435,8 @@ Specifies whether Kerberos authentication is allowed.
|
||||
This can be in the form of a Kerberos ticket, or if
|
||||
.Cm PasswordAuthentication
|
||||
is yes, the password provided by the user will be validated through
|
||||
the Kerberos KDC. To use this option, the server needs a
|
||||
the Kerberos KDC.
|
||||
To use this option, the server needs a
|
||||
Kerberos servtab which allows the verification of the KDC's identity.
|
||||
Default is
|
||||
.Dq yes .
|
||||
@@ -431,8 +444,7 @@ Default is
|
||||
If set then if password authentication through Kerberos fails then
|
||||
the password will be validated via any additional local mechanism
|
||||
such as
|
||||
.Pa /etc/passwd
|
||||
or SecurID.
|
||||
.Pa /etc/passwd .
|
||||
Default is
|
||||
.Dq yes .
|
||||
.It Cm KerberosTgtPassing
|
||||
@@ -488,7 +500,7 @@ The default is 10.
|
||||
Alternatively, random early drop can be enabled by specifying
|
||||
the three colon separated values
|
||||
.Dq start:rate:full
|
||||
(e.g. "10:30:60").
|
||||
(e.g., "10:30:60").
|
||||
.Nm
|
||||
will refuse connection attempts with a probabillity of
|
||||
.Dq rate/100
|
||||
@@ -610,8 +622,9 @@ directory or files world-writable.
|
||||
The default is
|
||||
.Dq yes .
|
||||
.It Cm Subsystem
|
||||
Configures an external subsystem (e.g. file transfer daemon).
|
||||
Arguments should be a subsystem name and a command to execute upon subsystem request.
|
||||
Configures an external subsystem (e.g., file transfer daemon).
|
||||
Arguments should be a subsystem name and a command to execute upon subsystem
|
||||
request.
|
||||
The command
|
||||
.Xr sftp-server 8
|
||||
implements the
|
||||
|
||||
+217
-38
@@ -40,14 +40,13 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sshd.c,v 1.126 2000/09/07 20:27:55 deraadt Exp $");
|
||||
RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "rsa.h"
|
||||
#include "ssh.h"
|
||||
#include "pty.h"
|
||||
#include "packet.h"
|
||||
#include "cipher.h"
|
||||
#include "mpaux.h"
|
||||
#include "servconf.h"
|
||||
#include "uidswap.h"
|
||||
@@ -63,6 +62,7 @@ RCSID("$OpenBSD: sshd.c,v 1.126 2000/09/07 20:27:55 deraadt Exp $");
|
||||
#include <openssl/rsa.h>
|
||||
#include "key.h"
|
||||
#include "dsa.h"
|
||||
#include "dh.h"
|
||||
|
||||
#include "auth.h"
|
||||
#include "myproposal.h"
|
||||
@@ -167,6 +167,9 @@ unsigned int utmp_len = MAXHOSTNAMELEN;
|
||||
void do_ssh1_kex();
|
||||
void do_ssh2_kex();
|
||||
|
||||
void ssh_dh1_server(Kex *, Buffer *_kexinit, Buffer *);
|
||||
void ssh_dhgex_server(Kex *, Buffer *_kexinit, Buffer *);
|
||||
|
||||
/*
|
||||
* Close all listening sockets
|
||||
*/
|
||||
@@ -328,6 +331,10 @@ sshd_exchange_identification(int sock_in, int sock_out)
|
||||
if (buf[i] == '\r') {
|
||||
buf[i] = '\n';
|
||||
buf[i + 1] = 0;
|
||||
/* Kludge for F-Secure Macintosh < 1.0.2 */
|
||||
if (i == 12 &&
|
||||
strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (buf[i] == '\n') {
|
||||
@@ -503,8 +510,15 @@ main(int ac, char **av)
|
||||
config_file_name = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
debug_flag = 1;
|
||||
options.log_level = SYSLOG_LEVEL_DEBUG;
|
||||
if (0 == debug_flag) {
|
||||
debug_flag = 1;
|
||||
options.log_level = SYSLOG_LEVEL_DEBUG1;
|
||||
} else if (options.log_level < SYSLOG_LEVEL_DEBUG3) {
|
||||
options.log_level++;
|
||||
} else {
|
||||
fprintf(stderr, "Too high debugging level.\n");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
inetd_flag = 1;
|
||||
@@ -520,8 +534,10 @@ main(int ac, char **av)
|
||||
break;
|
||||
case 'p':
|
||||
options.ports_from_cmdline = 1;
|
||||
if (options.num_ports >= MAX_PORTS)
|
||||
fatal("too many ports.\n");
|
||||
if (options.num_ports >= MAX_PORTS) {
|
||||
fprintf(stderr, "too many ports.\n");
|
||||
exit(1);
|
||||
}
|
||||
options.ports[options.num_ports++] = atoi(optarg);
|
||||
break;
|
||||
case 'g':
|
||||
@@ -547,7 +563,7 @@ main(int ac, char **av)
|
||||
fprintf(stderr, "Usage: %s [options]\n", av0);
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr, " -f file Configuration file (default %s)\n", SERVER_CONFIG_FILE);
|
||||
fprintf(stderr, " -d Debugging mode\n");
|
||||
fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n");
|
||||
fprintf(stderr, " -i Started from inetd\n");
|
||||
fprintf(stderr, " -q Quiet (no logging)\n");
|
||||
fprintf(stderr, " -p port Listen on the specified port (default: 22)\n");
|
||||
@@ -1123,7 +1139,7 @@ do_ssh1_kex()
|
||||
packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
|
||||
|
||||
/* Declare which ciphers we support. */
|
||||
packet_put_int(cipher_mask1());
|
||||
packet_put_int(cipher_mask_ssh1(0));
|
||||
|
||||
/* Declare supported authentication types. */
|
||||
auth_mask = 0;
|
||||
@@ -1164,7 +1180,7 @@ do_ssh1_kex()
|
||||
/* Get cipher type and check whether we accept this. */
|
||||
cipher_type = packet_get_char();
|
||||
|
||||
if (!(cipher_mask() & (1 << cipher_type)))
|
||||
if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))
|
||||
packet_disconnect("Warning: client selects unsupported cipher.");
|
||||
|
||||
/* Get check bytes from the packet. These must match those we
|
||||
@@ -1268,18 +1284,8 @@ do_ssh2_kex()
|
||||
{
|
||||
Buffer *server_kexinit;
|
||||
Buffer *client_kexinit;
|
||||
int payload_len, dlen;
|
||||
int slen;
|
||||
unsigned int klen, kout;
|
||||
unsigned char *signature = NULL;
|
||||
unsigned char *server_host_key_blob = NULL;
|
||||
unsigned int sbloblen;
|
||||
DH *dh;
|
||||
BIGNUM *dh_client_pub = 0;
|
||||
BIGNUM *shared_secret = 0;
|
||||
int payload_len;
|
||||
int i;
|
||||
unsigned char *kbuf;
|
||||
unsigned char *hash;
|
||||
Kex *kex;
|
||||
char *cprop[PROPOSAL_MAX];
|
||||
|
||||
@@ -1299,8 +1305,63 @@ do_ssh2_kex()
|
||||
for (i = 0; i < PROPOSAL_MAX; i++)
|
||||
xfree(cprop[i]);
|
||||
|
||||
/* KEXDH */
|
||||
switch (kex->kex_type) {
|
||||
case DH_GRP1_SHA1:
|
||||
ssh_dh1_server(kex, client_kexinit, server_kexinit);
|
||||
break;
|
||||
case DH_GEX_SHA1:
|
||||
ssh_dhgex_server(kex, client_kexinit, server_kexinit);
|
||||
break;
|
||||
default:
|
||||
fatal("Unsupported key exchange %d", kex->kex_type);
|
||||
}
|
||||
|
||||
debug("send SSH2_MSG_NEWKEYS.");
|
||||
packet_start(SSH2_MSG_NEWKEYS);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
debug("done: send SSH2_MSG_NEWKEYS.");
|
||||
|
||||
debug("Wait SSH2_MSG_NEWKEYS.");
|
||||
packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS);
|
||||
debug("GOT SSH2_MSG_NEWKEYS.");
|
||||
|
||||
#ifdef DEBUG_KEXDH
|
||||
/* send 1st encrypted/maced/compressed message */
|
||||
packet_start(SSH2_MSG_IGNORE);
|
||||
packet_put_cstring("markus");
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
#endif
|
||||
|
||||
debug("done: KEX2.");
|
||||
}
|
||||
|
||||
/*
|
||||
* SSH2 key exchange
|
||||
*/
|
||||
|
||||
/* diffie-hellman-group1-sha1 */
|
||||
|
||||
void
|
||||
ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
|
||||
{
|
||||
#ifdef DEBUG_KEXDH
|
||||
int i;
|
||||
#endif
|
||||
int payload_len, dlen;
|
||||
int slen;
|
||||
unsigned char *signature = NULL;
|
||||
unsigned char *server_host_key_blob = NULL;
|
||||
unsigned int sbloblen;
|
||||
unsigned int klen, kout;
|
||||
unsigned char *kbuf;
|
||||
unsigned char *hash;
|
||||
BIGNUM *shared_secret = 0;
|
||||
DH *dh;
|
||||
BIGNUM *dh_client_pub = 0;
|
||||
|
||||
/* KEXDH */
|
||||
debug("Wait SSH2_MSG_KEXDH_INIT.");
|
||||
packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT);
|
||||
|
||||
@@ -1312,7 +1373,7 @@ do_ssh2_kex()
|
||||
|
||||
#ifdef DEBUG_KEXDH
|
||||
fprintf(stderr, "\ndh_client_pub= ");
|
||||
bignum_print(dh_client_pub);
|
||||
BN_print_fp(stderr, dh_client_pub);
|
||||
fprintf(stderr, "\n");
|
||||
debug("bits %d", BN_num_bits(dh_client_pub));
|
||||
#endif
|
||||
@@ -1322,12 +1383,13 @@ do_ssh2_kex()
|
||||
|
||||
#ifdef DEBUG_KEXDH
|
||||
fprintf(stderr, "\np= ");
|
||||
bignum_print(dh->p);
|
||||
BN_print_fp(stderr, dh->p);
|
||||
fprintf(stderr, "\ng= ");
|
||||
bignum_print(dh->g);
|
||||
bn_print(dh->g);
|
||||
fprintf(stderr, "\npub= ");
|
||||
bignum_print(dh->pub_key);
|
||||
BN_print_fp(stderr, dh->pub_key);
|
||||
fprintf(stderr, "\n");
|
||||
DHparams_print_fp(stderr, dh);
|
||||
#endif
|
||||
if (!dh_pub_is_valid(dh, dh_client_pub))
|
||||
packet_disconnect("bad client public DH value");
|
||||
@@ -1350,7 +1412,8 @@ do_ssh2_kex()
|
||||
xfree(kbuf);
|
||||
|
||||
/* XXX precompute? */
|
||||
dsa_make_key_blob(sensitive_data.dsa_host_key, &server_host_key_blob, &sbloblen);
|
||||
dsa_make_key_blob(sensitive_data.dsa_host_key,
|
||||
&server_host_key_blob, &sbloblen);
|
||||
|
||||
/* calc H */ /* XXX depends on 'kex' */
|
||||
hash = kex_hash(
|
||||
@@ -1400,23 +1463,139 @@ do_ssh2_kex()
|
||||
|
||||
/* have keys, free DH */
|
||||
DH_free(dh);
|
||||
}
|
||||
|
||||
debug("send SSH2_MSG_NEWKEYS.");
|
||||
packet_start(SSH2_MSG_NEWKEYS);
|
||||
/* diffie-hellman-group-exchange-sha1 */
|
||||
|
||||
void
|
||||
ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
|
||||
{
|
||||
#ifdef DEBUG_KEXDH
|
||||
int i;
|
||||
#endif
|
||||
int payload_len, dlen;
|
||||
int slen, nbits;
|
||||
unsigned char *signature = NULL;
|
||||
unsigned char *server_host_key_blob = NULL;
|
||||
unsigned int sbloblen;
|
||||
unsigned int klen, kout;
|
||||
unsigned char *kbuf;
|
||||
unsigned char *hash;
|
||||
BIGNUM *shared_secret = 0;
|
||||
DH *dh;
|
||||
BIGNUM *dh_client_pub = 0;
|
||||
|
||||
/* KEXDHGEX */
|
||||
debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST.");
|
||||
packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_REQUEST);
|
||||
nbits = packet_get_int();
|
||||
dh = choose_dh(nbits);
|
||||
|
||||
debug("Sending SSH2_MSG_KEX_DH_GEX_GROUP.");
|
||||
packet_start(SSH2_MSG_KEX_DH_GEX_GROUP);
|
||||
packet_put_bignum2(dh->p);
|
||||
packet_put_bignum2(dh->g);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
debug("done: send SSH2_MSG_NEWKEYS.");
|
||||
|
||||
debug("Wait SSH2_MSG_NEWKEYS.");
|
||||
packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS);
|
||||
debug("GOT SSH2_MSG_NEWKEYS.");
|
||||
debug("Wait SSH2_MSG_KEX_DH_GEX_INIT.");
|
||||
packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_INIT);
|
||||
|
||||
/* key, cert */
|
||||
dh_client_pub = BN_new();
|
||||
if (dh_client_pub == NULL)
|
||||
fatal("dh_client_pub == NULL");
|
||||
packet_get_bignum2(dh_client_pub, &dlen);
|
||||
|
||||
#ifdef DEBUG_KEXDH
|
||||
/* send 1st encrypted/maced/compressed message */
|
||||
packet_start(SSH2_MSG_IGNORE);
|
||||
packet_put_cstring("markus");
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
fprintf(stderr, "\ndh_client_pub= ");
|
||||
BN_print_fp(stderr, dh_client_pub);
|
||||
fprintf(stderr, "\n");
|
||||
debug("bits %d", BN_num_bits(dh_client_pub));
|
||||
#endif
|
||||
debug("done: KEX2.");
|
||||
|
||||
#ifdef DEBUG_KEXDH
|
||||
fprintf(stderr, "\np= ");
|
||||
BN_print_fp(stderr, dh->p);
|
||||
fprintf(stderr, "\ng= ");
|
||||
bn_print(dh->g);
|
||||
fprintf(stderr, "\npub= ");
|
||||
BN_print_fp(stderr, dh->pub_key);
|
||||
fprintf(stderr, "\n");
|
||||
DHparams_print_fp(stderr, dh);
|
||||
#endif
|
||||
if (!dh_pub_is_valid(dh, dh_client_pub))
|
||||
packet_disconnect("bad client public DH value");
|
||||
|
||||
klen = DH_size(dh);
|
||||
kbuf = xmalloc(klen);
|
||||
kout = DH_compute_key(kbuf, dh_client_pub, dh);
|
||||
|
||||
#ifdef DEBUG_KEXDH
|
||||
debug("shared secret: len %d/%d", klen, kout);
|
||||
fprintf(stderr, "shared secret == ");
|
||||
for (i = 0; i< kout; i++)
|
||||
fprintf(stderr, "%02x", (kbuf[i])&0xff);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
shared_secret = BN_new();
|
||||
|
||||
BN_bin2bn(kbuf, kout, shared_secret);
|
||||
memset(kbuf, 0, klen);
|
||||
xfree(kbuf);
|
||||
|
||||
/* XXX precompute? */
|
||||
dsa_make_key_blob(sensitive_data.dsa_host_key,
|
||||
&server_host_key_blob, &sbloblen);
|
||||
|
||||
/* calc H */ /* XXX depends on 'kex' */
|
||||
hash = kex_hash_gex(
|
||||
client_version_string,
|
||||
server_version_string,
|
||||
buffer_ptr(client_kexinit), buffer_len(client_kexinit),
|
||||
buffer_ptr(server_kexinit), buffer_len(server_kexinit),
|
||||
(char *)server_host_key_blob, sbloblen,
|
||||
nbits, dh->p, dh->g,
|
||||
dh_client_pub,
|
||||
dh->pub_key,
|
||||
shared_secret
|
||||
);
|
||||
buffer_free(client_kexinit);
|
||||
buffer_free(server_kexinit);
|
||||
xfree(client_kexinit);
|
||||
xfree(server_kexinit);
|
||||
#ifdef DEBUG_KEXDH
|
||||
fprintf(stderr, "hash == ");
|
||||
for (i = 0; i< 20; i++)
|
||||
fprintf(stderr, "%02x", (hash[i])&0xff);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
/* save session id := H */
|
||||
/* XXX hashlen depends on KEX */
|
||||
session_id2_len = 20;
|
||||
session_id2 = xmalloc(session_id2_len);
|
||||
memcpy(session_id2, hash, session_id2_len);
|
||||
|
||||
/* sign H */
|
||||
/* XXX hashlen depends on KEX */
|
||||
dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20);
|
||||
|
||||
destroy_sensitive_data();
|
||||
|
||||
/* send server hostkey, DH pubkey 'f' and singed H */
|
||||
packet_start(SSH2_MSG_KEX_DH_GEX_REPLY);
|
||||
packet_put_string((char *)server_host_key_blob, sbloblen);
|
||||
packet_put_bignum2(dh->pub_key); /* f */
|
||||
packet_put_string((char *)signature, slen);
|
||||
packet_send();
|
||||
xfree(signature);
|
||||
xfree(server_host_key_blob);
|
||||
packet_write_wait();
|
||||
|
||||
kex_derive_keys(kex, hash, shared_secret);
|
||||
packet_set_kex(kex);
|
||||
|
||||
/* have keys, free DH */
|
||||
DH_free(dh);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ CFLAGS+=-DHAVE_LOGIN_CAP
|
||||
|
||||
SRCS= sshd.c auth-rhosts.c auth-passwd.c auth-rsa.c auth-rh-rsa.c \
|
||||
pty.c log-server.c login.c servconf.c serverloop.c \
|
||||
auth.c auth1.c auth2.c auth-options.c session.c
|
||||
auth.c auth1.c auth2.c auth-options.c session.c dh.c
|
||||
|
||||
.include <bsd.own.mk> # for KERBEROS and AFS
|
||||
|
||||
@@ -26,7 +26,7 @@ DPADD+= ${LIBKRB}
|
||||
.endif # KERBEROS
|
||||
|
||||
.if (${SKEY:L} == "yes")
|
||||
SRCS+= auth-skey.c
|
||||
SRCS+= auth-skey.c auth2-skey.c
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
@@ -37,6 +37,7 @@ PasswordAuthentication yes
|
||||
PermitEmptyPasswords no
|
||||
# Uncomment to disable s/key passwords
|
||||
#SkeyAuthentication no
|
||||
#KbdInteractiveAuthentication yes
|
||||
|
||||
# To change Kerberos options
|
||||
#KerberosAuthentication no
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: util.c,v 1.5 2000/09/07 20:27:55 deraadt Exp $ */
|
||||
/* $OpenBSD: util.c,v 1.6 2000/10/27 07:32:19 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: util.c,v 1.5 2000/09/07 20:27:55 deraadt Exp $");
|
||||
RCSID("$OpenBSD: util.c,v 1.6 2000/10/27 07:32:19 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
@@ -48,18 +48,15 @@ void
|
||||
set_nonblock(int fd)
|
||||
{
|
||||
int val;
|
||||
if (isatty(fd)) {
|
||||
/* do not mess with tty's */
|
||||
debug("no set_nonblock for tty fd %d", fd);
|
||||
return;
|
||||
}
|
||||
val = fcntl(fd, F_GETFL, 0);
|
||||
if (val < 0) {
|
||||
error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (val & O_NONBLOCK)
|
||||
if (val & O_NONBLOCK) {
|
||||
debug("fd %d IS O_NONBLOCK", fd);
|
||||
return;
|
||||
}
|
||||
debug("fd %d setting O_NONBLOCK", fd);
|
||||
val |= O_NONBLOCK;
|
||||
if (fcntl(fd, F_SETFL, val) == -1)
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
#define SSH_VERSION "OpenSSH_2.2.0"
|
||||
/* $OpenBSD: version.h,v 1.13 2000/10/16 09:38:45 djm Exp $ */
|
||||
|
||||
#define SSH_VERSION "OpenSSH_2.3.0"
|
||||
|
||||
Reference in New Issue
Block a user