1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Removing support for SSH-1

Source commit: 75607516cc12c02235795c32cd3f9e67d920bade
This commit is contained in:
Martin Prikryl
2021-05-25 15:08:09 +00:00
parent c9ea2bc666
commit 5dfcf1eb9f
29 changed files with 73 additions and 3951 deletions

View File

@@ -170,21 +170,6 @@
<BuildOrder>23</BuildOrder>
<BuildOrder>19</BuildOrder>
</CppCompile>
<CppCompile Include="putty\ssh1bpp.c">
<BuildOrder>53</BuildOrder>
</CppCompile>
<CppCompile Include="putty\ssh1censor.c">
<BuildOrder>57</BuildOrder>
</CppCompile>
<CppCompile Include="putty\ssh1connection.c">
<BuildOrder>64</BuildOrder>
</CppCompile>
<CppCompile Include="putty\ssh1connection-client.c">
<BuildOrder>71</BuildOrder>
</CppCompile>
<CppCompile Include="putty\ssh1login.c">
<BuildOrder>65</BuildOrder>
</CppCompile>
<CppCompile Include="putty\ssh2bpp.c">
<BuildOrder>54</BuildOrder>
</CppCompile>
@@ -245,14 +230,6 @@
<CppCompile Include="putty\sshcommon.c">
<BuildOrder>62</BuildOrder>
</CppCompile>
<CppCompile Include="putty\sshcrc.c">
<BuildOrder>38</BuildOrder>
<BuildOrder>36</BuildOrder>
</CppCompile>
<CppCompile Include="putty\sshcrcda.c">
<BuildOrder>41</BuildOrder>
<BuildOrder>35</BuildOrder>
</CppCompile>
<CppCompile Include="putty\sshdes.c">
<BuildOrder>44</BuildOrder>
<BuildOrder>32</BuildOrder>

View File

