1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-04-21 13:05:04 -05:00

Prevent network errors from summarily closing the window when CoE is off

[originally from svn r613]
This commit is contained in:
Simon Tatham 2000-09-22 11:04:57 +00:00
parent 985207d4a9
commit e5ef37f3f5
7 changed files with 148 additions and 48 deletions

10
plink.c
View File

@ -20,6 +20,16 @@ void fatalbox (char *p, ...) {
WSACleanup(); WSACleanup();
exit(1); exit(1);
} }
void connection_fatal (char *p, ...) {
va_list ap;
fprintf(stderr, "FATAL ERROR: ", p);
va_start(ap, p);
vfprintf(stderr, p, ap);
va_end(ap);
fputc('\n', stderr);
WSACleanup();
exit(1);
}
HANDLE outhandle; HANDLE outhandle;

View File

@ -241,6 +241,7 @@ void palette_reset (void);
void write_clip (void *, int); void write_clip (void *, int);
void get_clip (void **, int *); void get_clip (void **, int *);
void optimised_move (int, int, int); void optimised_move (int, int, int);
void connection_fatal(char *, ...);
void fatalbox (char *, ...); void fatalbox (char *, ...);
void beep (int); void beep (int);
#define OPTIMISE_IS_SCROLL 1 #define OPTIMISE_IS_SCROLL 1

10
raw.c
View File

