summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2000-12-05 02:20:19 +0000
committergreen <green@FreeBSD.org>2000-12-05 02:20:19 +0000
commit1c5144a169aecf147a657c0e0e0a6460e92b5b83 (patch)
treedb590dc709e61e16f11313599d2edbc3d7990745 /crypto
parentc972e7aad1a6bdf921bbf261f2f93198504e35cf (diff)
parent2aecee364f2b1fa8b38c4d29600f05f33075cddf (diff)
downloadFreeBSD-src-1c5144a169aecf147a657c0e0e0a6460e92b5b83.zip
FreeBSD-src-1c5144a169aecf147a657c0e0e0a6460e92b5b83.tar.gz
This commit was generated by cvs2svn to compensate for changes in r69587,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'crypto')
-rw-r--r--crypto/openssh/LICENCE2
-rw-r--r--crypto/openssh/Makefile.inc2
-rw-r--r--crypto/openssh/RFC.nroff2
-rw-r--r--crypto/openssh/atomicio.c2
-rw-r--r--crypto/openssh/auth-options.c48
-rw-r--r--crypto/openssh/auth-options.h6
-rw-r--r--crypto/openssh/auth-rhosts.c5
-rw-r--r--crypto/openssh/auth.h22
-rw-r--r--crypto/openssh/auth2-skey.c104
-rw-r--r--crypto/openssh/authfd.h9
-rw-r--r--crypto/openssh/authfile.h4
-rw-r--r--crypto/openssh/channels.c111
-rw-r--r--crypto/openssh/channels.h41
-rw-r--r--crypto/openssh/cli.c196
-rw-r--r--crypto/openssh/cli.h16
-rw-r--r--crypto/openssh/clientloop.c33
-rw-r--r--crypto/openssh/compat.c48
-rw-r--r--crypto/openssh/compat.h4
-rw-r--r--crypto/openssh/deattack.c4
-rw-r--r--crypto/openssh/dh.c157
-rw-r--r--crypto/openssh/dh.h35
-rw-r--r--crypto/openssh/dispatch.c8
-rw-r--r--crypto/openssh/dispatch.h6
-rw-r--r--crypto/openssh/kex.c169
-rw-r--r--crypto/openssh/kex.h35
-rw-r--r--crypto/openssh/lib/Makefile3
-rw-r--r--crypto/openssh/log-client.c8
-rw-r--r--crypto/openssh/log-server.c18
-rw-r--r--crypto/openssh/log.c27
-rw-r--r--crypto/openssh/myproposal.h10
-rw-r--r--crypto/openssh/packet.c72
-rw-r--r--crypto/openssh/readpass.c82
-rw-r--r--crypto/openssh/rijndael.c493
-rw-r--r--crypto/openssh/rijndael.h31
-rw-r--r--crypto/openssh/scp.19
-rw-r--r--crypto/openssh/scp.c174
-rw-r--r--crypto/openssh/serverloop.c22
-rw-r--r--crypto/openssh/sftp-server.820
-rw-r--r--crypto/openssh/ssh-keygen.15
-rw-r--r--crypto/openssh/ssh-keygen.c105
-rw-r--r--crypto/openssh/ssh2.h8
-rw-r--r--crypto/openssh/sshconnect2.c878
-rw-r--r--crypto/openssh/sshd/Makefile4
-rw-r--r--crypto/openssh/util.c13
-rw-r--r--crypto/openssh/version.h4
45 files changed, 2407 insertions, 648 deletions
diff --git a/crypto/openssh/LICENCE b/crypto/openssh/LICENCE
index e8ab01b..7c2346a 100644
--- a/crypto/openssh/LICENCE
+++ b/crypto/openssh/LICENCE
@@ -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]
diff --git a/crypto/openssh/Makefile.inc b/crypto/openssh/Makefile.inc
index fddf3da..85e1454 100644
--- a/crypto/openssh/Makefile.inc
+++ b/crypto/openssh/Makefile.inc
@@ -1,5 +1,7 @@
CFLAGS+= -I${.CURDIR}/..
+CFLAGS+= -Wall
+
.include <bsd.obj.mk>
.if exists(${.CURDIR}/../lib/${__objdir})
diff --git a/crypto/openssh/RFC.nroff b/crypto/openssh/RFC.nroff
index dccc954..bf7146a 100644
--- a/crypto/openssh/RFC.nroff
+++ b/crypto/openssh/RFC.nroff
@@ -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
diff --git a/crypto/openssh/atomicio.c b/crypto/openssh/atomicio.c
index 019eda8..744ccc7 100644
--- a/crypto/openssh/atomicio.c
+++ b/crypto/openssh/atomicio.c
@@ -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"
diff --git a/crypto/openssh/auth-options.c b/crypto/openssh/auth-options.c
index da69652..c9c149d 100644
--- a/crypto/openssh/auth-options.c
+++ b/crypto/openssh/auth-options.c
@@ -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;
}
diff --git a/crypto/openssh/auth-options.h b/crypto/openssh/auth-options.h
index 9044d98..00fae22 100644
--- a/crypto/openssh/auth-options.h
+++ b/crypto/openssh/auth-options.h
@@ -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
diff --git a/crypto/openssh/auth-rhosts.c b/crypto/openssh/auth-rhosts.c
index 901c8d1..8314e23 100644
--- a/crypto/openssh/auth-rhosts.c
+++ b/crypto/openssh/auth-rhosts.c
@@ -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);
/*
diff --git a/crypto/openssh/auth.h b/crypto/openssh/auth.h
index 65bf7ae..721d763 100644
--- a/crypto/openssh/auth.h
+++ b/crypto/openssh/auth.h
@@ -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
-
diff --git a/crypto/openssh/auth2-skey.c b/crypto/openssh/auth2-skey.c
new file mode 100644
index 0000000..9de08fc
--- /dev/null
+++ b/crypto/openssh/auth2-skey.c
@@ -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);
+ }
+}
diff --git a/crypto/openssh/authfd.h b/crypto/openssh/authfd.h
index b7a137d..2d24652 100644
--- a/crypto/openssh/authfd.h
+++ b/crypto/openssh/authfd.h
@@ -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;
diff --git a/crypto/openssh/authfile.h b/crypto/openssh/authfile.h
index 4283d93..525b4aa 100644
--- a/crypto/openssh/authfile.h
+++ b/crypto/openssh/authfile.h
@@ -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.
diff --git a/crypto/openssh/channels.c b/crypto/openssh/channels.c
index e9a64d9..81bd715 100644
--- a/crypto/openssh/channels.c
+++ b/crypto/openssh/channels.c
@@ -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;
diff --git a/crypto/openssh/channels.h b/crypto/openssh/channels.h
index c0d6019..0052686 100644
--- a/crypto/openssh/channels.h
+++ b/crypto/openssh/channels.h
@@ -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);
-
-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);
+ 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 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);
diff --git a/crypto/openssh/cli.c b/crypto/openssh/cli.c
new file mode 100644
index 0000000..ab9a7dc
--- /dev/null
+++ b/crypto/openssh/cli.c
@@ -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;
+}
diff --git a/crypto/openssh/cli.h b/crypto/openssh/cli.h
new file mode 100644
index 0000000..c419404
--- /dev/null
+++ b/crypto/openssh/cli.h
@@ -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 */
diff --git a/crypto/openssh/clientloop.c b/crypto/openssh/clientloop.c
index 4a10b98..bccb9be 100644
--- a/crypto/openssh/clientloop.c
+++ b/crypto/openssh/clientloop.c
@@ -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);
diff --git a/crypto/openssh/compat.c b/crypto/openssh/compat.c
index eeb6e2e..a9daabc 100644
--- a/crypto/openssh/compat.c
+++ b/crypto/openssh/compat.c
@@ -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(&reg, check[i].pat, REG_EXTENDED|REG_NOSUB);
+ if (ret != 0) {
+ regerror(ret, &reg, ebuf, sizeof(ebuf));
+ ebuf[sizeof(ebuf)-1] = '\0';
+ error("regerror: %s", ebuf);
+ continue;
+ }
+ ret = regexec(&reg, version, 0, NULL, 0);
+ regfree(&reg);
+ 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 ","
diff --git a/crypto/openssh/compat.h b/crypto/openssh/compat.h
index 5be188b..f14efaf 100644
--- a/crypto/openssh/compat.h
+++ b/crypto/openssh/compat.h
@@ -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);
diff --git a/crypto/openssh/deattack.c b/crypto/openssh/deattack.c
index 74a46c0..df1d224 100644
--- a/crypto/openssh/deattack.c
+++ b/crypto/openssh/deattack.c
@@ -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;
diff --git a/crypto/openssh/dh.c b/crypto/openssh/dh.c
new file mode 100644
index 0000000..ff84619
--- /dev/null
+++ b/crypto/openssh/dh.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));
+}
diff --git a/crypto/openssh/dh.h b/crypto/openssh/dh.h
new file mode 100644
index 0000000..09b11fd
--- /dev/null
+++ b/crypto/openssh/dh.h
@@ -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
diff --git a/crypto/openssh/dispatch.c b/crypto/openssh/dispatch.c
index 3daac20..db8951c 100644
--- a/crypto/openssh/dispatch.c
+++ b/crypto/openssh/dispatch.c
@@ -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)
diff --git a/crypto/openssh/dispatch.h b/crypto/openssh/dispatch.h
index dc9d3dd..e60174c 100644
--- a/crypto/openssh/dispatch.h
+++ b/crypto/openssh/dispatch.h
@@ -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);
diff --git a/crypto/openssh/kex.c b/crypto/openssh/kex.c
index 8a83db4..68b9e52 100644
--- a/crypto/openssh/kex.c
+++ b/crypto/openssh/kex.c
@@ -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)
{
@@ -237,6 +260,59 @@ kex_hash(
}
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)
{
Buffer b;
@@ -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;
}
diff --git a/crypto/openssh/kex.h b/crypto/openssh/kex.h
index 8c89687..2129581 100644
--- a/crypto/openssh/kex.h
+++ b/crypto/openssh/kex.h
@@ -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
diff --git a/crypto/openssh/lib/Makefile b/crypto/openssh/lib/Makefile
index 4bbe222..396186b 100644
--- a/crypto/openssh/lib/Makefile
+++ b/crypto/openssh/lib/Makefile
@@ -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
diff --git a/crypto/openssh/log-client.c b/crypto/openssh/log-client.c
index 616d3d0..505c8c3 100644
--- a/crypto/openssh/log-client.c
+++ b/crypto/openssh/log-client.c
@@ -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);
diff --git a/crypto/openssh/log-server.c b/crypto/openssh/log-server.c
index 11d650b..de3d5cf 100644
--- a/crypto/openssh/log-server.c
+++ b/crypto/openssh/log-server.c
@@ -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:
diff --git a/crypto/openssh/log.c b/crypto/openssh/log.c
index a6d9e05..ce89c59 100644
--- a/crypto/openssh/log.c
+++ b/crypto/openssh/log.c
@@ -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 }
};
diff --git a/crypto/openssh/myproposal.h b/crypto/openssh/myproposal.h
index 18db954..98060dc 100644
--- a/crypto/openssh/myproposal.h
+++ b/crypto/openssh/myproposal.h
@@ -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 ""
diff --git a/crypto/openssh/packet.c b/crypto/openssh/packet.c
index 670c0ed..3216fda 100644
--- a/crypto/openssh/packet.c
+++ b/crypto/openssh/packet.c
@@ -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;
diff --git a/crypto/openssh/readpass.c b/crypto/openssh/readpass.c
index c38292f..f3a7dcb 100644
--- a/crypto/openssh/readpass.c
+++ b/crypto/openssh/readpass.c
@@ -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);
}
diff --git a/crypto/openssh/rijndael.c b/crypto/openssh/rijndael.c
new file mode 100644
index 0000000..0eb313d
--- /dev/null
+++ b/crypto/openssh/rijndael.c
@@ -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];
+}
diff --git a/crypto/openssh/rijndael.h b/crypto/openssh/rijndael.h
new file mode 100644
index 0000000..c13f18c
--- /dev/null
+++ b/crypto/openssh/rijndael.h
@@ -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_ */
diff --git a/crypto/openssh/scp.1 b/crypto/openssh/scp.1
index 4ef3fe5..0a2ca1a 100644
--- a/crypto/openssh/scp.1
+++ b/crypto/openssh/scp.1
@@ -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
diff --git a/crypto/openssh/scp.c b/crypto/openssh/scp.c
index ec1f3d1..a412b8d 100644
--- a/crypto/openssh/scp.c
+++ b/crypto/openssh/scp.c
@@ -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 'p':
- pflag = 1;
+ case 'o':
+ case 'c':
+ case 'i':
+ addargs("-%c%s", ch, optarg);
break;
case 'P':
- port = optarg;
+ addargs("-p%s", optarg);
+ break;
+ case 'B':
+ addargs("-oBatchmode yes");
+ break;
+ case 'p':
+ pflag = 1;
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;
+}
diff --git a/crypto/openssh/serverloop.c b/crypto/openssh/serverloop.c
index ed2886a..f63131d 100644
--- a/crypto/openssh/serverloop.c
+++ b/crypto/openssh/serverloop.c
@@ -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);
diff --git a/crypto/openssh/sftp-server.8 b/crypto/openssh/sftp-server.8
index 9811a3b..41a698e 100644
--- a/crypto/openssh/sftp-server.8
+++ b/crypto/openssh/sftp-server.8
@@ -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 .
diff --git a/crypto/openssh/ssh-keygen.1 b/crypto/openssh/ssh-keygen.1
index b328ce0..e1b1525 100644
--- a/crypto/openssh/ssh-keygen.1
+++ b/crypto/openssh/ssh-keygen.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.
diff --git a/crypto/openssh/ssh-keygen.c b/crypto/openssh/ssh-keygen.c
index 29ee62d..e7b057f 100644
--- a/crypto/openssh/ssh-keygen.c
+++ b/crypto/openssh/ssh-keygen.c
@@ -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,19 +132,84 @@ 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)
{
Key *k;
@@ -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);
diff --git a/crypto/openssh/ssh2.h b/crypto/openssh/ssh2.h
index 47628dd..fe0146c 100644
--- a/crypto/openssh/ssh2.h
+++ b/crypto/openssh/ssh2.h
@@ -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
diff --git a/crypto/openssh/sshconnect2.c b/crypto/openssh/sshconnect2.c
index d225359..6ba23d4 100644
--- a/crypto/openssh/sshconnect2.c
+++ b/crypto/openssh/sshconnect2.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect2.c,v 1.18 2000/09/07 20:27:55 deraadt Exp $");
+RCSID("$OpenBSD: sshconnect2.c,v 1.27 2000/10/19 16:45:16 provos Exp $");
#include <openssl/bn.h>
#include <openssl/rsa.h>
@@ -37,7 +37,6 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.18 2000/09/07 20:27:55 deraadt Exp $");
#include "rsa.h"
#include "buffer.h"
#include "packet.h"
-#include "cipher.h"
#include "uidswap.h"
#include "compat.h"
#include "readconf.h"
@@ -49,8 +48,13 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.18 2000/09/07 20:27:55 deraadt Exp $");
#include "dsa.h"
#include "sshconnect.h"
#include "authfile.h"
+#include "cli.h"
+#include "dispatch.h"
#include "authfd.h"
+void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
+void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
+
/* import */
extern char *client_version_string;
extern char *server_version_string;
@@ -64,9 +68,94 @@ unsigned char *session_id2 = NULL;
int session_id2_len = 0;
void
-ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr,
- Buffer *client_kexinit, Buffer *server_kexinit)
+ssh_kex2(char *host, struct sockaddr *hostaddr)
+{
+ int i, plen;
+ Kex *kex;
+ Buffer *client_kexinit, *server_kexinit;
+ char *sprop[PROPOSAL_MAX];
+
+ if (options.ciphers == NULL) {
+ if (options.cipher == SSH_CIPHER_3DES) {
+ options.ciphers = "3des-cbc";
+ } else if (options.cipher == SSH_CIPHER_BLOWFISH) {
+ options.ciphers = "blowfish-cbc";
+ } else if (options.cipher == SSH_CIPHER_DES) {
+ fatal("cipher DES not supported for protocol version 2");
+ }
+ }
+ if (options.ciphers != NULL) {
+ myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+ myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+ }
+ if (options.compression) {
+ myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
+ myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
+ } else {
+ myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none";
+ myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
+ }
+
+ /* buffers with raw kexinit messages */
+ server_kexinit = xmalloc(sizeof(*server_kexinit));
+ buffer_init(server_kexinit);
+ client_kexinit = kex_init(myproposal);
+
+ /* algorithm negotiation */
+ kex_exchange_kexinit(client_kexinit, server_kexinit, sprop);
+ kex = kex_choose_conf(myproposal, sprop, 0);
+ for (i = 0; i < PROPOSAL_MAX; i++)
+ xfree(sprop[i]);
+
+ /* server authentication and session key agreement */
+ switch(kex->kex_type) {
+ case DH_GRP1_SHA1:
+ ssh_dh1_client(kex, host, hostaddr,
+ client_kexinit, server_kexinit);
+ break;
+ case DH_GEX_SHA1:
+ ssh_dhgex_client(kex, host, hostaddr, client_kexinit,
+ server_kexinit);
+ break;
+ default:
+ fatal("Unsupported key exchange %d", kex->kex_type);
+ }
+
+ buffer_free(client_kexinit);
+ buffer_free(server_kexinit);
+ xfree(client_kexinit);
+ xfree(server_kexinit);
+
+ debug("Wait SSH2_MSG_NEWKEYS.");
+ packet_read_expect(&plen, SSH2_MSG_NEWKEYS);
+ packet_done();
+ debug("GOT SSH2_MSG_NEWKEYS.");
+
+ debug("send SSH2_MSG_NEWKEYS.");
+ packet_start(SSH2_MSG_NEWKEYS);
+ packet_send();
+ packet_write_wait();
+ debug("done: send 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.");
+}
+
+/* diffie-hellman-group1-sha1 */
+
+void
+ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
+ Buffer *client_kexinit, Buffer *server_kexinit)
{
+#ifdef DEBUG_KEXDH
+ int i;
+#endif
int plen, dlen;
unsigned int klen, kout;
char *signature = NULL;
@@ -90,11 +179,11 @@ ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr,
#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_fp(stderr, 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
@@ -112,7 +201,7 @@ ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr,
fatal("cannot decode server_host_key_blob");
check_host_key(host, hostaddr, server_host_key,
- options.user_hostfile2, options.system_hostfile2);
+ options.user_hostfile2, options.system_hostfile2);
/* DH paramter f, server public DH key */
dh_server_pub = BN_new();
@@ -122,7 +211,7 @@ ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr,
#ifdef DEBUG_KEXDH
fprintf(stderr, "\ndh_server_pub= ");
- bignum_print(dh_server_pub);
+ BN_print_fp(stderr, dh_server_pub);
fprintf(stderr, "\n");
debug("bits %d", BN_num_bits(dh_server_pub));
#endif
@@ -182,79 +271,351 @@ ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr,
memcpy(session_id2, hash, session_id2_len);
}
+/* diffie-hellman-group-exchange-sha1 */
+
+/*
+ * Estimates the group order for a Diffie-Hellman group that has an
+ * attack complexity approximately the same as O(2**bits). Estimate
+ * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
+ */
+
+int
+dh_estimate(int bits)
+{
+
+ if (bits < 64)
+ return (512); /* O(2**63) */
+ if (bits < 128)
+ return (1024); /* O(2**86) */
+ if (bits < 192)
+ return (2048); /* O(2**116) */
+ return (4096); /* O(2**156) */
+}
+
void
-ssh_kex2(char *host, struct sockaddr *hostaddr)
+ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
+ Buffer *client_kexinit, Buffer *server_kexinit)
{
- int i, plen;
- Kex *kex;
- Buffer *client_kexinit, *server_kexinit;
- char *sprop[PROPOSAL_MAX];
+#ifdef DEBUG_KEXDH
+ int i;
+#endif
+ int plen, dlen;
+ unsigned int klen, kout;
+ char *signature = NULL;
+ unsigned int slen, nbits;
+ char *server_host_key_blob = NULL;
+ Key *server_host_key;
+ unsigned int sbloblen;
+ DH *dh;
+ BIGNUM *dh_server_pub = 0;
+ BIGNUM *shared_secret = 0;
+ BIGNUM *p = 0, *g = 0;
+ unsigned char *kbuf;
+ unsigned char *hash;
- if (options.ciphers != NULL) {
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
- } else if (options.cipher == SSH_CIPHER_3DES) {
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- myproposal[PROPOSAL_ENC_ALGS_STOC] =
- (char *) cipher_name(SSH_CIPHER_3DES_CBC);
- } else if (options.cipher == SSH_CIPHER_BLOWFISH) {
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- myproposal[PROPOSAL_ENC_ALGS_STOC] =
- (char *) cipher_name(SSH_CIPHER_BLOWFISH_CBC);
- }
- if (options.compression) {
- myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
- myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
- } else {
- myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none";
- myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
- }
+ nbits = dh_estimate(kex->enc[MODE_OUT].cipher->key_len * 8);
- /* buffers with raw kexinit messages */
- server_kexinit = xmalloc(sizeof(*server_kexinit));
- buffer_init(server_kexinit);
- client_kexinit = kex_init(myproposal);
+ debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST.");
+ packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
+ packet_put_int(nbits);
+ packet_send();
+ packet_write_wait();
- /* algorithm negotiation */
- kex_exchange_kexinit(client_kexinit, server_kexinit, sprop);
- kex = kex_choose_conf(myproposal, sprop, 0);
- for (i = 0; i < PROPOSAL_MAX; i++)
- xfree(sprop[i]);
+#ifdef DEBUG_KEXDH
+ fprintf(stderr, "\nnbits = %d", nbits);
+#endif
- /* server authentication and session key agreement */
- ssh_kex_dh(kex, host, hostaddr, client_kexinit, server_kexinit);
+ debug("Wait SSH2_MSG_KEX_DH_GEX_GROUP.");
- buffer_free(client_kexinit);
- buffer_free(server_kexinit);
- xfree(client_kexinit);
- xfree(server_kexinit);
+ packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP);
- debug("Wait SSH2_MSG_NEWKEYS.");
- packet_read_expect(&plen, SSH2_MSG_NEWKEYS);
- packet_done();
- debug("GOT SSH2_MSG_NEWKEYS.");
+ debug("Got SSH2_MSG_KEX_DH_GEX_GROUP.");
- debug("send SSH2_MSG_NEWKEYS.");
- packet_start(SSH2_MSG_NEWKEYS);
- packet_send();
- packet_write_wait();
- debug("done: send SSH2_MSG_NEWKEYS.");
+ if ((p = BN_new()) == NULL)
+ fatal("BN_new");
+ packet_get_bignum2(p, &dlen);
+ if ((g = BN_new()) == NULL)
+ fatal("BN_new");
+ packet_get_bignum2(g, &dlen);
+ if ((dh = dh_new_group(g, p)) == NULL)
+ fatal("dh_new_group");
#ifdef DEBUG_KEXDH
- /* send 1st encrypted/maced/compressed message */
- packet_start(SSH2_MSG_IGNORE);
- packet_put_cstring("markus");
+ fprintf(stderr, "\np= ");
+ BN_print_fp(stderr, dh->p);
+ fprintf(stderr, "\ng= ");
+ BN_print_fp(stderr, dh->g);
+ fprintf(stderr, "\npub= ");
+ BN_print_fp(stderr, dh->pub_key);
+ fprintf(stderr, "\n");
+ DHparams_print_fp(stderr, dh);
+#endif
+
+ debug("Sending SSH2_MSG_KEX_DH_GEX_INIT.");
+ /* generate and send 'e', client DH public key */
+ packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
+ packet_put_bignum2(dh->pub_key);
packet_send();
packet_write_wait();
+
+ debug("Wait SSH2_MSG_KEX_DH_GEX_REPLY.");
+
+ packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY);
+
+ debug("Got SSH2_MSG_KEXDH_REPLY.");
+
+ /* key, cert */
+ server_host_key_blob = packet_get_string(&sbloblen);
+ server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen);
+ if (server_host_key == NULL)
+ fatal("cannot decode server_host_key_blob");
+
+ check_host_key(host, hostaddr, server_host_key,
+ options.user_hostfile2, options.system_hostfile2);
+
+ /* DH paramter f, server public DH key */
+ dh_server_pub = BN_new();
+ if (dh_server_pub == NULL)
+ fatal("dh_server_pub == NULL");
+ packet_get_bignum2(dh_server_pub, &dlen);
+
+#ifdef DEBUG_KEXDH
+ fprintf(stderr, "\ndh_server_pub= ");
+ BN_print_fp(stderr, dh_server_pub);
+ fprintf(stderr, "\n");
+ debug("bits %d", BN_num_bits(dh_server_pub));
#endif
- debug("done: KEX2.");
+
+ /* signed H */
+ signature = packet_get_string(&slen);
+ packet_done();
+
+ if (!dh_pub_is_valid(dh, dh_server_pub))
+ packet_disconnect("bad server public DH value");
+
+ klen = DH_size(dh);
+ kbuf = xmalloc(klen);
+ kout = DH_compute_key(kbuf, dh_server_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);
+
+ /* calc and verify H */
+ 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),
+ server_host_key_blob, sbloblen,
+ nbits, dh->p, dh->g,
+ dh->pub_key,
+ dh_server_pub,
+ shared_secret
+ );
+ xfree(server_host_key_blob);
+ DH_free(dh);
+#ifdef DEBUG_KEXDH
+ fprintf(stderr, "hash == ");
+ for (i = 0; i< 20; i++)
+ fprintf(stderr, "%02x", (hash[i])&0xff);
+ fprintf(stderr, "\n");
+#endif
+ if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
+ fatal("dsa_verify failed for server_host_key");
+ key_free(server_host_key);
+
+ kex_derive_keys(kex, hash, shared_secret);
+ packet_set_kex(kex);
+
+ /* save session id */
+ session_id2_len = 20;
+ session_id2 = xmalloc(session_id2_len);
+ memcpy(session_id2, hash, session_id2_len);
}
/*
* Authenticate user
*/
+
+typedef struct Authctxt Authctxt;
+typedef struct Authmethod Authmethod;
+
+typedef int sign_cb_fn(
+ Authctxt *authctxt, Key *key,
+ unsigned char **sigp, int *lenp, unsigned char *data, int datalen);
+
+struct Authctxt {
+ const char *server_user;
+ const char *host;
+ const char *service;
+ AuthenticationConnection *agent;
+ Authmethod *method;
+ int success;
+};
+struct Authmethod {
+ char *name; /* string to compare against server's list */
+ int (*userauth)(Authctxt *authctxt);
+ int *enabled; /* flag in option struct that enables method */
+ int *batch_flag; /* flag in option struct that disables method */
+};
+
+void input_userauth_success(int type, int plen, void *ctxt);
+void input_userauth_failure(int type, int plen, void *ctxt);
+void input_userauth_error(int type, int plen, void *ctxt);
+void input_userauth_info_req(int type, int plen, void *ctxt);
+
+int userauth_none(Authctxt *authctxt);
+int userauth_pubkey(Authctxt *authctxt);
+int userauth_passwd(Authctxt *authctxt);
+int userauth_kbdint(Authctxt *authctxt);
+
+void authmethod_clear();
+Authmethod *authmethod_get(char *authlist);
+Authmethod *authmethod_lookup(const char *name);
+
+Authmethod authmethods[] = {
+ {"publickey",
+ userauth_pubkey,
+ &options.dsa_authentication,
+ NULL},
+ {"password",
+ userauth_passwd,
+ &options.password_authentication,
+ &options.batch_mode},
+ {"keyboard-interactive",
+ userauth_kbdint,
+ &options.kbd_interactive_authentication,
+ &options.batch_mode},
+ {"none",
+ userauth_none,
+ NULL,
+ NULL},
+ {NULL, NULL, NULL, NULL}
+};
+
+void
+ssh_userauth2(const char *server_user, char *host)
+{
+ Authctxt authctxt;
+ int type;
+ int plen;
+
+ debug("send SSH2_MSG_SERVICE_REQUEST");
+ packet_start(SSH2_MSG_SERVICE_REQUEST);
+ packet_put_cstring("ssh-userauth");
+ packet_send();
+ packet_write_wait();
+ type = packet_read(&plen);
+ if (type != SSH2_MSG_SERVICE_ACCEPT) {
+ fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
+ }
+ if (packet_remaining() > 0) {
+ char *reply = packet_get_string(&plen);
+ debug("service_accept: %s", reply);
+ xfree(reply);
+ packet_done();
+ } else {
+ debug("buggy server: service_accept w/o service");
+ }
+ packet_done();
+ debug("got SSH2_MSG_SERVICE_ACCEPT");
+
+ /* setup authentication context */
+ authctxt.agent = ssh_get_authentication_connection();
+ authctxt.server_user = server_user;
+ authctxt.host = host;
+ authctxt.service = "ssh-connection"; /* service name */
+ authctxt.success = 0;
+ authctxt.method = authmethod_lookup("none");
+ if (authctxt.method == NULL)
+ fatal("ssh_userauth2: internal error: cannot send userauth none request");
+ authmethod_clear();
+
+ /* initial userauth request */
+ userauth_none(&authctxt);
+
+ dispatch_init(&input_userauth_error);
+ dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
+ dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
+ dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
+
+ if (authctxt.agent != NULL)
+ ssh_close_authentication_connection(authctxt.agent);
+
+ debug("ssh-userauth2 successfull: method %s", authctxt.method->name);
+}
+void
+input_userauth_error(int type, int plen, void *ctxt)
+{
+ fatal("input_userauth_error: bad message during authentication");
+}
+void
+input_userauth_success(int type, int plen, void *ctxt)
+{
+ Authctxt *authctxt = ctxt;
+ if (authctxt == NULL)
+ fatal("input_userauth_success: no authentication context");
+ authctxt->success = 1; /* break out */
+}
+void
+input_userauth_failure(int type, int plen, void *ctxt)
+{
+ Authmethod *method = NULL;
+ Authctxt *authctxt = ctxt;
+ char *authlist = NULL;
+ int partial;
+
+ if (authctxt == NULL)
+ fatal("input_userauth_failure: no authentication context");
+
+ authlist = packet_get_string(NULL);
+ partial = packet_get_char();
+ packet_done();
+
+ if (partial != 0)
+ debug("partial success");
+ debug("authentications that can continue: %s", authlist);
+
+ for (;;) {
+ method = authmethod_get(authlist);
+ if (method == NULL)
+ fatal("Unable to find an authentication method");
+ authctxt->method = method;
+ if (method->userauth(authctxt) != 0) {
+ debug2("we sent a %s packet, wait for reply", method->name);
+ break;
+ } else {
+ debug2("we did not send a packet, disable method");
+ method->enabled = NULL;
+ }
+ }
+ xfree(authlist);
+}
+
+int
+userauth_none(Authctxt *authctxt)
+{
+ /* initial userauth request */
+ packet_start(SSH2_MSG_USERAUTH_REQUEST);
+ packet_put_cstring(authctxt->server_user);
+ packet_put_cstring(authctxt->service);
+ packet_put_cstring(authctxt->method->name);
+ packet_send();
+ packet_write_wait();
+ return 1;
+}
+
int
-ssh2_try_passwd(const char *server_user, const char *host, const char *service)
+userauth_passwd(Authctxt *authctxt)
{
static int attempt = 0;
char prompt[80];
@@ -267,12 +628,12 @@ ssh2_try_passwd(const char *server_user, const char *host, const char *service)
error("Permission denied, please try again.");
snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
- server_user, host);
+ authctxt->server_user, authctxt->host);
password = read_passphrase(prompt, 0);
packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_cstring(server_user);
- packet_put_cstring(service);
- packet_put_cstring("password");
+ packet_put_cstring(authctxt->server_user);
+ packet_put_cstring(authctxt->service);
+ packet_put_cstring(authctxt->method->name);
packet_put_char(0);
packet_put_cstring(password);
memset(password, 0, strlen(password));
@@ -282,45 +643,40 @@ ssh2_try_passwd(const char *server_user, const char *host, const char *service)
return 1;
}
-typedef int sign_fn(
- Key *key,
- unsigned char **sigp, int *lenp,
- unsigned char *data, int datalen);
-
int
-ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
- const char *server_user, const char *host, const char *service)
+sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
{
Buffer b;
unsigned char *blob, *signature;
int bloblen, slen;
int skip = 0;
int ret = -1;
+ int have_sig = 1;
dsa_make_key_blob(k, &blob, &bloblen);
/* data to be signed */
buffer_init(&b);
- if (datafellows & SSH_COMPAT_SESSIONID_ENCODING) {
- buffer_put_string(&b, session_id2, session_id2_len);
- skip = buffer_len(&b);
- } else {
+ if (datafellows & SSH_OLD_SESSIONID) {
buffer_append(&b, session_id2, session_id2_len);
skip = session_id2_len;
+ } else {
+ buffer_put_string(&b, session_id2, session_id2_len);
+ skip = buffer_len(&b);
}
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, server_user);
+ buffer_put_cstring(&b, authctxt->server_user);
buffer_put_cstring(&b,
datafellows & SSH_BUG_PUBKEYAUTH ?
"ssh-userauth" :
- service);
- buffer_put_cstring(&b, "publickey");
- buffer_put_char(&b, 1);
+ authctxt->service);
+ buffer_put_cstring(&b, authctxt->method->name);
+ buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_string(&b, blob, bloblen);
/* generate signature */
- ret = do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
+ ret = (*sign_callback)(authctxt, k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
if (ret == -1) {
xfree(blob);
buffer_free(&b);
@@ -333,10 +689,10 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
buffer_clear(&b);
buffer_append(&b, session_id2, session_id2_len);
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, server_user);
- buffer_put_cstring(&b, service);
- buffer_put_cstring(&b, "publickey");
- buffer_put_char(&b, 1);
+ buffer_put_cstring(&b, authctxt->server_user);
+ buffer_put_cstring(&b, authctxt->service);
+ buffer_put_cstring(&b, authctxt->method->name);
+ buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_string(&b, blob, bloblen);
}
@@ -347,7 +703,7 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
/* skip session id and packet type */
if (buffer_len(&b) < skip + 1)
- fatal("ssh2_try_pubkey: internal error");
+ fatal("userauth_pubkey: internal error");
buffer_consume(&b, skip + 1);
/* put remaining data from buffer into packet */
@@ -362,12 +718,18 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
return 1;
}
+/* sign callback */
+int dsa_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp,
+ unsigned char *data, int datalen)
+{
+ return dsa_sign(key, sigp, lenp, data, datalen);
+}
+
int
-ssh2_try_pubkey(char *filename,
- const char *server_user, const char *host, const char *service)
+userauth_pubkey_identity(Authctxt *authctxt, char *filename)
{
Key *k;
- int ret = 0;
+ int i, ret, try_next;
struct stat st;
if (stat(filename, &st) != 0) {
@@ -382,39 +744,42 @@ ssh2_try_pubkey(char *filename,
char *passphrase;
char prompt[300];
snprintf(prompt, sizeof prompt,
- "Enter passphrase for DSA key '%.100s': ",
- filename);
- passphrase = read_passphrase(prompt, 0);
- success = load_private_key(filename, passphrase, k, NULL);
- memset(passphrase, 0, strlen(passphrase));
- xfree(passphrase);
+ "Enter passphrase for %s key '%.100s': ",
+ key_type(k), filename);
+ for (i = 0; i < options.number_of_password_prompts; i++) {
+ passphrase = read_passphrase(prompt, 0);
+ if (strcmp(passphrase, "") != 0) {
+ success = load_private_key(filename, passphrase, k, NULL);
+ try_next = 0;
+ } else {
+ debug2("no passphrase given, try next key");
+ try_next = 1;
+ }
+ memset(passphrase, 0, strlen(passphrase));
+ xfree(passphrase);
+ if (success || try_next)
+ break;
+ debug2("bad passphrase given, try again...");
+ }
if (!success) {
key_free(k);
return 0;
}
}
- ret = ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service);
+ ret = sign_and_send_pubkey(authctxt, k, dsa_sign_cb);
key_free(k);
return ret;
}
-int agent_sign(
- Key *key,
- unsigned char **sigp, int *lenp,
+/* sign callback */
+int agent_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp,
unsigned char *data, int datalen)
{
- int ret = -1;
- AuthenticationConnection *ac = ssh_get_authentication_connection();
- if (ac != NULL) {
- ret = ssh_agent_sign(ac, key, sigp, lenp, data, datalen);
- ssh_close_authentication_connection(ac);
- }
- return ret;
+ return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen);
}
int
-ssh2_try_agent(AuthenticationConnection *ac,
- const char *server_user, const char *host, const char *service)
+userauth_pubkey_agent(Authctxt *authctxt)
{
static int called = 0;
char *comment;
@@ -422,104 +787,243 @@ ssh2_try_agent(AuthenticationConnection *ac,
int ret;
if (called == 0) {
- k = ssh_get_first_identity(ac, &comment, 2);
- called ++;
+ k = ssh_get_first_identity(authctxt->agent, &comment, 2);
+ called = 1;
} else {
- k = ssh_get_next_identity(ac, &comment, 2);
+ k = ssh_get_next_identity(authctxt->agent, &comment, 2);
}
- if (k == NULL)
+ if (k == NULL) {
+ debug2("no more DSA keys from agent");
return 0;
+ }
debug("trying DSA agent key %s", comment);
xfree(comment);
- ret = ssh2_sign_and_send_pubkey(k, agent_sign, server_user, host, service);
+ ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb);
key_free(k);
return ret;
}
-void
-ssh_userauth2(const char *server_user, char *host)
+int
+userauth_pubkey(Authctxt *authctxt)
{
- AuthenticationConnection *ac = ssh_get_authentication_connection();
- int type;
- int plen;
- int sent;
- unsigned int dlen;
- int partial;
- int i = 0;
- char *auths;
- char *service = "ssh-connection"; /* service name */
+ static int idx = 0;
+ int sent = 0;
- debug("send SSH2_MSG_SERVICE_REQUEST");
- packet_start(SSH2_MSG_SERVICE_REQUEST);
- packet_put_cstring("ssh-userauth");
+ if (authctxt->agent != NULL)
+ sent = userauth_pubkey_agent(authctxt);
+ while (sent == 0 && idx < options.num_identity_files2)
+ sent = userauth_pubkey_identity(authctxt, options.identity_files2[idx++]);
+ return sent;
+}
+
+/*
+ * Send userauth request message specifying keyboard-interactive method.
+ */
+int
+userauth_kbdint(Authctxt *authctxt)
+{
+ static int attempt = 0;
+
+ if (attempt++ >= options.number_of_password_prompts)
+ return 0;
+
+ debug2("userauth_kbdint");
+ packet_start(SSH2_MSG_USERAUTH_REQUEST);
+ packet_put_cstring(authctxt->server_user);
+ packet_put_cstring(authctxt->service);
+ packet_put_cstring(authctxt->method->name);
+ packet_put_cstring(""); /* lang */
+ packet_put_cstring(options.kbd_interactive_devices ?
+ options.kbd_interactive_devices : "");
packet_send();
packet_write_wait();
- type = packet_read(&plen);
- if (type != SSH2_MSG_SERVICE_ACCEPT) {
- fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
- }
- if (packet_remaining() > 0) {
- char *reply = packet_get_string(&plen);
- debug("service_accept: %s", reply);
- xfree(reply);
- } else {
- /* payload empty for ssh-2.0.13 ?? */
- debug("buggy server: service_accept w/o service");
+ dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
+ return 1;
+}
+
+/*
+ * parse SSH2_MSG_USERAUTH_INFO_REQUEST, prompt user and send
+ * SSH2_MSG_USERAUTH_INFO_RESPONSE
+ */
+void
+input_userauth_info_req(int type, int plen, void *ctxt)
+{
+ Authctxt *authctxt = ctxt;
+ char *name = NULL;
+ char *inst = NULL;
+ char *lang = NULL;
+ char *prompt = NULL;
+ char *response = NULL;
+ unsigned int num_prompts, i;
+ int echo = 0;
+
+ debug2("input_userauth_info_req");
+
+ if (authctxt == NULL)
+ fatal("input_userauth_info_req: no authentication context");
+
+ name = packet_get_string(NULL);
+ inst = packet_get_string(NULL);
+ lang = packet_get_string(NULL);
+
+ if (strlen(name) > 0)
+ cli_mesg(name);
+ xfree(name);
+
+ if (strlen(inst) > 0)
+ cli_mesg(inst);
+ xfree(inst);
+ xfree(lang); /* unused */
+
+ num_prompts = packet_get_int();
+ /*
+ * Begin to build info response packet based on prompts requested.
+ * We commit to providing the correct number of responses, so if
+ * further on we run into a problem that prevents this, we have to
+ * be sure and clean this up and send a correct error response.
+ */
+ packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
+ packet_put_int(num_prompts);
+
+ for (i = 0; i < num_prompts; i++) {
+ prompt = packet_get_string(NULL);
+ echo = packet_get_char();
+
+ response = cli_prompt(prompt, echo);
+
+ packet_put_cstring(response);
+ memset(response, 0, strlen(response));
+ xfree(response);
+ xfree(prompt);
}
- packet_done();
- debug("got SSH2_MSG_SERVICE_ACCEPT");
+ packet_done(); /* done with parsing incoming message. */
- /* INITIAL request for auth */
- packet_start(SSH2_MSG_USERAUTH_REQUEST);
- packet_put_cstring(server_user);
- packet_put_cstring(service);
- packet_put_cstring("none");
packet_send();
packet_write_wait();
+}
- for (;;) {
- sent = 0;
- type = packet_read(&plen);
- if (type == SSH2_MSG_USERAUTH_SUCCESS)
+/* find auth method */
+
+#define DELIM ","
+
+static char *def_authlist = "publickey,password";
+static char *authlist_current = NULL; /* clean copy used for comparison */
+static char *authname_current = NULL; /* last used auth method */
+static char *authlist_working = NULL; /* copy that gets modified by strtok_r() */
+static char *authlist_state = NULL; /* state variable for strtok_r() */
+
+/*
+ * Before starting to use a new authentication method list sent by the
+ * server, reset internal variables. This should also be called when
+ * finished processing server list to free resources.
+ */
+void
+authmethod_clear()
+{
+ if (authlist_current != NULL) {
+ xfree(authlist_current);
+ authlist_current = NULL;
+ }
+ if (authlist_working != NULL) {
+ xfree(authlist_working);
+ authlist_working = NULL;
+ }
+ if (authname_current != NULL) {
+ xfree(authname_current);
+ authlist_state = NULL;
+ }
+ if (authlist_state != NULL)
+ authlist_state = NULL;
+ return;
+}
+
+/*
+ * given auth method name, if configurable options permit this method fill
+ * in auth_ident field and return true, otherwise return false.
+ */
+int
+authmethod_is_enabled(Authmethod *method)
+{
+ if (method == NULL)
+ return 0;
+ /* return false if options indicate this method is disabled */
+ if (method->enabled == NULL || *method->enabled == 0)
+ return 0;
+ /* return false if batch mode is enabled but method needs interactive mode */
+ if (method->batch_flag != NULL && *method->batch_flag != 0)
+ return 0;
+ return 1;
+}
+
+Authmethod *
+authmethod_lookup(const char *name)
+{
+ Authmethod *method = NULL;
+ if (name != NULL)
+ for (method = authmethods; method->name != NULL; method++)
+ if (strcmp(name, method->name) == 0)
+ return method;
+ debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
+ return NULL;
+}
+
+/*
+ * Given the authentication method list sent by the server, return the
+ * next method we should try. If the server initially sends a nil list,
+ * use a built-in default list. If the server sends a nil list after
+ * previously sending a valid list, continue using the list originally
+ * sent.
+ */
+
+Authmethod *
+authmethod_get(char *authlist)
+{
+ char *name = NULL, *authname_old;
+ Authmethod *method = NULL;
+
+ /* Use a suitable default if we're passed a nil list. */
+ if (authlist == NULL || strlen(authlist) == 0)
+ authlist = def_authlist;
+
+ if (authlist_current == NULL || strcmp(authlist, authlist_current) != 0) {
+ /* start over if passed a different list */
+ debug3("start over, passed a different list");
+ authmethod_clear();
+ authlist_current = xstrdup(authlist);
+ authlist_working = xstrdup(authlist);
+ name = strtok_r(authlist_working, DELIM, &authlist_state);
+ } else {
+ /*
+ * try to use previously used authentication method
+ * or continue to use previously passed list
+ */
+ name = (authname_current != NULL) ?
+ authname_current : strtok_r(NULL, DELIM, &authlist_state);
+ }
+
+ while (name != NULL) {
+ debug3("authmethod_lookup %s", name);
+ method = authmethod_lookup(name);
+ if (method != NULL && authmethod_is_enabled(method)) {
+ debug3("authmethod_is_enabled %s", name);
break;
- if (type != SSH2_MSG_USERAUTH_FAILURE)
- fatal("access denied: %d", type);
- /* SSH2_MSG_USERAUTH_FAILURE means: try again */
- auths = packet_get_string(&dlen);
- debug("authentications that can continue: %s", auths);
- partial = packet_get_char();
- packet_done();
- if (partial)
- debug("partial success");
- if (options.dsa_authentication &&
- strstr(auths, "publickey") != NULL) {
- if (ac != NULL)
- sent = ssh2_try_agent(ac,
- server_user, host, service);
- if (!sent) {
- while (i < options.num_identity_files2) {
- sent = ssh2_try_pubkey(
- options.identity_files2[i++],
- server_user, host, service);
- if (sent)
- break;
- }
- }
- }
- if (!sent) {
- if (options.password_authentication &&
- !options.batch_mode &&
- strstr(auths, "password") != NULL) {
- sent = ssh2_try_passwd(server_user, host, service);
- }
}
- if (!sent)
- fatal("Permission denied (%s).", auths);
- xfree(auths);
+ name = strtok_r(NULL, DELIM, &authlist_state);
+ method = NULL;
}
- if (ac != NULL)
- ssh_close_authentication_connection(ac);
- packet_done();
- debug("ssh-userauth2 successfull");
+
+ authname_old = authname_current;
+ if (method != NULL) {
+ debug("next auth method to try is %s", name);
+ authname_current = xstrdup(name);
+ } else {
+ debug("no more auth methods to try");
+ authname_current = NULL;
+ }
+
+ if (authname_old != NULL)
+ xfree(authname_old);
+
+ return (method);
}
diff --git a/crypto/openssh/sshd/Makefile b/crypto/openssh/sshd/Makefile
index 0adfcd6..0a9fba8 100644
--- a/crypto/openssh/sshd/Makefile
+++ b/crypto/openssh/sshd/Makefile
@@ -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>
diff --git a/crypto/openssh/util.c b/crypto/openssh/util.c
index 71808f1..1a591a6 100644
--- a/crypto/openssh/util.c
+++ b/crypto/openssh/util.c
@@ -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)
diff --git a/crypto/openssh/version.h b/crypto/openssh/version.h
index bfd4327..ea78e8c 100644
--- a/crypto/openssh/version.h
+++ b/crypto/openssh/version.h
@@ -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"
OpenPOWER on IntegriCloud