@@ -956,11 +956,6 @@ UnicodeString __fastcall ParseOpenSshPubLine(const UnicodeString & Line, const s
return Result;
}
//---------------------------------------------------------------------------
UnicodeString __fastcall GetSsh1KeyType()
{
return UnicodeString(ssh_rsa.cache_id);
}
//---------------------------------------------------------------------------
UnicodeString __fastcall GetKeyTypeHuman(const UnicodeString & KeyType)
{
UnicodeString Result;

View File

@@ -37,7 +37,6 @@ void __fastcall DllHijackingProtection();
UnicodeString __fastcall ParseOpenSshPubLine(const UnicodeString & Line, const struct ssh_keyalg *& Algorithm);
//---------------------------------------------------------------------------
UnicodeString __fastcall GetKeyTypeHuman(const UnicodeString & KeyType);
UnicodeString __fastcall GetSsh1KeyType();
//---------------------------------------------------------------------------
bool IsOpenSSH(const UnicodeString & SshImplementation);
//---------------------------------------------------------------------------

View File

@@ -123,27 +123,16 @@ inline void __fastcall TSecureShell::UpdateSessionInfo()
{
if (!FSessionInfoValid)
{
FSshVersion = get_ssh_version(FBackendHandle);
DebugAssert(get_ssh_version(FBackendHandle) == 2);
FSessionInfo.ProtocolBaseName = L"SSH";
FSessionInfo.ProtocolName =
FORMAT(L"%s-%d", (FSessionInfo.ProtocolBaseName, get_ssh_version(FBackendHandle)));
FSessionInfo.SecurityProtocolName = FSessionInfo.ProtocolName;
if (FSshVersion == 1)
{
FSessionInfo.CSCipher = GetCipherName(get_cipher(FBackendHandle));
FSessionInfo.SCCipher = FSessionInfo.CSCipher;
// Retrieval of compression is not implemented for SSH-1
FSessionInfo.CSCompression = UnicodeString();
FSessionInfo.SCCompression = UnicodeString();
}
else
{
FSessionInfo.CSCipher = GetCipherName(get_cscipher(FBackendHandle));
FSessionInfo.SCCipher = GetCipherName(get_sccipher(FBackendHandle));
FSessionInfo.CSCompression = GetCompressorName(get_cscomp(FBackendHandle));
FSessionInfo.SCCompression = GetDecompressorName(get_sccomp(FBackendHandle));
}
FSessionInfo.CSCipher = GetCipherName(get_cscipher(FBackendHandle));
FSessionInfo.SCCipher = GetCipherName(get_sccipher(FBackendHandle));
FSessionInfo.CSCompression = GetCompressorName(get_cscomp(FBackendHandle));
FSessionInfo.SCCompression = GetDecompressorName(get_sccomp(FBackendHandle));
FSessionInfoValid = true;
}
@@ -259,10 +248,8 @@ Conf * __fastcall TSecureShell::StoreToConfig(TSessionData * Data, bool Simple)
conf_set_filename(conf, CONF_keyfile, KeyFileFileName);
filename_free(KeyFileFileName);
conf_set_int(conf, CONF_sshprot, Data->SshProt);
conf_set_bool(conf, CONF_ssh2_des_cbc, Data->Ssh2DES);
conf_set_bool(conf, CONF_ssh_no_userauth, Data->SshNoUserAuth);
conf_set_bool(conf, CONF_try_tis_auth, Data->AuthTIS);
conf_set_bool(conf, CONF_try_ki_auth, Data->AuthKI);
conf_set_bool(conf, CONF_try_gssapi_auth, Data->AuthGSSAPI);
conf_set_bool(conf, CONF_try_gssapi_kex, Data->AuthGSSAPIKEX);
@@ -285,9 +272,6 @@ Conf * __fastcall TSecureShell::StoreToConfig(TSessionData * Data, bool Simple)
conf_set_int(conf, CONF_proxy_dns, Data->ProxyDNS);
conf_set_bool(conf, CONF_even_proxy_localhost, Data->ProxyLocalhost);
conf_set_int(conf, CONF_sshbug_ignore1, Data->Bug[sbIgnore1]);
conf_set_int(conf, CONF_sshbug_plainpw1, Data->Bug[sbPlainPW1]);
conf_set_int(conf, CONF_sshbug_rsa1, Data->Bug[sbRSA1]);
conf_set_int(conf, CONF_sshbug_hmac2, Data->Bug[sbHMAC2]);
conf_set_int(conf, CONF_sshbug_derivekey2, Data->Bug[sbDeriveKey2]);
conf_set_int(conf, CONF_sshbug_rsapad2, Data->Bug[sbRSAPad2]);
@@ -2176,14 +2160,7 @@ unsigned long __fastcall TSecureShell::MaxPacketSize()
UpdateSessionInfo();
}
if (FSshVersion == 1)
{
return 0;
}
else
{
return winscp_query(FBackendHandle, WINSCP_QUERY_REMMAXPKT);
}
return winscp_query(FBackendHandle, WINSCP_QUERY_REMMAXPKT);
}
//---------------------------------------------------------------------------
UnicodeString __fastcall TSecureShell::FormatKeyStr(UnicodeString KeyStr)
@@ -2416,16 +2393,8 @@ UnicodeString TSecureShell::StoreHostKey(
void TSecureShell::ParseFingerprint(const UnicodeString & Fingerprint, UnicodeString & SignKeyType, UnicodeString & Hash)
{
UnicodeString Buf = Fingerprint;
UnicodeString SignKeyAlg, SignKeySize;
if (get_ssh_version(FBackendHandle) == 1)
{
SignKeyAlg = GetSsh1KeyType();
}
else
{
SignKeyAlg = CutToChar(Buf, L' ', false);
}
SignKeySize = CutToChar(Buf, L' ', false);
UnicodeString SignKeyAlg = CutToChar(Buf, L' ', false);
UnicodeString SignKeySize = CutToChar(Buf, L' ', false);
SignKeyType = SignKeyAlg + L' ' + SignKeySize;
Hash = Buf;
}
@@ -2448,21 +2417,16 @@ void __fastcall TSecureShell::VerifyHostKey(
UnicodeString SignKeyType, MD5, SHA256;
ParseFingerprint(AFingerprintMD5, SignKeyType, MD5);
if (get_ssh_version(FBackendHandle) == 1)
DebugAssert(get_ssh_version(FBackendHandle) == 2);
UnicodeString SignKeyTypeSHA256;
ParseFingerprint(AFingerprintSHA256, SignKeyTypeSHA256, SHA256);
DebugAssert(SignKeyTypeSHA256 == SignKeyType);
if (DebugAlwaysTrue(StartsText(L"SHA256:", SHA256)))
{
DebugAssert(AFingerprintSHA256.IsEmpty());
SHA256 = L"-";
}
else
{
UnicodeString SignKeyTypeSHA256;
ParseFingerprint(AFingerprintSHA256, SignKeyTypeSHA256, SHA256);
DebugAssert(SignKeyTypeSHA256 == SignKeyType);
if (DebugAlwaysTrue(StartsText(L"SHA256:", SHA256)))
{
CutToChar(SHA256, L':', false);
}
CutToChar(SHA256, L':', false);
}
UnicodeString FingerprintMD5 = SignKeyType + L' ' + MD5;
DebugAssert(AFingerprintMD5 == FingerprintMD5);
UnicodeString FingerprintSHA256 = SignKeyType + L' ' + SHA256;
@@ -2755,14 +2719,7 @@ void __fastcall TSecureShell::CollectUsage()
Configuration->Usage->Inc(L"OpenedSessionsPrivateKey2");
}
if (FSshVersion == 1)
{
Configuration->Usage->Inc(L"OpenedSessionsSSH1");
}
else if (FSshVersion == 2)
{
Configuration->Usage->Inc(L"OpenedSessionsSSH2");
}
Configuration->Usage->Inc(L"OpenedSessionsSSH2");
if (SshImplementation == sshiOpenSSH)
{

View File

@@ -45,7 +45,6 @@ private:
bool FStoredPasswordTried;
bool FStoredPasswordTriedForKI;
bool FStoredPassphraseTried;
int FSshVersion;
bool FOpened;
bool FClosed;
int FWaiting;

View File

@@ -34,7 +34,6 @@ const UnicodeString CipherNames[CIPHER_COUNT] = {L"WARN", L"3des", L"blowfish",
const UnicodeString KexNames[KEX_COUNT] = {L"WARN", L"dh-group1-sha1", L"dh-group14-sha1", L"dh-gex-sha1", L"rsa", L"ecdh"};
const UnicodeString HostKeyNames[HOSTKEY_COUNT] = {L"WARN", L"rsa", L"dsa", L"ecdsa", L"ed25519", L"ed448"};
const UnicodeString GssLibNames[GSSLIB_COUNT] = {L"gssapi32", L"sspi", L"custom"};
const wchar_t SshProtList[][10] = {L"1", L"1>2", L"2>1", L"2"};
// Update also order in Ssh2CipherList()
const TCipher DefaultCipherList[CIPHER_COUNT] =
{ cipAES, cipChaCha20, cipBlowfish, cip3DES, cipWarn, cipArcfour, cipDES };
@@ -129,7 +128,6 @@ void __fastcall TSessionData::DefaultSettings()
Timeout = 15;
TryAgent = true;
AgentFwd = false;
AuthTIS = false;
AuthKI = true;
AuthKIPassword = true;
AuthGSSAPI = true;
@@ -138,7 +136,6 @@ void __fastcall TSessionData::DefaultSettings()
LogicalHostName = L"";
ChangeUsername = false;
Compression = false;
SshProt = ssh2only;
Ssh2DES = false;
SshNoUserAuth = false;
for (int Index = 0; Index < CIPHER_COUNT; Index++)
@@ -338,11 +335,9 @@ void __fastcall TSessionData::NonPersistant()
PROPERTY(Timeout); \
PROPERTY(TryAgent); \
PROPERTY(AgentFwd); \
PROPERTY(AuthTIS); \
PROPERTY(LogicalHostName); \
PROPERTY(ChangeUsername); \
PROPERTY(Compression); \
PROPERTY(SshProt); \
PROPERTY(Ssh2DES); \
PROPERTY(SshNoUserAuth); \
PROPERTY(CipherList); \
@@ -661,7 +656,6 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
Timeout = Storage->ReadInteger(L"Timeout", Timeout);
TryAgent = Storage->ReadBool(L"TryAgent", TryAgent);
AgentFwd = Storage->ReadBool(L"AgentFwd", AgentFwd);
AuthTIS = Storage->ReadBool(L"AuthTIS", AuthTIS);
AuthKI = Storage->ReadBool(L"AuthKI", AuthKI);
AuthKIPassword = Storage->ReadBool(L"AuthKIPassword", AuthKIPassword);
// Continue to use setting keys of previous kerberos implementation (vaclav tomec),
@@ -676,17 +670,6 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
LogicalHostName = Storage->ReadString(L"LogicalHostName", Storage->ReadString(L"GSSAPIServerRealm", Storage->ReadString(L"KerbPrincipal", LogicalHostName)));
ChangeUsername = Storage->ReadBool(L"ChangeUsername", ChangeUsername);
Compression = Storage->ReadBool(L"Compression", Compression);
TSshProt ASshProt = (TSshProt)Storage->ReadInteger(L"SshProt", SshProt);
// Old sessions may contain the values correponding to the fallbacks we used to allow; migrate them
if (ASshProt == ssh2deprecated)
{
ASshProt = ssh2only;
}
else if (ASshProt == ssh1deprecated)
{
ASshProt = ssh1only;
}
SshProt = ASshProt;
Ssh2DES = Storage->ReadBool(L"Ssh2DES", Ssh2DES);
SshNoUserAuth = Storage->ReadBool(L"SshNoUserAuth", SshNoUserAuth);
CipherList = Storage->ReadString(L"Cipher", CipherList);
@@ -799,9 +782,6 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
#define READ_BUG(BUG) \
Bug[sb##BUG] = TAutoSwitch(2 - Storage->ReadInteger(L"Bug"#BUG, \
2 - Bug[sb##BUG]));
READ_BUG(Ignore1);
READ_BUG(PlainPW1);
READ_BUG(RSA1);
READ_BUG(HMAC2);
READ_BUG(DeriveKey2);
READ_BUG(RSAPad2);
@@ -1040,7 +1020,6 @@ void __fastcall TSessionData::DoSave(THierarchicalStorage * Storage,
WRITE_DATA(Integer, Timeout);
WRITE_DATA(Bool, TryAgent);
WRITE_DATA(Bool, AgentFwd);
WRITE_DATA(Bool, AuthTIS);
WRITE_DATA(Bool, AuthKI);
WRITE_DATA(Bool, AuthKIPassword);
WRITE_DATA(String, Note);
@@ -1065,7 +1044,6 @@ void __fastcall TSessionData::DoSave(THierarchicalStorage * Storage,
WRITE_DATA(Bool, ChangeUsername);
WRITE_DATA(Bool, Compression);
WRITE_DATA(Integer, SshProt);
WRITE_DATA(Bool, Ssh2DES);
WRITE_DATA(Bool, SshNoUserAuth);
WRITE_DATA_EX(String, L"Cipher", CipherList, );
@@ -1173,9 +1151,6 @@ void __fastcall TSessionData::DoSave(THierarchicalStorage * Storage,
#define WRITE_DATA_CONV_FUNC(X) (2 - (X))
#define WRITE_BUG(BUG) WRITE_DATA_CONV(Integer, L"Bug" #BUG, Bug[sb##BUG]);
WRITE_BUG(Ignore1);
WRITE_BUG(PlainPW1);
WRITE_BUG(RSA1);
WRITE_BUG(HMAC2);
WRITE_BUG(DeriveKey2);
WRITE_BUG(RSAPad2);
@@ -2653,11 +2628,6 @@ void __fastcall TSessionData::SetAgentFwd(bool value)
SET_SESSION_PROPERTY(AgentFwd);
}
//---------------------------------------------------------------------
void __fastcall TSessionData::SetAuthTIS(bool value)
{
SET_SESSION_PROPERTY(AuthTIS);
}
//---------------------------------------------------------------------
void __fastcall TSessionData::SetAuthKI(bool value)
{
SET_SESSION_PROPERTY(AuthKI);
@@ -2693,11 +2663,6 @@ void __fastcall TSessionData::SetCompression(bool value)
SET_SESSION_PROPERTY(Compression);
}
//---------------------------------------------------------------------
void __fastcall TSessionData::SetSshProt(TSshProt value)
{
SET_SESSION_PROPERTY(SshProt);
}
//---------------------------------------------------------------------
void __fastcall TSessionData::SetSsh2DES(bool value)
{
SET_SESSION_PROPERTY(Ssh2DES);
@@ -2708,11 +2673,6 @@ void __fastcall TSessionData::SetSshNoUserAuth(bool value)
SET_SESSION_PROPERTY(SshNoUserAuth);
}
//---------------------------------------------------------------------
UnicodeString __fastcall TSessionData::GetSshProtStr()
{
return SshProtList[FSshProt];
}
//---------------------------------------------------------------------
bool __fastcall TSessionData::GetUsesSsh()
{
return IsSshProtocol(FSProtocol);
@@ -4346,7 +4306,6 @@ UnicodeString __fastcall TSessionData::ComposePath(
void __fastcall TSessionData::DisableAuthentationsExceptPassword()
{
SshNoUserAuth = false;
AuthTIS = false;
AuthKI = false;
AuthKIPassword = false;
AuthGSSAPI = false;

View File

@@ -17,7 +17,6 @@ enum TFSProtocol { fsSCPonly = 0, fsSFTP = 1, fsSFTPonly = 2, fsFTP = 5, fsWebDA
#define FSPROTOCOL_COUNT (fsS3+1)
extern const wchar_t * ProxyMethodNames;
enum TProxyMethod { pmNone, pmSocks4, pmSocks5, pmHTTP, pmTelnet, pmCmd };
enum TSshProt { ssh1only, ssh1deprecated, ssh2deprecated, ssh2only };
enum TKex { kexWarn, kexDHGroup1, kexDHGroup14, kexDHGEx, kexRSA, kexECDH };
#define KEX_COUNT (kexECDH+1)
enum THostKey { hkWarn, hkRSA, hkDSA, hkECDSA, hkED25519, hkED448, hkMax };
@@ -25,7 +24,7 @@ enum THostKey { hkWarn, hkRSA, hkDSA, hkECDSA, hkED25519, hkED448, hkMax };
enum TGssLib { gssGssApi32, gssSspi, gssCustom };
#define GSSLIB_COUNT (gssCustom+1)
// names have to match PuTTY registry entries (see settings.c)
enum TSshBug { sbIgnore1, sbPlainPW1, sbRSA1, sbHMAC2, sbDeriveKey2, sbRSAPad2,
enum TSshBug { sbHMAC2, sbDeriveKey2, sbRSAPad2,
sbPKSessID2, sbRekey2, sbMaxPkt2, sbIgnore2, sbOldGex2, sbWinAdj, sbChanReq };
#define BUG_COUNT (sbChanReq+1)
enum TSftpBug { sbSymlink, sbSignedTS };
@@ -114,7 +113,6 @@ private:
bool FTryAgent;
bool FAgentFwd;
UnicodeString FListingCommand;
bool FAuthTIS;
bool FAuthKI;
bool FAuthKIPassword;
bool FAuthGSSAPI;
@@ -122,7 +120,6 @@ private:
bool FGSSAPIFwdTGT;
bool FChangeUsername;
bool FCompression;
TSshProt FSshProt;
bool FSsh2DES;
bool FSshNoUserAuth;
TCipher FCiphers[CIPHER_COUNT];
@@ -263,7 +260,6 @@ private:
void __fastcall SetPingInterval(int value);
void __fastcall SetTryAgent(bool value);
void __fastcall SetAgentFwd(bool value);
void __fastcall SetAuthTIS(bool value);
void __fastcall SetAuthKI(bool value);
void __fastcall SetAuthKIPassword(bool value);
void __fastcall SetAuthGSSAPI(bool value);
@@ -271,7 +267,6 @@ private:
void __fastcall SetGSSAPIFwdTGT(bool value);
void __fastcall SetChangeUsername(bool value);
void __fastcall SetCompression(bool value);
void __fastcall SetSshProt(TSshProt value);
void __fastcall SetSsh2DES(bool value);
void __fastcall SetSshNoUserAuth(bool value);
void __fastcall SetCipher(int Index, TCipher value);
@@ -337,7 +332,6 @@ private:
void __fastcall SetSourceAddress(const UnicodeString & value);
void __fastcall SetProtocolFeatures(const UnicodeString & value);
void __fastcall SetSshSimple(bool value);
UnicodeString __fastcall GetSshProtStr();
bool __fastcall GetUsesSsh();
void __fastcall SetCipherList(UnicodeString value);
UnicodeString __fastcall GetCipherList() const;
@@ -557,7 +551,6 @@ public:
__property bool TryAgent = { read=FTryAgent, write=SetTryAgent };
__property bool AgentFwd = { read=FAgentFwd, write=SetAgentFwd };
__property UnicodeString ListingCommand = { read = FListingCommand, write = SetListingCommand };
__property bool AuthTIS = { read=FAuthTIS, write=SetAuthTIS };
__property bool AuthKI = { read=FAuthKI, write=SetAuthKI };
__property bool AuthKIPassword = { read=FAuthKIPassword, write=SetAuthKIPassword };
__property bool AuthGSSAPI = { read=FAuthGSSAPI, write=SetAuthGSSAPI };
@@ -565,7 +558,6 @@ public:
__property bool GSSAPIFwdTGT = { read=FGSSAPIFwdTGT, write=SetGSSAPIFwdTGT };
__property bool ChangeUsername = { read=FChangeUsername, write=SetChangeUsername };
__property bool Compression = { read=FCompression, write=SetCompression };
__property TSshProt SshProt = { read=FSshProt, write=SetSshProt };
__property bool UsesSsh = { read = GetUsesSsh };
__property bool Ssh2DES = { read=FSsh2DES, write=SetSsh2DES };
__property bool SshNoUserAuth = { read=FSshNoUserAuth, write=SetSshNoUserAuth };
@@ -623,7 +615,6 @@ public:
__property UnicodeString SourceAddress = { read=FSourceAddress, write=SetSourceAddress };
__property UnicodeString ProtocolFeatures = { read=FProtocolFeatures, write=SetProtocolFeatures };
__property bool SshSimple = { read=FSshSimple, write=SetSshSimple };
__property UnicodeString SshProtStr = { read=GetSshProtStr };
__property UnicodeString CipherList = { read=GetCipherList, write=SetCipherList };
__property UnicodeString KexList = { read=GetKexList, write=SetKexList };
__property UnicodeString HostKeyList = { read=GetHostKeyList, write=SetHostKeyList };

View File

@@ -1272,12 +1272,11 @@ void __fastcall TSessionLog::DoAddStartupInfo(TSessionData * Data)
}
if (Data->UsesSsh)
{
ADF(L"SSH protocol version: %s; Compression: %s",
(Data->SshProtStr, BooleanToEngStr(Data->Compression)));
ADF(L"Compression: %s", (BooleanToEngStr(Data->Compression)));
ADF(L"Bypass authentication: %s",
(BooleanToEngStr(Data->SshNoUserAuth)));
ADF(L"Try agent: %s; Agent forwarding: %s; TIS/CryptoCard: %s; KI: %s; GSSAPI: %s",
(BooleanToEngStr(Data->TryAgent), BooleanToEngStr(Data->AgentFwd), BooleanToEngStr(Data->AuthTIS),
ADF(L"Try agent: %s; Agent forwarding: %s; KI: %s; GSSAPI: %s",
(BooleanToEngStr(Data->TryAgent), BooleanToEngStr(Data->AgentFwd),
BooleanToEngStr(Data->AuthKI), BooleanToEngStr(Data->AuthGSSAPI)));
if (Data->AuthGSSAPI)
{

View File

@@ -1534,7 +1534,6 @@ void __fastcall TTerminal::OpenTunnel()
// inherit most SSH options of the main session (except for private key and bugs)
FTunnelData->Compression = FSessionData->Compression;
FTunnelData->SshProt = FSessionData->SshProt;
FTunnelData->CipherList = FSessionData->CipherList;
FTunnelData->Ssh2DES = FSessionData->Ssh2DES;
@@ -1548,7 +1547,6 @@ void __fastcall TTerminal::OpenTunnel()
FTunnelData->GSSAPIFwdTGT = FSessionData->GSSAPIFwdTGT;
FTunnelData->TryAgent = FSessionData->TryAgent;
FTunnelData->AgentFwd = FSessionData->AgentFwd;
FTunnelData->AuthTIS = FSessionData->AuthTIS;
FTunnelData->AuthKI = FSessionData->AuthKI;
FTunnelData->AuthKIPassword = FSessionData->AuthKIPassword;

View File

@@ -63,9 +63,6 @@ void __fastcall TSiteAdvancedDialog::InitControls()
{
ComboAutoSwitchInitialize(UtfCombo);
ComboAutoSwitchInitialize(BugIgnore1Combo);
ComboAutoSwitchInitialize(BugPlainPW1Combo);
ComboAutoSwitchInitialize(BugRSA1Combo);
ComboAutoSwitchInitialize(BugHMAC2Combo);
ComboAutoSwitchInitialize(BugDeriveKey2Combo);
ComboAutoSwitchInitialize(BugRSAPad2Combo);
@@ -243,7 +240,6 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
// Authentication page
SshNoUserAuthCheck->Checked = FSessionData->SshNoUserAuth;
TryAgentCheck->Checked = FSessionData->TryAgent;
AuthTISCheck->Checked = FSessionData->AuthTIS;
AuthKICheck->Checked = FSessionData->AuthKI;
AuthKIPasswordCheck->Checked = FSessionData->AuthKIPassword;
AuthGSSAPICheck3->Checked = FSessionData->AuthGSSAPI;
@@ -254,14 +250,6 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
// SSH page
Ssh2LegacyDESCheck->Checked = FSessionData->Ssh2DES;
CompressionCheck->Checked = FSessionData->Compression;
if (FSessionData->SshProt == ssh1only)
{
SshProtCombo2->ItemIndex = 0;
}
else
{
SshProtCombo2->ItemIndex = 1;
}
CipherListBox->Items->Clear();
DebugAssert(CIPHER_NAME_WARN+CIPHER_COUNT-1 == CIPHER_NAME_CHACHA20);
@@ -388,9 +376,6 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
// Bugs page
#define LOAD_BUG_COMBO(BUG) \
ComboAutoSwitchLoad(Bug ## BUG ## Combo, FSessionData->Bug[sb ## BUG])
LOAD_BUG_COMBO(Ignore1);
LOAD_BUG_COMBO(PlainPW1);
LOAD_BUG_COMBO(RSA1);
LOAD_BUG_COMBO(HMAC2);
LOAD_BUG_COMBO(DeriveKey2);
LOAD_BUG_COMBO(RSAPad2);
@@ -444,11 +429,6 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
UpdateControls();
}
//---------------------------------------------------------------------
TSshProt __fastcall TSiteAdvancedDialog::GetSshProt()
{
return (SshProtCombo2->ItemIndex == 0) ? ssh1only : ssh2only;
}
//---------------------------------------------------------------------
bool TSiteAdvancedDialog::IsDefaultSftpServer()
{
return
@@ -466,8 +446,6 @@ void __fastcall TSiteAdvancedDialog::SaveSession(TSessionData * SessionData)
SessionData->Compression = CompressionCheck->Checked;
SessionData->Ssh2DES = Ssh2LegacyDESCheck->Checked;
SessionData->SshProt = GetSshProt();
for (int Index = 0; Index < CIPHER_COUNT; Index++)
{
SessionData->Cipher[Index] = (TCipher)CipherListBox->Items->Objects[Index];
@@ -488,7 +466,6 @@ void __fastcall TSiteAdvancedDialog::SaveSession(TSessionData * SessionData)
// Authentication page
SessionData->SshNoUserAuth = SshNoUserAuthCheck->Checked;
SessionData->TryAgent = TryAgentCheck->Checked;
SessionData->AuthTIS = AuthTISCheck->Checked;
SessionData->AuthKI = AuthKICheck->Checked;
SessionData->AuthKIPassword = AuthKIPasswordCheck->Checked;
SessionData->AuthGSSAPI = AuthGSSAPICheck3->Checked;
@@ -674,9 +651,6 @@ void __fastcall TSiteAdvancedDialog::SaveSession(TSessionData * SessionData)
// Bugs page
#define SAVE_BUG_COMBO(BUG) SessionData->Bug[sb ## BUG] = ComboAutoSwitchSave(Bug ## BUG ## Combo)
SAVE_BUG_COMBO(Ignore1);
SAVE_BUG_COMBO(PlainPW1);
SAVE_BUG_COMBO(RSA1);
SAVE_BUG_COMBO(HMAC2);
SAVE_BUG_COMBO(DeriveKey2);
SAVE_BUG_COMBO(RSAPad2);
@@ -872,20 +846,14 @@ void __fastcall TSiteAdvancedDialog::UpdateControls()
// ssh/authentication sheet
AuthSheet->Enabled = SshProtocol;
EnableControl(SshNoUserAuthCheck, (GetSshProt() == ssh2only));
EnableControl(AuthenticationGroup,
!SshNoUserAuthCheck->Enabled || !SshNoUserAuthCheck->Checked);
EnableControl(AuthTISCheck, AuthenticationGroup->Enabled && (GetSshProt() == ssh1only));
EnableControl(AuthKICheck, AuthenticationGroup->Enabled && (GetSshProt() == ssh2only));
EnableControl(AuthKIPasswordCheck,
AuthenticationGroup->Enabled &&
((AuthTISCheck->Enabled && AuthTISCheck->Checked) ||
(AuthKICheck->Enabled && AuthKICheck->Checked)));
AuthenticationGroup->Enabled && (AuthKICheck->Enabled && AuthKICheck->Checked));
EnableControl(AuthenticationParamsGroup, AuthenticationGroup->Enabled);
EnableControl(AgentFwdCheck, AuthenticationParamsGroup->Enabled && TryAgentCheck->Checked);
EnableControl(PrivateKeyViewButton, PrivateKeyEdit3->Enabled && !PrivateKeyEdit3->Text.IsEmpty());
EnableControl(AuthGSSAPICheck3,
AuthenticationGroup->Enabled && (GetSshProt() == ssh2only));
EnableControl(AuthGSSAPICheck3, AuthenticationGroup->Enabled);
EnableControl(GSSAPIFwdTGTCheck,
AuthGSSAPICheck3->Enabled && AuthGSSAPICheck3->Checked);
@@ -894,39 +862,15 @@ void __fastcall TSiteAdvancedDialog::UpdateControls()
EnableControl(CipherUpButton, CipherListBox->ItemIndex > 0);
EnableControl(CipherDownButton, CipherListBox->ItemIndex >= 0 &&
CipherListBox->ItemIndex < CipherListBox->Items->Count-1);
EnableControl(Ssh2LegacyDESCheck, (GetSshProt() == ssh2only));
// ssh/kex sheet
KexSheet->Enabled = SshProtocol && (GetSshProt() == ssh2only) &&
(BugRekey2Combo->ItemIndex != 2);
KexSheet->Enabled = SshProtocol && (BugRekey2Combo->ItemIndex != 2);
EnableControl(KexUpButton, KexListBox->ItemIndex > 0);
EnableControl(KexDownButton, KexListBox->ItemIndex >= 0 &&
KexListBox->ItemIndex < KexListBox->Items->Count-1);
// ssh/bugs sheet
BugsSheet->Enabled = SshProtocol;
EnableControl(BugIgnore1Combo, (GetSshProt() == ssh1only));
EnableControl(BugIgnore1Label, BugIgnore1Combo->Enabled);
EnableControl(BugPlainPW1Combo, (GetSshProt() == ssh1only));
EnableControl(BugPlainPW1Label, BugPlainPW1Combo->Enabled);
EnableControl(BugRSA1Combo, (GetSshProt() == ssh1only));
EnableControl(BugRSA1Label, BugRSA1Combo->Enabled);
EnableControl(BugHMAC2Combo, (GetSshProt() == ssh2only));
EnableControl(BugHMAC2Label, BugHMAC2Combo->Enabled);
EnableControl(BugDeriveKey2Combo, (GetSshProt() == ssh2only));
EnableControl(BugDeriveKey2Label, BugDeriveKey2Combo->Enabled);
EnableControl(BugRSAPad2Combo, (GetSshProt() == ssh2only));
EnableControl(BugRSAPad2Label, BugRSAPad2Combo->Enabled);
EnableControl(BugPKSessID2Combo, (GetSshProt() == ssh2only));
EnableControl(BugPKSessID2Label, BugPKSessID2Combo->Enabled);
EnableControl(BugRekey2Combo, (GetSshProt() == ssh2only));
EnableControl(BugRekey2Label, BugRekey2Combo->Enabled);
EnableControl(BugMaxPkt2Combo, (GetSshProt() == ssh2only));
EnableControl(BugMaxPkt2Label, BugMaxPkt2Combo->Enabled);
EnableControl(BugIgnore2Combo, (GetSshProt() == ssh2only));
EnableControl(BugIgnore2Label, BugIgnore2Combo->Enabled);
EnableControl(BugWinAdjCombo, (GetSshProt() == ssh2only));
EnableControl(BugWinAdjLabel, BugWinAdjCombo->Enabled);
// connection/proxy sheet
// this is probaqbly overkill, now we do not allow changing protocol on
@@ -1368,7 +1312,7 @@ void __fastcall TSiteAdvancedDialog::PrivateKeyEdit3AfterDialog(TObject * Sender
TFilenameEdit * Edit = dynamic_cast<TFilenameEdit *>(Sender);
if (Name != Edit->Text)
{
VerifyAndConvertKey(Name, GetSshProt(), true);
VerifyAndConvertKey(Name, true);
}
}
//---------------------------------------------------------------------------
@@ -1378,9 +1322,9 @@ void __fastcall TSiteAdvancedDialog::FormCloseQuery(TObject * /*Sender*/,
if (ModalResult == DefaultResult(this))
{
// StripPathQuotes should not be needed as we do not feed quotes anymore
VerifyKey(StripPathQuotes(PrivateKeyEdit3->Text), GetSshProt());
VerifyKey(StripPathQuotes(PrivateKeyEdit3->Text));
// for tunnel SSH version is not configurable
VerifyKey(StripPathQuotes(TunnelPrivateKeyEdit3->Text), ssh2only);
VerifyKey(StripPathQuotes(TunnelPrivateKeyEdit3->Text));
VerifyCertificate(StripPathQuotes(TlsCertificateFileEdit->Text));
// Particularly for EncryptKey*Edit's
ExitActiveControl(this);
@@ -1630,7 +1574,7 @@ void __fastcall TSiteAdvancedDialog::PrivateKeyToolsButtonClick(TObject * /*Send
{
UnicodeString Dummy;
PrivateKeyGenerateItem->Enabled = FindTool(PuttygenTool, Dummy);
PrivateKeyUploadItem->Enabled = (GetSshProt() == ssh2only) && (NormalizeFSProtocol(FSessionData->FSProtocol) == fsSFTP);
PrivateKeyUploadItem->Enabled = (NormalizeFSProtocol(FSessionData->FSProtocol) == fsSFTP);
MenuPopup(PrivateKeyMenu, PrivateKeyToolsButton);
}
//---------------------------------------------------------------------------
@@ -1660,7 +1604,7 @@ void __fastcall TSiteAdvancedDialog::PrivateKeyUploadItemClick(TObject * /*Sende
void __fastcall TSiteAdvancedDialog::PrivateKeyViewButtonClick(TObject * /*Sender*/)
{
UnicodeString FileName = PrivateKeyEdit3->Text;
VerifyAndConvertKey(FileName, GetSshProt(), false);
VerifyAndConvertKey(FileName, false);
PrivateKeyEdit3->Text = FileName;
UnicodeString CommentDummy;
UnicodeString Line = GetPublicKeyLine(FileName, CommentDummy);

View File

@@ -1988,21 +1988,13 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
Left = 0
Top = 6
Width = 393
Height = 71
Height = 46
Anchors = [akLeft, akTop, akRight]
Caption = 'Protocol options'
TabOrder = 0
DesignSize = (
393
71)
object Label37: TLabel
Left = 12
Top = 42
Width = 103
Height = 13
Caption = 'SSH protocol version:'
FocusControl = SshProtCombo2
end
46)
object CompressionCheck: TCheckBox
Left = 16
Top = 19
@@ -2013,23 +2005,10 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
TabOrder = 0
OnClick = DataChange
end
object SshProtCombo2: TComboBox
Left = 303
Top = 37
Width = 80
Height = 21
Style = csDropDownList
Anchors = [akTop, akRight]
TabOrder = 1
OnChange = DataChange
Items.Strings = (
'1 (insecure)'
'2')
end
end
object EncryptionGroup: TGroupBox
Left = 0
Top = 83
Top = 58
Width = 393
Height = 171
Anchors = [akLeft, akTop, akRight]
@@ -2066,7 +2045,7 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
Width = 367
Height = 17
Anchors = [akLeft, akTop, akRight]
Caption = 'Enable legacy use of single-&DES in SSH-2'
Caption = 'Enable legacy use of single-&DES'
TabOrder = 3
end
object CipherUpButton: TButton
@@ -2243,13 +2222,13 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
Left = 0
Top = 32
Width = 393
Height = 117
Height = 94
Anchors = [akLeft, akTop, akRight]
Caption = 'Authentication options'
TabOrder = 1
DesignSize = (
393
117)
94)
object TryAgentCheck: TCheckBox
Left = 12
Top = 19
@@ -2260,16 +2239,6 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
TabOrder = 0
OnClick = DataChange
end
object AuthTISCheck: TCheckBox
Left = 12
Top = 88
Width = 373
Height = 17
Anchors = [akLeft, akTop, akRight]
Caption = 'Atte&mpt TIS or CryptoCard authentication (SSH-1)'
TabOrder = 3
OnClick = DataChange
end
object AuthKICheck: TCheckBox
Left = 12
Top = 42
@@ -2293,7 +2262,7 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
end
object AuthenticationParamsGroup: TGroupBox
Left = 0
Top = 154
Top = 132
Width = 393
Height = 120
Anchors = [akLeft, akTop, akRight]
@@ -2360,7 +2329,7 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
end
object GSSAPIGroup: TGroupBox
Left = 0
Top = 279
Top = 258
Width = 393
Height = 71
Anchors = [akLeft, akTop, akRight]
@@ -2405,131 +2374,77 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
Left = 0
Top = 6
Width = 393
Height = 289
Height = 217
Anchors = [akLeft, akTop, akRight]
Caption = 'Detection of known bugs in SSH servers'
TabOrder = 0
DesignSize = (
393
289)
object BugIgnore1Label: TLabel
Left = 12
Top = 212
Width = 169
Height = 13
Caption = 'Chokes on SSH-1 &ignore messages:'
FocusControl = BugIgnore1Combo
end
object BugPlainPW1Label: TLabel
Left = 12
Top = 236
Width = 195
Height = 13
Caption = 'Refuses all SSH-1 pass&word camouflage:'
FocusControl = BugPlainPW1Combo
end
object BugRSA1Label: TLabel
Left = 12
Top = 260
Width = 181
Height = 13
Caption = 'Chokes on SSH-1 &RSA authentication:'
FocusControl = BugRSA1Combo
end
217)
object BugHMAC2Label: TLabel
Left = 12
Top = 68
Width = 154
Width = 144
Height = 13
Caption = 'Miscomputes SSH-2 H&MAC keys:'
Caption = 'Miscomputes SSH H&MAC keys:'
FocusControl = BugHMAC2Combo
end
object BugDeriveKey2Label: TLabel
Left = 12
Top = 92
Width = 176
Width = 166
Height = 13
Caption = 'Miscomputes SSH-2 &encryption keys:'
Caption = 'Miscomputes SSH &encryption keys:'
FocusControl = BugDeriveKey2Combo
end
object BugRSAPad2Label: TLabel
Left = 12
Top = 116
Width = 210
Width = 200
Height = 13
Caption = 'Requires &padding on SSH-2 RSA signatures:'
Caption = 'Requires &padding on SSH RSA signatures:'
FocusControl = BugRSAPad2Combo
end
object BugPKSessID2Label: TLabel
Left = 12
Top = 140
Width = 195
Width = 185
Height = 13
Caption = 'Misuses the sessio&n ID in SSH-2 PK auth:'
Caption = 'Misuses the sessio&n ID in SSH PK auth:'
FocusControl = BugPKSessID2Combo
end
object BugRekey2Label: TLabel
Left = 12
Top = 164
Width = 187
Width = 177
Height = 13
Caption = 'Handles SSH-2 &key re-exchange badly:'
Caption = 'Handles SSH &key re-exchange badly:'
FocusControl = BugRekey2Combo
end
object BugMaxPkt2Label: TLabel
Left = 12
Top = 188
Width = 176
Width = 166
Height = 13
Caption = 'Ignores SSH-2 ma&ximum packet size:'
Caption = 'Ignores SSH ma&ximum packet size:'
FocusControl = BugMaxPkt2Combo
end
object BugIgnore2Label: TLabel
Left = 12
Top = 20
Width = 169
Width = 159
Height = 13
Caption = 'Chokes on SSH-&2 ignore messages:'
Caption = 'Chokes on SSH i&gnore messages:'
FocusControl = BugIgnore2Combo
end
object BugWinAdjLabel: TLabel
Left = 12
Top = 44
Width = 212
Width = 202
Height = 13
Caption = 'Chokes on WinSCP'#39's SSH-2 '#39'winadj'#39' requests'
Caption = 'Chokes on WinSCP'#39's SSH '#39'&winadj'#39' requests'
FocusControl = BugWinAdjCombo
end
object BugIgnore1Combo: TComboBox
Left = 320
Top = 207
Width = 61
Height = 21
Style = csDropDownList
Anchors = [akTop, akRight]
TabOrder = 8
OnChange = DataChange
end
object BugPlainPW1Combo: TComboBox
Left = 320
Top = 231
Width = 61
Height = 21
Style = csDropDownList
Anchors = [akTop, akRight]
TabOrder = 9
OnChange = DataChange
end
object BugRSA1Combo: TComboBox
Left = 320
Top = 255
Width = 61
Height = 21
Style = csDropDownList
Anchors = [akTop, akRight]
TabOrder = 10
OnChange = DataChange
end
object BugHMAC2Combo: TComboBox
Left = 320
Top = 63

View File

@@ -29,7 +29,6 @@ __published:
TPageControl *PageControl;
TTabSheet *AdvancedSheet;
TGroupBox *ProtocolGroup;
TLabel *Label37;
TCheckBox *CompressionCheck;
TTabSheet *EnvironmentSheet;
TTabSheet *ScpSheet;
@@ -62,12 +61,6 @@ __published:
TEdit *ProxyTelnetCommandEdit;
TTabSheet *BugsSheet;
TGroupBox *BugsGroupBox;
TLabel *BugIgnore1Label;
TComboBox *BugIgnore1Combo;
TLabel *BugPlainPW1Label;
TComboBox *BugPlainPW1Combo;
TLabel *BugRSA1Label;
TComboBox *BugRSA1Combo;
TLabel *BugHMAC2Label;
TComboBox *BugHMAC2Combo;
TLabel *BugDeriveKey2Label;
@@ -76,7 +69,6 @@ __published:
TComboBox *BugRSAPad2Combo;
TTabSheet *AuthSheet;
TGroupBox *AuthenticationGroup;
TCheckBox *AuthTISCheck;
TCheckBox *AuthKICheck;
TGroupBox *EncryptionGroup;
TListBox *CipherListBox;
@@ -252,7 +244,6 @@ __published:
TLabel *Label4;
TFilenameEdit *TlsCertificateFileEdit;
TCheckBox *TrimVMSVersionsCheck;
TComboBox *SshProtCombo2;
TCheckBox *FollowDirectorySymlinksCheck;
TImageList *ColorImageList120;
TImageList *ColorImageList144;
@@ -371,7 +362,6 @@ private:
TProxyMethod __fastcall GetProxyMethod();
int __fastcall GetFtpProxyLogonType();
void __fastcall UpdateNavigationTree();
TSshProt __fastcall GetSshProt();
void __fastcall SessionColorChange(TColor Color);
TTlsVersion __fastcall IndexToTlsVersion(int Index);
int __fastcall TlsVersionToIndex(TTlsVersion TlsVersion);

View File

@@ -9,7 +9,6 @@ int is_ssh(Plug * plug);
int get_ssh_version(Backend * be);
Seat * get_ssh_seat(Plug * plug);
#ifdef WINSCP_SSH
const ssh_cipher * get_cipher(Backend * be);
const ssh_cipher * get_cscipher(Backend * be);
const ssh_cipher * get_sccipher(Backend * be);
#endif

34
source/putty/ssh.c vendored
View File

@@ -187,12 +187,13 @@ static void ssh_got_ssh_version(struct ssh_version_receiver *rcv,
* connect_to_host().
*/
assert(ssh->version == major_version);
assert(ssh->version == 2);
old_bpp = ssh->bpp;
ssh->remote_bugs = ssh_verstring_get_bugs(old_bpp);
if (!ssh->bare_connection) {
if (ssh->version == 2) {
/*WINSCP if (ssh->version == 2)*/ {
PacketProtocolLayer *userauth_layer, *transport_child_layer;
/*
@@ -294,19 +295,7 @@ static void ssh_got_ssh_version(struct ssh_version_receiver *rcv,
ssh2_userauth_set_transport_layer(userauth_layer,
ssh->base_layer);
} else {
ssh->bpp = ssh1_bpp_new(ssh->logctx);
ssh_connect_bpp(ssh);
connection_layer = ssh1_connection_new(ssh, ssh->conf, &ssh->cl);
ssh_connect_ppl(ssh, connection_layer);
ssh->base_layer = ssh1_login_new(
ssh->conf, ssh->savedhost, ssh->savedport, connection_layer);
ssh_connect_ppl(ssh, ssh->base_layer);
}
} // WINSCP
} else {
ssh->bpp = ssh2_bare_bpp_new(ssh->logctx);
@@ -734,7 +723,7 @@ static char *connect_to_host(
SockAddr *addr;
const char *err;
char *loghost;
int addressfamily, sshprot;
int addressfamily;
ssh_hostport_setup(host, port, ssh->conf,
&ssh->savedhost, &ssh->savedport, &loghost);
@@ -811,15 +800,8 @@ static char *connect_to_host(
* The SSH version number is always fixed (since we no longer support
* fallback between versions), so set it now.
*/
sshprot = conf_get_int(ssh->conf, CONF_sshprot);
assert(sshprot == 0 || sshprot == 3);
if (sshprot == 0)
/* SSH-1 only */
ssh->version = 1;
if (sshprot == 3 || ssh->bare_connection) {
/* SSH-2 only */
ssh->version = 2;
}
ssh->version = 2; // WINSCP
/*
* Set up the initial BPP that will do the version string
@@ -1296,12 +1278,6 @@ Seat * get_ssh_seat(Plug * plug)
return container_of(plug, Ssh, plug)->seat;
}
const ssh_cipher * get_cipher(Backend * be)
{
Ssh * ssh = container_of(be, Ssh, backend);
return ssh1_bpp_get_cipher(ssh->bpp);
}
const ssh_cipher * get_cscipher(Backend * be)
{
Ssh * ssh = container_of(be, Ssh, backend);

395
source/putty/ssh1bpp.c vendored
View File

@@ -1,395 +0,0 @@
/*
* Binary packet protocol for SSH-1.
*/
#include <assert.h>
#include "putty.h"
#include "ssh.h"
#include "sshbpp.h"
#include "sshcr.h"
struct ssh1_bpp_state {
int crState;
long len, pad, biglen, length, maxlen;
unsigned char *data;
uint32_t realcrc, gotcrc;
int chunk;
PktIn *pktin;
ssh_cipher *cipher_in, *cipher_out;
struct crcda_ctx *crcda_ctx;
uint8_t iv[8]; /* for crcda */
bool pending_compression_request;
ssh_compressor *compctx;
ssh_decompressor *decompctx;
BinaryPacketProtocol bpp;
};
static void ssh1_bpp_free(BinaryPacketProtocol *bpp);
static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp);
static void ssh1_bpp_handle_output(BinaryPacketProtocol *bpp);
static void ssh1_bpp_queue_disconnect(BinaryPacketProtocol *bpp,
const char *msg, int category);
static PktOut *ssh1_bpp_new_pktout(int type);
static const BinaryPacketProtocolVtable ssh1_bpp_vtable = {
// WINSCP
/*.free =*/ ssh1_bpp_free,
/*.handle_input =*/ ssh1_bpp_handle_input,
/*.handle_output =*/ ssh1_bpp_handle_output,
/*.new_pktout =*/ ssh1_bpp_new_pktout,
/*.queue_disconnect =*/ ssh1_bpp_queue_disconnect,
/*.packet_size_limit =*/ 0xFFFFFFFF, /* no special limit for this bpp */
};
BinaryPacketProtocol *ssh1_bpp_new(LogContext *logctx)
{
struct ssh1_bpp_state *s = snew(struct ssh1_bpp_state);
memset(s, 0, sizeof(*s));
s->bpp.vt = &ssh1_bpp_vtable;
s->bpp.logctx = logctx;
ssh_bpp_common_setup(&s->bpp);
return &s->bpp;
}
static void ssh1_bpp_free(BinaryPacketProtocol *bpp)
{
struct ssh1_bpp_state *s = container_of(bpp, struct ssh1_bpp_state, bpp);
if (s->cipher_in)
ssh_cipher_free(s->cipher_in);
if (s->cipher_out)
ssh_cipher_free(s->cipher_out);
if (s->compctx)
ssh_compressor_free(s->compctx);
if (s->decompctx)
ssh_decompressor_free(s->decompctx);
if (s->crcda_ctx)
crcda_free_context(s->crcda_ctx);
sfree(s->pktin);
sfree(s);
}
void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
const ssh_cipheralg *cipher,
const void *session_key)
{
struct ssh1_bpp_state *s;
assert(bpp->vt == &ssh1_bpp_vtable);
s = container_of(bpp, struct ssh1_bpp_state, bpp);
assert(!s->cipher_in);
assert(!s->cipher_out);
if (cipher) {
s->cipher_in = ssh_cipher_new(cipher);
s->cipher_out = ssh_cipher_new(cipher);
ssh_cipher_setkey(s->cipher_in, session_key);
ssh_cipher_setkey(s->cipher_out, session_key);
assert(!s->crcda_ctx);
s->crcda_ctx = crcda_make_context();
bpp_logevent("Initialised %s encryption", cipher->text_name);
memset(s->iv, 0, sizeof(s->iv));
assert(cipher->blksize <= sizeof(s->iv));
ssh_cipher_setiv(s->cipher_in, s->iv);
ssh_cipher_setiv(s->cipher_out, s->iv);
}
}
void ssh1_bpp_start_compression(BinaryPacketProtocol *bpp)
{
struct ssh1_bpp_state *s;
assert(bpp->vt == &ssh1_bpp_vtable);
s = container_of(bpp, struct ssh1_bpp_state, bpp);
assert(!s->compctx);
assert(!s->decompctx);
s->compctx = ssh_compressor_new(&ssh_zlib);
s->decompctx = ssh_decompressor_new(&ssh_zlib);
bpp_logevent("Started zlib (RFC1950) compression");
}
#define BPP_READ(ptr, len) do \
{ \
bool success; \
crMaybeWaitUntilV((success = bufchain_try_fetch_consume( \
s->bpp.in_raw, ptr, len)) || \
s->bpp.input_eof); \
if (!success) \
goto eof; \
ssh_check_frozen(s->bpp.ssh); \
} while (0)
static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)
{
struct ssh1_bpp_state *s = container_of(bpp, struct ssh1_bpp_state, bpp);
crBegin(s->crState);
while (1) {
s->maxlen = 0;
s->length = 0;
{
unsigned char lenbuf[4];
BPP_READ(lenbuf, 4);
s->len = toint(GET_32BIT_MSB_FIRST(lenbuf));
}
if (s->len < 5 || s->len > 262144) { /* SSH1.5-mandated max size */
ssh_sw_abort(s->bpp.ssh,
"Out-of-range packet length from remote suggests"
" data stream corruption");
crStopV;
}
s->pad = 8 - (s->len % 8);
s->biglen = s->len + s->pad;
s->length = s->len - 5;
/*
* Allocate the packet to return, now we know its length.
*/
s->pktin = snew_plus(PktIn, s->biglen);
s->pktin->qnode.prev = s->pktin->qnode.next = NULL;
s->pktin->qnode.on_free_queue = false;
s->pktin->type = 0;
s->maxlen = s->biglen;
s->data = snew_plus_get_aux(s->pktin);
BPP_READ(s->data, s->biglen);
if (s->cipher_in && detect_attack(s->crcda_ctx,
s->data, s->biglen, s->iv)) {
ssh_sw_abort(s->bpp.ssh,
"Network attack (CRC compensation) detected!");
crStopV;
}
/* Save the last cipher block, to be passed to the next call
* to detect_attack */
assert(s->biglen >= 8);
memcpy(s->iv, s->data + s->biglen - 8, sizeof(s->iv));
if (s->cipher_in)
ssh_cipher_decrypt(s->cipher_in, s->data, s->biglen);
s->realcrc = crc32_ssh1(make_ptrlen(s->data, s->biglen - 4));
s->gotcrc = GET_32BIT_MSB_FIRST(s->data + s->biglen - 4);
if (s->gotcrc != s->realcrc) {
ssh_sw_abort(s->bpp.ssh, "Incorrect CRC received on packet");
crStopV;
}
if (s->decompctx) {
unsigned char *decompblk;
int decomplen;
if (!ssh_decompressor_decompress(
s->decompctx, s->data + s->pad, s->length + 1,
&decompblk, &decomplen)) {
ssh_sw_abort(s->bpp.ssh,
"Zlib decompression encountered invalid data");
crStopV;
}
if (s->maxlen < s->pad + decomplen) {
PktIn *old_pktin = s->pktin;
s->maxlen = s->pad + decomplen;
s->pktin = snew_plus(PktIn, s->maxlen);
*s->pktin = *old_pktin; /* structure copy */
s->data = snew_plus_get_aux(s->pktin);
smemclr(old_pktin, s->biglen);
sfree(old_pktin);
}
memcpy(s->data + s->pad, decompblk, decomplen);
sfree(decompblk);
s->length = decomplen - 1;
}
/*
* Now we can find the bounds of the semantic content of the
* packet, and the initial type byte.
*/
s->data += s->pad;
s->pktin->type = *s->data++;
BinarySource_INIT(s->pktin, s->data, s->length);
if (s->bpp.logctx) {
logblank_t blanks[MAX_BLANKS];
int nblanks = ssh1_censor_packet(
s->bpp.pls, s->pktin->type, false,
make_ptrlen(s->data, s->length), blanks);
log_packet(s->bpp.logctx, PKT_INCOMING, s->pktin->type,
ssh1_pkt_type(s->pktin->type),
get_ptr(s->pktin), get_avail(s->pktin), nblanks, blanks,
NULL, 0, NULL);
}
s->pktin->qnode.formal_size = get_avail(s->pktin);
pq_push(&s->bpp.in_pq, s->pktin);
{
int type = s->pktin->type;
s->pktin = NULL;
switch (type) {
case SSH1_SMSG_SUCCESS:
case SSH1_SMSG_FAILURE:
if (s->pending_compression_request) {
/*
* This is the response to
* SSH1_CMSG_REQUEST_COMPRESSION.
*/
if (type == SSH1_SMSG_SUCCESS) {
/*
* If the response was positive, start
* compression.
*/
ssh1_bpp_start_compression(&s->bpp);
}
/*
* Either way, cancel the pending flag, and
* schedule a run of our output side in case we
* had any packets queued up in the meantime.
*/
s->pending_compression_request = false;
queue_idempotent_callback(&s->bpp.ic_out_pq);
}
break;
}
}
}
eof:
if (!s->bpp.expect_close) {
ssh_remote_error(s->bpp.ssh,
"Remote side unexpectedly closed network connection");
} else {
ssh_remote_eof(s->bpp.ssh, "Remote side closed network connection");
}
return; /* avoid touching s now it's been freed */
crFinishV;
}
static PktOut *ssh1_bpp_new_pktout(int pkt_type)
{
PktOut *pkt = ssh_new_packet();
pkt->length = 4 + 8; /* space for length + max padding */
put_byte(pkt, pkt_type);
pkt->prefix = pkt->length;
pkt->type = pkt_type;
pkt->downstream_id = 0;
pkt->additional_log_text = NULL;
return pkt;
}
static void ssh1_bpp_format_packet(struct ssh1_bpp_state *s, PktOut *pkt)
{
int pad, biglen, pktoffs;
uint32_t crc;
int len;
if (s->bpp.logctx) {
ptrlen pktdata = make_ptrlen(pkt->data + pkt->prefix,
pkt->length - pkt->prefix);
logblank_t blanks[MAX_BLANKS];
int nblanks = ssh1_censor_packet(
s->bpp.pls, pkt->type, true, pktdata, blanks);
log_packet(s->bpp.logctx, PKT_OUTGOING, pkt->type,
ssh1_pkt_type(pkt->type),
pktdata.ptr, pktdata.len, nblanks, blanks,
NULL, 0, NULL);
}
if (s->compctx) {
unsigned char *compblk;
int complen;
ssh_compressor_compress(s->compctx, pkt->data + 12, pkt->length - 12,
&compblk, &complen, 0);
/* Replace the uncompressed packet data with the compressed
* version. */
pkt->length = 12;
put_data(pkt, compblk, complen);
sfree(compblk);
}
put_uint32(pkt, 0); /* space for CRC */
len = pkt->length - 4 - 8; /* len(type+data+CRC) */
pad = 8 - (len % 8);
pktoffs = 8 - pad;
biglen = len + pad; /* len(padding+type+data+CRC) */
random_read(pkt->data + pktoffs, 4+8 - pktoffs);
crc = crc32_ssh1(
make_ptrlen(pkt->data + pktoffs + 4, biglen - 4)); /* all ex len */
PUT_32BIT_MSB_FIRST(pkt->data + pktoffs + 4 + biglen - 4, crc);
PUT_32BIT_MSB_FIRST(pkt->data + pktoffs, len);
if (s->cipher_out)
ssh_cipher_encrypt(s->cipher_out, pkt->data + pktoffs + 4, biglen);
bufchain_add(s->bpp.out_raw, pkt->data + pktoffs,
biglen + 4); /* len(length+padding+type+data+CRC) */
}
static void ssh1_bpp_handle_output(BinaryPacketProtocol *bpp)
{
struct ssh1_bpp_state *s = container_of(bpp, struct ssh1_bpp_state, bpp);
PktOut *pkt;
if (s->pending_compression_request) {
/*
* Don't send any output packets while we're awaiting a
* response to SSH1_CMSG_REQUEST_COMPRESSION, because if they
* cross over in transit with the responding SSH1_CMSG_SUCCESS
* then the other end could decode them with the wrong
* compression settings.
*/
return;
}
while ((pkt = pq_pop(&s->bpp.out_pq)) != NULL) {
int type = pkt->type;
ssh1_bpp_format_packet(s, pkt);
ssh_free_pktout(pkt);
if (type == SSH1_CMSG_REQUEST_COMPRESSION) {
/*
* When we see the actual compression request go past, set
* the pending flag, and stop processing packets this
* time.
*/
s->pending_compression_request = true;
break;
}
}
}
static void ssh1_bpp_queue_disconnect(BinaryPacketProtocol *bpp,
const char *msg, int category)
{
PktOut *pkt = ssh_bpp_new_pktout(bpp, SSH1_MSG_DISCONNECT);
put_stringz(pkt, msg);
pq_push(&bpp->out_pq, pkt);
}
#ifdef MPEXT
const ssh_cipher * ssh1_bpp_get_cipher(BinaryPacketProtocol *bpp)
{
return container_of(bpp, struct ssh1_bpp_state, bpp)->cipher_in; // cipher_out should be the same
}
#endif

View File

@@ -1,76 +0,0 @@
/*
* Packet-censoring code for SSH-1, used to identify sensitive fields
* like passwords so that the logging system can avoid writing them
* into log files.
*/
#include <assert.h>
#include "putty.h"
#include "ssh.h"
int ssh1_censor_packet(
const PacketLogSettings *pls, int type, bool sender_is_client,
ptrlen pkt, logblank_t *blanks)
{
int nblanks = 0;
ptrlen str;
BinarySource src[1];
BinarySource_BARE_INIT_PL(src, pkt);
if (pls->omit_data &&
(type == SSH1_SMSG_STDOUT_DATA ||
type == SSH1_SMSG_STDERR_DATA ||
type == SSH1_CMSG_STDIN_DATA ||
type == SSH1_MSG_CHANNEL_DATA)) {
/* "Session data" packets - omit the data string. */
if (type == SSH1_MSG_CHANNEL_DATA)
get_uint32(src); /* skip channel id */
str = get_string(src);
if (!get_err(src)) {
assert(nblanks < MAX_BLANKS);
blanks[nblanks].offset = src->pos - str.len;
blanks[nblanks].type = PKTLOG_OMIT;
blanks[nblanks].len = str.len;
nblanks++;
}
}
if (sender_is_client && pls->omit_passwords) {
if (type == SSH1_CMSG_AUTH_PASSWORD ||
type == SSH1_CMSG_AUTH_TIS_RESPONSE ||
type == SSH1_CMSG_AUTH_CCARD_RESPONSE) {
/* If this is a password or similar packet, blank the
* password(s). */
assert(nblanks < MAX_BLANKS);
blanks[nblanks].offset = 0;
blanks[nblanks].len = pkt.len;
blanks[nblanks].type = PKTLOG_BLANK;
nblanks++;
} else if (type == SSH1_CMSG_X11_REQUEST_FORWARDING) {
/*
* If this is an X forwarding request packet, blank the
* fake auth data.
*
* Note that while we blank the X authentication data
* here, we don't take any special action to blank the
* start of an X11 channel, so using MIT-MAGIC-COOKIE-1
* and actually opening an X connection without having
* session blanking enabled is likely to leak your cookie
* into the log.
*/
get_string(src); /* skip protocol name */
str = get_string(src);
if (!get_err(src)) {
assert(nblanks < MAX_BLANKS);
blanks[nblanks].offset = src->pos - str.len;
blanks[nblanks].type = PKTLOG_BLANK;
blanks[nblanks].len = str.len;
nblanks++;
}
}
}
return nblanks;
}

View File

@@ -1,558 +0,0 @@
/*
* Client-specific parts of the SSH-1 connection layer.
*/
#include <assert.h>
#include "putty.h"
#include "ssh.h"
#include "sshbpp.h"
#include "sshppl.h"
#include "sshchan.h"
#include "sshcr.h"
#include "ssh1connection.h"
// WINSCP
#define queue_toplevel_callback(FN, CTX) queue_toplevel_callback(get_log_callback_set(CTX->cl.logctx), FN, CTX)
void ssh1_connection_direction_specific_setup(
struct ssh1_connection_state *s)
{
if (!s->mainchan) {
/*
* Start up the main session, by telling mainchan.c to do it
* all just as it would in SSH-2, and translating those
* concepts to SSH-1's non-channel-shaped idea of the main
* session.
*/
s->mainchan = mainchan_new(
&s->ppl, &s->cl, s->conf, s->term_width, s->term_height,
false /* is_simple */, NULL);
}
}
typedef void (*sf_handler_fn_t)(struct ssh1_connection_state *s,
bool success, void *ctx);
struct outstanding_succfail {
sf_handler_fn_t handler;
void *ctx;
struct outstanding_succfail *next;
/*
* The 'trivial' flag is set if this handler is in response to a
* request for which the SSH-1 protocol doesn't actually specify a
* response packet. The client of this system (mainchan.c) will
* expect to get an acknowledgment regardless, so we arrange to
* send that ack immediately after the rest of the queue empties.
*/
bool trivial;
};
static void ssh1_connection_process_trivial_succfails(void *vs);
static void ssh1_queue_succfail_handler(
struct ssh1_connection_state *s, sf_handler_fn_t handler, void *ctx,
bool trivial)
{
struct outstanding_succfail *osf = snew(struct outstanding_succfail);
osf->handler = handler;
osf->ctx = ctx;
osf->trivial = trivial;
osf->next = NULL;
if (s->succfail_tail)
s->succfail_tail->next = osf;
else
s->succfail_head = osf;
s->succfail_tail = osf;
/* In case this one was trivial and the queue was already empty,
* we should make sure we run the handler promptly, and the
* easiest way is to queue it anyway and then run a trivials pass
* by callback. */
queue_toplevel_callback(ssh1_connection_process_trivial_succfails, s);
}
static void ssh1_connection_process_succfail(
struct ssh1_connection_state *s, bool success)
{
struct outstanding_succfail *prevhead = s->succfail_head;
s->succfail_head = s->succfail_head->next;
if (!s->succfail_head)
s->succfail_tail = NULL;
prevhead->handler(s, success, prevhead->ctx);
sfree(prevhead);
}
static void ssh1_connection_process_trivial_succfails(void *vs)
{
struct ssh1_connection_state *s = (struct ssh1_connection_state *)vs;
while (s->succfail_head && s->succfail_head->trivial)
ssh1_connection_process_succfail(s, true);
}
bool ssh1_handle_direction_specific_packet(
struct ssh1_connection_state *s, PktIn *pktin)
{
PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
PktOut *pktout;
struct ssh1_channel *c;
unsigned remid;
struct ssh_rportfwd pf, *pfp;
ptrlen host, data;
int port;
switch (pktin->type) {
case SSH1_SMSG_SUCCESS:
case SSH1_SMSG_FAILURE:
if (!s->succfail_head) {
ssh_remote_error(s->ppl.ssh,
"Received %s with no outstanding request",
ssh1_pkt_type(pktin->type));
return true;
}
ssh1_connection_process_succfail(
s, pktin->type == SSH1_SMSG_SUCCESS);
queue_toplevel_callback(
ssh1_connection_process_trivial_succfails, s);
return true;
case SSH1_SMSG_X11_OPEN:
remid = get_uint32(pktin);
/* Refuse if X11 forwarding is disabled. */
if (!s->X11_fwd_enabled) {
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
put_uint32(pktout, remid);
pq_push(s->ppl.out_pq, pktout);
ppl_logevent("Rejected X11 connect request");
} else {
c = snew(struct ssh1_channel);
c->connlayer = s;
ssh1_channel_init(c);
c->remoteid = remid;
c->chan = x11_new_channel(s->x11authtree, &c->sc,
NULL, -1, false);
c->remoteid = remid;
c->halfopen = false;
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION);
put_uint32(pktout, c->remoteid);
put_uint32(pktout, c->localid);
pq_push(s->ppl.out_pq, pktout);
ppl_logevent("Opened X11 forward channel");
}
return true;
case SSH1_SMSG_AGENT_OPEN:
remid = get_uint32(pktin);
/* Refuse if agent forwarding is disabled. */
if (!ssh_agent_forwarding_permitted(&s->cl)) {
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
put_uint32(pktout, remid);
pq_push(s->ppl.out_pq, pktout);
} else {
c = snew(struct ssh1_channel);
c->connlayer = s;
ssh1_channel_init(c);
c->remoteid = remid;
c->halfopen = false;
/*
* If possible, make a stream-oriented connection to the
* agent and set up an ordinary port-forwarding type
* channel over it.
*/
{ // WINSCP
Plug *plug;
Channel *ch = portfwd_raw_new(&s->cl, &plug, true);
Socket *skt = agent_connect(plug);
if (!sk_socket_error(skt)) {
portfwd_raw_setup(ch, skt, &c->sc);
c->chan = ch;
} else {
portfwd_raw_free(ch);
/*
* Otherwise, fall back to the old-fashioned system of
* parsing the forwarded data stream ourselves for
* message boundaries, and passing each individual
* message to the one-off agent_query().
*/
c->chan = agentf_new(&c->sc);
}
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION);
put_uint32(pktout, c->remoteid);
put_uint32(pktout, c->localid);
pq_push(s->ppl.out_pq, pktout);
} // WINSCP
}
return true;
case SSH1_MSG_PORT_OPEN:
remid = get_uint32(pktin);
host = get_string(pktin);
port = toint(get_uint32(pktin));
pf.dhost = mkstr(host);
pf.dport = port;
pfp = find234(s->rportfwds, &pf, NULL);
if (!pfp) {
ppl_logevent("Rejected remote port open request for %s:%d",
pf.dhost, port);
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
put_uint32(pktout, remid);
pq_push(s->ppl.out_pq, pktout);
} else {
char *err;
c = snew(struct ssh1_channel);
c->connlayer = s;
ppl_logevent("Received remote port open request for %s:%d",
pf.dhost, port);
err = portfwdmgr_connect(
s->portfwdmgr, &c->chan, pf.dhost, port,
&c->sc, pfp->addressfamily);
if (err) {
ppl_logevent("Port open failed: %s", err);
sfree(err);
ssh1_channel_free(c);
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
put_uint32(pktout, remid);
pq_push(s->ppl.out_pq, pktout);
} else {
ssh1_channel_init(c);
c->remoteid = remid;
c->halfopen = false;
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION);
put_uint32(pktout, c->remoteid);
put_uint32(pktout, c->localid);
pq_push(s->ppl.out_pq, pktout);
ppl_logevent("Forwarded port opened successfully");
}
}
sfree(pf.dhost);
return true;
case SSH1_SMSG_STDOUT_DATA:
case SSH1_SMSG_STDERR_DATA:
data = get_string(pktin);
if (!get_err(pktin)) {
int bufsize = seat_output(
s->ppl.seat, pktin->type == SSH1_SMSG_STDERR_DATA,
data.ptr, data.len);
if (!s->stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {
s->stdout_throttling = true;
ssh_throttle_conn(s->ppl.ssh, +1);
}
}
return true;
case SSH1_SMSG_EXIT_STATUS: {
int exitcode = get_uint32(pktin);
ppl_logevent("Server sent command exit status %d", exitcode);
ssh_got_exitcode(s->ppl.ssh, exitcode);
s->session_terminated = true;
return true;
}
default:
return false;
}
}
static void ssh1mainchan_succfail_wantreply(struct ssh1_connection_state *s,
bool success, void *ctx)
{
chan_request_response(s->mainchan_chan, success);
}
static void ssh1mainchan_succfail_nowantreply(struct ssh1_connection_state *s,
bool success, void *ctx)
{
}
static void ssh1mainchan_queue_response(struct ssh1_connection_state *s,
bool want_reply, bool trivial)
{
sf_handler_fn_t handler = (want_reply ? ssh1mainchan_succfail_wantreply :
ssh1mainchan_succfail_nowantreply);
ssh1_queue_succfail_handler(s, handler, NULL, trivial);
}
static void ssh1mainchan_request_x11_forwarding(
SshChannel *sc, bool want_reply, const char *authproto,
const char *authdata, int screen_number, bool oneshot)
{
struct ssh1_connection_state *s =
container_of(sc, struct ssh1_connection_state, mainchan_sc);
PktOut *pktout;
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_X11_REQUEST_FORWARDING);
put_stringz(pktout, authproto);
put_stringz(pktout, authdata);
if (s->local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER)
put_uint32(pktout, screen_number);
pq_push(s->ppl.out_pq, pktout);
ssh1mainchan_queue_response(s, want_reply, false);
}
static void ssh1mainchan_request_agent_forwarding(
SshChannel *sc, bool want_reply)
{
struct ssh1_connection_state *s =
container_of(sc, struct ssh1_connection_state, mainchan_sc);
PktOut *pktout;
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_CMSG_AGENT_REQUEST_FORWARDING);
pq_push(s->ppl.out_pq, pktout);
ssh1mainchan_queue_response(s, want_reply, false);
}
static void ssh1mainchan_request_pty(
SshChannel *sc, bool want_reply, Conf *conf, int w, int h)
{
struct ssh1_connection_state *s =
container_of(sc, struct ssh1_connection_state, mainchan_sc);
PktOut *pktout;
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_REQUEST_PTY);
put_stringz(pktout, conf_get_str(s->conf, CONF_termtype));
put_uint32(pktout, h);
put_uint32(pktout, w);
put_uint32(pktout, 0); /* width in pixels */
put_uint32(pktout, 0); /* height in pixels */
write_ttymodes_to_packet(
BinarySink_UPCAST(pktout), 1,
get_ttymodes_from_conf(s->ppl.seat, conf));
pq_push(s->ppl.out_pq, pktout);
ssh1mainchan_queue_response(s, want_reply, false);
}
static bool ssh1mainchan_send_env_var(
SshChannel *sc, bool want_reply, const char *var, const char *value)
{
return false; /* SSH-1 doesn't support this at all */
}
static void ssh1mainchan_start_shell(SshChannel *sc, bool want_reply)
{
struct ssh1_connection_state *s =
container_of(sc, struct ssh1_connection_state, mainchan_sc);
PktOut *pktout;
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_EXEC_SHELL);
pq_push(s->ppl.out_pq, pktout);
ssh1mainchan_queue_response(s, want_reply, true);
}
static void ssh1mainchan_start_command(
SshChannel *sc, bool want_reply, const char *command)
{
struct ssh1_connection_state *s =
container_of(sc, struct ssh1_connection_state, mainchan_sc);
PktOut *pktout;
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_EXEC_CMD);
put_stringz(pktout, command);
pq_push(s->ppl.out_pq, pktout);
ssh1mainchan_queue_response(s, want_reply, true);
}
static bool ssh1mainchan_start_subsystem(
SshChannel *sc, bool want_reply, const char *subsystem)
{
return false; /* SSH-1 doesn't support this at all */
}
static bool ssh1mainchan_send_serial_break(
SshChannel *sc, bool want_reply, int length)
{
return false; /* SSH-1 doesn't support this at all */
}
static bool ssh1mainchan_send_signal(
SshChannel *sc, bool want_reply, const char *signame)
{
return false; /* SSH-1 doesn't support this at all */
}
static void ssh1mainchan_send_terminal_size_change(
SshChannel *sc, int w, int h)
{
struct ssh1_connection_state *s =
container_of(sc, struct ssh1_connection_state, mainchan_sc);
PktOut *pktout;
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_WINDOW_SIZE);
put_uint32(pktout, h);
put_uint32(pktout, w);
put_uint32(pktout, 0); /* width in pixels */
put_uint32(pktout, 0); /* height in pixels */
pq_push(s->ppl.out_pq, pktout);
}
static void ssh1mainchan_hint_channel_is_simple(SshChannel *sc)
{
}
static size_t ssh1mainchan_write(
SshChannel *sc, bool is_stderr, const void *data, size_t len)
{
struct ssh1_connection_state *s =
container_of(sc, struct ssh1_connection_state, mainchan_sc);
PktOut *pktout;
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_STDIN_DATA);
put_string(pktout, data, len);
pq_push(s->ppl.out_pq, pktout);
return 0;
}
static void ssh1mainchan_write_eof(SshChannel *sc)
{
struct ssh1_connection_state *s =
container_of(sc, struct ssh1_connection_state, mainchan_sc);
PktOut *pktout;
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_EOF);
pq_push(s->ppl.out_pq, pktout);
}
static const SshChannelVtable ssh1mainchan_vtable = {
// WINSCP
/*.write =*/ ssh1mainchan_write,
/*.write_eof =*/ ssh1mainchan_write_eof,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // WINSCP
/*.request_x11_forwarding =*/ ssh1mainchan_request_x11_forwarding,
/*.request_agent_forwarding =*/ ssh1mainchan_request_agent_forwarding,
/*.request_pty =*/ ssh1mainchan_request_pty,
/*.send_env_var =*/ ssh1mainchan_send_env_var,
/*.start_shell =*/ ssh1mainchan_start_shell,
/*.start_command =*/ ssh1mainchan_start_command,
/*.start_subsystem =*/ ssh1mainchan_start_subsystem,
/*.send_serial_break =*/ ssh1mainchan_send_serial_break,
/*.send_signal =*/ ssh1mainchan_send_signal,
/*.send_terminal_size_change =*/ ssh1mainchan_send_terminal_size_change,
/*.hint_channel_is_simple =*/ ssh1mainchan_hint_channel_is_simple,
/* other methods are NULL */
};
static void ssh1_session_confirm_callback(void *vctx)
{
struct ssh1_connection_state *s = (struct ssh1_connection_state *)vctx;
chan_open_confirmation(s->mainchan_chan);
}
SshChannel *ssh1_session_open(ConnectionLayer *cl, Channel *chan)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
s->mainchan_sc.vt = &ssh1mainchan_vtable;
s->mainchan_sc.cl = &s->cl;
s->mainchan_chan = chan;
queue_toplevel_callback(ssh1_session_confirm_callback, s);
return &s->mainchan_sc;
}
static void ssh1_rportfwd_response(struct ssh1_connection_state *s,
bool success, void *ctx)
{
PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
struct ssh_rportfwd *rpf = (struct ssh_rportfwd *)ctx;
if (success) {
ppl_logevent("Remote port forwarding from %s enabled",
rpf->log_description);
} else {
ppl_logevent("Remote port forwarding from %s refused",
rpf->log_description);
{ // WINSCP
struct ssh_rportfwd *realpf = del234(s->rportfwds, rpf);
assert(realpf == rpf);
portfwdmgr_close(s->portfwdmgr, rpf->pfr);
free_rportfwd(rpf);
} // WINSCP
}
}
struct ssh_rportfwd *ssh1_rportfwd_alloc(
ConnectionLayer *cl,
const char *shost, int sport, const char *dhost, int dport,
int addressfamily, const char *log_description, PortFwdRecord *pfr,
ssh_sharing_connstate *share_ctx)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
struct ssh_rportfwd *rpf = snew(struct ssh_rportfwd);
rpf->shost = dupstr(shost);
rpf->sport = sport;
rpf->dhost = dupstr(dhost);
rpf->dport = dport;
rpf->addressfamily = addressfamily;
rpf->log_description = dupstr(log_description);
rpf->pfr = pfr;
if (add234(s->rportfwds, rpf) != rpf) {
free_rportfwd(rpf);
return NULL;
}
{ // WINSCP
PktOut *pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_CMSG_PORT_FORWARD_REQUEST);
put_uint32(pktout, rpf->sport);
put_stringz(pktout, rpf->dhost);
put_uint32(pktout, rpf->dport);
pq_push(s->ppl.out_pq, pktout);
} // WINSCP
ssh1_queue_succfail_handler(s, ssh1_rportfwd_response, rpf, false);
return rpf;
}
SshChannel *ssh1_serverside_x11_open(
ConnectionLayer *cl, Channel *chan, const SocketPeerInfo *pi)
{
unreachable("Should never be called in the client");
}
SshChannel *ssh1_serverside_agent_open(ConnectionLayer *cl, Channel *chan)
{
unreachable("Should never be called in the client");
}
bool ssh1_connection_need_antispoof_prompt(struct ssh1_connection_state *s)
{
return !seat_set_trust_status(s->ppl.seat, false);
}

View File

@@ -1,851 +0,0 @@
/*
* Packet protocol layer for the SSH-1 'connection protocol', i.e.
* everything after authentication finishes.
*/
#include <assert.h>
#include "putty.h"
#include "ssh.h"
#include "sshbpp.h"
#include "sshppl.h"
#include "sshchan.h"
#include "sshcr.h"
#include "ssh1connection.h"
// WINSCP
#define queue_toplevel_callback(FN, CTX) queue_toplevel_callback(get_log_callback_set(CTX->cl.logctx), FN, CTX)
static int ssh1_rportfwd_cmp(void *av, void *bv)
{
struct ssh_rportfwd *a = (struct ssh_rportfwd *) av;
struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;
int i;
if ( (i = strcmp(a->dhost, b->dhost)) != 0)
return i < 0 ? -1 : +1;
if (a->dport > b->dport)
return +1;
if (a->dport < b->dport)
return -1;
return 0;
}
static void ssh1_connection_free(PacketProtocolLayer *);
static void ssh1_connection_process_queue(PacketProtocolLayer *);
static void ssh1_connection_special_cmd(PacketProtocolLayer *ppl,
SessionSpecialCode code, int arg);
static bool ssh1_connection_want_user_input(PacketProtocolLayer *ppl);
static void ssh1_connection_got_user_input(PacketProtocolLayer *ppl);
static void ssh1_connection_reconfigure(PacketProtocolLayer *ppl, Conf *conf);
static unsigned int ssh1_connection_winscp_query(PacketProtocolLayer *ppl, int query);
static const PacketProtocolLayerVtable ssh1_connection_vtable = {
// WINSCP
/*.free =*/ ssh1_connection_free,
/*.process_queue =*/ ssh1_connection_process_queue,
/*.get_specials =*/ ssh1_common_get_specials,
/*.special_cmd =*/ ssh1_connection_special_cmd,
/*.want_user_input =*/ ssh1_connection_want_user_input,
/*.got_user_input =*/ ssh1_connection_got_user_input,
/*.reconfigure =*/ ssh1_connection_reconfigure,
/*.queued_data_size =*/ ssh_ppl_default_queued_data_size,
/*.name =*/ NULL, /* no layer names in SSH-1 */
ssh1_connection_winscp_query,
};
static void ssh1_rportfwd_remove(
ConnectionLayer *cl, struct ssh_rportfwd *rpf);
static SshChannel *ssh1_lportfwd_open(
ConnectionLayer *cl, const char *hostname, int port,
const char *description, const SocketPeerInfo *pi, Channel *chan);
static struct X11FakeAuth *ssh1_add_x11_display(
ConnectionLayer *cl, int authtype, struct X11Display *disp);
static bool ssh1_agent_forwarding_permitted(ConnectionLayer *cl);
static void ssh1_terminal_size(ConnectionLayer *cl, int width, int height);
static void ssh1_stdout_unthrottle(ConnectionLayer *cl, size_t bufsize);
static size_t ssh1_stdin_backlog(ConnectionLayer *cl);
static void ssh1_throttle_all_channels(ConnectionLayer *cl, bool throttled);
static bool ssh1_ldisc_option(ConnectionLayer *cl, int option);
static void ssh1_set_ldisc_option(ConnectionLayer *cl, int option, bool value);
static void ssh1_enable_x_fwd(ConnectionLayer *cl);
static void ssh1_set_wants_user_input(ConnectionLayer *cl, bool wanted);
static const ConnectionLayerVtable ssh1_connlayer_vtable = {
// WINSCP
/*.rportfwd_alloc =*/ ssh1_rportfwd_alloc,
/*.rportfwd_remove =*/ ssh1_rportfwd_remove,
/*.lportfwd_open =*/ ssh1_lportfwd_open,
/*.session_open =*/ ssh1_session_open,
/*.serverside_x11_open =*/ ssh1_serverside_x11_open,
/*.serverside_agent_open =*/ ssh1_serverside_agent_open,
/*.add_x11_display =*/ ssh1_add_x11_display,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, // WINSCP
/*.agent_forwarding_permitted =*/ ssh1_agent_forwarding_permitted,
/*.terminal_size =*/ ssh1_terminal_size,
/*.stdout_unthrottle =*/ ssh1_stdout_unthrottle,
/*.stdin_backlog =*/ ssh1_stdin_backlog,
/*.throttle_all_channels =*/ ssh1_throttle_all_channels,
/*.ldisc_option =*/ ssh1_ldisc_option,
/*.set_ldisc_option =*/ ssh1_set_ldisc_option,
/*.enable_x_fwd =*/ ssh1_enable_x_fwd,
/*.set_wants_user_input =*/ ssh1_set_wants_user_input,
/* other methods are NULL */
};
static size_t ssh1channel_write(
SshChannel *c, bool is_stderr, const void *buf, size_t len);
static void ssh1channel_write_eof(SshChannel *c);
static void ssh1channel_initiate_close(SshChannel *c, const char *err);
static void ssh1channel_unthrottle(SshChannel *c, size_t bufsize);
static Conf *ssh1channel_get_conf(SshChannel *c);
static void ssh1channel_window_override_removed(SshChannel *c) { /* ignore */ }
static const SshChannelVtable ssh1channel_vtable = {
// WINSCP
/*.write =*/ ssh1channel_write,
/*.write_eof =*/ ssh1channel_write_eof,
/*.initiate_close =*/ ssh1channel_initiate_close,
/*.unthrottle =*/ ssh1channel_unthrottle,
/*.get_conf =*/ ssh1channel_get_conf,
/*.window_override_removed =*/ ssh1channel_window_override_removed,
/* everything else is NULL */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // WINSCP
};
static void ssh1_channel_try_eof(struct ssh1_channel *c);
static void ssh1_channel_close_local(struct ssh1_channel *c,
const char *reason);
static void ssh1_channel_destroy(struct ssh1_channel *c);
static void ssh1_channel_check_close(struct ssh1_channel *c);
static int ssh1_channelcmp(void *av, void *bv)
{
const struct ssh1_channel *a = (const struct ssh1_channel *) av;
const struct ssh1_channel *b = (const struct ssh1_channel *) bv;
if (a->localid < b->localid)
return -1;
if (a->localid > b->localid)
return +1;
return 0;
}
static int ssh1_channelfind(void *av, void *bv)
{
const unsigned *a = (const unsigned *) av;
const struct ssh1_channel *b = (const struct ssh1_channel *) bv;
if (*a < b->localid)
return -1;
if (*a > b->localid)
return +1;
return 0;
}
void ssh1_channel_free(struct ssh1_channel *c)
{
if (c->chan)
chan_free(c->chan);
sfree(c);
}
PacketProtocolLayer *ssh1_connection_new(
Ssh *ssh, Conf *conf, ConnectionLayer **cl_out)
{
struct ssh1_connection_state *s = snew(struct ssh1_connection_state);
memset(s, 0, sizeof(*s));
s->ppl.vt = &ssh1_connection_vtable;
s->conf = conf_copy(conf);
s->channels = newtree234(ssh1_channelcmp);
s->x11authtree = newtree234(x11_authcmp);
/* Need to get the log context for s->cl now, because we won't be
* helpfully notified when a copy is written into s->ppl by our
* owner. */
s->cl.vt = &ssh1_connlayer_vtable;
s->cl.logctx = ssh_get_logctx(ssh);
s->portfwdmgr = portfwdmgr_new(&s->cl);
s->rportfwds = newtree234(ssh1_rportfwd_cmp);
*cl_out = &s->cl;
return &s->ppl;
}
static void ssh1_connection_free(PacketProtocolLayer *ppl)
{
struct ssh1_connection_state *s =
container_of(ppl, struct ssh1_connection_state, ppl);
struct X11FakeAuth *auth;
struct ssh1_channel *c;
struct ssh_rportfwd *rpf;
conf_free(s->conf);
while ((c = delpos234(s->channels, 0)) != NULL)
ssh1_channel_free(c);
freetree234(s->channels);
if (s->mainchan_chan)
chan_free(s->mainchan_chan);
if (s->x11disp)
x11_free_display(s->x11disp);
while ((auth = delpos234(s->x11authtree, 0)) != NULL)
x11_free_fake_auth(auth);
freetree234(s->x11authtree);
while ((rpf = delpos234(s->rportfwds, 0)) != NULL)
free_rportfwd(rpf);
freetree234(s->rportfwds);
portfwdmgr_free(s->portfwdmgr);
if (s->antispoof_prompt)
free_prompts(s->antispoof_prompt);
delete_callbacks_for_context(get_seat_callback_set(ppl->seat), s);
sfree(s);
}
void ssh1_connection_set_protoflags(PacketProtocolLayer *ppl,
int local, int remote)
{
pinitassert(ppl->vt == &ssh1_connection_vtable);
struct ssh1_connection_state *s =
container_of(ppl, struct ssh1_connection_state, ppl);
s->local_protoflags = local;
s->remote_protoflags = remote;
}
static bool ssh1_connection_filter_queue(struct ssh1_connection_state *s)
{
PktIn *pktin;
ptrlen data;
struct ssh1_channel *c;
unsigned localid;
bool expect_halfopen;
while (1) {
if (ssh1_common_filter_queue(&s->ppl))
return true;
if ((pktin = pq_peek(s->ppl.in_pq)) == NULL)
return false;
switch (pktin->type) {
case SSH1_MSG_CHANNEL_DATA:
case SSH1_MSG_CHANNEL_OPEN_CONFIRMATION:
case SSH1_MSG_CHANNEL_OPEN_FAILURE:
case SSH1_MSG_CHANNEL_CLOSE:
case SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION:
/*
* Common preliminary code for all the messages from the
* server that cite one of our channel ids: look up that
* channel id, check it exists, and if it's for a sharing
* downstream, pass it on.
*/
localid = get_uint32(pktin);
c = find234(s->channels, &localid, ssh1_channelfind);
expect_halfopen = (
pktin->type == SSH1_MSG_CHANNEL_OPEN_CONFIRMATION ||
pktin->type == SSH1_MSG_CHANNEL_OPEN_FAILURE);
if (!c || c->halfopen != expect_halfopen) {
ssh_remote_error(
s->ppl.ssh, "Received %s for %s channel %u",
ssh1_pkt_type(pktin->type),
!c ? "nonexistent" : c->halfopen ? "half-open" : "open",
localid);
return true;
}
switch (pktin->type) {
case SSH1_MSG_CHANNEL_OPEN_CONFIRMATION:
assert(c->halfopen);
c->remoteid = get_uint32(pktin);
c->halfopen = false;
c->throttling_conn = false;
chan_open_confirmation(c->chan);
/*
* Now that the channel is fully open, it's possible
* in principle to immediately close it. Check whether
* it wants us to!
*
* This can occur if a local socket error occurred
* between us sending out CHANNEL_OPEN and receiving
* OPEN_CONFIRMATION. If that happens, all we can do
* is immediately initiate close proceedings now that
* we know the server's id to put in the close
* message. We'll have handled that in this code by
* having already turned c->chan into a zombie, so its
* want_close method (which ssh1_channel_check_close
* will consult) will already be returning true.
*/
ssh1_channel_check_close(c);
if (c->pending_eof)
ssh1_channel_try_eof(c); /* in case we had a pending EOF */
break;
case SSH1_MSG_CHANNEL_OPEN_FAILURE:
assert(c->halfopen);
chan_open_failed(c->chan, NULL);
chan_free(c->chan);
del234(s->channels, c);
ssh1_channel_free(c);
break;
case SSH1_MSG_CHANNEL_DATA:
data = get_string(pktin);
if (!get_err(pktin)) {
int bufsize = chan_send(
c->chan, false, data.ptr, data.len);
if (!c->throttling_conn && bufsize > SSH1_BUFFER_LIMIT) {
c->throttling_conn = true;
ssh_throttle_conn(s->ppl.ssh, +1);
}
}
break;
case SSH1_MSG_CHANNEL_CLOSE:
if (!(c->closes & CLOSES_RCVD_CLOSE)) {
c->closes |= CLOSES_RCVD_CLOSE;
chan_send_eof(c->chan);
ssh1_channel_check_close(c);
}
break;
case SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION:
if (!(c->closes & CLOSES_RCVD_CLOSECONF)) {
if (!(c->closes & CLOSES_SENT_CLOSE)) {
ssh_remote_error(
s->ppl.ssh,
"Received CHANNEL_CLOSE_CONFIRMATION for channel"
" %u for which we never sent CHANNEL_CLOSE\n",
c->localid);
return true;
}
c->closes |= CLOSES_RCVD_CLOSECONF;
ssh1_channel_check_close(c);
}
break;
}
pq_pop(s->ppl.in_pq);
break;
default:
if (ssh1_handle_direction_specific_packet(s, pktin)) {
pq_pop(s->ppl.in_pq);
if (ssh1_check_termination(s))
return true;
} else {
return false;
}
}
}
}
static PktIn *ssh1_connection_pop(struct ssh1_connection_state *s)
{
ssh1_connection_filter_queue(s);
return pq_pop(s->ppl.in_pq);
}
static void ssh1_connection_process_queue(PacketProtocolLayer *ppl)
{
struct ssh1_connection_state *s =
container_of(ppl, struct ssh1_connection_state, ppl);
PktIn *pktin;
if (ssh1_connection_filter_queue(s)) /* no matter why we were called */
return;
crBegin(s->crState);
/*
* Signal the seat that authentication is done, so that it can
* deploy spoofing defences. If it doesn't have any, deploy our
* own fallback one.
*
* We do this here rather than at the end of userauth, because we
* might not have gone through userauth at all (if we're a
* connection-sharing downstream).
*/
if (ssh1_connection_need_antispoof_prompt(s)) {
s->antispoof_prompt = new_prompts();
s->antispoof_prompt->to_server = true;
s->antispoof_prompt->from_server = false;
s->antispoof_prompt->name = dupstr("Authentication successful");
add_prompt(
s->antispoof_prompt,
dupstr("Access granted. Press Return to begin session. "), false);
s->antispoof_ret = seat_get_userpass_input(
s->ppl.seat, s->antispoof_prompt, NULL);
while (1) {
while (s->antispoof_ret < 0 &&
bufchain_size(s->ppl.user_input) > 0)
s->antispoof_ret = seat_get_userpass_input(
s->ppl.seat, s->antispoof_prompt, s->ppl.user_input);
if (s->antispoof_ret >= 0)
break;
s->want_user_input = true;
crReturnV;
s->want_user_input = false;
}
free_prompts(s->antispoof_prompt);
s->antispoof_prompt = NULL;
}
portfwdmgr_config(s->portfwdmgr, s->conf);
s->portfwdmgr_configured = true;
while (!s->finished_setup) {
ssh1_connection_direction_specific_setup(s);
crReturnV;
}
while (1) {
/*
* By this point, most incoming packets are already being
* handled by filter_queue, and we need only pay attention to
* the unusual ones.
*/
if ((pktin = ssh1_connection_pop(s)) != NULL) {
ssh_proto_error(s->ppl.ssh, "Unexpected packet received, "
"type %d (%s)", pktin->type,
ssh1_pkt_type(pktin->type));
return;
}
crReturnV;
}
crFinishV;
}
static void ssh1_channel_check_close(struct ssh1_channel *c)
{
struct ssh1_connection_state *s = c->connlayer;
PktOut *pktout;
if (c->halfopen) {
/*
* If we've sent out our own CHANNEL_OPEN but not yet seen
* either OPEN_CONFIRMATION or OPEN_FAILURE in response, then
* it's too early to be sending close messages of any kind.
*/
return;
}
if ((!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes) ||
chan_want_close(c->chan, (c->closes & CLOSES_SENT_CLOSE),
(c->closes & CLOSES_RCVD_CLOSE))) &&
!(c->closes & CLOSES_SENT_CLOSECONF)) {
/*
* We have both sent and received CLOSE (or the channel type
* doesn't need us to), which means the channel is in final
* wind-up. Send CLOSE and/or CLOSE_CONFIRMATION, whichever we
* haven't sent yet.
*/
if (!(c->closes & CLOSES_SENT_CLOSE)) {
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_MSG_CHANNEL_CLOSE);
put_uint32(pktout, c->remoteid);
pq_push(s->ppl.out_pq, pktout);
c->closes |= CLOSES_SENT_CLOSE;
}
if (c->closes & CLOSES_RCVD_CLOSE) {
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION);
put_uint32(pktout, c->remoteid);
pq_push(s->ppl.out_pq, pktout);
c->closes |= CLOSES_SENT_CLOSECONF;
}
}
if (!((CLOSES_SENT_CLOSECONF | CLOSES_RCVD_CLOSECONF) & ~c->closes)) {
/*
* We have both sent and received CLOSE_CONFIRMATION, which
* means we're completely done with the channel.
*/
ssh1_channel_destroy(c);
}
}
static void ssh1_channel_try_eof(struct ssh1_channel *c)
{
struct ssh1_connection_state *s = c->connlayer;
PktOut *pktout;
assert(c->pending_eof); /* precondition for calling us */
if (c->halfopen)
return; /* can't close: not even opened yet */
c->pending_eof = false; /* we're about to send it */
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_MSG_CHANNEL_CLOSE);
put_uint32(pktout, c->remoteid);
pq_push(s->ppl.out_pq, pktout);
c->closes |= CLOSES_SENT_CLOSE;
ssh1_channel_check_close(c);
}
/*
* Close any local socket and free any local resources associated with
* a channel. This converts the channel into a zombie.
*/
static void ssh1_channel_close_local(struct ssh1_channel *c,
const char *reason)
{
struct ssh1_connection_state *s = c->connlayer;
PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
char *msg = chan_log_close_msg(c->chan);
if (msg != NULL) {
ppl_logevent("%s%s%s", msg, reason ? " " : "", reason ? reason : "");
sfree(msg);
}
chan_free(c->chan);
c->chan = zombiechan_new();
}
static void ssh1_check_termination_callback(void *vctx)
{
struct ssh1_connection_state *s = (struct ssh1_connection_state *)vctx;
ssh1_check_termination(s);
}
static void ssh1_channel_destroy(struct ssh1_channel *c)
{
struct ssh1_connection_state *s = c->connlayer;
ssh1_channel_close_local(c, NULL);
del234(s->channels, c);
ssh1_channel_free(c);
/*
* If that was the last channel left open, we might need to
* terminate. But we'll be a bit cautious, by doing that in a
* toplevel callback, just in case anything on the current call
* stack objects to this entire PPL being freed.
*/
queue_toplevel_callback(ssh1_check_termination_callback, s);
}
bool ssh1_check_termination(struct ssh1_connection_state *s)
{
/*
* Decide whether we should terminate the SSH connection now.
* Called after a channel goes away, or when the main session
* returns SSH1_SMSG_EXIT_STATUS; we terminate when none of either
* is left.
*/
if (s->session_terminated && count234(s->channels) == 0) {
PktOut *pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_CMSG_EXIT_CONFIRMATION);
pq_push(s->ppl.out_pq, pktout);
ssh_user_close(s->ppl.ssh, "Session finished");
return true;
}
return false;
}
/*
* Set up most of a new ssh1_channel. Leaves chan untouched (since it
* will sometimes have been filled in before calling this).
*/
void ssh1_channel_init(struct ssh1_channel *c)
{
struct ssh1_connection_state *s = c->connlayer;
c->closes = 0;
c->pending_eof = false;
c->throttling_conn = false;
c->sc.vt = &ssh1channel_vtable;
c->sc.cl = &s->cl;
c->localid = alloc_channel_id(s->channels, struct ssh1_channel);
add234(s->channels, c);
}
static Conf *ssh1channel_get_conf(SshChannel *sc)
{
struct ssh1_channel *c = container_of(sc, struct ssh1_channel, sc);
struct ssh1_connection_state *s = c->connlayer;
return s->conf;
}
static void ssh1channel_write_eof(SshChannel *sc)
{
struct ssh1_channel *c = container_of(sc, struct ssh1_channel, sc);
if (c->closes & CLOSES_SENT_CLOSE)
return;
c->pending_eof = true;
ssh1_channel_try_eof(c);
}
static void ssh1channel_initiate_close(SshChannel *sc, const char *err)
{
struct ssh1_channel *c = container_of(sc, struct ssh1_channel, sc);
char *reason;
reason = err ? dupprintf("due to local error: %s", err) : NULL;
ssh1_channel_close_local(c, reason);
sfree(reason);
c->pending_eof = false; /* this will confuse a zombie channel */
ssh1_channel_check_close(c);
}
static void ssh1channel_unthrottle(SshChannel *sc, size_t bufsize)
{
struct ssh1_channel *c = container_of(sc, struct ssh1_channel, sc);
struct ssh1_connection_state *s = c->connlayer;
if (c->throttling_conn && bufsize <= SSH1_BUFFER_LIMIT) {
c->throttling_conn = false;
ssh_throttle_conn(s->ppl.ssh, -1);
}
}
static size_t ssh1channel_write(
SshChannel *sc, bool is_stderr, const void *buf, size_t len)
{
struct ssh1_channel *c = container_of(sc, struct ssh1_channel, sc);
struct ssh1_connection_state *s = c->connlayer;
pinitassert(!(c->closes & CLOSES_SENT_CLOSE));
PktOut *pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_MSG_CHANNEL_DATA);
put_uint32(pktout, c->remoteid);
put_string(pktout, buf, len);
pq_push(s->ppl.out_pq, pktout);
/*
* In SSH-1 we can return 0 here - implying that channels are
* never individually throttled - because the only circumstance
* that can cause throttling will be the whole SSH connection
* backing up, in which case _everything_ will be throttled as a
* whole.
*/
return 0;
}
static struct X11FakeAuth *ssh1_add_x11_display(
ConnectionLayer *cl, int authtype, struct X11Display *disp)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
struct X11FakeAuth *auth = x11_invent_fake_auth(s->x11authtree, authtype);
auth->disp = disp;
return auth;
}
static SshChannel *ssh1_lportfwd_open(
ConnectionLayer *cl, const char *hostname, int port,
const char *description, const SocketPeerInfo *pi, Channel *chan)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
struct ssh1_channel *c = snew(struct ssh1_channel);
PktOut *pktout;
c->connlayer = s;
ssh1_channel_init(c);
c->halfopen = true;
c->chan = chan;
ppl_logevent("Opening connection to %s:%d for %s",
hostname, port, description);
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_MSG_PORT_OPEN);
put_uint32(pktout, c->localid);
put_stringz(pktout, hostname);
put_uint32(pktout, port);
/* originator string would go here, but we didn't specify
* SSH_PROTOFLAG_HOST_IN_FWD_OPEN */
pq_push(s->ppl.out_pq, pktout);
return &c->sc;
}
static void ssh1_rportfwd_remove(ConnectionLayer *cl, struct ssh_rportfwd *rpf)
{
/*
* We cannot cancel listening ports on the server side in SSH-1!
* There's no message to support it.
*/
}
static bool ssh1_agent_forwarding_permitted(ConnectionLayer *cl)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
return conf_get_bool(s->conf, CONF_agentfwd) && agent_exists();
}
static void ssh1_connection_special_cmd(PacketProtocolLayer *ppl,
SessionSpecialCode code, int arg)
{
struct ssh1_connection_state *s =
container_of(ppl, struct ssh1_connection_state, ppl);
PktOut *pktout;
if (code == SS_PING || code == SS_NOP) {
if (!(s->ppl.remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE)) {
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_MSG_IGNORE);
put_stringz(pktout, "");
pq_push(s->ppl.out_pq, pktout);
}
} else if (s->mainchan) {
mainchan_special_cmd(s->mainchan, code, arg);
}
}
static void ssh1_terminal_size(ConnectionLayer *cl, int width, int height)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
s->term_width = width;
s->term_height = height;
if (s->mainchan)
mainchan_terminal_size(s->mainchan, width, height);
}
static void ssh1_stdout_unthrottle(ConnectionLayer *cl, size_t bufsize)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
if (s->stdout_throttling && bufsize < SSH1_BUFFER_LIMIT) {
s->stdout_throttling = false;
ssh_throttle_conn(s->ppl.ssh, -1);
}
}
static size_t ssh1_stdin_backlog(ConnectionLayer *cl)
{
return 0;
}
static void ssh1_throttle_all_channels(ConnectionLayer *cl, bool throttled)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
struct ssh1_channel *c;
int i;
for (i = 0; NULL != (c = index234(s->channels, i)); i++)
chan_set_input_wanted(c->chan, !throttled);
}
static bool ssh1_ldisc_option(ConnectionLayer *cl, int option)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
return s->ldisc_opts[option];
}
static void ssh1_set_ldisc_option(ConnectionLayer *cl, int option, bool value)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
s->ldisc_opts[option] = value;
}
static void ssh1_enable_x_fwd(ConnectionLayer *cl)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
s->X11_fwd_enabled = true;
}
static void ssh1_set_wants_user_input(ConnectionLayer *cl, bool wanted)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
s->want_user_input = wanted;
s->finished_setup = true;
}
static bool ssh1_connection_want_user_input(PacketProtocolLayer *ppl)
{
struct ssh1_connection_state *s =
container_of(ppl, struct ssh1_connection_state, ppl);
return s->want_user_input;
}
static void ssh1_connection_got_user_input(PacketProtocolLayer *ppl)
{
struct ssh1_connection_state *s =
container_of(ppl, struct ssh1_connection_state, ppl);
while (s->mainchan && bufchain_size(s->ppl.user_input) > 0) {
/*
* Add user input to the main channel's buffer.
*/
ptrlen data = bufchain_prefix(s->ppl.user_input);
if (data.len > 512)
data.len = 512;
sshfwd_write(&s->mainchan_sc, data.ptr, data.len);
bufchain_consume(s->ppl.user_input, data.len);
}
}
static void ssh1_connection_reconfigure(PacketProtocolLayer *ppl, Conf *conf)
{
struct ssh1_connection_state *s =
container_of(ppl, struct ssh1_connection_state, ppl);
conf_free(s->conf);
s->conf = conf_copy(conf);
if (s->portfwdmgr_configured)
portfwdmgr_config(s->portfwdmgr, s->conf);
}
#include <puttyexp.h>
static unsigned int ssh1_connection_winscp_query(PacketProtocolLayer *ppl, int query)
{
struct ssh1_connection_state *s =
container_of(ppl, struct ssh1_connection_state, ppl);
if (query == WINSCP_QUERY_TIMER)
{
return 0; // dummy
}
else if (query == WINSCP_QUERY_REMMAXPKT)
{
return 0; // dummy
}
else if (query == WINSCP_QUERY_MAIN_CHANNEL)
{
return s->finished_setup;
}
else
{
assert(0);
return 0;
}
}