@ -149,8 +149,11 @@ static int raw_msg (WPARAM wParam, LPARAM lParam) {
* the queue; so it's possible that we can get here even with s * the queue; so it's possible that we can get here even with s
* invalid. If so, we return 1 and don't worry about it. * invalid. If so, we return 1 and don't worry about it.
*/ */
if (s == INVALID_SOCKET) if (s == INVALID_SOCKET) {
closesocket(s);
s = INVALID_SOCKET;
return 1; return 1;
}
if (WSAGETSELECTERROR(lParam) != 0) if (WSAGETSELECTERROR(lParam) != 0)
return -WSAGETSELECTERROR(lParam); return -WSAGETSELECTERROR(lParam);
@ -161,8 +164,11 @@ static int raw_msg (WPARAM wParam, LPARAM lParam) {
ret = recv(s, buf, sizeof(buf), 0); ret = recv(s, buf, sizeof(buf), 0);
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK) if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
return 1; return 1;
if (ret < 0) /* any _other_ error */ if (ret < 0) { /* any _other_ error */
closesocket(s);
s = INVALID_SOCKET;
return -10000-WSAGetLastError(); return -10000-WSAGetLastError();
}
if (ret == 0) { if (ret == 0) {
s = INVALID_SOCKET; s = INVALID_SOCKET;
return 0; return 0;

13
scp.c
View File

@ -157,6 +157,19 @@ void fatalbox(char *fmt, ...)
exit(1); exit(1);
} }
void connection_fatal(char *fmt, ...)
{
char str[0x100]; /* Make the size big enough */
va_list ap;
va_start(ap, fmt);
strcpy(str, "Fatal:");
vsprintf(str+strlen(str), fmt, ap);
va_end(ap);
strcat(str, "\n");
tell_str(stderr, str);
exit(1);
}
/* /*
* Print an error message and exit after closing the SSH link. * Print an error message and exit after closing the SSH link.

126
ssh.c
View File

@ -20,6 +20,9 @@
if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \ if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \
fprintf(stderr, "%s\n", s); } fprintf(stderr, "%s\n", s); }
#define bombout(msg) ( ssh_state == SSH_STATE_CLOSED, closesocket(s), \
s = INVALID_SOCKET, connection_fatal msg )
#define SSH1_MSG_DISCONNECT 1 /* 0x1 */ #define SSH1_MSG_DISCONNECT 1 /* 0x1 */
#define SSH1_SMSG_PUBLIC_KEY 2 /* 0x2 */ #define SSH1_SMSG_PUBLIC_KEY 2 /* 0x2 */
#define SSH1_CMSG_SESSION_KEY 3 /* 0x3 */ #define SSH1_CMSG_SESSION_KEY 3 /* 0x3 */
@ -248,8 +251,10 @@ static void s_write (char *buf, int len) {
while (len > 0) { while (len > 0) {
int i = send (s, buf, len, 0); int i = send (s, buf, len, 0);
noise_ultralight(i); noise_ultralight(i);
if (i <= 0) if (i <= 0) {
fatalbox("Lost connection while sending"); bombout(("Lost connection while sending"));
return;
}
if (i > 0) if (i > 0)
len -= i, buf += i; len -= i, buf += i;
} }
@ -372,7 +377,8 @@ next_packet:
realcrc = crc32(pktin.data, biglen-4); realcrc = crc32(pktin.data, biglen-4);
gotcrc = GET_32BIT(pktin.data+biglen-4); gotcrc = GET_32BIT(pktin.data+biglen-4);
if (gotcrc != realcrc) { if (gotcrc != realcrc) {
fatalbox("Incorrect CRC received on packet"); bombout(("Incorrect CRC received on packet"));
crReturn(0);
} }
if (pktin.type == SSH1_SMSG_STDOUT_DATA || if (pktin.type == SSH1_SMSG_STDOUT_DATA ||
@ -381,8 +387,10 @@ next_packet:
pktin.type == SSH1_SMSG_AUTH_TIS_CHALLENGE || pktin.type == SSH1_SMSG_AUTH_TIS_CHALLENGE ||
pktin.type == SSH1_SMSG_AUTH_CCARD_CHALLENGE) { pktin.type == SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
long strlen = GET_32BIT(pktin.body); long strlen = GET_32BIT(pktin.body);
if (strlen + 4 != pktin.length) if (strlen + 4 != pktin.length) {
fatalbox("Received data packet with bogus string length"); bombout(("Received data packet with bogus string length"));
crReturn(0);
}
} }
if (pktin.type == SSH1_MSG_DEBUG) { if (pktin.type == SSH1_MSG_DEBUG) {
@ -503,8 +511,10 @@ next_packet:
/* /*
* Check the MAC. * Check the MAC.
*/ */
if (scmac && !scmac->verify(pktin.data, len+4, incoming_sequence)) if (scmac && !scmac->verify(pktin.data, len+4, incoming_sequence)) {
fatalbox("Incorrect MAC received on packet"); bombout(("Incorrect MAC received on packet"));
crReturn(0);
}
incoming_sequence++; /* whether or not we MACed */ incoming_sequence++; /* whether or not we MACed */
pktin.savedpos = 6; pktin.savedpos = 6;
@ -950,8 +960,10 @@ Bignum ssh2_pkt_getmp(void) {
ssh2_pkt_getstring(&p, &length); ssh2_pkt_getstring(&p, &length);
if (!p) if (!p)
return NULL; return NULL;
if (p[0] & 0x80) if (p[0] & 0x80) {
fatalbox("internal error: Can't handle negative mpints"); bombout(("internal error: Can't handle negative mpints"));
return NULL;
}
b = newbn((length+1)/2); b = newbn((length+1)/2);
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
j = length - 1 - i; j = length - 1 - i;
@ -1069,8 +1081,10 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
if (!ispkt) crWaitUntil(ispkt); if (!ispkt) crWaitUntil(ispkt);
if (pktin.type != SSH1_SMSG_PUBLIC_KEY) if (pktin.type != SSH1_SMSG_PUBLIC_KEY) {
fatalbox("Public key packet not received"); bombout(("Public key packet not received"));
crReturn(0);
}
logevent("Received public keys"); logevent("Received public keys");
@ -1180,8 +1194,10 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
crWaitUntil(ispkt); crWaitUntil(ispkt);
if (pktin.type != SSH1_SMSG_SUCCESS) if (pktin.type != SSH1_SMSG_SUCCESS) {
fatalbox("Encryption not successfully enabled"); bombout(("Encryption not successfully enabled"));
crReturn(0);
}
logevent("Successfully started encryption"); logevent("Successfully started encryption");
@ -1500,8 +1516,10 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
c_write("Server refused our public key.\r\n", 32); c_write("Server refused our public key.\r\n", 32);
continue; /* go and try password */ continue; /* go and try password */
} }
if (pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) if (pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
fatalbox("Bizarre response to offer of public key"); bombout(("Bizarre response to offer of public key"));
crReturn(0);
}
ssh1_read_bignum(pktin.body, &challenge); ssh1_read_bignum(pktin.body, &challenge);
response = rsadecrypt(challenge, &pubkey); response = rsadecrypt(challenge, &pubkey);
freebn(pubkey.private_exponent); /* burn the evidence */ freebn(pubkey.private_exponent); /* burn the evidence */
@ -1526,7 +1544,8 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
45); 45);
continue; /* go and try password */ continue; /* go and try password */
} else if (pktin.type != SSH1_SMSG_SUCCESS) { } else if (pktin.type != SSH1_SMSG_SUCCESS) {
fatalbox("Bizarre response to RSA authentication response"); bombout(("Bizarre response to RSA authentication response"));
crReturn(0);
} }
break; /* we're through! */ break; /* we're through! */
@ -1545,7 +1564,8 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
ssh_state = SSH_STATE_CLOSED; ssh_state = SSH_STATE_CLOSED;
crReturn(1); crReturn(1);
} else if (pktin.type != SSH1_SMSG_SUCCESS) { } else if (pktin.type != SSH1_SMSG_SUCCESS) {
fatalbox("Strange packet received, type %d", pktin.type); bombout(("Strange packet received, type %d", pktin.type));
crReturn(0);
} }
} }
@ -1570,7 +1590,8 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
send_packet(SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END); send_packet(SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END);
do { crReturnV; } while (!ispkt); do { crReturnV; } while (!ispkt);
if (pktin.type != SSH1_SMSG_SUCCESS && pktin.type != SSH1_SMSG_FAILURE) { if (pktin.type != SSH1_SMSG_SUCCESS && pktin.type != SSH1_SMSG_FAILURE) {
fatalbox("Protocol confusion"); bombout(("Protocol confusion"));
crReturnV;
} else if (pktin.type == SSH1_SMSG_FAILURE) { } else if (pktin.type == SSH1_SMSG_FAILURE) {
logevent("Agent forwarding refused"); logevent("Agent forwarding refused");
} else } else
@ -1587,7 +1608,8 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
ssh_state = SSH_STATE_INTERMED; ssh_state = SSH_STATE_INTERMED;
do { crReturnV; } while (!ispkt); do { crReturnV; } while (!ispkt);
if (pktin.type != SSH1_SMSG_SUCCESS && pktin.type != SSH1_SMSG_FAILURE) { if (pktin.type != SSH1_SMSG_SUCCESS && pktin.type != SSH1_SMSG_FAILURE) {
fatalbox("Protocol confusion"); bombout(("Protocol confusion"));
crReturnV;
} else if (pktin.type == SSH1_SMSG_FAILURE) { } else if (pktin.type == SSH1_SMSG_FAILURE) {
c_write("Server refused to allocate pty\r\n", 32); c_write("Server refused to allocate pty\r\n", 32);
} }
@ -1713,7 +1735,8 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
} else if (pktin.type == SSH1_SMSG_EXIT_STATUS) { } else if (pktin.type == SSH1_SMSG_EXIT_STATUS) {
send_packet(SSH1_CMSG_EXIT_CONFIRMATION, PKT_END); send_packet(SSH1_CMSG_EXIT_CONFIRMATION, PKT_END);
} else { } else {
fatalbox("Strange packet received: type %d", pktin.type); bombout(("Strange packet received: type %d", pktin.type));
crReturnV;
} }
} else { } else {
send_packet(SSH1_CMSG_STDIN_DATA, send_packet(SSH1_CMSG_STDIN_DATA,
@ -1890,7 +1913,8 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
* to. * to.
*/ */
if (pktin.type != SSH2_MSG_KEXINIT) { if (pktin.type != SSH2_MSG_KEXINIT) {
fatalbox("expected key exchange packet from server"); bombout(("expected key exchange packet from server"));
crReturn(0);
} }
kex = NULL; hostkey = NULL; cscipher_tobe = NULL; sccipher_tobe = NULL; kex = NULL; hostkey = NULL; cscipher_tobe = NULL; sccipher_tobe = NULL;
csmac_tobe = NULL; scmac_tobe = NULL; cscomp_tobe = NULL; sccomp_tobe = NULL; csmac_tobe = NULL; scmac_tobe = NULL; cscomp_tobe = NULL; sccomp_tobe = NULL;
@ -1956,8 +1980,10 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
* Currently we only support Diffie-Hellman and DSS, so let's * Currently we only support Diffie-Hellman and DSS, so let's
* bomb out if those aren't selected. * bomb out if those aren't selected.
*/ */
if (kex != &ssh_diffiehellman || hostkey != &ssh_dss) if (kex != &ssh_diffiehellman || hostkey != &ssh_dss) {
fatalbox("internal fault: chaos in SSH 2 transport layer"); bombout(("internal fault: chaos in SSH 2 transport layer"));
crReturn(0);
}
/* /*
* Now we begin the fun. Generate and send e for Diffie-Hellman. * Now we begin the fun. Generate and send e for Diffie-Hellman.
@ -1969,7 +1995,8 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
crWaitUntil(ispkt); crWaitUntil(ispkt);
if (pktin.type != SSH2_MSG_KEXDH_REPLY) { if (pktin.type != SSH2_MSG_KEXDH_REPLY) {
fatalbox("expected key exchange packet from server"); bombout(("expected key exchange packet from server"));
crReturn(0);
} }
ssh2_pkt_getstring(&hostkeydata, &hostkeylen); ssh2_pkt_getstring(&hostkeydata, &hostkeylen);
f = ssh2_pkt_getmp(); f = ssh2_pkt_getmp();
@ -1991,15 +2018,19 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
#endif #endif
hostkey->setkey(hostkeydata, hostkeylen); hostkey->setkey(hostkeydata, hostkeylen);
if (!hostkey->verifysig(sigdata, siglen, exchange_hash, 20)) if (!hostkey->verifysig(sigdata, siglen, exchange_hash, 20)) {
fatalbox("Server failed host key check"); bombout(("Server failed host key check"));
crReturn(0);
}
/* /*
* Expect SSH2_MSG_NEWKEYS from server. * Expect SSH2_MSG_NEWKEYS from server.
*/ */
crWaitUntil(ispkt); crWaitUntil(ispkt);
if (pktin.type != SSH2_MSG_NEWKEYS) if (pktin.type != SSH2_MSG_NEWKEYS) {
fatalbox("expected new-keys packet from server"); bombout(("expected new-keys packet from server"));
crReturn(0);
}
/* /*
* Authenticate remote host: verify host key. (We've already * Authenticate remote host: verify host key. (We've already
@ -2065,8 +2096,10 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
ssh2_pkt_addstring("ssh-userauth"); ssh2_pkt_addstring("ssh-userauth");
ssh2_pkt_send(); ssh2_pkt_send();
crWaitUntilV(ispkt); crWaitUntilV(ispkt);
if (pktin.type != SSH2_MSG_SERVICE_ACCEPT) if (pktin.type != SSH2_MSG_SERVICE_ACCEPT) {
fatalbox("Server refused user authentication protocol"); bombout(("Server refused user authentication protocol"));
crReturnV;
}
/* /*
* FIXME: currently we support only password authentication. * FIXME: currently we support only password authentication.
@ -2211,11 +2244,13 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
ssh2_pkt_send(); ssh2_pkt_send();
crWaitUntilV(ispkt); crWaitUntilV(ispkt);
if (pktin.type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) { if (pktin.type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
fatalbox("Server refused to open a session"); bombout(("Server refused to open a session"));
crReturnV;
/* FIXME: error data comes back in FAILURE packet */ /* FIXME: error data comes back in FAILURE packet */
} }
if (ssh2_pkt_getuint32() != mainchan->localid) { if (ssh2_pkt_getuint32() != mainchan->localid) {
fatalbox("Server's channel confirmation cited wrong channel"); bombout(("Server's channel confirmation cited wrong channel"));
crReturnV;
} }
mainchan->remoteid = ssh2_pkt_getuint32(); mainchan->remoteid = ssh2_pkt_getuint32();
mainchan->u.v2.remwindow = ssh2_pkt_getuint32(); mainchan->u.v2.remwindow = ssh2_pkt_getuint32();
@ -2253,7 +2288,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
if (pktin.type != SSH2_MSG_CHANNEL_SUCCESS) { if (pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin.type != SSH2_MSG_CHANNEL_FAILURE) { if (pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
fatalbox("Server got confused by pty request"); bombout(("Server got confused by pty request"));
crReturnV;
} }
c_write("Server refused to allocate pty\r\n", 32); c_write("Server refused to allocate pty\r\n", 32);
} else { } else {
@ -2286,11 +2322,13 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
} while (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST); } while (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
if (pktin.type != SSH2_MSG_CHANNEL_SUCCESS) { if (pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin.type != SSH2_MSG_CHANNEL_FAILURE) { if (pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
fatalbox("Server got confused by shell request"); bombout(("Server got confused by shell/command request"));
crReturnV;
} }
fatalbox("Server refused to start a shell"); bombout(("Server refused to start a shell/command"));
crReturnV;
} else { } else {
logevent("Started a shell"); logevent("Started a shell/command");
} }
/* /*
@ -2353,7 +2391,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
mainchan->u.v2.remwindow += ssh2_pkt_getuint32(); mainchan->u.v2.remwindow += ssh2_pkt_getuint32();
try_send = TRUE; try_send = TRUE;
} else { } else {
fatalbox("Strange packet received: type %d", pktin.type); bombout(("Strange packet received: type %d", pktin.type));
crReturnV;
} }
} else { } else {
/* /*
@ -2458,8 +2497,11 @@ static int ssh_msg (WPARAM wParam, LPARAM lParam) {
if (s == INVALID_SOCKET) if (s == INVALID_SOCKET)
return 1; return 1;
if (WSAGETSELECTERROR(lParam) != 0) if (WSAGETSELECTERROR(lParam) != 0) {
closesocket(s);
s = INVALID_SOCKET;
return -WSAGETSELECTERROR(lParam); return -WSAGETSELECTERROR(lParam);
}
switch (WSAGETSELECTEVENT(lParam)) { switch (WSAGETSELECTEVENT(lParam)) {
case FD_READ: case FD_READ:
@ -2467,8 +2509,11 @@ static int ssh_msg (WPARAM wParam, LPARAM lParam) {
ret = recv(s, buf, sizeof(buf), 0); ret = recv(s, buf, sizeof(buf), 0);
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK) if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
return 1; return 1;
if (ret < 0) /* any _other_ error */ if (ret < 0) { /* any _other_ error */
closesocket(s);
s = INVALID_SOCKET;
return -10000-WSAGetLastError(); return -10000-WSAGetLastError();
}
if (ret == 0) { if (ret == 0) {
s = INVALID_SOCKET; s = INVALID_SOCKET;
return 0; return 0;
@ -2622,7 +2667,8 @@ int ssh_scp_recv(unsigned char *buf, int len)
closesocket(s); closesocket(s);
s = INVALID_SOCKET; s = INVALID_SOCKET;
} else { } else {
fatalbox("Strange packet received: type %d", pktin.type); bombout(("Strange packet received: type %d", pktin.type));
return 0;
} }
} }

