|
@@ -299,16 +299,16 @@ enum {
|
|
|
* Coroutine mechanics for the sillier bits of the code. If these
|
|
|
* macros look impenetrable to you, you might find it helpful to
|
|
|
* read
|
|
|
- *
|
|
|
+ *
|
|
|
* http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
|
|
|
- *
|
|
|
+ *
|
|
|
* which explains the theory behind these macros.
|
|
|
- *
|
|
|
+ *
|
|
|
* In particular, if you are getting `case expression not constant'
|
|
|
* errors when building with MS Visual Studio, this is because MS's
|
|
|
* Edit and Continue debugging feature causes their compiler to
|
|
|
* violate ANSI C. To disable Edit and Continue debugging:
|
|
|
- *
|
|
|
+ *
|
|
|
* - right-click ssh.c in the FileView
|
|
|
* - click Settings
|
|
|
* - select the C/C++ tab and the General category
|
|
@@ -369,20 +369,20 @@ static void ssh2_msg_something_unimplemented(Ssh ssh, struct Packet *pktin);
|
|
|
/*
|
|
|
* Buffer management constants. There are several of these for
|
|
|
* various different purposes:
|
|
|
- *
|
|
|
+ *
|
|
|
* - SSH1_BUFFER_LIMIT is the amount of backlog that must build up
|
|
|
* on a local data stream before we throttle the whole SSH
|
|
|
* connection (in SSH-1 only). Throttling the whole connection is
|
|
|
* pretty drastic so we set this high in the hope it won't
|
|
|
* happen very often.
|
|
|
- *
|
|
|
+ *
|
|
|
* - SSH_MAX_BACKLOG is the amount of backlog that must build up
|
|
|
* on the SSH connection itself before we defensively throttle
|
|
|
* _all_ local data streams. This is pretty drastic too (though
|
|
|
* thankfully unlikely in SSH-2 since the window mechanism should
|
|
|
* ensure that the server never has any need to throttle its end
|
|
|
* of the connection), so we set this high as well.
|
|
|
- *
|
|
|
+ *
|
|
|
* - OUR_V2_WINSIZE is the maximum window size we present on SSH-2
|
|
|
* channels.
|
|
|
*
|
|
@@ -496,12 +496,12 @@ struct ssh_channel {
|
|
|
int halfopen;
|
|
|
/*
|
|
|
* In SSH-1, this value contains four bits:
|
|
|
- *
|
|
|
+ *
|
|
|
* 1 We have sent SSH1_MSG_CHANNEL_CLOSE.
|
|
|
* 2 We have sent SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.
|
|
|
* 4 We have received SSH1_MSG_CHANNEL_CLOSE.
|
|
|
* 8 We have received SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.
|
|
|
- *
|
|
|
+ *
|
|
|
* A channel is completely finished with when all four bits are set.
|
|
|
*
|
|
|
* In SSH-2, the four bits mean:
|
|
@@ -582,7 +582,7 @@ struct ssh_channel {
|
|
|
* 2-3-4 tree storing remote->local port forwardings. SSH-1 and SSH-2
|
|
|
* use this structure in different ways, reflecting SSH-2's
|
|
|
* altogether saner approach to port forwarding.
|
|
|
- *
|
|
|
+ *
|
|
|
* In SSH-1, you arrange a remote forwarding by sending the server
|
|
|
* the remote port number, and the local destination host:port.
|
|
|
* When a connection comes in, the server sends you back that
|
|
@@ -594,14 +594,14 @@ struct ssh_channel {
|
|
|
* through it to a dodgy SSH server. Hence, we must store a list of
|
|
|
* host:port pairs we _are_ trying to forward to, and reject a
|
|
|
* connection request from the server if it's not in the list.
|
|
|
- *
|
|
|
+ *
|
|
|
* In SSH-2, each side of the connection minds its own business and
|
|
|
* doesn't send unnecessary information to the other. You arrange a
|
|
|
* remote forwarding by sending the server just the remote port
|
|
|
* number. When a connection comes in, the server tells you which
|
|
|
* of its ports was connected to; and _you_ have to remember what
|
|
|
* local host:port pair went with that port number.
|
|
|
- *
|
|
|
+ *
|
|
|
* Hence, in SSH-1 this structure is indexed by destination
|
|
|
* host:port pair, whereas in SSH-2 it is indexed by source port.
|
|
|
*/
|
|
@@ -1644,7 +1644,7 @@ static struct Packet *ssh2_rdpkt(Ssh ssh, const unsigned char **data,
|
|
|
bombout(("No valid incoming packet found"));
|
|
|
ssh_free_packet(st->pktin);
|
|
|
crStop(NULL);
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
st->pktin->maxlen = st->packetlen + st->maclen;
|
|
|
st->pktin->data = sresize(st->pktin->data,
|
|
@@ -2345,23 +2345,23 @@ static int ssh2_pkt_construct(Ssh ssh, struct Packet *pkt)
|
|
|
* Routines called from the main SSH code to send packets. There
|
|
|
* are quite a few of these, because we have two separate
|
|
|
* mechanisms for delaying the sending of packets:
|
|
|
- *
|
|
|
+ *
|
|
|
* - In order to send an IGNORE message and a password message in
|
|
|
* a single fixed-length blob, we require the ability to
|
|
|
* concatenate the encrypted forms of those two packets _into_ a
|
|
|
* single blob and then pass it to our <network.h> transport
|
|
|
* layer in one go. Hence, there's a deferment mechanism which
|
|
|
* works after packet encryption.
|
|
|
- *
|
|
|
+ *
|
|
|
* - In order to avoid sending any connection-layer messages
|
|
|
* during repeat key exchange, we have to queue up any such
|
|
|
* outgoing messages _before_ they are encrypted (and in
|
|
|
* particular before they're allocated sequence numbers), and
|
|
|
* then send them once we've finished.
|
|
|
- *
|
|
|
+ *
|
|
|
* I call these mechanisms `defer' and `queue' respectively, so as
|
|
|
* to distinguish them reasonably easily.
|
|
|
- *
|
|
|
+ *
|
|
|
* The functions send_noqueue() and defer_noqueue() free the packet
|
|
|
* structure they are passed. Every outgoing packet goes through
|
|
|
* precisely one of these functions in its life; packets passed to
|
|
@@ -2483,7 +2483,7 @@ static void ssh2_pkt_defer(Ssh ssh, struct Packet *pkt)
|
|
|
/*
|
|
|
* Send the whole deferred data block constructed by
|
|
|
* ssh2_pkt_defer() or SSH-1's defer_packet().
|
|
|
- *
|
|
|
+ *
|
|
|
* The expected use of the defer mechanism is that you call
|
|
|
* ssh2_pkt_defer() a few times, then call ssh_pkt_defersend(). If
|
|
|
* not currently queueing, this simply sets up deferred_send_data
|
|
@@ -2526,7 +2526,7 @@ static void ssh2_pkt_send_with_padding(Ssh ssh, struct Packet *pkt,
|
|
|
/*
|
|
|
* The simplest way to do this is to adjust the
|
|
|
* variable-length padding field in the outgoing packet.
|
|
|
- *
|
|
|
+ *
|
|
|
* Currently compiled out, because some Cisco SSH servers
|
|
|
* don't like excessively padded packets (bah, why's it
|
|
|
* always Cisco?)
|
|
@@ -2680,7 +2680,7 @@ static int ssh1_pkt_getrsakey(struct Packet *pkt, struct RSAKey *key,
|
|
|
|
|
|
if (j < 0)
|
|
|
return FALSE;
|
|
|
-
|
|
|
+
|
|
|
pkt->savedpos += j;
|
|
|
assert(pkt->savedpos < pkt->length);
|
|
|
|
|
@@ -3064,7 +3064,7 @@ static int do_ssh_init(Ssh ssh, unsigned char c)
|
|
|
int proto1, proto2;
|
|
|
};
|
|
|
crState(do_ssh_init_state);
|
|
|
-
|
|
|
+
|
|
|
crBeginState;
|
|
|
|
|
|
/* Search for a line beginning with the protocol name prefix in
|
|
@@ -3153,7 +3153,7 @@ static int do_ssh_init(Ssh ssh, unsigned char c)
|
|
|
ssh->v_s = snewn(len + 1, char);
|
|
|
memcpy(ssh->v_s, s->vstring, len);
|
|
|
ssh->v_s[len] = 0;
|
|
|
-
|
|
|
+
|
|
|
/*
|
|
|
* Initialise SSH-2 protocol.
|
|
|
*/
|
|
@@ -3203,7 +3203,7 @@ static int do_ssh_connection_init(Ssh ssh, unsigned char c)
|
|
|
int i;
|
|
|
};
|
|
|
crState(do_ssh_connection_init_state);
|
|
|
-
|
|
|
+
|
|
|
crBeginState;
|
|
|
|
|
|
/* Search for a line beginning with the protocol name prefix in
|
|
@@ -3981,7 +3981,7 @@ static int do_ssh1_login(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
memcpy(cookie, ptr, 8);
|
|
|
|
|
|
if (!ssh1_pkt_getrsakey(pktin, &s->servkey, &s->keystr1) ||
|
|
|
- !ssh1_pkt_getrsakey(pktin, &s->hostkey, &s->keystr2)) {
|
|
|
+ !ssh1_pkt_getrsakey(pktin, &s->hostkey, &s->keystr2)) {
|
|
|
bombout(("Failed to read SSH-1 public keys from public key packet"));
|
|
|
crStop(0);
|
|
|
}
|
|
@@ -4101,7 +4101,7 @@ static int do_ssh1_login(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
}
|
|
|
if (!ret) {
|
|
|
bombout(("SSH-1 public key encryptions failed due to bad formatting"));
|
|
|
- crStop(0);
|
|
|
+ crStop(0);
|
|
|
}
|
|
|
|
|
|
logevent("Encrypted session key");
|
|
@@ -4786,29 +4786,29 @@ static int do_ssh1_login(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
* SSH1_MSG_IGNORE packets. This way a passive
|
|
|
* listener can't tell which is the password, and
|
|
|
* hence can't deduce the password length.
|
|
|
- *
|
|
|
+ *
|
|
|
* Anybody with a password length greater than 16
|
|
|
* bytes is going to have enough entropy in their
|
|
|
* password that a listener won't find it _that_
|
|
|
* much help to know how long it is. So what we'll
|
|
|
* do is:
|
|
|
- *
|
|
|
+ *
|
|
|
* - if password length < 16, we send 15 packets
|
|
|
* containing string lengths 1 through 15
|
|
|
- *
|
|
|
+ *
|
|
|
* - otherwise, we let N be the nearest multiple
|
|
|
* of 8 below the password length, and send 8
|
|
|
* packets containing string lengths N through
|
|
|
* N+7. This won't obscure the order of
|
|
|
* magnitude of the password length, but it will
|
|
|
* introduce a bit of extra uncertainty.
|
|
|
- *
|
|
|
+ *
|
|
|
* A few servers can't deal with SSH1_MSG_IGNORE, at
|
|
|
* least in this context. For these servers, we need
|
|
|
* an alternative defence. We make use of the fact
|
|
|
* that the password is interpreted as a C string:
|
|
|
* so we can append a NUL, then some random data.
|
|
|
- *
|
|
|
+ *
|
|
|
* A few servers can deal with neither SSH1_MSG_IGNORE
|
|
|
* here _nor_ a padded password string.
|
|
|
* For these servers we are left with no defences
|
|
@@ -4855,7 +4855,7 @@ static int do_ssh1_login(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
logevent("Sending password with camouflage packets");
|
|
|
ssh_pkt_defersend(ssh);
|
|
|
sfree(randomstr);
|
|
|
- }
|
|
|
+ }
|
|
|
else if (!(ssh->remote_bugs & BUG_NEEDS_SSH1_PLAIN_PASSWORD)) {
|
|
|
/*
|
|
|
* The server can't deal with SSH1_MSG_IGNORE
|
|
@@ -5848,7 +5848,7 @@ static void do_ssh1_connection(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
{
|
|
|
crBegin(ssh->do_ssh1_connection_crstate);
|
|
|
|
|
|
- ssh->packet_dispatch[SSH1_SMSG_STDOUT_DATA] =
|
|
|
+ ssh->packet_dispatch[SSH1_SMSG_STDOUT_DATA] =
|
|
|
ssh->packet_dispatch[SSH1_SMSG_STDERR_DATA] =
|
|
|
ssh1_smsg_stdout_stderr_data;
|
|
|
|
|
@@ -5989,14 +5989,14 @@ static void do_ssh1_connection(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
|
|
|
/*
|
|
|
* Start the shell or command.
|
|
|
- *
|
|
|
+ *
|
|
|
* Special case: if the first-choice command is an SSH-2
|
|
|
* subsystem (hence not usable here) and the second choice
|
|
|
* exists, we fall straight back to that.
|
|
|
*/
|
|
|
{
|
|
|
char *cmd = conf_get_str(ssh->conf, CONF_remote_cmd);
|
|
|
-
|
|
|
+
|
|
|
if (conf_get_int(ssh->conf, CONF_ssh_subsys) &&
|
|
|
conf_get_str(ssh->conf, CONF_remote_cmd2)) {
|
|
|
cmd = conf_get_str(ssh->conf, CONF_remote_cmd2);
|
|
@@ -6587,7 +6587,7 @@ static void do_ssh2_transport(Ssh ssh, const void *vin, int inlen,
|
|
|
|
|
|
s->our_kexinitlen = s->pktout->length - 5;
|
|
|
s->our_kexinit = snewn(s->our_kexinitlen, unsigned char);
|
|
|
- memcpy(s->our_kexinit, s->pktout->data + 5, s->our_kexinitlen);
|
|
|
+ memcpy(s->our_kexinit, s->pktout->data + 5, s->our_kexinitlen);
|
|
|
|
|
|
ssh2_pkt_send_noqueue(ssh, s->pktout);
|
|
|
|
|
@@ -7404,7 +7404,7 @@ static void do_ssh2_transport(Ssh ssh, const void *vin, int inlen,
|
|
|
* function so that other things can run on top of the
|
|
|
* transport. If we ever see a KEXINIT, we must go back to the
|
|
|
* start.
|
|
|
- *
|
|
|
+ *
|
|
|
* We _also_ go back to the start if we see pktin==NULL and
|
|
|
* inlen negative, because this is a special signal meaning
|
|
|
* `initiate client-driven rekey', and `in' contains a message
|
|
@@ -7430,7 +7430,7 @@ static void do_ssh2_transport(Ssh ssh, const void *vin, int inlen,
|
|
|
logevent("Server initiated key re-exchange");
|
|
|
} else {
|
|
|
if (inlen == -2) {
|
|
|
- /*
|
|
|
+ /*
|
|
|
* authconn has seen a USERAUTH_SUCCEEDED. Time to enable
|
|
|
* delayed compression, if it's available.
|
|
|
*
|
|
@@ -8906,7 +8906,7 @@ static void ssh2_setup_env(struct ssh_channel *c, struct Packet *pktin,
|
|
|
|
|
|
/*
|
|
|
* Send environment variables.
|
|
|
- *
|
|
|
+ *
|
|
|
* Simplest thing here is to send all the requests at once, and
|
|
|
* then wait for a whole bunch of successes or failures.
|
|
|
*/
|
|
@@ -9051,7 +9051,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
ssh->packet_dispatch[SSH2_MSG_CHANNEL_EXTENDED_DATA] = ssh2_msg_authconn;
|
|
|
ssh->packet_dispatch[SSH2_MSG_CHANNEL_EOF] = ssh2_msg_authconn;
|
|
|
ssh->packet_dispatch[SSH2_MSG_CHANNEL_CLOSE] = ssh2_msg_authconn;
|
|
|
-
|
|
|
+
|
|
|
s->done_service_req = FALSE;
|
|
|
s->we_are_in = s->userauth_success = FALSE;
|
|
|
s->agent_response = NULL;
|
|
@@ -9119,7 +9119,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
s->publickey_blob =
|
|
|
ssh2_userkey_loadpub(s->keyfile,
|
|
|
&s->publickey_algorithm,
|
|
|
- &s->publickey_bloblen,
|
|
|
+ &s->publickey_bloblen,
|
|
|
&s->publickey_comment, &error);
|
|
|
if (s->publickey_blob) {
|
|
|
s->privatekey_available = (keytype == SSH_KEYTYPE_SSH2);
|
|
@@ -9129,7 +9129,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
ssh2_userkey_encrypted(s->keyfile, NULL);
|
|
|
} else {
|
|
|
char *msgbuf;
|
|
|
- logeventf(ssh, "Unable to load key (%s)",
|
|
|
+ logeventf(ssh, "Unable to load key (%s)",
|
|
|
error);
|
|
|
msgbuf = dupprintf(MPEXT_BOM "Unable to load key file "
|
|
|
"\"%.150s\" (%s)\r\n",
|
|
@@ -9266,16 +9266,16 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
* beginning to try another username, if this is configured on.
|
|
|
* (If they specify a username in the config, they are never
|
|
|
* asked, even if they do give a wrong password.)
|
|
|
- *
|
|
|
+ *
|
|
|
* I think this best serves the needs of
|
|
|
- *
|
|
|
+ *
|
|
|
* - the people who have no configuration, no keys, and just
|
|
|
* want to try repeated (username,password) pairs until they
|
|
|
* type both correctly
|
|
|
- *
|
|
|
+ *
|
|
|
* - people who have keys and configuration but occasionally
|
|
|
* need to fall back to passwords
|
|
|
- *
|
|
|
+ *
|
|
|
* - people with a key held in Pageant, who might not have
|
|
|
* logged in to a particular machine before; so they want to
|
|
|
* type a username, and then _either_ their key will be
|
|
@@ -9299,7 +9299,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
s->cur_prompt = new_prompts(ssh->frontend);
|
|
|
s->cur_prompt->to_server = TRUE;
|
|
|
s->cur_prompt->name = dupstr("SSH login name");
|
|
|
- add_prompt(s->cur_prompt, dupstr("login as: "), TRUE);
|
|
|
+ add_prompt(s->cur_prompt, dupstr("login as: "), TRUE);
|
|
|
ret = get_userpass_input(s->cur_prompt, NULL, 0);
|
|
|
while (ret < 0) {
|
|
|
ssh->send_ok = 1;
|
|
@@ -9552,7 +9552,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
s->gotit = TRUE;
|
|
|
|
|
|
} else {
|
|
|
-
|
|
|
+
|
|
|
void *vret;
|
|
|
|
|
|
if (flags & FLAG_VERBOSE) {
|
|
@@ -10051,7 +10051,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
ssh2_pkt_addstring(s->pktout, ""); /* lang */
|
|
|
ssh2_pkt_addstring(s->pktout, ""); /* submethods */
|
|
|
ssh2_pkt_send(ssh, s->pktout);
|
|
|
-
|
|
|
+
|
|
|
logevent("Attempting keyboard-interactive authentication");
|
|
|
|
|
|
crWaitUntilV(pktin);
|
|
@@ -10268,7 +10268,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
|
|
|
while (pktin->type == SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ) {
|
|
|
|
|
|
- /*
|
|
|
+ /*
|
|
|
* We're being asked for a new password
|
|
|
* (perhaps not for the first time).
|
|
|
* Loop until the server accepts it.
|
|
@@ -10277,7 +10277,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
int got_new = FALSE; /* not live over crReturn */
|
|
|
char *prompt; /* not live over crReturn */
|
|
|
int prompt_len; /* not live over crReturn */
|
|
|
-
|
|
|
+
|
|
|
{
|
|
|
const char *msg;
|
|
|
if (changereq_first_time)
|
|
@@ -10387,7 +10387,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
|
|
free_prompts(s->cur_prompt);
|
|
|
ssh2_pkt_send_with_padding(ssh, s->pktout, 256);
|
|
|
logevent("Sent new password");
|
|
|
-
|
|
|
+
|
|
|
/*
|
|
|
* Now see what the server has to say about it.
|
|
|
* (If it's CHANGEREQ again, it's not happy with the
|