View File

@@ -1,123 +0,0 @@
struct ssh1_channel;
struct outstanding_succfail;
struct ssh1_connection_state {
int crState;
Conf *conf;
int local_protoflags, remote_protoflags;
tree234 *channels; /* indexed by local id */
/* In SSH-1, the main session doesn't take the form of a 'channel'
* according to the wire protocol. But we want to use the same API
* for it, so we define an SshChannel here - but one that uses a
* separate vtable from the usual one, so it doesn't map to a
* struct ssh1_channel as all the others do. */
SshChannel mainchan_sc;
Channel *mainchan_chan; /* the other end of mainchan_sc */
mainchan *mainchan; /* and its subtype */
bool got_pty;
bool ldisc_opts[LD_N_OPTIONS];
bool stdout_throttling;
bool want_user_input;
bool session_terminated;
int term_width, term_height, term_width_orig, term_height_orig;
bool X11_fwd_enabled;
struct X11Display *x11disp;
struct X11FakeAuth *x11auth;
tree234 *x11authtree;
tree234 *rportfwds;
PortFwdManager *portfwdmgr;
bool portfwdmgr_configured;
bool finished_setup;
/*
* These store the list of requests that we're waiting for
* SSH_SMSG_{SUCCESS,FAILURE} replies to. (Those messages don't
* come with any indication of what they're in response to, so we
* have to keep track of the queue ourselves.)
*/
struct outstanding_succfail *succfail_head, *succfail_tail;
bool compressing; /* used in server mode only */
bool sent_exit_status; /* also for server mode */
prompts_t *antispoof_prompt;
int antispoof_ret;
const SshServerConfig *ssc;
ConnectionLayer cl;
PacketProtocolLayer ppl;
};
struct ssh1_channel {
struct ssh1_connection_state *connlayer;
unsigned remoteid, localid;
int type;
/* True if we opened this channel but server hasn't confirmed. */
bool halfopen;
/* Bitmap of whether we've sent/received CHANNEL_CLOSE and
* CHANNEL_CLOSE_CONFIRMATION. */
#define CLOSES_SENT_CLOSE 1
#define CLOSES_SENT_CLOSECONF 2
#define CLOSES_RCVD_CLOSE 4
#define CLOSES_RCVD_CLOSECONF 8
int closes;
/*
* This flag indicates that an EOF is pending on the outgoing side
* of the channel: that is, wherever we're getting the data for
* this channel has sent us some data followed by EOF. We can't
* actually send the EOF until we've finished sending the data, so
* we set this flag instead to remind us to do so once our buffer
* is clear.
*/
bool pending_eof;
/*
* True if this channel is causing the underlying connection to be
* throttled.
*/
bool throttling_conn;
/*
* True if we currently have backed-up data on the direction of
* this channel pointing out of the SSH connection, and therefore
* would prefer the 'Channel' implementation not to read further
* local input if possible.
*/
bool throttled_by_backlog;
Channel *chan; /* handle the client side of this channel, if not */
SshChannel sc; /* entry point for chan to talk back to */
};
SshChannel *ssh1_session_open(ConnectionLayer *cl, Channel *chan);
void ssh1_channel_init(struct ssh1_channel *c);
void ssh1_channel_free(struct ssh1_channel *c);
struct ssh_rportfwd *ssh1_rportfwd_alloc(
ConnectionLayer *cl,
const char *shost, int sport, const char *dhost, int dport,
int addressfamily, const char *log_description, PortFwdRecord *pfr,
ssh_sharing_connstate *share_ctx);
SshChannel *ssh1_serverside_x11_open(
ConnectionLayer *cl, Channel *chan, const SocketPeerInfo *pi);
SshChannel *ssh1_serverside_agent_open(ConnectionLayer *cl, Channel *chan);
void ssh1_connection_direction_specific_setup(
struct ssh1_connection_state *s);
bool ssh1_handle_direction_specific_packet(
struct ssh1_connection_state *s, PktIn *pktin);
bool ssh1_check_termination(struct ssh1_connection_state *s);
bool ssh1_connection_need_antispoof_prompt(struct ssh1_connection_state *s);

