upstream commit
avoid more fatal/exit in the packet.c paths that
ssh-keyscan uses; feedback and "looks good" markus@
diff --git a/dispatch.c b/dispatch.c
index 9ff5e3d..900a2c1 100644
--- a/dispatch.c
+++ b/dispatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dispatch.c,v 1.24 2015/01/28 22:05:31 djm Exp $ */
+/* $OpenBSD: dispatch.c,v 1.25 2015/01/30 01:13:33 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -49,9 +49,9 @@
fatal("protocol error");
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- ssh_packet_write_wait(ssh);
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ sshpkt_fatal(ssh, __func__, r);
return 0;
}
diff --git a/opacket.c b/opacket.c
index a137b5a..7618eae 100644
--- a/opacket.c
+++ b/opacket.c
@@ -223,6 +223,8 @@
packet_set_connection(int fd_in, int fd_out)
{
active_state = ssh_packet_set_connection(active_state, fd_in, fd_out);
+ if (active_state == NULL)
+ fatal("%s: ssh_packet_set_connection failed", __func__);
}
void
@@ -255,20 +257,8 @@
u_char type;
int r;
- if ((r = ssh_packet_read_seqnr(active_state, &type, seqnr)) != 0) {
- switch (r) {
- case SSH_ERR_CONN_CLOSED:
- logit("Connection closed by %.200s",
- ssh_remote_ipaddr(active_state));
- cleanup_exit(255);
- case SSH_ERR_CONN_TIMEOUT:
- logit("Connection to %.200s timed out while "
- "waiting to read", ssh_remote_ipaddr(active_state));
- cleanup_exit(255);
- default:
- fatal("%s: %s", __func__, ssh_err(r));
- }
- }
+ if ((r = ssh_packet_read_seqnr(active_state, &type, seqnr)) != 0)
+ sshpkt_fatal(active_state, __func__, r);
return type;
}
@@ -279,7 +269,7 @@
int r;
if ((r = ssh_packet_read_poll_seqnr(active_state, &type, seqnr)))
- fatal("%s: %s", __func__, ssh_err(r));
+ sshpkt_fatal(active_state, __func__, r);
return type;
}
@@ -296,5 +286,32 @@
int r;
if ((r = ssh_packet_process_incoming(active_state, buf, len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ sshpkt_fatal(active_state, __func__, r);
+}
+
+void
+packet_write_wait(void)
+{
+ int r;
+
+ if ((r = ssh_packet_write_wait(active_state)) != 0)
+ sshpkt_fatal(active_state, __func__, r);
+}
+
+void
+packet_write_poll(void)
+{
+ int r;
+
+ if ((r = ssh_packet_write_poll(active_state)) != 0)
+ sshpkt_fatal(active_state, __func__, r);
+}
+
+void
+packet_read_expect(int expected_type)
+{
+ int r;
+
+ if ((r = ssh_packet_read_expect(active_state, expected_type)) != 0)
+ sshpkt_fatal(active_state, __func__, r);
}
diff --git a/opacket.h b/opacket.h
index 261ed1f..e563d8d 100644
--- a/opacket.h
+++ b/opacket.h
@@ -45,6 +45,9 @@
int packet_read_seqnr(u_int32_t *);
int packet_read_poll_seqnr(u_int32_t *);
void packet_process_incoming(const char *buf, u_int len);
+void packet_write_wait(void);
+void packet_write_poll(void);
+void packet_read_expect(int expected_type);
#define packet_set_timeout(timeout, count) \
ssh_packet_set_timeout(active_state, (timeout), (count))
#define packet_connection_is_on_socket() \
@@ -85,8 +88,6 @@
ssh_packet_send(active_state)
#define packet_read() \
ssh_packet_read(active_state)
-#define packet_read_expect(expected_type) \
- ssh_packet_read_expect(active_state, (expected_type))
#define packet_get_int64() \
ssh_packet_get_int64(active_state)
#define packet_get_bignum(value) \
@@ -105,10 +106,6 @@
ssh_packet_send_debug(active_state, (fmt), ##args)
#define packet_disconnect(fmt, args...) \
ssh_packet_disconnect(active_state, (fmt), ##args)
-#define packet_write_poll() \
- ssh_packet_write_poll(active_state)
-#define packet_write_wait() \
- ssh_packet_write_wait(active_state)
#define packet_have_data_to_write() \
ssh_packet_have_data_to_write(active_state)
#define packet_not_very_much_data_to_write() \
diff --git a/packet.c b/packet.c
index eb178f1..f9ce084 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.204 2015/01/28 21:15:47 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.205 2015/01/30 01:13:33 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -272,20 +272,26 @@
const struct sshcipher *none = cipher_by_name("none");
int r;
- if (none == NULL)
- fatal("%s: cannot load cipher 'none'", __func__);
+ if (none == NULL) {
+ error("%s: cannot load cipher 'none'", __func__);
+ return NULL;
+ }
if (ssh == NULL)
ssh = ssh_alloc_session_state();
- if (ssh == NULL)
- fatal("%s: cound not allocate state", __func__);
+ if (ssh == NULL) {
+ error("%s: cound not allocate state", __func__);
+ return NULL;
+ }
state = ssh->state;
state->connection_in = fd_in;
state->connection_out = fd_out;
if ((r = cipher_init(&state->send_context, none,
(const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
(r = cipher_init(&state->receive_context, none,
- (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0)
- fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
+ (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) {
+ error("%s: cipher_init failed: %s", __func__, ssh_err(r));
+ return NULL;
+ }
state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
deattack_init(&state->deattack);
return ssh;
@@ -893,8 +899,8 @@
/*
* Note that the packet is now only buffered in output. It won't be
- * actually sent until packet_write_wait or packet_write_poll is
- * called.
+ * actually sent until ssh_packet_write_wait or ssh_packet_write_poll
+ * is called.
*/
r = 0;
out:
@@ -1263,8 +1269,12 @@
if (setp == NULL)
return SSH_ERR_ALLOC_FAIL;
- /* Since we are blocking, ensure that all written packets have been sent. */
- ssh_packet_write_wait(ssh);
+ /*
+ * Since we are blocking, ensure that all written packets have
+ * been sent.
+ */
+ if ((r = ssh_packet_write_wait(ssh)) != 0)
+ return r;
/* Stay in the loop until we have received a complete packet. */
for (;;) {
@@ -1351,16 +1361,22 @@
* that given, and gives a fatal error and exits if there is a mismatch.
*/
-void
-ssh_packet_read_expect(struct ssh *ssh, int expected_type)
+int
+ssh_packet_read_expect(struct ssh *ssh, u_int expected_type)
{
- int type;
+ int r;
+ u_char type;
- type = ssh_packet_read(ssh);
- if (type != expected_type)
- ssh_packet_disconnect(ssh,
+ if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
+ return r;
+ if (type != expected_type) {
+ if ((r = sshpkt_disconnect(ssh,
"Protocol error: expected packet type %d, got %d",
- expected_type, type);
+ expected_type, type)) != 0)
+ return r;
+ return SSH_ERR_PROTOCOL_ERROR;
+ }
+ return 0;
}
/* Checks if a full packet is available in the data received so far via
@@ -1377,6 +1393,7 @@
{
struct session_state *state = ssh->state;
u_int len, padded_len;
+ const char *emsg;
const u_char *cp;
u_char *p;
u_int checksum, stored_checksum;
@@ -1389,9 +1406,12 @@
return 0;
/* Get length of incoming packet. */
len = PEEK_U32(sshbuf_ptr(state->input));
- if (len < 1 + 2 + 2 || len > 256 * 1024)
- ssh_packet_disconnect(ssh, "Bad packet length %u.",
- len);
+ if (len < 1 + 2 + 2 || len > 256 * 1024) {
+ if ((r = sshpkt_disconnect(ssh, "Bad packet length %u",
+ len)) != 0)
+ return r;
+ return SSH_ERR_CONN_CORRUPT;
+ }
padded_len = (len + 8) & ~7;
/* Check if the packet has been entirely received. */
@@ -1410,19 +1430,27 @@
* Ariel Futoransky(futo@core-sdi.com)
*/
if (!state->receive_context.plaintext) {
+ emsg = NULL;
switch (detect_attack(&state->deattack,
sshbuf_ptr(state->input), padded_len)) {
case DEATTACK_OK:
break;
case DEATTACK_DETECTED:
- ssh_packet_disconnect(ssh,
- "crc32 compensation attack: network attack detected"
- );
+ emsg = "crc32 compensation attack detected";
+ break;
case DEATTACK_DOS_DETECTED:
- ssh_packet_disconnect(ssh,
- "deattack denial of service detected");
+ emsg = "deattack denial of service detected";
+ break;
default:
- ssh_packet_disconnect(ssh, "deattack error");
+ emsg = "deattack error";
+ break;
+ }
+ if (emsg != NULL) {
+ error("%s", emsg);
+ if ((r = sshpkt_disconnect(ssh, "%s", emsg)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ return r;
+ return SSH_ERR_CONN_CORRUPT;
}
}
@@ -1451,16 +1479,24 @@
goto out;
/* Test check bytes. */
- if (len != sshbuf_len(state->incoming_packet))
- ssh_packet_disconnect(ssh,
- "packet_read_poll1: len %d != sshbuf_len %zd.",
+ if (len != sshbuf_len(state->incoming_packet)) {
+ error("%s: len %d != sshbuf_len %zd", __func__,
len, sshbuf_len(state->incoming_packet));
+ if ((r = sshpkt_disconnect(ssh, "invalid packet length")) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ return r;
+ return SSH_ERR_CONN_CORRUPT;
+ }
cp = sshbuf_ptr(state->incoming_packet) + len - 4;
stored_checksum = PEEK_U32(cp);
- if (checksum != stored_checksum)
- ssh_packet_disconnect(ssh,
- "Corrupted check bytes on input.");
+ if (checksum != stored_checksum) {
+ error("Corrupted check bytes on input");
+ if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ return r;
+ return SSH_ERR_CONN_CORRUPT;
+ }
if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0)
goto out;
@@ -1478,9 +1514,13 @@
state->p_read.bytes += padded_len + 4;
if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
goto out;
- if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX)
- ssh_packet_disconnect(ssh,
- "Invalid ssh1 packet type: %d", *typep);
+ if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX) {
+ error("Invalid ssh1 packet type: %d", *typep);
+ if ((r = sshpkt_disconnect(ssh, "invalid packet type")) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ return r;
+ return SSH_ERR_PROTOCOL_ERROR;
+ }
r = 0;
out:
return r;
@@ -1634,7 +1674,6 @@
if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
goto out;
}
- /* XXX now it's safe to use fatal/packet_disconnect */
if (seqnr_p != NULL)
*seqnr_p = state->p_read.seqnr;
if (++state->p_read.seqnr == 0)
@@ -1648,9 +1687,13 @@
/* get padlen */
padlen = sshbuf_ptr(state->incoming_packet)[4];
DBG(debug("input: padlen %d", padlen));
- if (padlen < 4)
- ssh_packet_disconnect(ssh,
- "Corrupted padlen %d on input.", padlen);
+ if (padlen < 4) {
+ if ((r = sshpkt_disconnect(ssh,
+ "Corrupted padlen %d on input.", padlen)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ return r;
+ return SSH_ERR_CONN_CORRUPT;
+ }
/* skip packet size + padlen, discard padding */
if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 ||
@@ -1677,9 +1720,13 @@
*/
if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
goto out;
- if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN)
- ssh_packet_disconnect(ssh,
- "Invalid ssh2 packet type: %d", *typep);
+ if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) {
+ if ((r = sshpkt_disconnect(ssh,
+ "Invalid ssh2 packet type: %d", *typep)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ return r;
+ return SSH_ERR_PROTOCOL_ERROR;
+ }
if (*typep == SSH2_MSG_NEWKEYS)
r = ssh_set_newkeys(ssh, MODE_IN);
else if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
@@ -1816,9 +1863,8 @@
* message is printed immediately, but only if the client is being executed
* in verbose mode. These messages are primarily intended to ease debugging
* authentication problems. The length of the formatted message must not
- * exceed 1024 bytes. This will automatically call packet_write_wait.
+ * exceed 1024 bytes. This will automatically call ssh_packet_write_wait.
*/
-
void
ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
{
@@ -1846,7 +1892,29 @@
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
}
- ssh_packet_write_wait(ssh);
+ if ((r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+}
+
+/*
+ * Pretty-print connection-terminating errors and exit.
+ */
+void
+sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
+{
+ switch (r) {
+ case SSH_ERR_CONN_CLOSED:
+ logit("Connection closed by %.200s", ssh_remote_ipaddr(ssh));
+ cleanup_exit(255);
+ case SSH_ERR_CONN_TIMEOUT:
+ logit("Connection to %.200s timed out while "
+ "waiting to write", ssh_remote_ipaddr(ssh));
+ cleanup_exit(255);
+ default:
+ fatal("%s%sConnection to %.200s: %s",
+ tag != NULL ? tag : "", tag != NULL ? ": " : "",
+ ssh_remote_ipaddr(ssh), ssh_err(r));
+ }
}
/*
@@ -1855,7 +1923,6 @@
* should not contain a newline. The length of the formatted message must
* not exceed 1024 bytes.
*/
-
void
ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
{
@@ -1879,30 +1946,26 @@
/* Display the error locally */
logit("Disconnecting: %.100s", buf);
- /* Send the disconnect message to the other side, and wait for it to get sent. */
- if (compat20) {
- if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
- (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
- (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
- (r = sshpkt_put_cstring(ssh, "")) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- } else {
- if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 ||
- (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- }
- ssh_packet_write_wait(ssh);
+ /*
+ * Send the disconnect message to the other side, and wait
+ * for it to get sent.
+ */
+ if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0)
+ sshpkt_fatal(ssh, __func__, r);
+
+ if ((r = ssh_packet_write_wait(ssh)) != 0)
+ sshpkt_fatal(ssh, __func__, r);
/* Close the connection. */
ssh_packet_close(ssh);
cleanup_exit(255);
}
-/* Checks if there is any buffered output, and tries to write some of the output. */
-
-void
+/*
+ * Checks if there is any buffered output, and tries to write some of
+ * the output.
+ */
+int
ssh_packet_write_poll(struct ssh *ssh)
{
struct session_state *state = ssh->state;
@@ -1916,33 +1979,33 @@
if (len == -1) {
if (errno == EINTR || errno == EAGAIN ||
errno == EWOULDBLOCK)
- return;
- fatal("Write failed: %.100s", strerror(errno));
+ return 0;
+ return SSH_ERR_SYSTEM_ERROR;
}
if (len == 0 && !cont)
- fatal("Write connection closed");
+ return SSH_ERR_CONN_CLOSED;
if ((r = sshbuf_consume(state->output, len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ return r;
}
+ return 0;
}
/*
* Calls packet_write_poll repeatedly until all pending output data has been
* written.
*/
-
-void
+int
ssh_packet_write_wait(struct ssh *ssh)
{
fd_set *setp;
- int ret, ms_remain = 0;
+ int ret, r, ms_remain = 0;
struct timeval start, timeout, *timeoutp = NULL;
struct session_state *state = ssh->state;
setp = (fd_set *)calloc(howmany(state->connection_out + 1,
NFDBITS), sizeof(fd_mask));
if (setp == NULL)
- fatal("%s: calloc failed", __func__);
+ return SSH_ERR_ALLOC_FAIL;
ssh_packet_write_poll(ssh);
while (ssh_packet_have_data_to_write(ssh)) {
memset(setp, 0, howmany(state->connection_out + 1,
@@ -1973,13 +2036,16 @@
}
}
if (ret == 0) {
- logit("Connection to %.200s timed out while "
- "waiting to write", ssh_remote_ipaddr(ssh));
- cleanup_exit(255);
+ free(setp);
+ return SSH_ERR_CONN_TIMEOUT;
}
- ssh_packet_write_poll(ssh);
+ if ((r = ssh_packet_write_poll(ssh)) != 0) {
+ free(setp);
+ return r;
+ }
}
free(setp);
+ return 0;
}
/* Returns true if there is buffered data to write to the connection. */
diff --git a/packet.h b/packet.h
index 8a9d0f6..01df9f4 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.65 2015/01/28 21:15:47 djm Exp $ */
+/* $OpenBSD: packet.h,v 1.66 2015/01/30 01:13:33 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -90,7 +90,7 @@
int ssh_packet_send2(struct ssh *);
int ssh_packet_read(struct ssh *);
-void ssh_packet_read_expect(struct ssh *, int type);
+int ssh_packet_read_expect(struct ssh *, u_int type);
int ssh_packet_read_poll(struct ssh *);
int ssh_packet_read_poll1(struct ssh *, u_char *);
int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p);
@@ -112,8 +112,8 @@
void ssh_packet_set_compress_hooks(struct ssh *, void *,
ssh_packet_comp_alloc_func *, ssh_packet_comp_free_func *);
-void ssh_packet_write_poll(struct ssh *);
-void ssh_packet_write_wait(struct ssh *);
+int ssh_packet_write_poll(struct ssh *);
+int ssh_packet_write_wait(struct ssh *);
int ssh_packet_have_data_to_write(struct ssh *);
int ssh_packet_not_very_much_data_to_write(struct ssh *);
@@ -148,8 +148,10 @@
/* new API */
int sshpkt_start(struct ssh *ssh, u_char type);
int sshpkt_send(struct ssh *ssh);
-int sshpkt_disconnect(struct ssh *, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
+int sshpkt_disconnect(struct ssh *, const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
int sshpkt_add_padding(struct ssh *, u_char);
+void sshpkt_fatal(struct ssh *ssh, const char *tag, int r);
int sshpkt_put(struct ssh *ssh, const void *v, size_t len);
int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b);
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index e59eaca..989f7ec 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keyscan.c,v 1.97 2015/01/28 21:15:47 djm Exp $ */
+/* $OpenBSD: ssh-keyscan.c,v 1.98 2015/01/30 01:13:33 djm Exp $ */
/*
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
@@ -466,7 +466,8 @@
return;
}
*cp = '\0';
- c->c_ssh = ssh_packet_set_connection(NULL, s, s);
+ if ((c->c_ssh = ssh_packet_set_connection(NULL, s, s)) == NULL)
+ fatal("ssh_packet_set_connection failed");
ssh_set_app_data(c->c_ssh, c); /* back link */
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
&remote_major, &remote_minor, remote_version) == 3)
diff --git a/ssh_api.c b/ssh_api.c
index 9794e0e..7097c06 100644
--- a/ssh_api.c
+++ b/ssh_api.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh_api.c,v 1.2 2015/01/26 06:10:03 djm Exp $ */
+/* $OpenBSD: ssh_api.c,v 1.3 2015/01/30 01:13:33 djm Exp $ */
/*
* Copyright (c) 2012 Markus Friedl. All rights reserved.
*
@@ -85,7 +85,8 @@
called = 1;
}
- ssh = ssh_packet_set_connection(NULL, -1, -1);
+ if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
if (is_server)
ssh_packet_set_server(ssh);
diff --git a/ssherr.c b/ssherr.c
index 0b79fbb..5c29c46 100644
--- a/ssherr.c
+++ b/ssherr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssherr.c,v 1.2 2015/01/28 21:15:47 djm Exp $ */
+/* $OpenBSD: ssherr.c,v 1.3 2015/01/30 01:13:33 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -129,6 +129,10 @@
return "Connection closed";
case SSH_ERR_CONN_TIMEOUT:
return "Connection timed out";
+ case SSH_ERR_CONN_CORRUPT:
+ return "Connection corrupted";
+ case SSH_ERR_PROTOCOL_ERROR:
+ return "Protocol error";
default:
return "unknown error";
}
diff --git a/ssherr.h b/ssherr.h
index ac5cd15..6f771b4 100644
--- a/ssherr.h
+++ b/ssherr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssherr.h,v 1.2 2015/01/28 21:15:47 djm Exp $ */
+/* $OpenBSD: ssherr.h,v 1.3 2015/01/30 01:13:33 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -75,6 +75,8 @@
#define SSH_ERR_KEY_REVOKED -51
#define SSH_ERR_CONN_CLOSED -52
#define SSH_ERR_CONN_TIMEOUT -53
+#define SSH_ERR_CONN_CORRUPT -54
+#define SSH_ERR_PROTOCOL_ERROR -55
/* Translate a numeric error code to a human-readable error string */
const char *ssh_err(int n);