summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.hgsigs2
-rw-r--r--.hgtags2
-rw-r--r--CHANGES59
-rw-r--r--Makefile.in6
-rw-r--r--algo.h16
-rw-r--r--auth.h2
-rw-r--r--bignum.h3
-rw-r--r--buffer.c4
-rw-r--r--cli-algo.c99
-rw-r--r--cli-auth.c57
-rw-r--r--cli-chansession.c4
-rw-r--r--cli-kex.c48
-rw-r--r--cli-main.c3
-rw-r--r--cli-runopts.c37
-rw-r--r--cli-service.c85
-rw-r--r--cli-session.c92
-rw-r--r--common-algo.c120
-rw-r--r--common-channel.c12
-rw-r--r--common-kex.c181
-rw-r--r--common-session.c41
-rw-r--r--config.guess557
-rw-r--r--config.sub368
-rw-r--r--configure.ac4
-rw-r--r--dbclient.121
-rw-r--r--dbutil.c32
-rw-r--r--dbutil.h9
-rw-r--r--debian/changelog12
-rw-r--r--debug.h7
-rw-r--r--dss.c6
-rw-r--r--ecdsa.c4
-rw-r--r--includes.h4
-rw-r--r--kex.h8
-rw-r--r--loginrec.c2
-rw-r--r--options.h11
-rw-r--r--packet.c124
-rw-r--r--process-packet.c19
-rw-r--r--queue.c2
-rw-r--r--queue.h2
-rw-r--r--random.c3
-rw-r--r--rsa.c6
-rw-r--r--runopts.h1
-rw-r--r--scp.c2
-rw-r--r--service.h2
-rw-r--r--session.h32
-rw-r--r--signkey.c18
-rw-r--r--svr-algo.c100
-rw-r--r--svr-auth.c13
-rw-r--r--svr-authpasswd.c8
-rw-r--r--svr-kex.c3
-rw-r--r--svr-session.c16
-rw-r--r--sysoptions.h11
-rw-r--r--termcodes.c8
52 files changed, 1332 insertions, 956 deletions
diff --git a/.hgsigs b/.hgsigs
index 5dcb50e..5c5eb40 100644
--- a/.hgsigs
+++ b/.hgsigs
@@ -2,3 +2,5 @@ aa2f51a6b81d33de5e9898a7f27c792a173d9b26 0 iD8DBQBOuADmjPn4sExkf7wRAv/fAJ9FJFvjD
3f12086c2ef2b9ffe36a822fdb3ff647fcec1831 0 iD8DBQBOuSlQjPn4sExkf7wRAvkbAKCgE1e8xEMQ16CGeoywhIQ0QR4eNgCfZdYYlzjb/+521Uvh5/7FRYEmrho=
85f835f2fe0ac2c503c50a414de127222fb0a57c 0 iD8DBQBPRkMUjPn4sExkf7wRAvM4AJ9mw2OAkyjhSbamM1MizlEJUX18HACgoFKQkYf6BnYxN34Nv2HhM0cmzUc=
9b80981212fe6c01b7c16b3ca7c4e66af56f12f1 0 iEYEABECAAYFAlFLKKcACgkQjPn4sExkf7xK7wCfcioCmJPsysSbQO6+4qZMVe0mmLwAn2/o+wRf4MrUXlohrr7aXEF9vdSB
+095b46180bbc412b029420587736a6185afc17e1 0 iEYEABECAAYFAlFsCnkACgkQjPn4sExkf7xLrwCfeMWjUaSmfU/fvseT5TdrYRqBEVQAoLz5SFLEA40C5f8zE8Ma/vgVJVIC
+f168962bab857ca030829e4cd73d9b32c868c874 0 iEYEABECAAYFAlFwDNwACgkQjPn4sExkf7wJ6QCePVovn/avKXUyNwNBYCcov6JLYqkAnRCPQdkXgv20N3t10r6PRMBBo1/S
diff --git a/.hgtags b/.hgtags
index 71a20fe..d3e2f04 100644
--- a/.hgtags
+++ b/.hgtags
@@ -36,3 +36,5 @@ d354464b2aa6f6ba0bf44d43bcae5aa798435393 DROPBEAR_2012.55
d7da3b1e15401eb234ec866d5eac992fc4cd5878 t:ltc-0.95-db-merge1
0000000000000000000000000000000000000000 t:ltc-0.95-db-merge1
1b8b2b9d6e94bc3cc5e61b620476ea36cc466e1b DROPBEAR_2013.56
+96b8bcb88017815040949a417caa55686271e8a9 DROPBEAR_2013.57
+e76614145aea67f66e4a4257685c771efba21aa1 DROPBEAR_2013.58
diff --git a/CHANGES b/CHANGES
index d21dc99..65d237b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,54 @@
+2013.58 - Thursday 18 April 2013
+
+- Fix building with Zlib disabled, thanks to Hans Harder and cuma@freetz
+
+- Use % as a separator for ports, fixes scp in multihop mode, from Hans Harder
+
+- Reject logins for other users when running as non-root, from Hans Harder
+
+- Disable client immediate authentication request by default, it prevents
+ passwordless logins from working
+
+2013.57 - Monday 15 April 2013
+
+- Decreased connection setup time particularly with high latency connections,
+ the number of round trips has been reduced for both client and server.
+ CPU time hasn't been changed.
+
+- Client will send an initial key exchange guess to save a round trip.
+ Dropbear implements an extension kexguess2@matt.ucc.asn.au to allow the first
+ packet guess to succeed in wider circumstances than the standard behaviour.
+ When communicating with other implementations the standard behaviour is used.
+
+- Client side: when public key or password authentication with
+ $DROPBEAR_PASSWORD is used an initial authentication request will
+ be sent immediately rather than querying the list of available methods.
+ This behaviour is enabled by CLI_IMMEDIATE_AUTH option (on by default),
+ please let the Dropbear author know if it causes any interoperability
+ problems.
+
+- Implement client escape characters ~. (terminate session) and
+ ~^Z (background session)
+
+- Server will more reliably clean up utmp when connection is closed, reported by
+ Mattias Walström
+
+- Don't crash if /dev/urandom isn't writable (RHEL5), thanks to Scott Case
+
+- Add "-y -y" client option to skip host key checking, thanks to Hans Harder
+
+- scp didn't work properly on systems using vfork(), thanks to Frank Van Uffelen
+
+- Added IUTF8 terminal mode support (Linux and Mac OS). Not standardised yet
+though probably will be soon
+
+- Some verbose DROPBEAR_TRACE output is now hidden unless $DROPBEAR_TRACE2
+ enviroment variable is set
+
+- Fix using asymmetric MAC algorithms (broke in )
+
+- Renamed configure.in to configure.ac to quieten autoconf, from Mike Frysinger
+
2013.56 - Thursday 21 March 2013
- Allow specifying cipher (-c) and MAC (-m) lists for dbclient
@@ -20,10 +71,10 @@
- Allow using IPv6 bracket notation for addresses in server "-p" option, from Ben Jencks
-- A few improvements for Android from Reimar Döffinger
+- A few improvements for Android from Reimar Döffinger
- Fix memory leak for TCP forwarded connections to hosts that timed out,
- reported by Norbert Benczúr. Appears to be a very long-standing bug.
+ reported by Norbert Benczúr. Appears to be a very long-standing bug.
- Fix "make clean" for out of tree builds
@@ -649,7 +700,7 @@ https://secure.ucc.asn.au/hg/dropbear/graph/default
Lobenstock and Mihnea Stoenescu
- Use daemon() function if available (or our own copy) rather than separate
- code (thanks to Frédéric Lavernhe for the report and debugging, and Bernard
+ code (thanks to Frédéric Lavernhe for the report and debugging, and Bernard
Blackham for his suggestion on what to look at)
- Fixed up support for first_kex_packet_follows, required to talk to ssh.com
@@ -768,7 +819,7 @@ https://secure.ucc.asn.au/hg/dropbear/graph/default
- Various signedness fixes
- Can listen on multiple ports
- added option to disable openpty with configure script,
- (from K.-P. Kirchdörfer <kapeka at epost.de>)
+ (from K.-P. Kirchdörfer <kapeka at epost.de>)
- Various cleanups to bignum code
(thanks to Tom St Denis <tomstdenis at iahu.ca>)
- Fix compile error when disabling RSA
diff --git a/Makefile.in b/Makefile.in
index 13d8e83..8d8d279 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -29,13 +29,13 @@ COMMONOBJS=dbutil.o buffer.o \
atomicio.o compat.o fake-rfc2553.o \
ltc_prng.o ecc.o ecdsa.o crypto_desc.o
-SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \
+SVROBJS=svr-kex.o svr-auth.o sshpty.o \
svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o\
svr-tcpfwd.o svr-authpam.o
-CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
- cli-session.o cli-service.o cli-runopts.o cli-chansession.o \
+CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
+ cli-session.o cli-runopts.o cli-chansession.o \
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \
cli-agentfwd.o list.o
diff --git a/algo.h b/algo.h
index 8c41eac..dbbafd0 100644
--- a/algo.h
+++ b/algo.h
@@ -98,10 +98,18 @@ struct dropbear_kex {
int have_algo(char* algo, size_t algolen, algo_type algos[]);
void buf_put_algolist(buffer * buf, algo_type localalgos[]);
-algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[],
- int *goodguess);
-algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
- int *goodguess);
+enum kexguess2_used {
+ KEXGUESS2_LOOK,
+ KEXGUESS2_NO,
+ KEXGUESS2_YES,
+};
+
+#define KEXGUESS2_ALGO_NAME "kexguess2@matt.ucc.asn.au"
+#define KEXGUESS2_ALGO_ID 99
+
+
+algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
+ enum kexguess2_used *kexguess2, int *goodguess);
#ifdef ENABLE_USER_ALGO_LIST
int check_user_algos(const char* user_algo_list, algo_type * algos,
diff --git a/auth.h b/auth.h
index 0fd9c73..df6634e 100644
--- a/auth.h
+++ b/auth.h
@@ -67,7 +67,7 @@ void recv_msg_userauth_pk_ok();
void recv_msg_userauth_info_request();
void cli_get_user();
void cli_auth_getmethods();
-void cli_auth_try();
+int cli_auth_try();
void recv_msg_userauth_banner();
void cli_pubkeyfail();
void cli_auth_password();
diff --git a/bignum.h b/bignum.h
index f7abc7d..11353c6 100644
--- a/bignum.h
+++ b/bignum.h
@@ -26,9 +26,10 @@
#define _BIGNUM_H_
#include "includes.h"
+#include "dbutil.h"
void m_mp_init(mp_int *mp);
-void m_mp_init_multi(mp_int *mp, ...);
+void m_mp_init_multi(mp_int *mp, ...) ATTRIB_SENTINEL;
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len);
void hash_process_mp(const struct ltc_hash_descriptor *hash_desc,
hash_state *hs, mp_int *mp);
diff --git a/buffer.c b/buffer.c
index d25adab..9bda652 100644
--- a/buffer.c
+++ b/buffer.c
@@ -287,7 +287,7 @@ void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
void buf_putmpint(buffer* buf, mp_int * mp) {
unsigned int len, pad = 0;
- TRACE(("enter buf_putmpint"))
+ TRACE2(("enter buf_putmpint"))
dropbear_assert(mp != NULL);
@@ -323,7 +323,7 @@ void buf_putmpint(buffer* buf, mp_int * mp) {
buf_incrwritepos(buf, len-pad);
}
- TRACE(("leave buf_putmpint"))
+ TRACE2(("leave buf_putmpint"))
}
/* Retrieve an mp_int from the buffer.
diff --git a/cli-algo.c b/cli-algo.c
deleted file mode 100644
index 09da41a..0000000
--- a/cli-algo.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Dropbear - a SSH2 server
- * SSH client implementation
- *
- * Copyright (c) 2002,2003 Matt Johnston
- * Copyright (c) 2004 by Mihnea Stoenescu
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE. */
-
-#include "algo.h"
-#include "dbutil.h"
-
-
-/*
- * The chosen [encryption | MAC | compression] algorithm to each
- * direction MUST be the first algorithm on the client's list
- * that is also on the server's list.
- */
-algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
- int *goodguess) {
-
- unsigned char * algolist = NULL;
- unsigned char * remotealgos[MAX_PROPOSED_ALGO];
- unsigned int len;
- unsigned int count, i, j;
- algo_type * ret = NULL;
-
- *goodguess = 0;
-
- /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
- algolist = buf_getstring(buf, &len);
- TRACE(("cli_buf_match_algo: %s", algolist))
- if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
- goto out; /* just a sanity check, no other use */
- }
-
- /* remotealgos will contain a list of the strings parsed out */
- /* We will have at least one string (even if it's just "") */
- remotealgos[0] = algolist;
- count = 1;
- /* Iterate through, replacing ','s with NULs, to split it into
- * words. */
- for (i = 0; i < len; i++) {
- if (algolist[i] == '\0') {
- /* someone is trying something strange */
- goto out;
- }
- if (algolist[i] == ',') {
- algolist[i] = '\0';
- remotealgos[count] = &algolist[i+1];
- count++;
- }
- if (count >= MAX_PROPOSED_ALGO) {
- break;
- }
- }
-
- /* iterate and find the first match */
-
- for (j = 0; localalgos[j].name != NULL; j++) {
- if (localalgos[j].usable) {
- len = strlen(localalgos[j].name);
- for (i = 0; i < count; i++) {
- if (len == strlen(remotealgos[i])
- && strncmp(localalgos[j].name,
- remotealgos[i], len) == 0) {
- if (i == 0 && j == 0) {
- /* was a good guess */
- *goodguess = 1;
- }
- ret = &localalgos[j];
- goto out;
- }
- }
- }
- }
-
-out:
- m_free(algolist);
- return ret;
-}
-
diff --git a/cli-auth.c b/cli-auth.c
index 321cbf3..efa9e9b 100644
--- a/cli-auth.c
+++ b/cli-auth.c
@@ -40,11 +40,18 @@ void cli_authinitialise() {
/* Send a "none" auth request to get available methods */
void cli_auth_getmethods() {
-
TRACE(("enter cli_auth_getmethods"))
-
+#ifdef CLI_IMMEDIATE_AUTH
+ ses.authstate.authtypes = AUTH_TYPE_PUBKEY;
+ if (getenv(DROPBEAR_PASSWORD_ENV)) {
+ ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT;
+ }
+ if (cli_auth_try() == DROPBEAR_SUCCESS) {
+ TRACE(("skipped initial none auth query"))
+ return;
+ }
+#endif
CHECKCLEARTOWRITE();
-
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
buf_putstring(ses.writepayload, cli_opts.username,
strlen(cli_opts.username));
@@ -54,7 +61,6 @@ void cli_auth_getmethods() {
encrypt_packet();
TRACE(("leave cli_auth_getmethods"))
-
}
void recv_msg_userauth_banner() {
@@ -240,7 +246,7 @@ void recv_msg_userauth_success() {
#endif
}
-void cli_auth_try() {
+int cli_auth_try() {
int finished = 0;
TRACE(("enter cli_auth_try"))
@@ -256,37 +262,40 @@ void cli_auth_try() {
}
#endif
-#ifdef ENABLE_CLI_INTERACT_AUTH
- if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
- fprintf(stderr, "Sorry, I won't let you use interactive auth unencrypted.\n");
- } else if (!finished && ses.authstate.authtypes & AUTH_TYPE_INTERACT) {
- if (cli_ses.auth_interact_failed) {
- finished = 0;
+#ifdef ENABLE_CLI_PASSWORD_AUTH
+ if (!finished && (ses.authstate.authtypes & AUTH_TYPE_PASSWORD)) {
+ if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
+ fprintf(stderr, "Sorry, I won't let you use password auth unencrypted.\n");
} else {
- cli_auth_interactive();
- cli_ses.lastauthtype = AUTH_TYPE_INTERACT;
+ cli_auth_password();
finished = 1;
+ cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
}
}
#endif
-#ifdef ENABLE_CLI_PASSWORD_AUTH
- if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
- fprintf(stderr, "Sorry, I won't let you use password auth unencrypted.\n");
- } else if (!finished && ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
- cli_auth_password();
- finished = 1;
- cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
+#ifdef ENABLE_CLI_INTERACT_AUTH
+ if (!finished && (ses.authstate.authtypes & AUTH_TYPE_INTERACT)) {
+ if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
+ fprintf(stderr, "Sorry, I won't let you use interactive auth unencrypted.\n");
+ } else {
+ if (!cli_ses.auth_interact_failed) {
+ cli_auth_interactive();
+ cli_ses.lastauthtype = AUTH_TYPE_INTERACT;
+ finished = 1;
+ }
+ }
}
#endif
TRACE(("cli_auth_try lastauthtype %d", cli_ses.lastauthtype))
- if (!finished) {
- dropbear_exit("No auth methods could be used.");
+ if (finished) {
+ TRACE(("leave cli_auth_try success"))
+ return DROPBEAR_SUCCESS;
}
-
- TRACE(("leave cli_auth_try"))
+ TRACE(("leave cli_auth_try failure"))
+ return DROPBEAR_FAILURE;
}
/* A helper for getpass() that exits if the user cancels. The returned
diff --git a/cli-chansession.c b/cli-chansession.c
index d3b14bb..37aa13d 100644
--- a/cli-chansession.c
+++ b/cli-chansession.c
@@ -82,14 +82,12 @@ out:
/* If the main session goes, we close it up */
static void cli_closechansess(struct Channel *UNUSED(channel)) {
+ cli_tty_cleanup(); /* Restore tty modes etc */
/* This channel hasn't gone yet, so we have > 1 */
if (ses.chancount > 1) {
dropbear_log(LOG_INFO, "Waiting for other channels to close...");
}
-
- cli_tty_cleanup(); /* Restore tty modes etc */
-
}
void cli_start_send_channel_request(struct Channel *channel,
diff --git a/cli-kex.c b/cli-kex.c
index f1bf67c..0cc730c 100644
--- a/cli-kex.c
+++ b/cli-kex.c
@@ -43,19 +43,35 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen);
#define MAX_KNOWNHOSTS_LINE 4500
void send_msg_kexdh_init() {
+ TRACE(("send_msg_kexdh_init()"))
+
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
if (IS_NORMAL_DH(ses.newkeys->algo_kex)) {
- cli_ses.dh_param = gen_kexdh_param();
+ if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
+ || !cli_ses.dh_param) {
+ if (cli_ses.dh_param) {
+ free_kexdh_param(cli_ses.dh_param);
+ }
+ cli_ses.dh_param = gen_kexdh_param();
+ }
buf_putmpint(ses.writepayload, &cli_ses.dh_param->pub);
} else {
#ifdef DROPBEAR_ECDH
- cli_ses.ecdh_param = gen_kexecdh_param();
+ if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
+ || !cli_ses.ecdh_param) {
+ if (cli_ses.ecdh_param) {
+ free_kexecdh_param(cli_ses.ecdh_param);
+ }
+ cli_ses.ecdh_param = gen_kexecdh_param();
+ }
buf_put_ecc_raw_pubkey_string(ses.writepayload, &cli_ses.ecdh_param->key);
#endif
}
+ cli_ses.param_kex_algo = ses.newkeys->algo_kex;
encrypt_packet();
- ses.requirenext = SSH_MSG_KEXDH_REPLY;
+ ses.requirenext[0] = SSH_MSG_KEXDH_REPLY;
+ ses.requirenext[1] = SSH_MSG_KEXINIT;
}
/* Handle a diffie-hellman key exchange reply. */
@@ -105,11 +121,20 @@ void recv_msg_kexdh_reply() {
buf_free(ecdh_qs);
#endif
}
- free_kexdh_param(cli_ses.dh_param);
- cli_ses.dh_param = NULL;
- if (buf_verify(ses.payload, hostkey, ses.hash)
- != DROPBEAR_SUCCESS) {
+ if (cli_ses.dh_param) {
+ free_kexdh_param(cli_ses.dh_param);
+ cli_ses.dh_param = NULL;
+ }
+#ifdef DROPBEAR_ECDH
+ if (cli_ses.ecdh_param) {
+ free_kexecdh_param(cli_ses.ecdh_param);
+ cli_ses.ecdh_param = NULL;
+ }
+#endif
+
+ cli_ses.param_kex_algo = NULL;
+ if (buf_verify(ses.payload, hostkey, ses.hash) != DROPBEAR_SUCCESS) {
dropbear_exit("Bad hostkey signature");
}
@@ -117,7 +142,8 @@ void recv_msg_kexdh_reply() {
hostkey = NULL;
send_msg_newkeys();
- ses.requirenext = SSH_MSG_NEWKEYS;
+ ses.requirenext[0] = SSH_MSG_NEWKEYS;
+ ses.requirenext[1] = 0;
TRACE(("leave recv_msg_kexdh_init"))
}
@@ -226,6 +252,11 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
buffer * line = NULL;
int ret;
+ if (cli_opts.no_hostkey_check) {
+ fprintf(stderr, "Caution, skipping hostkey check for %s\n", cli_opts.remotehost);
+ return;
+ }
+
hostsfile = open_known_hosts_file(&readonly);
if (!hostsfile) {
ask_to_confirm(keyblob, keybloblen);
@@ -255,7 +286,6 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
/* Compare hostnames */
if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen),
hostlen) != 0) {
- TRACE(("hosts don't match"))
continue;
}
diff --git a/cli-main.c b/cli-main.c
index 2d4905e..3ebde8a 100644
--- a/cli-main.c
+++ b/cli-main.c
@@ -103,8 +103,7 @@ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
}
/* Do the cleanup first, since then the terminal will be reset */
- cli_session_cleanup();
- common_session_cleanup();
+ session_cleanup();
_dropbear_log(LOG_INFO, fmtbuf, param);
diff --git a/cli-runopts.c b/cli-runopts.c
index 5ddcc21..91a2f42 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -62,6 +62,7 @@ static void printhelp() {
"-N Don't run a remote command\n"
"-f Run in background after auth\n"
"-y Always accept remote host key if unknown\n"
+ "-y -y Don't perform any remote host key checking (caution)\n"
"-s Request a subsystem (use by external sftp)\n"
#ifdef ENABLE_CLI_PUBKEY_AUTH
"-i <identityfile> (multiple allowed)\n"
@@ -130,6 +131,7 @@ void cli_getopts(int argc, char ** argv) {
cli_opts.backgrounded = 0;
cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
cli_opts.always_accept_key = 0;
+ cli_opts.no_hostkey_check = 0;
cli_opts.is_subsystem = 0;
#ifdef ENABLE_CLI_PUBKEY_AUTH
cli_opts.privkeys = list_new();
@@ -213,6 +215,10 @@ void cli_getopts(int argc, char ** argv) {
switch (argv[i][1]) {
case 'y': /* always accept the remote hostkey */
+ if (cli_opts.always_accept_key) {
+ // twice means no checking at all
+ cli_opts.no_hostkey_check = 1;
+ }
cli_opts.always_accept_key = 1;
break;
case 'p': /* remoteport */
@@ -461,20 +467,31 @@ multihop_passthrough_args() {
int total;
unsigned int len = 0;
m_list_elem *iter;
- /* Fill out -i and -W options that make sense for all
+ /* Fill out -i, -y, -W options that make sense for all
* the intermediate processes */
for (iter = cli_opts.privkeys->first; iter; iter = iter->next)
{
sign_key * key = (sign_key*)iter->item;
len += 3 + strlen(key->filename);
}
- len += 20; // space for -W <size>, terminator.
+ len += 30; // space for -W <size>, terminator.
ret = m_malloc(len);
total = 0;
+ if (cli_opts.no_hostkey_check)
+ {
+ int written = snprintf(ret+total, len-total, "-y -y ");
+ total += written;
+ }
+ else if (cli_opts.always_accept_key)
+ {
+ int written = snprintf(ret+total, len-total, "-y ");
+ total += written;
+ }
+
if (opts.recv_window != DEFAULT_RECV_WINDOW)
{
- int written = snprintf(ret+total, len-total, "-W %d", opts.recv_window);
+ int written = snprintf(ret+total, len-total, "-W %d ", opts.recv_window);
total += written;
}
@@ -482,11 +499,17 @@ multihop_passthrough_args() {
{
sign_key * key = (sign_key*)iter->item;
const size_t size = len - total;
- int written = snprintf(ret+total, size, "-i %s", key->filename);
+ int written = snprintf(ret+total, size, "-i %s ", key->filename);
dropbear_assert((unsigned int)written < size);
total += written;
}
+ /* if args were passed, total will be not zero, and it will have a space at the end, so remove that */
+ if (total > 0)
+ {
+ total--;
+ }
+
return ret;
}
@@ -587,7 +610,11 @@ static void parse_hostname(const char* orighostarg) {
cli_opts.username = m_strdup(cli_opts.own_user);
}
- port = strchr(cli_opts.remotehost, '/');
+ port = strchr(cli_opts.remotehost, '%');
+ if (!port) {
+ // legacy separator
+ port = strchr(cli_opts.remotehost, '/');
+ }
if (port) {
*port = '\0';
cli_opts.remoteport = port+1;
diff --git a/cli-service.c b/cli-service.c
deleted file mode 100644
index f763103..0000000
--- a/cli-service.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Dropbear SSH
- *
- * Copyright (c) 2002,2003 Matt Johnston
- * Copyright (c) 2004 by Mihnea Stoenescu
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE. */
-
-#include "includes.h"
-#include "service.h"
-#include "dbutil.h"
-#include "packet.h"
-#include "buffer.h"
-#include "session.h"
-#include "ssh.h"
-
-void send_msg_service_request(char* servicename) {
-
- TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
-
- CHECKCLEARTOWRITE();
-
- buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
- buf_putstring(ses.writepayload, servicename, strlen(servicename));
-
- encrypt_packet();
- TRACE(("leave send_msg_service_request"))
-}
-
-/* This just sets up the state variables right for the main client session loop
- * to deal with */
-void recv_msg_service_accept() {
-
- unsigned char* servicename;
- unsigned int len;
-
- TRACE(("enter recv_msg_service_accept"))
-
- servicename = buf_getstring(ses.payload, &len);
-
- /* ssh-userauth */
- if (cli_ses.state == SERVICE_AUTH_REQ_SENT
- && len == SSH_SERVICE_USERAUTH_LEN
- && strncmp(SSH_SERVICE_USERAUTH, servicename, len) == 0) {
-
- cli_ses.state = SERVICE_AUTH_ACCEPT_RCVD;
- m_free(servicename);
- TRACE(("leave recv_msg_service_accept: done ssh-userauth"))
- return;
- }
-
- /* ssh-connection */
- if (cli_ses.state == SERVICE_CONN_REQ_SENT
- && len == SSH_SERVICE_CONNECTION_LEN
- && strncmp(SSH_SERVICE_CONNECTION, servicename, len) == 0) {
-
- if (ses.authstate.authdone != 1) {
- dropbear_exit("Request for connection before auth");
- }
-
- cli_ses.state = SERVICE_CONN_ACCEPT_RCVD;
- m_free(servicename);
- TRACE(("leave recv_msg_service_accept: done ssh-connection"))
- return;
- }
-
- dropbear_exit("Unrecognised service accept");
-}
diff --git a/cli-session.c b/cli-session.c
index 55040af..e2eae26 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -42,6 +42,8 @@ static void cli_remoteclosed();
static void cli_sessionloop();
static void cli_session_init();
static void cli_finished();
+static void recv_msg_service_accept(void);
+static void cli_session_cleanup(void);
struct clientsession cli_ses; /* GLOBAL */
@@ -96,7 +98,7 @@ void cli_session(int sock_in, int sock_out) {
sessinitdone = 1;
/* Exchange identification */
- session_identification();
+ send_session_identification();
send_msg_kexinit();
@@ -106,6 +108,12 @@ void cli_session(int sock_in, int sock_out) {
}
+#ifdef USE_KEX_FIRST_FOLLOWS
+static void cli_send_kex_first_guess() {
+ send_msg_kexdh_init();
+}
+#endif
+
static void cli_session_init() {
cli_ses.state = STATE_NOTHING;
@@ -139,37 +147,61 @@ static void cli_session_init() {
/* For printing "remote host closed" for the user */
ses.remoteclosed = cli_remoteclosed;
- ses.buf_match_algo = cli_buf_match_algo;
+
+ ses.extra_session_cleanup = cli_session_cleanup;
/* packet handlers */
ses.packettypes = cli_packettypes;
ses.isserver = 0;
+
+#ifdef USE_KEX_FIRST_FOLLOWS
+ ses.send_kex_first_guess = cli_send_kex_first_guess;
+#endif
+
+}
+
+static void send_msg_service_request(char* servicename) {
+
+ TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
+
+ CHECKCLEARTOWRITE();
+
+ buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
+ buf_putstring(ses.writepayload, servicename, strlen(servicename));
+
+ encrypt_packet();
+ TRACE(("leave send_msg_service_request"))
+}
+
+static void recv_msg_service_accept(void) {
+ // do nothing, if it failed then the server MUST have disconnected
}
/* This function drives the progress of the session - it initiates KEX,
* service, userauth and channel requests */
static void cli_sessionloop() {
- TRACE(("enter cli_sessionloop"))
+ TRACE2(("enter cli_sessionloop"))
- if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
- cli_ses.kex_state = KEXINIT_RCVD;
+ if (ses.lastpacket == 0) {
+ TRACE2(("exit cli_sessionloop: no real packets yet"))
+ return;
}
- if (cli_ses.kex_state == KEXINIT_RCVD) {
-
+ if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
/* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT
* negotiation would have failed. */
- send_msg_kexdh_init();
- cli_ses.kex_state = KEXDH_INIT_SENT;
+ if (!ses.kexstate.our_first_follows_matches) {
+ send_msg_kexdh_init();
+ }
+ cli_ses.kex_state = KEXDH_INIT_SENT;
TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD"))
return;
}
/* A KEX has finished, so we should go back to our KEX_NOTHING state */
- if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.recvkexinit == 0
- && ses.kexstate.sentkexinit == 0) {
+ if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.sentnewkeys) {
cli_ses.kex_state = KEX_NOTHING;
}
@@ -179,10 +211,10 @@ static void cli_sessionloop() {
return;
}
- /* We should exit if we haven't donefirstkex: we shouldn't reach here
- * in normal operation */
if (ses.kexstate.donefirstkex == 0) {
- TRACE(("XXX XXX might be bad! leave cli_sessionloop: haven't donefirstkex"))
+ /* We might reach here if we have partial packet reads or have
+ * received SSG_MSG_IGNORE etc. Just skip it */
+ TRACE2(("donefirstkex false\n"))
return;
}
@@ -192,19 +224,15 @@ static void cli_sessionloop() {
/* We've got the transport layer sorted, we now need to request
* userauth */
send_msg_service_request(SSH_SERVICE_USERAUTH);
- cli_ses.state = SERVICE_AUTH_REQ_SENT;
- TRACE(("leave cli_sessionloop: sent userauth service req"))
- return;
-
- /* userauth code */
- case SERVICE_AUTH_ACCEPT_RCVD:
cli_auth_getmethods();
cli_ses.state = USERAUTH_REQ_SENT;
TRACE(("leave cli_sessionloop: sent userauth methods req"))
return;
case USERAUTH_FAIL_RCVD:
- cli_auth_try();
+ if (cli_auth_try() == DROPBEAR_FAILURE) {
+ dropbear_exit("No auth methods could be used.");
+ }
cli_ses.state = USERAUTH_REQ_SENT;
TRACE(("leave cli_sessionloop: cli_auth_try"))
return;
@@ -235,13 +263,6 @@ static void cli_sessionloop() {
}
}
-#ifdef ENABLE_CLI_LOCALTCPFWD
- setup_localtcp();
-#endif
-#ifdef ENABLE_CLI_REMOTETCPFWD
- setup_remotetcp();
-#endif
-
#ifdef ENABLE_CLI_NETCAT
if (cli_opts.netcat_host) {
cli_send_netcat_request();
@@ -250,6 +271,14 @@ static void cli_sessionloop() {
if (!cli_opts.no_cmd) {
cli_send_chansess_request();
}
+
+#ifdef ENABLE_CLI_LOCALTCPFWD
+ setup_localtcp();
+#endif
+#ifdef ENABLE_CLI_REMOTETCPFWD
+ setup_remotetcp();
+#endif
+
TRACE(("leave cli_sessionloop: running"))
cli_ses.state = SESSION_RUNNING;
return;
@@ -271,11 +300,11 @@ static void cli_sessionloop() {
break;
}
- TRACE(("leave cli_sessionloop: fell out"))
+ TRACE2(("leave cli_sessionloop: fell out"))
}
-void cli_session_cleanup() {
+static void cli_session_cleanup(void) {
if (!sessinitdone) {
return;
@@ -293,8 +322,7 @@ void cli_session_cleanup() {
static void cli_finished() {
- cli_session_cleanup();
- common_session_cleanup();
+ session_cleanup();
fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport);
exit(cli_ses.retval);
diff --git a/common-algo.c b/common-algo.c
index 5d5de01..a8d9669 100644
--- a/common-algo.c
+++ b/common-algo.c
@@ -25,6 +25,7 @@
#include "includes.h"
#include "algo.h"
+#include "session.h"
#include "dbutil.h"
#include "kex.h"
#include "ltc_prng.h"
@@ -257,6 +258,9 @@ algo_type sshkex[] = {
#endif
{"diffie-hellman-group1-sha1", 0, &kex_dh_group1, 1, NULL},
{"diffie-hellman-group14-sha1", 0, &kex_dh_group14, 1, NULL},
+#ifdef USE_KEXGUESS2
+ {KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL},
+#endif
{NULL, 0, NULL, 0, NULL}
};
@@ -299,6 +303,122 @@ void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
buf_free(algolist);
}
+/* match the first algorithm in the comma-separated list in buf which is
+ * also in localalgos[], or return NULL on failure.
+ * (*goodguess) is set to 1 if the preferred client/server algos match,
+ * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
+ * guessed correctly */
+algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
+ enum kexguess2_used *kexguess2, int *goodguess)
+{
+
+ unsigned char * algolist = NULL;
+ const unsigned char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO];
+ unsigned int len;
+ unsigned int remotecount, localcount, clicount, servcount, i, j;
+ algo_type * ret = NULL;
+ const unsigned char **clinames, **servnames;
+
+ if (goodguess) {
+ *goodguess = 0;
+ }
+
+ /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
+ algolist = buf_getstring(buf, &len);
+ TRACE(("buf_match_algo: %s", algolist))
+ if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
+ goto out;
+ }
+
+ /* remotenames will contain a list of the strings parsed out */
+ /* We will have at least one string (even if it's just "") */
+ remotenames[0] = algolist;
+ remotecount = 1;
+ for (i = 0; i < len; i++) {
+ if (algolist[i] == '\0') {
+ /* someone is trying something strange */
+ goto out;
+ }
+ if (algolist[i] == ',') {
+ algolist[i] = '\0';
+ remotenames[remotecount] = &algolist[i+1];
+ remotecount++;
+ }
+ if (remotecount >= MAX_PROPOSED_ALGO) {
+ break;
+ }
+ }
+ if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) {
+ for (i = 0; i < remotecount; i++)
+ {
+ if (strcmp(remotenames[i], KEXGUESS2_ALGO_NAME) == 0) {
+ *kexguess2 = KEXGUESS2_YES;
+ break;
+ }
+ }
+ if (*kexguess2 == KEXGUESS2_LOOK) {
+ *kexguess2 = KEXGUESS2_NO;
+ }
+ }
+
+ for (i = 0; localalgos[i].name != NULL; i++) {
+ if (localalgos[i].usable) {
+ localnames[i] = localalgos[i].name;
+ } else {
+ localnames[i] = NULL;
+ }
+ }
+ localcount = i;
+
+ if (IS_DROPBEAR_SERVER) {
+ clinames = remotenames;
+ clicount = remotecount;
+ servnames = localnames;
+ servcount = localcount;
+ } else {
+ clinames = localnames;
+ clicount = localcount;
+ servnames = remotenames;
+ servcount = remotecount;
+ }
+
+ /* iterate and find the first match */
+ for (i = 0; i < clicount; i++) {
+ for (j = 0; j < servcount; j++) {
+ if (!(servnames[j] && clinames[i])) {
+ // unusable algos are NULL
+ continue;
+ }
+ if (strcmp(servnames[j], clinames[i]) == 0) {
+ /* set if it was a good guess */
+ if (goodguess && kexguess2) {
+ if (*kexguess2 == KEXGUESS2_YES) {
+ if (i == 0) {
+ *goodguess = 1;
+ }
+
+ } else {
+ if (i == 0 && j == 0) {
+ *goodguess = 1;
+ }
+ }
+ }
+ /* set the algo to return */
+ if (IS_DROPBEAR_SERVER) {
+ ret = &localalgos[j];
+ } else {
+ ret = &localalgos[i];
+ }
+ goto out;
+ }
+ }
+ }
+
+out:
+ m_free(algolist);
+ return ret;
+}
+
#ifdef DROPBEAR_NONE_CIPHER
void
diff --git a/common-channel.c b/common-channel.c
index 05b9d11..8b7369c 100644
--- a/common-channel.c
+++ b/common-channel.c
@@ -273,10 +273,10 @@ static unsigned int write_pending(struct Channel * channel) {
static void check_close(struct Channel *channel) {
int close_allowed = 0;
- TRACE(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
+ TRACE2(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
channel->writefd, channel->readfd,
channel->errfd, channel->sent_close, channel->recv_close))
- TRACE(("writebuf size %d extrabuf size %d",
+ TRACE2(("writebuf size %d extrabuf size %d",
channel->writebuf ? cbuf_getused(channel->writebuf) : 0,
channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
@@ -561,7 +561,11 @@ static void remove_channel(struct Channel * channel) {
TRACE(("CLOSE errfd %d", channel->errfd))
close(channel->errfd);
- channel->typedata = NULL;
+ if (!channel->close_handler_done
+ && channel->type->closehandler) {
+ channel->type->closehandler(channel);
+ channel->close_handler_done = 1;
+ }
ses.channels[channel->index] = NULL;
m_free(channel);
@@ -625,7 +629,7 @@ static void send_msg_channel_data(struct Channel *channel, int isextended) {
* exttype if is extended */
maxlen = MIN(maxlen,
ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
- TRACE(("maxlen %d", maxlen))
+ TRACE(("maxlen %zd", maxlen))
if (maxlen == 0) {
TRACE(("leave send_msg_channel_data: no window"))
return;
diff --git a/common-kex.c b/common-kex.c
index 8e1b6e0..0cd3db3 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -80,9 +80,10 @@ const unsigned char dh_p_14[DH_P_14_LEN] = {
static const int DH_G_VAL = 2;
static void kexinitialise();
-void gen_new_keys();
+static void gen_new_keys();
#ifndef DISABLE_ZLIB
-static void gen_new_zstreams();
+static void gen_new_zstream_recv();
+static void gen_new_zstream_trans();
#endif
static void read_kex_algos();
/* helper function for gen_new_keys */
@@ -132,8 +133,8 @@ void send_msg_kexinit() {
/* languages_server_to_client */
buf_putstring(ses.writepayload, "", 0);
- /* first_kex_packet_follows - unimplemented for now */
- buf_putbyte(ses.writepayload, 0x00);
+ /* first_kex_packet_follows */
+ buf_putbyte(ses.writepayload, (ses.send_kex_first_guess != NULL));
/* reserved unit32 */
buf_putint(ses.writepayload, 0);
@@ -145,16 +146,60 @@ void send_msg_kexinit() {
encrypt_packet();
ses.dataallowed = 0; /* don't send other packets during kex */
+ ses.kexstate.sentkexinit = 1;
+
+ ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
+
+ if (ses.send_kex_first_guess) {
+ ses.newkeys->algo_kex = sshkex[0].data;
+ ses.newkeys->algo_hostkey = sshhostkey[0].val;
+ ses.send_kex_first_guess();
+ }
+
TRACE(("DATAALLOWED=0"))
TRACE(("-> KEXINIT"))
- ses.kexstate.sentkexinit = 1;
+
}
-/* *** NOTE regarding (send|recv)_msg_newkeys ***
- * Changed by mihnea from the original kex.c to set dataallowed after a
- * completed key exchange, no matter the order in which it was performed.
- * This enables client mode without affecting server functionality.
- */
+static void switch_keys() {
+ TRACE2(("enter switch_keys"))
+ if (!(ses.kexstate.sentkexinit && ses.kexstate.recvkexinit)) {
+ dropbear_exit("Unexpected newkeys message");
+ }
+
+ if (!ses.keys) {
+ ses.keys = m_malloc(sizeof(*ses.newkeys));
+ }
+ if (ses.kexstate.recvnewkeys && ses.newkeys->recv.valid) {
+ TRACE(("switch_keys recv"))
+#ifndef DISABLE_ZLIB
+ gen_new_zstream_recv();
+#endif
+ ses.keys->recv = ses.newkeys->recv;
+ m_burn(&ses.newkeys->recv, sizeof(ses.newkeys->recv));
+ ses.newkeys->recv.valid = 0;
+ }
+ if (ses.kexstate.sentnewkeys && ses.newkeys->trans.valid) {
+ TRACE(("switch_keys trans"))
+#ifndef DISABLE_ZLIB
+ gen_new_zstream_trans();
+#endif
+ ses.keys->trans = ses.newkeys->trans;
+ m_burn(&ses.newkeys->trans, sizeof(ses.newkeys->trans));
+ ses.newkeys->trans.valid = 0;
+ }
+ if (ses.kexstate.sentnewkeys && ses.kexstate.recvnewkeys)
+ {
+ TRACE(("switch_keys done"))
+ ses.keys->algo_kex = ses.newkeys->algo_kex;
+ ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
+ ses.keys->allow_compress = 0;
+ m_free(ses.newkeys);
+ ses.newkeys = NULL;
+ kexinitialise();
+ }
+ TRACE2(("leave switch_keys"))
+}
/* Bring new keys into use after a key exchange, and let the client know*/
void send_msg_newkeys() {
@@ -165,44 +210,25 @@ void send_msg_newkeys() {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS);
encrypt_packet();
-
+
/* set up our state */
- if (ses.kexstate.recvnewkeys) {
- TRACE(("while RECVNEWKEYS=1"))
- gen_new_keys();
- kexinitialise(); /* we've finished with this kex */
- TRACE((" -> DATAALLOWED=1"))
- ses.dataallowed = 1; /* we can send other packets again now */
- ses.kexstate.donefirstkex = 1;
- } else {
- ses.kexstate.sentnewkeys = 1;
- TRACE(("SENTNEWKEYS=1"))
- }
+ ses.kexstate.sentnewkeys = 1;
+ ses.kexstate.donefirstkex = 1;
+ ses.dataallowed = 1; /* we can send other packets again now */
+ gen_new_keys();
+ switch_keys();
- TRACE(("-> MSG_NEWKEYS"))
TRACE(("leave send_msg_newkeys"))
}
/* Bring the new keys into use after a key exchange */
void recv_msg_newkeys() {
- TRACE(("<- MSG_NEWKEYS"))
TRACE(("enter recv_msg_newkeys"))
- /* simply check if we've sent SSH_MSG_NEWKEYS, and if so,
- * switch to the new keys */
- if (ses.kexstate.sentnewkeys) {
- TRACE(("while SENTNEWKEYS=1"))
- gen_new_keys();
- kexinitialise(); /* we've finished with this kex */
- TRACE((" -> DATAALLOWED=1"))
- ses.dataallowed = 1; /* we can send other packets again now */
- ses.kexstate.donefirstkex = 1;
- } else {
- TRACE(("RECVNEWKEYS=1"))
- ses.kexstate.recvnewkeys = 1;
- }
+ ses.kexstate.recvnewkeys = 1;
+ switch_keys();
TRACE(("leave recv_msg_newkeys"))
}
@@ -237,11 +263,13 @@ static void kexinitialise() {
ses.kexstate.sentnewkeys = 0;
/* first_packet_follows */
- ses.kexstate.firstfollows = 0;
+ ses.kexstate.them_firstfollows = 0;
ses.kexstate.datatrans = 0;
ses.kexstate.datarecv = 0;
+ ses.kexstate.our_first_follows_matches = 0;
+
ses.kexstate.lastkextime = time(NULL);
}
@@ -284,8 +312,7 @@ static void hashkeys(unsigned char *out, unsigned int outlen,
* ses.newkeys is the new set of keys which are generated, these are only
* taken into use after both sides have sent a newkeys message */
-/* Originally from kex.c, generalized for cli/svr mode --mihnea */
-void gen_new_keys() {
+static void gen_new_keys() {
unsigned char C2S_IV[MAX_IV_LEN];
unsigned char C2S_key[MAX_KEY_LEN];
@@ -367,15 +394,9 @@ void gen_new_keys() {
ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hash_desc->name);
}
-#ifndef DISABLE_ZLIB
- gen_new_zstreams();
-#endif
-
- /* Switch over to the new keys */
- m_burn(ses.keys, sizeof(struct key_context));
- m_free(ses.keys);
- ses.keys = ses.newkeys;
- ses.newkeys = NULL;
+ /* Ready to switch over */
+ ses.newkeys->trans.valid = 1;
+ ses.newkeys->recv.valid = 1;
m_burn(C2S_IV, sizeof(C2S_IV));
m_burn(C2S_key, sizeof(C2S_key));
@@ -401,7 +422,7 @@ int is_compress_recv() {
/* Set up new zlib compression streams, close the old ones. Only
* called from gen_new_keys() */
-static void gen_new_zstreams() {
+static void gen_new_zstream_recv() {
/* create new zstreams */
if (ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB
@@ -416,6 +437,17 @@ static void gen_new_zstreams() {
} else {
ses.newkeys->recv.zstream = NULL;
}
+ /* clean up old keys */
+ if (ses.keys->recv.zstream != NULL) {
+ if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
+ /* Z_DATA_ERROR is ok, just means that stream isn't ended */
+ dropbear_exit("Crypto error");
+ }
+ m_free(ses.keys->recv.zstream);
+ }
+}
+
+static void gen_new_zstream_trans() {
if (ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB
|| ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
@@ -433,14 +465,6 @@ static void gen_new_zstreams() {
ses.newkeys->trans.zstream = NULL;
}
- /* clean up old keys */
- if (ses.keys->recv.zstream != NULL) {
- if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
- /* Z_DATA_ERROR is ok, just means that stream isn't ended */
- dropbear_exit("Crypto error");
- }
- m_free(ses.keys->recv.zstream);
- }
if (ses.keys->trans.zstream != NULL) {
if (deflateEnd(ses.keys->trans.zstream) == Z_STREAM_ERROR) {
/* Z_DATA_ERROR is ok, just means that stream isn't ended */
@@ -523,7 +547,7 @@ void recv_msg_kexinit() {
buf_putstring(ses.kexhashbuf,
ses.transkexinit->data, ses.transkexinit->len);
- ses.requirenext = SSH_MSG_KEXDH_INIT;
+ ses.requirenext[0] = SSH_MSG_KEXDH_INIT;
}
buf_free(ses.transkexinit);
@@ -550,7 +574,7 @@ struct kex_dh_param *gen_kexdh_param() {
DEF_MP_INT(dh_q);
DEF_MP_INT(dh_g);
- TRACE(("enter send_msg_kexdh_reply"))
+ TRACE(("enter gen_kexdh_vals"))
struct kex_dh_param *param = m_malloc(sizeof(*param));
m_mp_init_multi(&param->pub, &param->priv, NULL);
@@ -739,20 +763,27 @@ static void read_kex_algos() {
buf_incrpos(ses.payload, 16); /* start after the cookie */
- ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
+ memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
+
+#ifdef USE_KEXGUESS2
+ enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
+#else
+ enum kexguess2_used kexguess2 = KEXGUESS2_NO;
+#endif
/* kex_algorithms */
- algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess);
+ algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
allgood &= goodguess;
- if (algo == NULL) {
+ if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
erralgo = "kex";
goto error;
}
+ TRACE(("kexguess2 %d", kexguess2))
TRACE(("kex algo %s", algo->name))
ses.newkeys->algo_kex = algo->data;
/* server_host_key_algorithms */
- algo = ses.buf_match_algo(ses.payload, sshhostkey, &goodguess);
+ algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess);
allgood &= goodguess;
if (algo == NULL) {
erralgo = "hostkey";
@@ -762,7 +793,7 @@ static void read_kex_algos() {
ses.newkeys->algo_hostkey = algo->val;
/* encryption_algorithms_client_to_server */
- c2s_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
+ c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
if (c2s_cipher_algo == NULL) {
erralgo = "enc c->s";
goto error;
@@ -770,7 +801,7 @@ static void read_kex_algos() {
TRACE(("enc c2s is %s", c2s_cipher_algo->name))
/* encryption_algorithms_server_to_client */
- s2c_cipher_algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
+ s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
if (s2c_cipher_algo == NULL) {
erralgo = "enc s->c";
goto error;
@@ -778,7 +809,7 @@ static void read_kex_algos() {
TRACE(("enc s2c is %s", s2c_cipher_algo->name))
/* mac_algorithms_client_to_server */
- c2s_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
+ c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
if (c2s_hash_algo == NULL) {
erralgo = "mac c->s";
goto error;
@@ -786,7 +817,7 @@ static void read_kex_algos() {
TRACE(("hash c2s is %s", c2s_hash_algo->name))
/* mac_algorithms_server_to_client */
- s2c_hash_algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
+ s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL);
if (s2c_hash_algo == NULL) {
erralgo = "mac s->c";
goto error;
@@ -794,7 +825,7 @@ static void read_kex_algos() {
TRACE(("hash s2c is %s", s2c_hash_algo->name))
/* compression_algorithms_client_to_server */
- c2s_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess);
+ c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
if (c2s_comp_algo == NULL) {
erralgo = "comp c->s";
goto error;
@@ -802,7 +833,7 @@ static void read_kex_algos() {
TRACE(("hash c2s is %s", c2s_comp_algo->name))
/* compression_algorithms_server_to_client */
- s2c_comp_algo = ses.buf_match_algo(ses.payload, ses.compress_algos, &goodguess);
+ s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL);
if (s2c_comp_algo == NULL) {
erralgo = "comp s->c";
goto error;
@@ -815,9 +846,10 @@ static void read_kex_algos() {
/* languages_server_to_client */
buf_eatstring(ses.payload);
- /* first_kex_packet_follows */
+ /* their first_kex_packet_follows */
if (buf_getbool(ses.payload)) {
- ses.kexstate.firstfollows = 1;
+ TRACE(("them kex firstfollows. allgood %d", allgood))
+ ses.kexstate.them_firstfollows = 1;
/* if the guess wasn't good, we ignore the packet sent */
if (!allgood) {
ses.ignorenext = 1;
@@ -860,6 +892,11 @@ static void read_kex_algos() {
/* reserved for future extensions */
buf_getint(ses.payload);
+
+ if (ses.send_kex_first_guess && allgood) {
+ TRACE(("our_first_follows_matches 1"))
+ ses.kexstate.our_first_follows_matches = 1;
+ }
return;
error:
diff --git a/common-session.c b/common-session.c
index ef8e6fa..470d1f6 100644
--- a/common-session.c
+++ b/common-session.c
@@ -33,12 +33,12 @@
#include "random.h"
#include "kex.h"
#include "channel.h"
-#include "atomicio.h"
#include "runopts.h"
static void checktimeouts();
static long select_timeout();
static int ident_readln(int fd, char* buf, int count);
+static void read_session_identification();
struct sshsession ses; /* GLOBAL */
@@ -49,8 +49,6 @@ int sessinitdone = 0; /* GLOBAL */
/* this is set when we get SIGINT or SIGTERM, the handler is in main.c */
int exitflag = 0; /* GLOBAL */
-
-
/* called only at the start of a session, set up initial state */
void common_session_init(int sock_in, int sock_out) {
@@ -84,7 +82,7 @@ void common_session_init(int sock_in, int sock_out) {
initqueue(&ses.writequeue);
- ses.requirenext = SSH_MSG_KEXINIT;
+ ses.requirenext[0] = SSH_MSG_KEXINIT;
ses.dataallowed = 1; /* we can send data until we actually
send the SSH_MSG_KEXINIT */
ses.ignorenext = 0;
@@ -141,7 +139,10 @@ void session_loop(void(*loophandler)()) {
FD_ZERO(&writefd);
FD_ZERO(&readfd);
dropbear_assert(ses.payload == NULL);
- if (ses.sock_in != -1) {
+
+ /* during initial setup we flush out the KEXINIT packet before
+ * attempting to read the remote version string, which might block */
+ if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue))) {
FD_SET(ses.sock_in, &readfd);
}
if (ses.sock_out != -1 && !isempty(&ses.writequeue)) {
@@ -195,7 +196,12 @@ void session_loop(void(*loophandler)()) {
if (ses.sock_in != -1) {
if (FD_ISSET(ses.sock_in, &readfd)) {
- read_packet();
+ if (!ses.remoteident) {
+ /* blocking read of the version string */
+ read_session_identification();
+ } else {
+ read_packet();
+ }
}
/* Process the decrypted packet. After this, the read buffer
@@ -225,7 +231,7 @@ void session_loop(void(*loophandler)()) {
}
/* clean up a session on exit */
-void common_session_cleanup() {
+void session_cleanup() {
TRACE(("enter session_cleanup"))
@@ -234,6 +240,10 @@ void common_session_cleanup() {
TRACE(("leave session_cleanup: !sessinitdone"))
return;
}
+
+ if (ses.extra_session_cleanup) {
+ ses.extra_session_cleanup();
+ }
if (ses.session_id) {
buf_burn(ses.session_id);
@@ -253,21 +263,20 @@ void common_session_cleanup() {
TRACE(("leave session_cleanup"))
}
+void send_session_identification() {
+ buffer *writebuf = buf_new(strlen(LOCAL_IDENT "\r\n") + 1);
+ buf_putbytes(writebuf, LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n"));
+ buf_putbyte(writebuf, 0x0); // packet type
+ buf_setpos(writebuf, 0);
+ enqueue(&ses.writequeue, writebuf);
+}
-void session_identification() {
-
+static void read_session_identification() {
/* max length of 255 chars */
char linebuf[256];
int len = 0;
char done = 0;
int i;
-
- /* write our version string, this blocks */
- if (atomicio(write, ses.sock_out, LOCAL_IDENT "\r\n",
- strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) {
- ses.remoteclosed();
- }
-
/* If they send more than 50 lines, something is wrong */
for (i = 0; i < 50; i++) {
len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf));
diff --git a/config.guess b/config.guess
index 6cc26cd..2055429 100644
--- a/config.guess
+++ b/config.guess
@@ -1,14 +1,12 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-# Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2007-01-15'
+timestamp='2013-04-24'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -17,26 +15,22 @@ timestamp='2007-01-15'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner <per@bothner.com>.
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner.
#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
#
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit build system type.
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+
me=`echo "$0" | sed -e 's,.*/,,'`
@@ -56,8 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -144,7 +137,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
@@ -170,7 +163,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep __ELF__ >/dev/null
+ | grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
@@ -180,7 +173,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
fi
;;
*)
- os=netbsd
+ os=netbsd
;;
esac
# The OS release
@@ -201,6 +194,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}"
exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
@@ -223,7 +220,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
@@ -269,7 +266,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- exit ;;
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
@@ -295,12 +295,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
- echo powerpc-ibm-os400
+ echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit ;;
- arm:riscos:*:*|arm:RISCOS:*:*)
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
@@ -324,14 +324,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
- i86pc:SunOS:5.*:*)
- echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH="i386"
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH="x86_64"
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
@@ -375,23 +394,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit ;;
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit ;;
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit ;;
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
@@ -461,8 +480,8 @@ EOF
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
- # DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=`/usr/bin/uname -p`
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -475,7 +494,7 @@ EOF
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
- exit ;;
+ exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
@@ -532,7 +551,7 @@ EOF
echo rs6000-ibm-aix3.2
fi
exit ;;
- *:AIX:*:[45])
+ *:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
@@ -575,52 +594,52 @@ EOF
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
- 532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
- esac ;;
- esac
+ esac ;;
+ esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ sed 's/^ //' << EOF >$dummy.c
- #define _HPUX_SOURCE
- #include <stdlib.h>
- #include <unistd.h>
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
- int main ()
- {
- #if defined(_SC_KERNEL_BITS)
- long bits = sysconf(_SC_KERNEL_BITS);
- #endif
- long cpu = sysconf (_SC_CPU_VERSION);
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
- case CPU_PA_RISC2_0:
- #if defined(_SC_KERNEL_BITS)
- switch (bits)
- {
- case 64: puts ("hppa2.0w"); break;
- case 32: puts ("hppa2.0n"); break;
- default: puts ("hppa2.0"); break;
- } break;
- #else /* !defined(_SC_KERNEL_BITS) */
- puts ("hppa2.0"); break;
- #endif
- default: puts ("hppa1.0"); break;
- }
- exit (0);
- }
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -640,7 +659,7 @@ EOF
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
- grep __LP64__ >/dev/null
+ grep -q __LP64__
then
HP_ARCH="hppa2.0w"
else
@@ -711,22 +730,22 @@ EOF
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
- exit ;;
+ exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
- exit ;;
+ exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
- exit ;;
+ exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
- exit ;;
+ exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
- exit ;;
+ exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
@@ -750,14 +769,14 @@ EOF
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -769,37 +788,51 @@ EOF
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
- case ${UNAME_MACHINE} in
- pc98)
- echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case ${UNAME_PROCESSOR} in
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
+ *:MINGW64*:*)
+ echo ${UNAME_MACHINE}-pc-mingw64
+ exit ;;
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
+ i*:MSYS*:*)
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
- x86:Interix*:[3456]*)
- echo i586-pc-interix${UNAME_RELEASE}
- exit ;;
- EM64T:Interix*:[3456]* | authenticamd:Interix*:[3456]*)
- echo x86_64-unknown-interix${UNAME_RELEASE}
- exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
@@ -829,20 +862,76 @@ EOF
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
- arm*:Linux:*:*)
+ aarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+ fi
+ fi
+ exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
cris:Linux:*:*)
- echo cris-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
crisv32:Linux:*:*)
- echo crisv32-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
frv:Linux:*:*)
- echo frv-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ hexagon:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ LIBC=gnu
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+ #else
+ #include <features.h>
+ #ifdef __UCLIBC__
+ LIBC=uclibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -853,74 +942,36 @@ EOF
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
- mips:Linux:*:*)
+ mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
- #undef mips
- #undef mipsel
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mipsel
+ CPU=${UNAME_MACHINE}el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips
+ CPU=${UNAME_MACHINE}
#else
CPU=
#endif
#endif
EOF
- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
- /^CPU/{
- s: ::g
- p
- }'`"
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
- mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips64
- #undef mips64el
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mips64el
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips64
- #else
- CPU=
- #endif
- #endif
-EOF
- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
- /^CPU/{
- s: ::g
- p
- }'`"
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
- ;;
- or32:Linux:*:*)
- echo or32-unknown-linux-gnu
+ or1k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
- ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
+ or32:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
- ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-gnu
exit ;;
- alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
- EV5) UNAME_MACHINE=alphaev5 ;;
- EV56) UNAME_MACHINE=alphaev56 ;;
- PCA56) UNAME_MACHINE=alphapca56 ;;
- PCA57) UNAME_MACHINE=alphapca56 ;;
- EV6) UNAME_MACHINE=alphaev6 ;;
- EV67) UNAME_MACHINE=alphaev67 ;;
- EV68*) UNAME_MACHINE=alphaev68 ;;
- esac
- objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
@@ -930,14 +981,17 @@ EOF
*) echo hppa-unknown-linux-gnu ;;
esac
exit ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
exit ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -945,78 +999,20 @@ EOF
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
+ tile*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-gnu
exit ;;
x86_64:Linux:*:*)
- echo x86_64-unknown-linux-gnu
+ LIBC=gnu
+ test -r /lib/libc.so && od -An -S13 /lib/libc.so | grep -q __uClibc_main && LIBC=uclibc
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
- xtensa:Linux:*:*)
- echo xtensa-unknown-linux-gnu
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
- i*86:Linux:*:*)
- # The BFD linker knows what the default object file format is, so
- # first see if it will tell us. cd to the root directory to prevent
- # problems with other programs or directories called `ld' in the path.
- # Set LC_ALL=C to ensure ld outputs messages in English.
- ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
- | sed -ne '/supported targets:/!d
- s/[ ][ ]*/ /g
- s/.*supported targets: *//
- s/ .*//
- p'`
- case "$ld_supported_targets" in
- elf32-i386)
- TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
- ;;
- a.out-i386-linux)
- echo "${UNAME_MACHINE}-pc-linux-gnuaout"
- exit ;;
- coff-i386)
- echo "${UNAME_MACHINE}-pc-linux-gnucoff"
- exit ;;
- "")
- # Either a pre-BFD a.out linker (linux-gnuoldld) or
- # one that does not give us useful --help.
- echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
- exit ;;
- esac
- # Determine whether the default compiler is a.out or elf
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <features.h>
- #ifdef __ELF__
- # ifdef __GLIBC__
- # if __GLIBC__ >= 2
- LIBC=gnu
- # else
- LIBC=gnulibc1
- # endif
- # else
- LIBC=gnulibc1
- # endif
- #else
- #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
- LIBC=gnu
- #else
- LIBC=gnuaout
- #endif
- #endif
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
- /^LIBC/{
- s: ::g
- p
- }'`"
- test x"${LIBC}" != x && {
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
- exit
- }
- test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
- ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
@@ -1024,11 +1020,11 @@ EOF
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
- # Unixware is an offshoot of SVR4, but it has its own version
- # number series starting with 2...
- # I am not positive that other SVR4 systems won't match this,
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
- # Use sysv4.2uw... so that sysv4* matches it.
+ # Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
@@ -1045,7 +1041,7 @@ EOF
i*86:syllable:*:*)
echo ${UNAME_MACHINE}-pc-syllable
exit ;;
- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit ;;
i*86:*DOS:*:*)
@@ -1060,7 +1056,7 @@ EOF
fi
exit ;;
i*86:*:5:[678]*)
- # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
@@ -1088,10 +1084,13 @@ EOF
exit ;;
pc:*:*:*)
# Left here for compatibility:
- # uname -m prints for DJGPP always 'pc', but it prints nothing about
- # the processor, so we play safe by assuming i386.
- echo i386-pc-msdosdjgpp
- exit ;;
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configury will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
@@ -1126,8 +1125,18 @@ EOF
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4; exit; } ;;
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit ;;
@@ -1140,7 +1149,7 @@ EOF
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit ;;
- PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
exit ;;
SM[BE]S:UNIX_SV:*:*)
@@ -1160,10 +1169,10 @@ EOF
echo ns32k-sni-sysv
fi
exit ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
@@ -1189,11 +1198,11 @@ EOF
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
+ echo mips-nec-sysv${UNAME_RELEASE}
else
- echo mips-unknown-sysv${UNAME_RELEASE}
+ echo mips-unknown-sysv${UNAME_RELEASE}
fi
- exit ;;
+ exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
@@ -1203,6 +1212,12 @@ EOF
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
@@ -1230,6 +1245,16 @@ EOF
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
case $UNAME_PROCESSOR in
+ i386)
+ eval $set_cc_for_build
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ UNAME_PROCESSOR="x86_64"
+ fi
+ fi ;;
unknown) UNAME_PROCESSOR=powerpc ;;
esac
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
@@ -1245,7 +1270,10 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
- NSE-?:NONSTOP_KERNEL:*:*)
+ NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
@@ -1290,13 +1318,13 @@ EOF
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
+ echo mips-sei-seiux${UNAME_RELEASE}
exit ;;
*:DragonFly:*:*)
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
*:*VMS:*:*)
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
@@ -1311,11 +1339,14 @@ EOF
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo ${UNAME_MACHINE}-unknown-esx
+ exit ;;
esac
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
eval $set_cc_for_build
cat >$dummy.c <<EOF
#ifdef _SEQUENT_
@@ -1333,11 +1364,11 @@ main ()
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
- "4"
+ "4"
#else
- ""
+ ""
#endif
- ); exit (0);
+ ); exit (0);
#endif
#endif
@@ -1471,9 +1502,9 @@ This script, last modified $timestamp, has failed to recognize
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
and
- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
If the version you run ($0) is already up to date, please
send the following data and any information you think might be
diff --git a/config.sub b/config.sub
index 5defff6..8b612ab 100644
--- a/config.sub
+++ b/config.sub
@@ -1,44 +1,40 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-# Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2007-01-18'
+timestamp='2013-04-24'
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
@@ -72,8 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -120,12 +115,18 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
- nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
- uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
@@ -148,10 +149,13 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray)
+ -apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
+ -bluegene*)
+ os=-cnk
+ ;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
@@ -166,10 +170,10 @@ case $os in
os=-chorusos
basic_machine=$1
;;
- -chorusrdb)
- os=-chorusrdb
+ -chorusrdb)
+ os=-chorusrdb
basic_machine=$1
- ;;
+ ;;
-hiux*)
os=-hiuxwe2
;;
@@ -214,6 +218,12 @@ case $os in
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
-lynx*)
os=-lynxos
;;
@@ -238,24 +248,34 @@ case $basic_machine in
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
+ | aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | be32 | be64 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
+ | epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
+ | le32 | le64 \
+ | lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | mcore | mep \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
- | mips64vr | mips64vrel \
+ | mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
@@ -266,31 +286,45 @@ case $basic_machine in
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
+ | moxie \
| mt \
| msp430 \
- | nios | nios2 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
- | or32 \
+ | open8 \
+ | or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
+ | rl78 | rx \
| score \
- | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu | strongarm \
- | tahoe | thumb | tic4x | tic80 | tron \
- | v850 | v850e \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
- | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
- | z8k)
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
basic_machine=$basic_machine-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12)
- # Motorola 68HC11/12.
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -300,6 +334,21 @@ case $basic_machine in
basic_machine=mt-unknown
;;
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
@@ -314,29 +363,37 @@ case $basic_machine in
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
+ | aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
+ | be32-* | be64-* \
| bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
+ | le32-* | le64-* \
+ | lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
- | mips64vr-* | mips64vrel-* \
+ | mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
@@ -347,31 +404,41 @@ case $basic_machine in
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
- | nios-* | nios2-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
- | romp-* | rs6000-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
- | tahoe-* | thumb-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
| tron-* \
- | v850-* | v850e-* | vax-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
| we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
- | xstormy16-* | xtensa-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
| ymp-* \
- | z8k-*)
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
@@ -389,7 +456,7 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
- abacus)
+ abacus)
basic_machine=abacus-unknown
;;
adobe68k)
@@ -435,6 +502,10 @@ case $basic_machine in
basic_machine=m68k-apollo
os=-bsd
;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -443,10 +514,35 @@ case $basic_machine in
basic_machine=ns32k-sequent
os=-dynix
;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
c90)
basic_machine=c90-cray
os=-unicos
;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
convex-c1)
basic_machine=c1-convex
os=-bsd
@@ -475,8 +571,8 @@ case $basic_machine in
basic_machine=craynv-cray
os=-unicosmp
;;
- cr16c)
- basic_machine=cr16c-unknown
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
os=-elf
;;
crds | unos)
@@ -514,6 +610,10 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
@@ -629,7 +729,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -668,6 +767,14 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
m88k-omron*)
basic_machine=m88k-omron
;;
@@ -679,10 +786,21 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
mingw32)
basic_machine=i386-pc
os=-mingw32
;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
miniframe)
basic_machine=m68000-convergent
;;
@@ -711,10 +829,18 @@ case $basic_machine in
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
+ msys)
+ basic_machine=i386-pc
+ os=-msys
+ ;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -779,6 +905,12 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -809,6 +941,14 @@ case $basic_machine in
basic_machine=i860-intel
os=-osf
;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
pbd)
basic_machine=sparc-tti
;;
@@ -853,9 +993,10 @@ case $basic_machine in
;;
power) basic_machine=power-ibm
;;
- ppc) basic_machine=powerpc-unknown
+ ppc | ppcbe) basic_machine=powerpc-unknown
;;
- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
@@ -880,7 +1021,11 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
- rdos)
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
basic_machine=i386-pc
os=-rdos
;;
@@ -949,6 +1094,9 @@ case $basic_machine in
basic_machine=i860-stratus
os=-sysv4
;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
sun2)
basic_machine=m68000-sun
;;
@@ -1005,17 +1153,9 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
- tic54x | c54x*)
- basic_machine=tic54x-unknown
- os=-coff
- ;;
- tic55x | c55x*)
- basic_machine=tic55x-unknown
- os=-coff
- ;;
- tic6x | c6x*)
- basic_machine=tic6x-unknown
- os=-coff
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
@@ -1084,6 +1224,9 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
ymp)
basic_machine=ymp-cray
os=-unicos
@@ -1092,6 +1235,10 @@ case $basic_machine in
basic_machine=z8k-unknown
os=-sim
;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
none)
basic_machine=none-none
os=-none
@@ -1130,7 +1277,7 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
- sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
@@ -1177,9 +1324,12 @@ esac
if [ x"$os" != x"" ]
then
case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
+ # First match some system type aliases
+ # that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
@@ -1200,21 +1350,23 @@ case $os in
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* \
+ | -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -openbsd* | -solidbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* \
- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
@@ -1222,7 +1374,7 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1261,7 +1413,7 @@ case $os in
-opened*)
os=-openedition
;;
- -os400*)
+ -os400*)
os=-os400
;;
-wince*)
@@ -1310,7 +1462,7 @@ case $os in
-sinix*)
os=-sysv4
;;
- -tpf*)
+ -tpf*)
os=-tpf
;;
-triton*)
@@ -1346,12 +1498,14 @@ case $os in
-aros*)
os=-aros
;;
- -kaos*)
- os=-kaos
- ;;
-zvmoe)
os=-zvmoe
;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -nacl*)
+ ;;
-none)
;;
*)
@@ -1374,10 +1528,10 @@ else
# system, and we'll never get to this point.
case $basic_machine in
- score-*)
+ score-*)
os=-elf
;;
- spu-*)
+ spu-*)
os=-elf
;;
*-acorn)
@@ -1389,8 +1543,20 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
- c4x-* | tic4x-*)
- os=-coff
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1410,14 +1576,11 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
;;
m68*-cisco)
os=-aout
;;
- mep-*)
+ mep-*)
os=-elf
;;
mips*-cisco)
@@ -1426,6 +1589,9 @@ case $basic_machine in
mips*-*)
os=-elf
;;
+ or1k-*)
+ os=-elf
+ ;;
or32-*)
os=-coff
;;
@@ -1444,7 +1610,7 @@ case $basic_machine in
*-ibm)
os=-aix
;;
- *-knuth)
+ *-knuth)
os=-mmixware
;;
*-wec)
@@ -1549,7 +1715,7 @@ case $basic_machine in
-sunos*)
vendor=sun
;;
- -aix*)
+ -cnk*|-aix*)
vendor=ibm
;;
-beos*)
diff --git a/configure.ac b/configure.ac
index d3d30b4..6f82450 100644
--- a/configure.ac
+++ b/configure.ac
@@ -211,7 +211,7 @@ AC_ARG_ENABLE(shadow,
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS([fcntl.h limits.h netinet/in.h netinet/tcp.h stdlib.h string.h sys/socket.h sys/time.h termios.h unistd.h crypt.h pty.h ioctl.h libutil.h libgen.h inttypes.h stropts.h utmp.h utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h pam/pam_appl.h netinet/in_systm.h])
+AC_CHECK_HEADERS([fcntl.h limits.h netinet/in.h netinet/tcp.h stdlib.h string.h sys/socket.h sys/time.h termios.h unistd.h crypt.h pty.h ioctl.h libutil.h libgen.h inttypes.h stropts.h utmp.h utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h pam/pam_appl.h netinet/in_systm.h sys/uio.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -616,7 +616,7 @@ AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
AC_FUNC_SELECT_ARGTYPES
AC_TYPE_SIGNAL
-AC_CHECK_FUNCS([dup2 getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo fork])
+AC_CHECK_FUNCS([dup2 getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo fork writev])
AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME))
diff --git a/dbclient.1 b/dbclient.1
index 69af18a..7ad550f 100644
--- a/dbclient.1
+++ b/dbclient.1
@@ -15,7 +15,7 @@ dbclient \- lightweight SSH2 client
.B dbclient
[
.I args ]
-.I [user1]@host1[/port1],[user2]@host2[/port2],...
+.I [user1]@host1[%port1],[user2]@host2[%port2],...
.SH DESCRIPTION
.B dbclient
@@ -24,10 +24,9 @@ environments, while still being functional and secure enough for general use.
.SH OPTIONS
.TP
.B \-p \fIport
-Remote port.
-Connect to port
+Connect to
.I port
-on the remote host.
+on the remote host. Alternatively a port can be specified as hostname%port.
Default is 22.
.TP
.B \-i \fIidfile
@@ -61,10 +60,10 @@ Login as
on the remote host.
.TP
.B \-t
-Allocate a pty.
+Allocate a PTY.
.TP
.B \-T
-Don't allocate a pty.
+Don't allocate a PTY.
.TP
.B \-N
Don't request a remote shell or run any commands. Any command arguments are ignored.
@@ -80,7 +79,8 @@ by the ssh server.
.TP
.B \-y
Always accept hostkeys if they are unknown. If a hostkey mismatch occurs the
-connection will abort as normal.
+connection will abort as normal. If specified a second time no host key checking
+is performed at all, this is usually undesirable.
.TP
.B \-A
Forward agent connections to the remote host. dbclient will use any
@@ -126,7 +126,7 @@ Dropbear will also allow multiple "hops" to be specified, separated by commas. I
this case a connection will be made to the first host, then a TCP forwarded
connection will be made through that to the second host, and so on. Hosts other than
the final destination will not see anything other than the encrypted SSH stream.
-A port for a host can be specified with a slash (eg matt@martello/44 ).
+A port for a host can be specified with a hash (eg matt@martello%44 ).
This syntax can also be used with scp or rsync (specifying dbclient as the
ssh/rsh command). A file can be "bounced" through multiple SSH hops, eg
@@ -136,6 +136,11 @@ Note that hostnames are resolved by the prior hop (so "canyons" would be resolve
in the example above, the same way as other -L TCP forwarded hosts are. Host keys are
checked locally based on the given hostname.
+.SH ESCAPE CHARACTERS
+Typing a newline followed by the key sequence \fI~.\fR (tilde, dot) will terminate a connection.
+The sequence \fI~^Z\fR (tilde, ctrl-z) will background the connection. This behaviour only
+applies when a PTY is used.
+
.SH ENVIRONMENT
.TP
.B DROPBEAR_PASSWORD
diff --git a/dbutil.c b/dbutil.c
index f2fe5b9..bdeb10c 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -138,15 +138,39 @@ void dropbear_log(int priority, const char* format, ...) {
#ifdef DEBUG_TRACE
void dropbear_trace(const char* format, ...) {
-
va_list param;
+ struct timeval tv;
if (!debug_trace) {
return;
}
+ gettimeofday(&tv, NULL);
+
va_start(param, format);
- fprintf(stderr, "TRACE (%d): ", getpid());
+ fprintf(stderr, "TRACE (%d) %d.%d: ", getpid(), tv.tv_sec, tv.tv_usec);
+ vfprintf(stderr, format, param);
+ fprintf(stderr, "\n");
+ va_end(param);
+}
+
+void dropbear_trace2(const char* format, ...) {
+ static int trace_env = -1;
+ va_list param;
+ struct timeval tv;
+
+ if (trace_env == -1) {
+ trace_env = getenv("DROPBEAR_TRACE2") ? 1 : 0;
+ }
+
+ if (!(debug_trace && trace_env)) {
+ return;
+ }
+
+ gettimeofday(&tv, NULL);
+
+ va_start(param, format);
+ fprintf(stderr, "TRACE2 (%d) %d.%d: ", getpid(), tv.tv_sec, tv.tv_usec);
vfprintf(stderr, format, param);
fprintf(stderr, "\n");
va_end(param);
@@ -733,8 +757,6 @@ int buf_getline(buffer * line, FILE * authfile) {
int c = EOF;
- TRACE(("enter buf_getline"))
-
buf_setpos(line, 0);
buf_setlen(line, 0);
@@ -758,10 +780,8 @@ out:
/* if we didn't read anything before EOF or error, exit */
if (c == EOF && line->pos == 0) {
- TRACE(("leave buf_getline: failure"))
return DROPBEAR_FAILURE;
} else {
- TRACE(("leave buf_getline: success"))
buf_setpos(line, 0);
return DROPBEAR_SUCCESS;
}
diff --git a/dbutil.h b/dbutil.h
index 5be3465..e13ed13 100644
--- a/dbutil.h
+++ b/dbutil.h
@@ -35,14 +35,12 @@ void startsyslog();
#ifdef __GNUC__
#define ATTRIB_PRINTF(fmt,args) __attribute__((format(printf, fmt, args)))
-#else
-#define ATTRIB_PRINTF(fmt,args)
-#endif
-
-#ifdef __GNUC__
#define ATTRIB_NORETURN __attribute__((noreturn))
+#define ATTRIB_SENTINEL __attribute__((sentinel))
#else
+#define ATTRIB_PRINTF(fmt,args)
#define ATTRIB_NORETURN
+#define ATTRIB_SENTINEL
#endif
extern void (*_dropbear_exit)(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
@@ -57,6 +55,7 @@ void fail_assert(const char* expr, const char* file, int line) ATTRIB_NORETURN;
#ifdef DEBUG_TRACE
void dropbear_trace(const char* format, ...) ATTRIB_PRINTF(1,2);
+void dropbear_trace2(const char* format, ...) ATTRIB_PRINTF(1,2);
void printhex(const char * label, const unsigned char * buf, int len);
void printmpint(const char *label, mp_int *mp);
extern int debug_trace;
diff --git a/debian/changelog b/debian/changelog
index 7b17620..d6aeeb8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+dropbear (2013.58-0.1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Matt Johnston <matt@ucc.asn.au> Thu, 18 Apr 2013 22:54:00 +0800
+
+dropbear (2013.57-0.1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Matt Johnston <matt@ucc.asn.au> Mon, 15 Apr 2013 22:54:00 +0800
+
dropbear (2013.56-0.1) unstable; urgency=low
* New upstream release.
diff --git a/debug.h b/debug.h
index 200c004..a761c2e 100644
--- a/debug.h
+++ b/debug.h
@@ -39,7 +39,8 @@
* Caution: Don't use this in an unfriendly environment (ie unfirewalled),
* since the printing may not sanitise strings etc. This will add a reasonable
* amount to your executable size. */
-/*#define DEBUG_TRACE*/
+/* #define DEBUG_TRACE */
+#define DEBUG_TRACE
/* All functions writing to the cleartext payload buffer call
* CHECKCLEARTOWRITE() before writing. This is only really useful if you're
@@ -63,13 +64,15 @@
/* you don't need to touch this block */
#ifdef DEBUG_TRACE
#define TRACE(X) dropbear_trace X;
+#define TRACE2(X) dropbear_trace2 X;
#else /*DEBUG_TRACE*/
#define TRACE(X)
+#define TRACE2(X)
#endif /*DEBUG_TRACE*/
/* To debug with GDB it is easier to run with no forking of child processes.
You will need to pass "-F" as well. */
-/*#define DEBUG_NOFORK*/
+#define DEBUG_NOFORK
/* For testing as non-root on shadowed systems, include the crypt of a password
diff --git a/dss.c b/dss.c
index d19033f..9817392 100644
--- a/dss.c
+++ b/dss.c
@@ -101,9 +101,9 @@ int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
/* Clear and free the memory used by a public or private key */
void dss_key_free(dropbear_dss_key *key) {
- TRACE(("enter dsa_key_free"))
+ TRACE2(("enter dsa_key_free"))
if (key == NULL) {
- TRACE(("enter dsa_key_free: key == NULL"))
+ TRACE2(("enter dsa_key_free: key == NULL"))
return;
}
if (key->p) {
@@ -127,7 +127,7 @@ void dss_key_free(dropbear_dss_key *key) {
m_free(key->x);
}
m_free(key);
- TRACE(("leave dsa_key_free"))
+ TRACE2(("leave dsa_key_free"))
}
/* put the dss public key into the buffer in the required format:
diff --git a/ecdsa.c b/ecdsa.c
index 9ff89b3..66612e4 100644
--- a/ecdsa.c
+++ b/ecdsa.c
@@ -242,11 +242,8 @@ out:
static int buf_get_ecdsa_verify_params(buffer *buf, struct dropbear_ecc_curve *curve,
void *r, void* s) {
int ret = DROPBEAR_FAILURE;
- unsigned char* ident = NULL;
- unsigned int ident_len;
unsigned int sig_len;
unsigned int sig_pos;
- unsigned char key_ident[30];
sig_len = buf_getint(buf);
sig_pos = buf->pos;
@@ -262,7 +259,6 @@ static int buf_get_ecdsa_verify_params(buffer *buf, struct dropbear_ecc_curve *c
ret = DROPBEAR_SUCCESS;
out:
- m_free(ident);
return ret;
}
diff --git a/includes.h b/includes.h
index 571a3be..203ccfd 100644
--- a/includes.h
+++ b/includes.h
@@ -120,6 +120,10 @@
#include <libgen.h>
#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
#ifdef BUNDLED_LIBTOM
#include "libtomcrypt/src/headers/tomcrypt.h"
#include "libtommath/tommath.h"
diff --git a/kex.h b/kex.h
index 10b31c8..e2e186b 100644
--- a/kex.h
+++ b/kex.h
@@ -61,13 +61,15 @@ struct KEXState {
unsigned sentkexinit : 1; /*set when we've sent/recv kexinit packet */
unsigned recvkexinit : 1;
- unsigned firstfollows : 1; /* true when first_kex_packet_follows is set */
+ unsigned them_firstfollows : 1; /* true when first_kex_packet_follows is set */
unsigned sentnewkeys : 1; /* set once we've send MSG_NEWKEYS (will be cleared once we have also received */
unsigned recvnewkeys : 1; /* set once we've received MSG_NEWKEYS (cleared once we have also sent */
unsigned donefirstkex : 1; /* Set to 1 after the first kex has completed,
ie the transport layer has been set up */
+ unsigned our_first_follows_matches : 1;
+
time_t lastkextime; /* time of the last kex */
unsigned int datatrans; /* data transmitted since last kex */
unsigned int datarecv; /* data received since last kex */
@@ -80,8 +82,8 @@ extern const unsigned char dh_p_1[DH_P_1_LEN];
extern const unsigned char dh_p_14[DH_P_14_LEN];
struct kex_dh_param {
- mp_int pub;
- mp_int priv;
+ mp_int pub; /* e */
+ mp_int priv; /* x */
};
#ifdef DROPBEAR_ECDH
diff --git a/loginrec.c b/loginrec.c
index 14b8090..d6ec75f 100644
--- a/loginrec.c
+++ b/loginrec.c
@@ -329,8 +329,6 @@ login_write (struct logininfo *li)
{
#ifndef HAVE_CYGWIN
if ((int)geteuid() != 0) {
- dropbear_log(LOG_WARNING,
- "Attempt to write login records by non-root user (aborting)");
return 1;
}
#endif
diff --git a/options.h b/options.h
index 0d30282..6199fb6 100644
--- a/options.h
+++ b/options.h
@@ -159,7 +159,7 @@ much traffic. */
#endif
/* Whether to do reverse DNS lookups. */
-#define DO_HOST_LOOKUP
+//#define DO_HOST_LOOKUP
/* Whether to print the message of the day (MOTD). This doesn't add much code
* size */
@@ -182,7 +182,7 @@ much traffic. */
#define ENABLE_SVR_PASSWORD_AUTH
/* PAM requires ./configure --enable-pam */
-/*#define ENABLE_SVR_PAM_AUTH*/
+//#define ENABLE_SVR_PAM_AUTH
#define ENABLE_SVR_PUBKEY_AUTH
/* Whether to take public key options in
@@ -210,6 +210,13 @@ much traffic. */
* return the password on standard output */
/*#define ENABLE_CLI_ASKPASS_HELPER*/
+/* Send a real auth request first rather than requesting a list of available methods.
+ * It saves a network round trip at login but prevents immediate login to
+ * accounts with no password, and might be rejected by some strict servers (none
+ * encountered yet) - hence it isn't enabled by default. */
+/* #define CLI_IMMEDIATE_AUTH */
+
+
/* Source for randomness. This must be able to provide hundreds of bytes per SSH
* connection without blocking. In addition /dev/random is used for seeding
* rsa/dss key generation */
diff --git a/packet.c b/packet.c
index f979cae..d458ccf 100644
--- a/packet.c
+++ b/packet.c
@@ -42,7 +42,7 @@ static void make_mac(unsigned int seqno, const struct key_context_directional *
static int checkmac();
#define ZLIB_COMPRESS_INCR 100
-#define ZLIB_DECOMPRESS_INCR 100
+#define ZLIB_DECOMPRESS_INCR 1024
#ifndef DISABLE_ZLIB
static buffer* buf_decompress(buffer* buf, unsigned int len);
static void buf_compress(buffer * dest, buffer * src, unsigned int len);
@@ -55,10 +55,62 @@ void write_packet() {
buffer * writebuf = NULL;
time_t now;
unsigned packet_type;
+ int all_ignore = 1;
+#ifdef HAVE_WRITEV
+ struct iovec *iov = NULL;
+ int i;
+ struct Link *l;
+#endif
- TRACE(("enter write_packet"))
+ TRACE2(("enter write_packet"))
dropbear_assert(!isempty(&ses.writequeue));
+#ifdef HAVE_WRITEV
+ iov = m_malloc(sizeof(*iov) * ses.writequeue.count);
+ for (l = ses.writequeue.head, i = 0; l; l = l->link, i++)
+ {
+ writebuf = (buffer*)l->item;
+ packet_type = writebuf->data[writebuf->len-1];
+ len = writebuf->len - 1 - writebuf->pos;
+ dropbear_assert(len > 0);
+ all_ignore &= (packet_type == SSH_MSG_IGNORE);
+ TRACE2(("write_packet writev #%d type %d len %d/%d", i, packet_type,
+ len, writebuf->len-1))
+ iov[i].iov_base = buf_getptr(writebuf, len);
+ iov[i].iov_len = len;
+ }
+ written = writev(ses.sock_out, iov, ses.writequeue.count);
+ if (written < 0) {
+ if (errno == EINTR) {
+ m_free(iov);
+ TRACE2(("leave writepacket: EINTR"))
+ return;
+ } else {
+ dropbear_exit("Error writing");
+ }
+ }
+
+ if (written == 0) {
+ ses.remoteclosed();
+ }
+
+ while (written > 0) {
+ writebuf = (buffer*)examine(&ses.writequeue);
+ len = writebuf->len - 1 - writebuf->pos;
+ if (len > written) {
+ // partial buffer write
+ buf_incrpos(writebuf, written);
+ written = 0;
+ } else {
+ written -= len;
+ dequeue(&ses.writequeue);
+ buf_free(writebuf);
+ }
+ }
+
+ m_free(iov);
+
+#else
/* Get the next buffer in the queue of encrypted packets to write*/
writebuf = (buffer*)examine(&ses.writequeue);
@@ -72,19 +124,13 @@ void write_packet() {
if (written < 0) {
if (errno == EINTR) {
- TRACE(("leave writepacket: EINTR"))
+ TRACE2(("leave writepacket: EINTR"))
return;
} else {
dropbear_exit("Error writing");
}
}
-
- now = time(NULL);
- ses.last_trx_packet_time = now;
-
- if (packet_type != SSH_MSG_IGNORE) {
- ses.last_packet_time = now;
- }
+ all_ignore = (packet_type == SSH_MSG_IGNORE);
if (written == 0) {
ses.remoteclosed();
@@ -100,7 +146,15 @@ void write_packet() {
buf_incrpos(writebuf, written);
}
- TRACE(("leave write_packet"))
+#endif
+ now = time(NULL);
+ ses.last_trx_packet_time = now;
+
+ if (!all_ignore) {
+ ses.last_packet_time = now;
+ }
+
+ TRACE2(("leave write_packet"))
}
/* Non-blocking function reading available portion of a packet into the
@@ -112,7 +166,7 @@ void read_packet() {
unsigned int maxlen;
unsigned char blocksize;
- TRACE(("enter read_packet"))
+ TRACE2(("enter read_packet"))
blocksize = ses.keys->recv.algo_crypt->blocksize;
if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
@@ -125,7 +179,7 @@ void read_packet() {
if (ret == DROPBEAR_FAILURE) {
/* didn't read enough to determine the length */
- TRACE(("leave read_packet: packetinit done"))
+ TRACE2(("leave read_packet: packetinit done"))
return;
}
}
@@ -147,7 +201,7 @@ void read_packet() {
if (len < 0) {
if (errno == EINTR || errno == EAGAIN) {
- TRACE(("leave read_packet: EINTR or EAGAIN"))
+ TRACE2(("leave read_packet: EINTR or EAGAIN"))
return;
} else {
dropbear_exit("Error reading: %s", strerror(errno));
@@ -163,7 +217,7 @@ void read_packet() {
/* The main select() loop process_packet() to
* handle the packet contents... */
}
- TRACE(("leave read_packet"))
+ TRACE2(("leave read_packet"))
}
/* Function used to read the initial portion of a packet, and determine the
@@ -197,7 +251,7 @@ static int read_packet_init() {
}
if (slen < 0) {
if (errno == EINTR) {
- TRACE(("leave read_packet_init: EINTR"))
+ TRACE2(("leave read_packet_init: EINTR"))
return DROPBEAR_FAILURE;
}
dropbear_exit("Error reading: %s", strerror(errno));
@@ -221,7 +275,7 @@ static int read_packet_init() {
}
len = buf_getint(ses.readbuf) + 4 + macsize;
- TRACE(("packet size is %d, block %d mac %d", len, blocksize, macsize))
+ TRACE2(("packet size is %d, block %d mac %d", len, blocksize, macsize))
/* check packet length */
@@ -247,7 +301,7 @@ void decrypt_packet() {
unsigned int padlen;
unsigned int len;
- TRACE(("enter decrypt_packet"))
+ TRACE2(("enter decrypt_packet"))
blocksize = ses.keys->recv.algo_crypt->blocksize;
macsize = ses.keys->recv.algo_mac->hashsize;
@@ -304,7 +358,7 @@ void decrypt_packet() {
ses.recvseq++;
- TRACE(("leave decrypt_packet"))
+ TRACE2(("leave decrypt_packet"))
}
/* Checks the mac at the end of a decrypted readbuf.
@@ -314,7 +368,7 @@ static int checkmac() {
unsigned char mac_bytes[MAX_MAC_LEN];
unsigned int mac_size, contents_len;
- mac_size = ses.keys->trans.algo_mac->hashsize;
+ mac_size = ses.keys->recv.algo_mac->hashsize;
contents_len = ses.readbuf->len - mac_size;
buf_setpos(ses.readbuf, 0);
@@ -366,7 +420,12 @@ static buffer* buf_decompress(buffer* buf, unsigned int len) {
}
if (zstream->avail_out == 0) {
- buf_resize(ret, ret->size + ZLIB_DECOMPRESS_INCR);
+ int new_size = 0;
+ if (ret->size >= RECV_MAX_PAYLOAD_LEN) {
+ dropbear_exit("bad packet, oversized decompressed");
+ }
+ new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR);
+ buf_resize(ret, new_size);
}
}
}
@@ -403,7 +462,6 @@ static void enqueue_reply_packet() {
ses.reply_queue_head = new_item;
}
ses.reply_queue_tail = new_item;
- TRACE(("leave enqueue_reply_packet"))
}
void maybe_flush_reply_queue() {
@@ -440,24 +498,18 @@ void encrypt_packet() {
unsigned int len, encrypt_buf_size;
unsigned char mac_bytes[MAX_MAC_LEN];
- TRACE(("enter encrypt_packet()"))
+ TRACE2(("enter encrypt_packet()"))
buf_setpos(ses.writepayload, 0);
packet_type = buf_getbyte(ses.writepayload);
buf_setpos(ses.writepayload, 0);
- TRACE(("encrypt_packet type is %d", packet_type))
+ TRACE2(("encrypt_packet type is %d", packet_type))
- if ((!ses.dataallowed && !packet_is_okay_kex(packet_type))
- || ses.kexstate.sentnewkeys) {
+ if ((!ses.dataallowed && !packet_is_okay_kex(packet_type))) {
/* During key exchange only particular packets are allowed.
Since this packet_type isn't OK we just enqueue it to send
after the KEX, see maybe_flush_reply_queue */
-
- /* We also enqueue packets here when we have sent a MSG_NEWKEYS
- * packet but are yet to received one. For simplicity we just switch
- * over all the keys at once. This is the 'ses.kexstate.sentnewkeys'
- * case. */
enqueue_reply_packet();
return;
}
@@ -559,7 +611,7 @@ void encrypt_packet() {
ses.kexstate.datatrans += writebuf->len;
ses.transseq++;
- TRACE(("leave encrypt_packet()"))
+ TRACE2(("leave encrypt_packet()"))
}
@@ -572,8 +624,6 @@ static void make_mac(unsigned int seqno, const struct key_context_directional *
unsigned long bufsize;
hmac_state hmac;
- TRACE(("enter writemac"))
-
if (key_state->algo_mac->hashsize > 0) {
/* calculate the mac */
if (hmac_init(&hmac,
@@ -602,7 +652,7 @@ static void make_mac(unsigned int seqno, const struct key_context_directional *
dropbear_exit("HMAC error");
}
}
- TRACE(("leave writemac"))
+ TRACE2(("leave writemac"))
}
#ifndef DISABLE_ZLIB
@@ -613,7 +663,7 @@ static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
unsigned int endpos = src->pos + len;
int result;
- TRACE(("enter buf_compress"))
+ TRACE2(("enter buf_compress"))
while (1) {
@@ -647,6 +697,6 @@ static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR);
}
- TRACE(("leave buf_compress"))
+ TRACE2(("leave buf_compress"))
}
#endif
diff --git a/process-packet.c b/process-packet.c
index 2ae410d..ecc4863 100644
--- a/process-packet.c
+++ b/process-packet.c
@@ -45,10 +45,10 @@ void process_packet() {
unsigned char type;
unsigned int i;
- TRACE(("enter process_packet"))
+ TRACE2(("enter process_packet"))
type = buf_getbyte(ses.payload);
- TRACE(("process_packet: packet type = %d", type))
+ TRACE(("process_packet: packet type = %d, len %d", type, ses.payload->len))
ses.lastpacket = type;
@@ -74,14 +74,15 @@ void process_packet() {
/* This applies for KEX, where the spec says the next packet MUST be
* NEWKEYS */
- if (ses.requirenext != 0) {
- if (ses.requirenext != type) {
- /* TODO send disconnect? */
- dropbear_exit("Unexpected packet type %d, expected %d", type,
- ses.requirenext);
+ if (ses.requirenext[0] != 0) {
+ if (ses.requirenext[0] != type
+ && (ses.requirenext[1] == 0 || ses.requirenext[1] != type)) {
+ dropbear_exit("Unexpected packet type %d, expected [%d,%d]", type,
+ ses.requirenext[0], ses.requirenext[1]);
} else {
/* Got what we expected */
- ses.requirenext = 0;
+ ses.requirenext[0] = 0;
+ ses.requirenext[1] = 0;
}
}
@@ -123,7 +124,7 @@ out:
buf_free(ses.payload);
ses.payload = NULL;
- TRACE(("leave process_packet"))
+ TRACE2(("leave process_packet"))
}
diff --git a/queue.c b/queue.c
index 7a80124..9d00808 100644
--- a/queue.c
+++ b/queue.c
@@ -70,7 +70,6 @@ void enqueue(struct Queue* queue, void* item) {
struct Link* newlink;
- TRACE(("enter enqueue"))
newlink = (struct Link*)m_malloc(sizeof(struct Link));
newlink->item = item;
@@ -85,5 +84,4 @@ void enqueue(struct Queue* queue, void* item) {
queue->head = newlink;
}
queue->count++;
- TRACE(("leave enqueue"))
}
diff --git a/queue.h b/queue.h
index 80fbb9d..8cffab7 100644
--- a/queue.h
+++ b/queue.h
@@ -36,7 +36,7 @@ struct Queue {
struct Link* head;
struct Link* tail;
- unsigned int count; /* safety value */
+ unsigned int count;
};
diff --git a/random.c b/random.c
index c5a522e..17e3086 100644
--- a/random.c
+++ b/random.c
@@ -158,6 +158,9 @@ static void write_urandom()
/* This is opportunistic, don't worry about failure */
unsigned char buf[INIT_SEED_SIZE];
FILE *f = fopen(DROPBEAR_URANDOM_DEV, "w");
+ if (!f) {
+ return;
+ }
genrandom(buf, sizeof(buf));
fwrite(buf, sizeof(buf), 1, f);
fclose(f);
diff --git a/rsa.c b/rsa.c
index 836b9f3..6fd30b8 100644
--- a/rsa.c
+++ b/rsa.c
@@ -138,10 +138,10 @@ out:
/* Clear and free the memory used by a public or private key */
void rsa_key_free(dropbear_rsa_key *key) {
- TRACE(("enter rsa_key_free"))
+ TRACE2(("enter rsa_key_free"))
if (key == NULL) {
- TRACE(("leave rsa_key_free: key == NULL"))
+ TRACE2(("leave rsa_key_free: key == NULL"))
return;
}
if (key->d) {
@@ -165,7 +165,7 @@ void rsa_key_free(dropbear_rsa_key *key) {
m_free(key->q);
}
m_free(key);
- TRACE(("leave rsa_key_free"))
+ TRACE2(("leave rsa_key_free"))
}
/* Put the public rsa key into the buffer in the required format:
diff --git a/runopts.h b/runopts.h
index d5dcc9d..ecb8618 100644
--- a/runopts.h
+++ b/runopts.h
@@ -124,6 +124,7 @@ typedef struct cli_runopts {
char *cmd;
int wantpty;
int always_accept_key;
+ int no_hostkey_check;
int no_cmd;
int backgrounded;
int is_subsystem;
diff --git a/scp.c b/scp.c
index 8715726..114d095 100644
--- a/scp.c
+++ b/scp.c
@@ -230,7 +230,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
close(pin[0]);
close(pout[1]);
-#ifdef USE_VFORK
+#ifndef USE_VFORK
arg_setup(host, remuser, cmd);
#endif
diff --git a/service.h b/service.h
index 197d8d1..9c60c09 100644
--- a/service.h
+++ b/service.h
@@ -26,7 +26,5 @@
#define _SERVICE_H_
void recv_msg_service_request(); /* Server */
-void send_msg_service_request(); /* Client */
-void recv_msg_service_accept(); /* Client */
#endif /* _SERVICE_H_ */
diff --git a/session.h b/session.h
index be789b3..7d7724c 100644
--- a/session.h
+++ b/session.h
@@ -44,8 +44,8 @@ extern int exitflag;
void common_session_init(int sock_in, int sock_out);
void session_loop(void(*loophandler)());
-void common_session_cleanup();
-void session_identification();
+void session_cleanup();
+void send_session_identification();
void send_msg_ignore();
const char* get_user_shell();
@@ -58,7 +58,6 @@ void svr_dropbear_log(int priority, const char* format, va_list param);
/* Client */
void cli_session(int sock_in, int sock_out);
-void cli_session_cleanup();
void cleantext(unsigned char* dirtytext);
/* crypto parameters that are stored individually for transmit and receive */
@@ -79,6 +78,7 @@ struct key_context_directional {
#endif
} cipher_state;
unsigned char mackey[MAX_MAC_LEN];
+ int valid;
};
struct key_context {
@@ -111,7 +111,10 @@ struct sshsession {
int sock_in;
int sock_out;
- unsigned char *remoteident;
+ /* remotehost will be initially NULL as we delay
+ * reading the remote version string. it will be set
+ * by the time any recv_() packet methods are called */
+ unsigned char *remoteident;
int maxfd; /* the maximum file descriptor to check with select() */
@@ -132,8 +135,9 @@ struct sshsession {
unsigned dataallowed : 1; /* whether we can send data packets or we are in
the middle of a KEX or something */
- unsigned char requirenext; /* byte indicating what packet we require next,
- or 0x00 for any */
+ unsigned char requirenext[2]; /* bytes indicating what packets we require next,
+ or 0x00 for any. Second option can only be
+ used if the first byte is also set */
unsigned char ignorenext; /* whether to ignore the next packet,
used for kex_follows stuff */
@@ -169,15 +173,11 @@ struct sshsession {
concluded (ie, while dataallowed was unset)*/
struct packetlist *reply_queue_head, *reply_queue_tail;
- algo_type*(*buf_match_algo)(buffer*buf, algo_type localalgos[],
- int *goodguess); /* The function to use to choose which algorithm
- to use from the ones presented by the remote
- side. Is specific to the client/server mode,
- hence the function-pointer callback.*/
-
void(*remoteclosed)(); /* A callback to handle closure of the
remote connection */
+ void(*extra_session_cleanup)(); /* client or server specific cleanup */
+ void(*send_kex_first_guess)();
struct AuthState authstate; /* Common amongst client and server, since most
struct elements are common */
@@ -233,10 +233,6 @@ typedef enum {
typedef enum {
STATE_NOTHING,
- SERVICE_AUTH_REQ_SENT,
- SERVICE_AUTH_ACCEPT_RCVD,
- SERVICE_CONN_REQ_SENT,
- SERVICE_CONN_ACCEPT_RCVD,
USERAUTH_REQ_SENT,
USERAUTH_FAIL_RCVD,
USERAUTH_SUCCESS_RCVD,
@@ -244,8 +240,12 @@ typedef enum {
} cli_state;
struct clientsession {
+
+ // XXX - move these to kexstate?
struct kex_dh_param *dh_param;
struct kex_ecdh_param *ecdh_param;
+ const struct dropbear_kex *param_kex_algo; /* KEX algorithm corresponding to current dh_e and dh_x */
+
cli_kex_state kex_state; /* Used for progressing KEX */
cli_state state; /* Used to progress auth/channelsession etc */
unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */
diff --git a/signkey.c b/signkey.c
index ef7556e..194c145 100644
--- a/signkey.c
+++ b/signkey.c
@@ -113,7 +113,7 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) {
int keytype;
int ret = DROPBEAR_FAILURE;
- TRACE(("enter buf_get_pub_key"))
+ TRACE2(("enter buf_get_pub_key"))
ident = buf_getstring(buf, &len);
keytype = signkey_type_from_name(ident, len);
@@ -124,7 +124,7 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) {
return DROPBEAR_FAILURE;
}
- TRACE(("buf_get_pub_key keytype is %d", keytype))
+ TRACE2(("buf_get_pub_key keytype is %d", keytype))
*type = keytype;
@@ -163,7 +163,7 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) {
}
#endif
- TRACE(("leave buf_get_pub_key"))
+ TRACE2(("leave buf_get_pub_key"))
return ret;
@@ -179,7 +179,7 @@ int buf_get_priv_key(buffer *buf, sign_key *key, int *type) {
int keytype;
int ret = DROPBEAR_FAILURE;
- TRACE(("enter buf_get_priv_key"))
+ TRACE2(("enter buf_get_priv_key"))
ident = buf_getstring(buf, &len);
keytype = signkey_type_from_name(ident, len);
@@ -227,7 +227,7 @@ int buf_get_priv_key(buffer *buf, sign_key *key, int *type) {
}
#endif
- TRACE(("leave buf_get_priv_key"))
+ TRACE2(("leave buf_get_priv_key"))
return ret;
@@ -238,7 +238,7 @@ void buf_put_pub_key(buffer* buf, sign_key *key, int type) {
buffer *pubkeys;
- TRACE(("enter buf_put_pub_key"))
+ TRACE2(("enter buf_put_pub_key"))
pubkeys = buf_new(MAX_PUBKEY_SIZE);
#ifdef DROPBEAR_DSS
@@ -262,7 +262,7 @@ void buf_put_pub_key(buffer* buf, sign_key *key, int type) {
buf_putbufstring(buf, pubkeys);
buf_free(pubkeys);
- TRACE(("leave buf_put_pub_key"))
+ TRACE2(("leave buf_put_pub_key"))
}
/* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */
@@ -296,7 +296,7 @@ void buf_put_priv_key(buffer* buf, sign_key *key, int type) {
void sign_key_free(sign_key *key) {
- TRACE(("enter sign_key_free"))
+ TRACE2(("enter sign_key_free"))
#ifdef DROPBEAR_DSS
dss_key_free(key->dsskey);
@@ -316,7 +316,7 @@ void sign_key_free(sign_key *key) {
m_free(key->filename);
m_free(key);
- TRACE(("leave sign_key_free"))
+ TRACE2(("leave sign_key_free"))
}
static char hexdig(unsigned char x) {
diff --git a/svr-algo.c b/svr-algo.c
deleted file mode 100644
index f8f9055..0000000
--- a/svr-algo.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Dropbear - a SSH2 server
- * SSH client implementation
- *
- * Copyright (c) 2002,2003 Matt Johnston
- * Copyright (c) 2004 by Mihnea Stoenescu
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE. */
-
-#include "algo.h"
-#include "dbutil.h"
-
-/* match the first algorithm in the comma-separated list in buf which is
- * also in localalgos[], or return NULL on failure.
- * (*goodguess) is set to 1 if the preferred client/server algos match,
- * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
- * guessed correctly */
-algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[],
- int *goodguess)
-{
-
- unsigned char * algolist = NULL;
- unsigned char * remotealgos[MAX_PROPOSED_ALGO];
- unsigned int len;
- unsigned int count, i, j;
- algo_type * ret = NULL;
-
- *goodguess = 0;
-
- /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
- algolist = buf_getstring(buf, &len);
- /* Debug this */
- TRACE(("buf_match_algo: %s", algolist))
- if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
- goto out; /* just a sanity check, no other use */
- }
-
- /* remotealgos will contain a list of the strings parsed out */
- /* We will have at least one string (even if it's just "") */
- remotealgos[0] = algolist;
- count = 1;
- /* Iterate through, replacing ','s with NULs, to split it into
- * words. */
- for (i = 0; i < len; i++) {
- if (algolist[i] == '\0') {
- /* someone is trying something strange */
- goto out;
- }
- if (algolist[i] == ',') {
- algolist[i] = '\0';
- remotealgos[count] = &algolist[i+1];
- count++;
- }
- if (count >= MAX_PROPOSED_ALGO) {
- break;
- }
- }
-
- /* iterate and find the first match */
- for (i = 0; i < count; i++) {
-
- len = strlen(remotealgos[i]);
-
- for (j = 0; localalgos[j].name != NULL; j++) {
- if (localalgos[j].usable) {
- if (len == strlen(localalgos[j].name) &&
- strncmp(localalgos[j].name, remotealgos[i], len) == 0) {
- /* set if it was a good guess */
- if (i == 0 && j == 0) {
- *goodguess = 1;
- }
- /* set the algo to return */
- ret = &localalgos[j];
- goto out;
- }
- }
- }
- }
-
-out:
- m_free(algolist);
- return ret;
-}
diff --git a/svr-auth.c b/svr-auth.c
index eb518fc..acac6f8 100644
--- a/svr-auth.c
+++ b/svr-auth.c
@@ -225,6 +225,7 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
char* listshell = NULL;
char* usershell = NULL;
+ int uid;
TRACE(("enter checkusername"))
if (userlen > MAX_USERNAME_LEN) {
return DROPBEAR_FAILURE;
@@ -254,6 +255,18 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
return DROPBEAR_FAILURE;
}
+ /* check if we are running as non-root, and login user is different from the server */
+ uid = geteuid();
+ if (uid != 0 && uid != ses.authstate.pw_uid) {
+ TRACE(("running as nonroot, only server uid is allowed"))
+ dropbear_log(LOG_WARNING,
+ "Login attempt with wrong user %s from %s",
+ ses.authstate.pw_name,
+ svr_ses.addrstring);
+ send_msg_userauth_failure(0, 1);
+ return DROPBEAR_FAILURE;
+ }
+
/* check for non-root if desired */
if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) {
TRACE(("leave checkusername: root login disabled"))
diff --git a/svr-authpasswd.c b/svr-authpasswd.c
index 38fccc2..17dd2a1 100644
--- a/svr-authpasswd.c
+++ b/svr-authpasswd.c
@@ -66,6 +66,14 @@ void svr_auth_password() {
m_burn(password, passwordlen);
m_free(password);
+ if (testcrypt == NULL) {
+ /* crypt() with an invalid salt like "!!" */
+ dropbear_log(LOG_WARNING, "User account '%s' is locked",
+ ses.authstate.pw_name);
+ send_msg_userauth_failure(0, 1);
+ return;
+ }
+
/* check for empty password */
if (passwdcrypt[0] == '\0') {
dropbear_log(LOG_WARNING, "User '%s' has blank password, rejected",
diff --git a/svr-kex.c b/svr-kex.c
index 2d2cdb1..664ae84 100644
--- a/svr-kex.c
+++ b/svr-kex.c
@@ -71,7 +71,8 @@ void recv_msg_kexdh_init() {
}
send_msg_newkeys();
- ses.requirenext = SSH_MSG_NEWKEYS;
+ ses.requirenext[0] = SSH_MSG_NEWKEYS;
+ ses.requirenext[1] = 0;
TRACE(("leave recv_msg_kexdh_init"))
}
diff --git a/svr-session.c b/svr-session.c
index a207d78..76ad450 100644
--- a/svr-session.c
+++ b/svr-session.c
@@ -73,6 +73,13 @@ static const struct ChanType *svr_chantypes[] = {
NULL /* Null termination is mandatory. */
};
+static void
+svr_session_cleanup(void)
+{
+ /* free potential public key options */
+ svr_pubkey_options_cleanup();
+}
+
void svr_session(int sock, int childpipe) {
char *host, *port;
size_t len;
@@ -103,10 +110,10 @@ void svr_session(int sock, int childpipe) {
/* set up messages etc */
ses.remoteclosed = svr_remoteclosed;
+ ses.extra_session_cleanup = svr_session_cleanup;
/* packet handlers */
ses.packettypes = svr_packettypes;
- ses.buf_match_algo = svr_buf_match_algo;
ses.isserver = 1;
@@ -114,7 +121,7 @@ void svr_session(int sock, int childpipe) {
sessinitdone = 1;
/* exchange identification, version etc */
- session_identification();
+ send_session_identification();
/* start off with key exchange */
send_msg_kexinit();
@@ -160,11 +167,8 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
if (svr_ses.server_pid == getpid())
#endif
{
- /* free potential public key options */
- svr_pubkey_options_cleanup();
-
/* must be after we've done with username etc */
- common_session_cleanup();
+ session_cleanup();
}
exit(exitcode);
diff --git a/sysoptions.h b/sysoptions.h
index d2ef0ab..c36ab8b 100644
--- a/sysoptions.h
+++ b/sysoptions.h
@@ -4,7 +4,7 @@
*******************************************************************/
#ifndef DROPBEAR_VERSION
-#define DROPBEAR_VERSION "2013.56"
+#define DROPBEAR_VERSION "2013.58"
#endif
#define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION
@@ -23,6 +23,15 @@
#define AUTH_TIMEOUT 300 /* we choose 5 minutes */
#endif
+/* A client should try and send an initial key exchange packet guessing
+ * the algorithm that will match - saves a round trip connecting, has little
+ * overhead if the guess was "wrong". */
+#define USE_KEX_FIRST_FOLLOWS
+/* Use protocol extension to allow "first follows" to succeed more frequently.
+ * This is currently Dropbear-specific but will gracefully fallback when connecting
+ * to other implementations. */
+#define USE_KEXGUESS2
+
/* Minimum key sizes for DSS and RSA */
#ifndef MIN_DSS_KEYLEN
#define MIN_DSS_KEYLEN 512
diff --git a/termcodes.c b/termcodes.c
index d59505c..490e6ce 100644
--- a/termcodes.c
+++ b/termcodes.c
@@ -107,8 +107,14 @@ const struct TermCode termcodes[MAX_TERMCODE+1] = {
#else
{0, 0},
#endif
- {0, 0}, /* 42 */
+ /* IUTF8 isn't standardised in rfc4254 but is likely soon.
+ * Implemented by linux and darwin */
+#ifdef IUTF8
+ {IUTF8, TERMCODE_INPUT},
+#else
{0, 0},
+#endif
+ {0, 0}, /* 43 */
{0, 0},
{0, 0},
{0, 0},