1284
source/putty/ssh1login.c vendored

File diff suppressed because it is too large Load Diff

View File

@@ -177,7 +177,6 @@ const char *ssh_verstring_get_local(BinaryPacketProtocol *);
int ssh_verstring_get_bugs(BinaryPacketProtocol *);
#ifdef MPEXT
const ssh_cipher * ssh1_bpp_get_cipher(BinaryPacketProtocol *bpp);
const ssh_cipher * ssh2_bpp_get_cscipher(BinaryPacketProtocol *bpp);
const ssh_cipher * ssh2_bpp_get_sccipher(BinaryPacketProtocol *bpp);
const struct ssh_compressor * ssh2_bpp_get_cscomp(BinaryPacketProtocol *bpp);

109
source/putty/sshcrc.c vendored
View File

@@ -1,109 +0,0 @@
/*
* CRC32 implementation, as used in SSH-1.
*
* This particular form of the CRC uses the polynomial
* P(x) = x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+1
* and represents polynomials in bit-reversed form, so that the x^0
* coefficient (constant term) appears in the bit with place value
* 2^31, and the x^31 coefficient in the bit with place value 2^0. In
* this representation, (x^32 mod P) = 0xEDB88320, so multiplying the
* current state by x is done by shifting right by one bit, and XORing
* that constant into the result if the bit shifted out was 1.
*
* There's a bewildering array of subtly different variants of CRC out
* there, using different polynomials, both bit orders, and varying
* the start and end conditions. There are catalogue websites such as
* http://reveng.sourceforge.net/crc-catalogue/ , which generally seem
* to have the convention of indexing CRCs by their 'check value',
* defined as whatever you get if you hash the 9-byte test string
* "123456789".
*
* The crc32_rfc1662() function below, which starts off the CRC state
* at 0xFFFFFFFF and complements it after feeding all the data, gives
* the check value 0xCBF43926, and matches the hash function that the
* above catalogue refers to as "CRC-32/ISO-HDLC"; among other things,
* it's also the "FCS-32" checksum described in RFC 1662 section C.3
* (hence the name I've given it here).
*
* The crc32_ssh1() function implements the variant form used by
* SSH-1, which uses the same update function, but starts the state at
* zero and doesn't complement it at the end of the computation. The
* check value for that version is 0x2DFD2D88, which that CRC
* catalogue doesn't list at all.
*/
#include <stdint.h>
#include <stdlib.h>
#include "ssh.h"
/*
* Multiply a CRC value by x^4. This implementation strategy avoids
* using a lookup table (which would be a side-channel hazard, since
* SSH-1 applies this CRC to decrypted session data).
*
* The basic idea is that you'd like to "multiply" the shifted-out 4
* bits by the CRC polynomial value 0xEDB88320, or rather by that
* value shifted right 3 bits (since you want the _last_ bit shifted
* out, i.e. the one originally at the 2^3 position, to generate
* 0xEDB88320 itself). But the scare-quoted "multiply" would have to
* be a multiplication of polynomials over GF(2), which differs from
* integer multiplication in that you don't have any carries. In other
* words, you make a copy of one input shifted left by the index of
* each set bit in the other, so that adding them all together would
* give you the ordinary integer product, and then you XOR them
* together instead.
*
* With a 4-bit multiplier, the two kinds of multiplication coincide
* provided the multiplicand has no two set bits at positions
* differing by less than 4, because then no two copies of the
* multiplier can overlap to generate a carry. So I break up the
* intended multiplicand K = 0xEDB88320 >> 3 into three sub-constants
* a,b,c with that property, such that a^b^c = K. Then I can multiply
* m by each of them separately, and XOR together the results.
*/
static inline uint32_t crc32_shift_4(uint32_t v)
{
const uint32_t a = 0x11111044, b = 0x08840020, c = 0x04220000;
uint32_t m = v & 0xF;
return (v >> 4) ^ (a*m) ^ (b*m) ^ (c*m);
}
/*
* The 8-bit shift you need every time you absorb an input byte,
* implemented simply by iterating the 4-bit shift twice.
*/
static inline uint32_t crc32_shift_8(uint32_t v)
{
return crc32_shift_4(crc32_shift_4(v));
}
/*
* Update an existing hash value with extra bytes of data.
*/
uint32_t crc32_update(uint32_t crc, ptrlen data)
{
const uint8_t *p = (const uint8_t *)data.ptr;
size_t len; // WINSCP
for (len = data.len; len-- > 0 ;)
crc = crc32_shift_8(crc ^ *p++);
return crc;
}
/*
* The SSH-1 variant of CRC-32.
*/
uint32_t crc32_ssh1(ptrlen data)
{
return crc32_update(0, data);
}
/*
* The official version of CRC-32. Nothing in PuTTY proper uses this,
* but it's useful to expose it to testcrypt so that we can implement
* standard test vectors.
*/
uint32_t crc32_rfc1662(ptrlen data)
{
return crc32_update(0xFFFFFFFF, data) ^ 0xFFFFFFFF;
}