View File

@ -608,8 +608,11 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) {
if (s == INVALID_SOCKET) if (s == INVALID_SOCKET)
return 1; return 1;
if (WSAGETSELECTERROR(lParam) != 0) if (WSAGETSELECTERROR(lParam) != 0) {
closesocket(s);
s = INVALID_SOCKET;
return -WSAGETSELECTERROR(lParam); return -WSAGETSELECTERROR(lParam);
}
switch (WSAGETSELECTEVENT(lParam)) { switch (WSAGETSELECTEVENT(lParam)) {
case FD_READ: case FD_READ:
@ -625,8 +628,11 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) {
ret = recv(s, buf, sizeof(buf), 0); ret = recv(s, buf, sizeof(buf), 0);
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK) if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
return 1; return 1;
if (ret < 0) /* any _other_ error */ if (ret < 0) { /* any _other_ error */
closesocket(s);
s = INVALID_SOCKET;
return -10000-WSAGetLastError(); return -10000-WSAGetLastError();
}
if (ret == 0) { if (ret == 0) {
s = INVALID_SOCKET; s = INVALID_SOCKET;
return 0; return 0;

View File

@ -520,6 +520,25 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
return msg.wParam; return msg.wParam;
} }
/*
* Print a message box and close the connection.
*/
void connection_fatal(char *fmt, ...) {
va_list ap;
char stuff[200];
va_start(ap, fmt);
vsprintf(stuff, fmt, ap);
va_end(ap);
MessageBox(hwnd, stuff, "PuTTY Fatal Error", MB_ICONERROR | MB_OK);
if (cfg.close_on_exit)
PostQuitMessage(1);
else {
session_closed = TRUE;
SetWindowText (hwnd, "PuTTY (inactive)");
}
}
/* /*
* Actually do the job requested by a WM_NETEVENT * Actually do the job requested by a WM_NETEVENT
*/ */
@ -546,10 +565,9 @@ static void enact_pending_netevent(void) {
sprintf(buf, "Unexpected network error %d", -i); sprintf(buf, "Unexpected network error %d", -i);
break; break;
} }
MessageBox(hwnd, buf, "PuTTY Fatal Error", connection_fatal(buf);
MB_ICONERROR | MB_OK); }
PostQuitMessage(1); if (i <= 0) {
} else if (i == 0) {
if (cfg.close_on_exit) if (cfg.close_on_exit)
PostQuitMessage(0); PostQuitMessage(0);
else { else {