View File

@@ -1,171 +0,0 @@
/* $OpenBSD: deattack.c,v 1.14 2001/06/23 15:12:18 itojun Exp $ */
/*
* Cryptographic attack detector for ssh - source code
*
* Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
*
* All rights reserved. Redistribution and use in source and binary
* forms, with or without modification, are permitted provided that
* this copyright notice is retained.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
* CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
* SOFTWARE.
*
* Ariel Futoransky <futo@core-sdi.com>
* <http://www.core-sdi.com>
*
* Modified for use in PuTTY by Simon Tatham
*/
#include <assert.h>
#include "misc.h"
#include "ssh.h"
/* SSH Constants */
#define SSH_MAXBLOCKS (32 * 1024)
#define SSH_BLOCKSIZE (8)
/* Hashing constants */
#define HASH_MINSIZE (8 * 1024)
#define HASH_ENTRYSIZE (sizeof(uint16_t))
#define HASH_FACTOR(x) ((x)*3/2)
#define HASH_UNUSEDCHAR (0xff)
#define HASH_UNUSED (0xffff)
#define HASH_IV (0xfffe)
#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
/* Hash function (Input keys are cipher results) */
#define HASH(x) GET_32BIT_MSB_FIRST(x)
#define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE))
static const uint8_t ONE[4] = { 1, 0, 0, 0 };
static const uint8_t ZERO[4] = { 0, 0, 0, 0 };
struct crcda_ctx {
uint16_t *h;
uint32_t n;
};
struct crcda_ctx *crcda_make_context(void)
{
struct crcda_ctx *ret = snew(struct crcda_ctx);
ret->h = NULL;
ret->n = HASH_MINSIZE / HASH_ENTRYSIZE;
return ret;
}
void crcda_free_context(struct crcda_ctx *ctx)
{
if (ctx) {
sfree(ctx->h);
ctx->h = NULL;
sfree(ctx);
}
}
static void crc_update(uint32_t *a, const void *b)
{
*a = crc32_update(*a, make_ptrlen(b, 4));
}
/* detect if a block is used in a particular pattern */
static bool check_crc(const uint8_t *S, const uint8_t *buf,
uint32_t len, const uint8_t *IV)
{
uint32_t crc;
const uint8_t *c;
crc = 0;
if (IV && !CMP(S, IV)) {
crc_update(&crc, ONE);
crc_update(&crc, ZERO);
}
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
if (!CMP(S, c)) {
crc_update(&crc, ONE);
crc_update(&crc, ZERO);
} else {
crc_update(&crc, ZERO);
crc_update(&crc, ZERO);
}
}
return (crc == 0);
}
/* Detect a crc32 compensation attack on a packet */
bool detect_attack(struct crcda_ctx *ctx,
const unsigned char *buf, uint32_t len,
const unsigned char *IV)
{
register uint32_t i, j;
uint32_t l;
register const uint8_t *c;
const uint8_t *d;
assert(!(len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
len % SSH_BLOCKSIZE != 0));
for (l = ctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
;
if (ctx->h == NULL) {
ctx->n = l;
ctx->h = snewn(ctx->n, uint16_t);
} else {
if (l > ctx->n) {
ctx->n = l;
ctx->h = sresize(ctx->h, ctx->n, uint16_t);
}
}
if (len <= HASH_MINBLOCKS) {
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
if (IV && (!CMP(c, IV))) {
if ((check_crc(c, buf, len, IV)))
return true; /* attack detected */
else
break;
}
for (d = buf; d < c; d += SSH_BLOCKSIZE) {
if (!CMP(c, d)) {
if ((check_crc(c, buf, len, IV)))
return true; /* attack detected */
else
break;
}
}
}
return false; /* ok */
}
memset(ctx->h, HASH_UNUSEDCHAR, ctx->n * HASH_ENTRYSIZE);
if (IV)
ctx->h[HASH(IV) & (ctx->n - 1)] = HASH_IV;
for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
for (i = HASH(c) & (ctx->n - 1); ctx->h[i] != HASH_UNUSED;
i = (i + 1) & (ctx->n - 1)) {
if (ctx->h[i] == HASH_IV) {
assert(IV); /* or we wouldn't have stored HASH_IV above */
if (!CMP(c, IV)) {
if (check_crc(c, buf, len, IV))
return true; /* attack detected */
else
break;
}
} else if (!CMP(c, buf + ctx->h[i] * SSH_BLOCKSIZE)) {
if (check_crc(c, buf, len, IV))
return true; /* attack detected */
else
break;
}
}
ctx->h[i] = j;
}
return false; /* ok */
}

View File

@@ -170,7 +170,7 @@
#define SFTP_STATUS_FILE_CORRUPT 242
#define KEY_TYPE_UNKNOWN2 243
#define KEY_TYPE_UNSUPPORTED2 244
#define KEY_TYPE_DIFFERENT_SSH 245
#define KEY_TYPE_SSH1 245
#define SFTP_OVERWRITE_FILE_ERROR2 246
#define SFTP_OVERWRITE_DELETE_BUTTON 247
#define SPACE_AVAILABLE_ERROR 248

View File

@@ -139,7 +139,7 @@ BEGIN
SFTP_STATUS_FILE_CORRUPT, "The file is corrupt; an filesystem integrity check should be run."
KEY_TYPE_UNKNOWN2, "File '%s' does not contain private key in known format."
KEY_TYPE_UNSUPPORTED2, "**Private key file '%s' contains key in %s format. WinSCP supports only PuTTY format.**"
KEY_TYPE_DIFFERENT_SSH, "Private key file '%s' contains key in %s format. It does not follow your preferred SSH protocol version."
KEY_TYPE_SSH1, "Private key file '%s' contains key in deprecated SSH-1 format."
SFTP_OVERWRITE_FILE_ERROR2, "Cannot overwrite remote file '%s'.$$\n \nPress 'Delete' to delete the file and create new one instead of overwriting it.$$"
SFTP_OVERWRITE_DELETE_BUTTON, "&Delete"
SPACE_AVAILABLE_ERROR, "Error checking space available for path '%s'."

View File

@@ -229,8 +229,7 @@ void __fastcall OpenSessionInPutty(const UnicodeString PuttyPath,
{
AddToList(PuttyParams, L"-C", L" ");
}
AddToList(PuttyParams,
((SessionData->SshProt == ssh1only || SessionData->SshProt == ssh1deprecated) ? L"-1" : L"-2"), L" ");
AddToList(PuttyParams, L"-2", L" ");
if (!SessionData->LogicalHostName.IsEmpty())
{
AddToList(PuttyParams, FORMAT(L"-loghost \"%s\"", (SessionData->LogicalHostName)), L" ");

View File

@@ -1895,7 +1895,7 @@ bool __fastcall TTerminalManager::UploadPublicKey(
const UnicodeString AuthorizedKeysFile = L"authorized_keys";
UnicodeString AuthorizedKeysFilePath = FORMAT(L"%s/%s", (SshFolder, AuthorizedKeysFile));
VerifyAndConvertKey(FileName, ssh2only, false);
VerifyAndConvertKey(FileName, false);
UnicodeString Comment;
UnicodeString Line = GetPublicKeyLine(FileName, Comment);

View File

@@ -1285,8 +1285,7 @@ static void __fastcall ConvertKey(UnicodeString & FileName, TKeyType Type)
}
}
//---------------------------------------------------------------------------
static void __fastcall DoVerifyKey(
UnicodeString & FileName, TSshProt SshProt, bool Convert, bool CanIgnore)
static void __fastcall DoVerifyKey(UnicodeString & FileName, bool Convert, bool CanIgnore)
{
if (!FileName.Trim().IsEmpty())
{
@@ -1330,14 +1329,7 @@ static void __fastcall DoVerifyKey(
break;
case ktSSH1:
case ktSSH2:
if ((Type == ktSSH1) != (SshProt == ssh1only))
{
Message =
MainInstructions(
FMTLOAD(KEY_TYPE_DIFFERENT_SSH,
(FileName, (Type == ktSSH1 ? L"SSH-1" : L"PuTTY SSH-2"))));
}
Message = MainInstructions(LoadStr(KEY_TYPE_SSH1));
break;
case ktSSH1Public:
@@ -1375,14 +1367,15 @@ static void __fastcall DoVerifyKey(
}
}
//---------------------------------------------------------------------------
void __fastcall VerifyAndConvertKey(UnicodeString & FileName, TSshProt SshProt, bool CanIgnore)
void __fastcall VerifyAndConvertKey(UnicodeString & FileName, bool CanIgnore)
{
DoVerifyKey(FileName, SshProt, true, CanIgnore);
DoVerifyKey(FileName, true, CanIgnore);
}
//---------------------------------------------------------------------------
void __fastcall VerifyKey(UnicodeString FileName, TSshProt SshProt)
void __fastcall VerifyKey(const UnicodeString & FileName)
{
DoVerifyKey(FileName, SshProt, false, true);
UnicodeString AFileName(FileName);
DoVerifyKey(AFileName, false, true);
}
//---------------------------------------------------------------------------
void __fastcall VerifyCertificate(const UnicodeString & FileName)

View File

@@ -71,8 +71,8 @@ void __fastcall CopyToClipboard(TStrings * Strings);
void __fastcall ShutDownWindows();
void __fastcall SuspendWindows();
void __fastcall EditSelectBaseName(HWND Edit);
void __fastcall VerifyAndConvertKey(UnicodeString & FileName, TSshProt SshProt, bool CanIgnore);
void __fastcall VerifyKey(UnicodeString FileName, TSshProt SshProt);
void __fastcall VerifyAndConvertKey(UnicodeString & FileName, bool CanIgnore);
void __fastcall VerifyKey(const UnicodeString & FileName);
void __fastcall VerifyCertificate(const UnicodeString & FileName);
TStrings * __fastcall GetUnwrappedMemoLines(TMemo * Memo);
bool __fastcall DetectSystemExternalEditor(