From 1b7a6271322baafd2dbf56be84efce2b876a1a58 Mon Sep 17 00:00:00 2001 From: martinprikryl Date: Mon, 14 Apr 2014 10:25:57 +0000 Subject: [PATCH] WinSCP 5.5.3 2014-04-14 http://winscp.net/eng/docs/history#5.5.3 --- deployment/WinSCPnet.nuspec | 8 +- deployment/winscpsetup.iss | 5 +- dotnet/properties/AssemblyInfo.cs | 2 +- libs/openssl/crypto/asn1/asn1_err.c | 2 +- libs/openssl/crypto/bio/bss_log.c | 2 +- libs/openssl/crypto/bn/bn.h | 11 ++ libs/openssl/crypto/bn/bn_lib.c | 52 ++++++++++ libs/openssl/crypto/buildinf.h | 6 +- libs/openssl/crypto/cryptlib.c | 2 +- libs/openssl/crypto/evp/bio_b64.c | 2 +- libs/openssl/crypto/modes/gcm128.c | 88 ++++++++++++++++ libs/openssl/crypto/opensslv.h | 6 +- libs/openssl/crypto/rand/md_rand.c | 3 + libs/openssl/crypto/rand/rand_win.c | 2 +- libs/openssl/crypto/symhacks.h | 6 ++ libs/openssl/crypto/x509/by_dir.c | 6 +- libs/openssl/crypto/x509/x509_vfy.c | 5 +- libs/openssl/e_os.h | 7 ++ libs/openssl/ssl/d1_both.c | 26 +++-- libs/openssl/ssl/kssl.h | 9 ++ libs/openssl/ssl/s23_clnt.c | 2 +- libs/openssl/ssl/s3_srvr.c | 4 +- libs/openssl/ssl/ssl.h | 2 +- libs/openssl/ssl/t1_enc.c | 3 +- libs/openssl/ssl/t1_lib.c | 46 +++++++-- libs/openssl/ssl/tls1.h | 6 ++ source/Console.cbproj | 2 +- source/DragExt.cbproj | 2 +- source/DragExt64.rc | 4 +- source/WinSCP.cbproj | 4 +- source/core/Common.cpp | 30 ++++++ source/core/Common.h | 2 + source/core/FtpFileSystem.cpp | 126 ++++++++++++++++++++--- source/core/FtpFileSystem.h | 1 + source/core/Script.cpp | 2 +- source/filezilla/AsyncSslSocketLayer.cpp | 36 +++++-- source/filezilla/AsyncSslSocketLayer.h | 2 + source/filezilla/FileZillaIntf.cpp | 1 + source/filezilla/FileZillaIntf.h | 2 + source/forms/CustomScpExplorer.cpp | 6 +- source/forms/Login.cpp | 40 +++++-- source/forms/Login.h | 2 + source/forms/Preferences.cpp | 106 ++++++++++--------- source/forms/Preferences.dfm | 2 + source/forms/Progress.cpp | 96 +++++++++-------- source/forms/ScpCommander.cpp | 2 +- source/packages/my/PathLabel.pas | 3 +- source/putty/SSH.C | 4 +- source/resource/TextsCore.h | 2 +- source/resource/TextsCore1.rc | 6 +- source/resource/TextsWin1.rc | 2 +- source/windows/GUITools.cpp | 35 ++++++- source/windows/GUITools.h | 1 + source/windows/Setup.cpp | 63 +++++++----- source/windows/TerminalManager.cpp | 12 ++- source/windows/TerminalManager.h | 1 + source/windows/Tools.cpp | 7 +- source/windows/Tools.h | 1 + source/windows/UserInterface.cpp | 4 + source/windows/WinConfiguration.cpp | 4 +- source/windows/WinMain.cpp | 9 +- 61 files changed, 708 insertions(+), 227 deletions(-) diff --git a/deployment/WinSCPnet.nuspec b/deployment/WinSCPnet.nuspec index 7cfd3634..82f6ac58 100644 --- a/deployment/WinSCPnet.nuspec +++ b/deployment/WinSCPnet.nuspec @@ -1,12 +1,12 @@ - WinSCPnet + WinSCP $version$ WinSCP .NET assembly Martin Prikryl Martin Prikryl - http://winscp.net/eng/docs/library#license + http://www.mozilla.org/MPL/2.0/ http://winscp.net/eng/docs/library http://winscp.net/pad/winscp.png false @@ -15,7 +15,9 @@ The library is primarily intended for advanced automation tasks that require conditional processing, loops or other control structures for which the basic scripting interface is too limited. The library is not a general purpose file transfer library. It particularly lacks support for interactive processing and as such it is not well suited for use in GUI applications. -For documentation and examples of use, see project website. +For documentation and examples of use, see project website. + +The NuGet package includes the assembly itself and a required WinSCP executable. When installed, it adds the assembly as reference to your project and sets up WinSCP executable to be copied to project output directory, so that it can be found on run-time. Copyright © 2012-2014 Martin Prikryl winscp sftp ftp ftps scp transfer diff --git a/deployment/winscpsetup.iss b/deployment/winscpsetup.iss index 10a543cd..c75083cd 100644 --- a/deployment/winscpsetup.iss +++ b/deployment/winscpsetup.iss @@ -1416,9 +1416,10 @@ begin Log('Preparing intallation report'); ReportData := Format( - 'installed=%d&silent=%d&ver=%s&lang=%s&', [ + 'installed=%d&silent=%d&ver=%s&lang=%s&prevver=%s&', [ Integer(InstallationDone), Integer(WizardSilent), - ExpandConstant('{#VersionOnly}'), ActiveLanguage]); + ExpandConstant('{#VersionOnly}'), ActiveLanguage, + PrevVersion]); #ifdef Chrome ReportData := ReportData + diff --git a/dotnet/properties/AssemblyInfo.cs b/dotnet/properties/AssemblyInfo.cs index 5120d2a0..0525c7d9 100644 --- a/dotnet/properties/AssemblyInfo.cs +++ b/dotnet/properties/AssemblyInfo.cs @@ -21,7 +21,7 @@ [assembly: AssemblyVersion("1.1.5.0")] [assembly: AssemblyFileVersion("1.1.5.0")] -[assembly: AssemblyInformationalVersionAttribute("5.5.2.0")] +[assembly: AssemblyInformationalVersionAttribute("5.5.3.0")] [assembly: CLSCompliant(true)] diff --git a/libs/openssl/crypto/asn1/asn1_err.c b/libs/openssl/crypto/asn1/asn1_err.c index 1a30bf11..aa60203b 100644 --- a/libs/openssl/crypto/asn1/asn1_err.c +++ b/libs/openssl/crypto/asn1/asn1_err.c @@ -305,7 +305,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ERR_REASON(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE),"unknown public key type"}, {ERR_REASON(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM),"unknown signature algorithm"}, {ERR_REASON(ASN1_R_UNKNOWN_TAG) ,"unknown tag"}, -{ERR_REASON(ASN1_R_UNKOWN_FORMAT) ,"unkown format"}, +{ERR_REASON(ASN1_R_UNKOWN_FORMAT) ,"unknown format"}, {ERR_REASON(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE),"unsupported any defined by type"}, {ERR_REASON(ASN1_R_UNSUPPORTED_CIPHER) ,"unsupported cipher"}, {ERR_REASON(ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM),"unsupported encryption algorithm"}, diff --git a/libs/openssl/crypto/bio/bss_log.c b/libs/openssl/crypto/bio/bss_log.c index b7dce5c1..2227b2b5 100644 --- a/libs/openssl/crypto/bio/bss_log.c +++ b/libs/openssl/crypto/bio/bss_log.c @@ -245,7 +245,7 @@ static int MS_CALLBACK slg_puts(BIO *bp, const char *str) static void xopenlog(BIO* bp, char* name, int level) { - if (GetVersion() < 0x80000000) + if (check_winnt()) bp->ptr = RegisterEventSourceA(NULL,name); else bp->ptr = NULL; diff --git a/libs/openssl/crypto/bn/bn.h b/libs/openssl/crypto/bn/bn.h index f34248ec..21a1a3fe 100644 --- a/libs/openssl/crypto/bn/bn.h +++ b/libs/openssl/crypto/bn/bn.h @@ -538,6 +538,8 @@ BIGNUM *BN_mod_inverse(BIGNUM *ret, BIGNUM *BN_mod_sqrt(BIGNUM *ret, const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx); +void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords); + /* Deprecated versions */ #ifndef OPENSSL_NO_DEPRECATED BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe, @@ -774,11 +776,20 @@ int RAND_pseudo_bytes(unsigned char *buf,int num); #define bn_fix_top(a) bn_check_top(a) +#define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2) +#define bn_wcheck_size(bn, words) \ + do { \ + const BIGNUM *_bnum2 = (bn); \ + assert(words <= (_bnum2)->dmax && words >= (_bnum2)->top); \ + } while(0) + #else /* !BN_DEBUG */ #define bn_pollute(a) #define bn_check_top(a) #define bn_fix_top(a) bn_correct_top(a) +#define bn_check_size(bn, bits) +#define bn_wcheck_size(bn, words) #endif diff --git a/libs/openssl/crypto/bn/bn_lib.c b/libs/openssl/crypto/bn/bn_lib.c index 7a5676de..5461e6ee 100644 --- a/libs/openssl/crypto/bn/bn_lib.c +++ b/libs/openssl/crypto/bn/bn_lib.c @@ -824,3 +824,55 @@ int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, } return bn_cmp_words(a,b,cl); } + +/* + * Constant-time conditional swap of a and b. + * a and b are swapped if condition is not 0. The code assumes that at most one bit of condition is set. + * nwords is the number of words to swap. The code assumes that at least nwords are allocated in both a and b, + * and that no more than nwords are used by either a or b. + * a and b cannot be the same number + */ +void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) + { + BN_ULONG t; + int i; + + bn_wcheck_size(a, nwords); + bn_wcheck_size(b, nwords); + + assert(a != b); + assert((condition & (condition - 1)) == 0); + assert(sizeof(BN_ULONG) >= sizeof(int)); + + condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1; + + t = (a->top^b->top) & condition; + a->top ^= t; + b->top ^= t; + +#define BN_CONSTTIME_SWAP(ind) \ + do { \ + t = (a->d[ind] ^ b->d[ind]) & condition; \ + a->d[ind] ^= t; \ + b->d[ind] ^= t; \ + } while (0) + + + switch (nwords) { + default: + for (i = 10; i < nwords; i++) + BN_CONSTTIME_SWAP(i); + /* Fallthrough */ + case 10: BN_CONSTTIME_SWAP(9); /* Fallthrough */ + case 9: BN_CONSTTIME_SWAP(8); /* Fallthrough */ + case 8: BN_CONSTTIME_SWAP(7); /* Fallthrough */ + case 7: BN_CONSTTIME_SWAP(6); /* Fallthrough */ + case 6: BN_CONSTTIME_SWAP(5); /* Fallthrough */ + case 5: BN_CONSTTIME_SWAP(4); /* Fallthrough */ + case 4: BN_CONSTTIME_SWAP(3); /* Fallthrough */ + case 3: BN_CONSTTIME_SWAP(2); /* Fallthrough */ + case 2: BN_CONSTTIME_SWAP(1); /* Fallthrough */ + case 1: BN_CONSTTIME_SWAP(0); + } +#undef BN_CONSTTIME_SWAP +} diff --git a/libs/openssl/crypto/buildinf.h b/libs/openssl/crypto/buildinf.h index ce884fd6..6cce7be1 100644 --- a/libs/openssl/crypto/buildinf.h +++ b/libs/openssl/crypto/buildinf.h @@ -9,11 +9,11 @@ /* auto-generated/updated by util/mk1mf.pl for crypto/cversion.c */ #define CFLAGS "cl /MD /Ox /O2 /Ob2 -DOPENSSL_THREADS -DDSO_WIN32 -DOPENSSL_USE_APPLINK -I. -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -DOPENSSL_NO_KRB5 -DOPENSSL_NO_JPAKE -DOPENSSL_NO_STATIC_ENGINE " #define PLATFORM "VC-WIN32" - #define DATE "Fri Jan 10 14:05:30 2014" + #define DATE "Wed Apr 9 09:25:41 2014" #endif #ifdef MK1MF_PLATFORM_BC_NT /* auto-generated/updated by util/mk1mf.pl for crypto/cversion.c */ - #define CFLAGS "bcc32 -DWIN32_LEAN_AND_MEAN -q -w-ccc -w-rch -w-pia -w-aus -w-par -w-inl -c -tWC -tWM -DOPENSSL_SYSNAME_WIN32 -DL_ENDIAN -DDSO_WIN32 -D_stricmp=stricmp -D_strnicmp=strnicmp -O2 -ff -fp -DBN_ASM -DMD5_ASM -DSHA1_ASM -DRMD160_ASM -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -DOPENSSL_NO_KRB5 -DOPENSSL_NO_JPAKE -DOPENSSL_NO_DYNAMIC_ENGINE " + #define CFLAGS "bcc32 -DWIN32_LEAN_AND_MEAN -q -w-ccc -w-rch -w-pia -w-aus -w-par -w-inl -c -tWC -tWM -DOPENSSL_SYSNAME_WIN32 -DL_ENDIAN -DDSO_WIN32 -D_stricmp=stricmp -D_strnicmp=strnicmp -D_timeb=timeb -D_ftime=ftime -O2 -ff -fp -DBN_ASM -DMD5_ASM -DSHA1_ASM -DRMD160_ASM -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -DOPENSSL_NO_KRB5 -DOPENSSL_NO_JPAKE -DOPENSSL_NO_DYNAMIC_ENGINE " #define PLATFORM "BC-NT" - #define DATE "Fri Jan 10 14:05:30 2014" + #define DATE "Wed Apr 9 09:25:42 2014" #endif diff --git a/libs/openssl/crypto/cryptlib.c b/libs/openssl/crypto/cryptlib.c index 304c6b70..0b77d8b7 100644 --- a/libs/openssl/crypto/cryptlib.c +++ b/libs/openssl/crypto/cryptlib.c @@ -889,7 +889,7 @@ void OPENSSL_showfatal (const char *fmta,...) #if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 /* this -------------v--- guards NT-specific calls */ - if (GetVersion() < 0x80000000 && OPENSSL_isservice() > 0) + if (check_winnt() && OPENSSL_isservice() > 0) { HANDLE h = RegisterEventSource(0,_T("OPENSSL")); const TCHAR *pmsg=buf; ReportEvent(h,EVENTLOG_ERROR_TYPE,0,0,0,1,0,&pmsg,0); diff --git a/libs/openssl/crypto/evp/bio_b64.c b/libs/openssl/crypto/evp/bio_b64.c index 72a2a672..ac6d441a 100644 --- a/libs/openssl/crypto/evp/bio_b64.c +++ b/libs/openssl/crypto/evp/bio_b64.c @@ -264,7 +264,7 @@ static int b64_read(BIO *b, char *out, int outl) } /* we fell off the end without starting */ - if (j == i) + if ((j == i) && (num == 0)) { /* Is this is one long chunk?, if so, keep on * reading until a new line. */ diff --git a/libs/openssl/crypto/modes/gcm128.c b/libs/openssl/crypto/modes/gcm128.c index 250063de..e1dc2b0f 100644 --- a/libs/openssl/crypto/modes/gcm128.c +++ b/libs/openssl/crypto/modes/gcm128.c @@ -810,7 +810,11 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx,const unsigned char *iv,size_t len) GCM_MUL(ctx,Yi); if (is_endian.little) +#ifdef BSWAP4 + ctr = BSWAP4(ctx->Yi.d[3]); +#else ctr = GETU32(ctx->Yi.c+12); +#endif else ctr = ctx->Yi.d[3]; } @@ -818,7 +822,11 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx,const unsigned char *iv,size_t len) (*ctx->block)(ctx->Yi.c,ctx->EK0.c,ctx->key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; } @@ -913,7 +921,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, } if (is_endian.little) +#ifdef BSWAP4 + ctr = BSWAP4(ctx->Yi.d[3]); +#else ctr = GETU32(ctx->Yi.c+12); +#endif else ctr = ctx->Yi.d[3]; @@ -947,7 +959,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; for (i=0; i<16/sizeof(size_t); ++i) @@ -969,7 +985,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; for (i=0; i<16/sizeof(size_t); ++i) @@ -988,7 +1008,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; for (i=0; i<16/sizeof(size_t); ++i) @@ -1004,7 +1028,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; while (len--) { @@ -1022,7 +1050,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; } @@ -1066,7 +1098,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, } if (is_endian.little) +#ifdef BSWAP4 + ctr = BSWAP4(ctx->Yi.d[3]); +#else ctr = GETU32(ctx->Yi.c+12); +#endif else ctr = ctx->Yi.d[3]; @@ -1103,7 +1139,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; for (i=0; i<16/sizeof(size_t); ++i) @@ -1123,7 +1163,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; for (i=0; i<16/sizeof(size_t); ++i) @@ -1141,7 +1185,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; for (i=0; i<16/sizeof(size_t); ++i) { @@ -1159,7 +1207,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; while (len--) { @@ -1180,7 +1232,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, (*block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; } @@ -1225,7 +1281,11 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, } if (is_endian.little) +#ifdef BSWAP4 + ctr = BSWAP4(ctx->Yi.d[3]); +#else ctr = GETU32(ctx->Yi.c+12); +#endif else ctr = ctx->Yi.d[3]; @@ -1247,7 +1307,11 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, (*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c); ctr += GHASH_CHUNK/16; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; GHASH(ctx,out,GHASH_CHUNK); @@ -1262,7 +1326,11 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, (*stream)(in,out,j,key,ctx->Yi.c); ctr += (unsigned int)j; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; in += i; @@ -1282,7 +1350,11 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, (*ctx->block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; while (len--) { @@ -1324,7 +1396,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, } if (is_endian.little) +#ifdef BSWAP4 + ctr = BSWAP4(ctx->Yi.d[3]); +#else ctr = GETU32(ctx->Yi.c+12); +#endif else ctr = ctx->Yi.d[3]; @@ -1349,7 +1425,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, (*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c); ctr += GHASH_CHUNK/16; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; out += GHASH_CHUNK; @@ -1375,7 +1455,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, (*stream)(in,out,j,key,ctx->Yi.c); ctr += (unsigned int)j; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; out += i; @@ -1386,7 +1470,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, (*ctx->block)(ctx->Yi.c,ctx->EKi.c,key); ++ctr; if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else PUTU32(ctx->Yi.c+12,ctr); +#endif else ctx->Yi.d[3] = ctr; while (len--) { diff --git a/libs/openssl/crypto/opensslv.h b/libs/openssl/crypto/opensslv.h index b27a5bb8..ebe71807 100644 --- a/libs/openssl/crypto/opensslv.h +++ b/libs/openssl/crypto/opensslv.h @@ -25,11 +25,11 @@ * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -#define OPENSSL_VERSION_NUMBER 0x1000106fL +#define OPENSSL_VERSION_NUMBER 0x1000107fL #ifdef OPENSSL_FIPS -#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1f-fips 6 Jan 2014" +#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1g-fips 7 Apr 2014" #else -#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1f 6 Jan 2014" +#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1g 7 Apr 2014" #endif #define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT diff --git a/libs/openssl/crypto/rand/md_rand.c b/libs/openssl/crypto/rand/md_rand.c index dd291637..aee1c30b 100644 --- a/libs/openssl/crypto/rand/md_rand.c +++ b/libs/openssl/crypto/rand/md_rand.c @@ -198,6 +198,9 @@ static void ssleay_rand_add(const void *buf, int num, double add) EVP_MD_CTX m; int do_not_lock; + if (!num) + return; + /* * (Based on the rand(3) manpage) * diff --git a/libs/openssl/crypto/rand/rand_win.c b/libs/openssl/crypto/rand/rand_win.c index 5d134e18..34ffcd23 100644 --- a/libs/openssl/crypto/rand/rand_win.c +++ b/libs/openssl/crypto/rand/rand_win.c @@ -750,7 +750,7 @@ static void readscreen(void) int y; /* y-coordinate of screen lines to grab */ int n = 16; /* number of screen lines to grab at a time */ - if (GetVersion() < 0x80000000 && OPENSSL_isservice()>0) + if (check_winnt() && OPENSSL_isservice()>0) return; /* Create a screen DC and a memory DC compatible to screen DC */ diff --git a/libs/openssl/crypto/symhacks.h b/libs/openssl/crypto/symhacks.h index 07a412f8..bd2f000d 100644 --- a/libs/openssl/crypto/symhacks.h +++ b/libs/openssl/crypto/symhacks.h @@ -204,6 +204,12 @@ #define SSL_CTX_set_next_protos_advertised_cb SSL_CTX_set_next_protos_adv_cb #undef SSL_CTX_set_next_proto_select_cb #define SSL_CTX_set_next_proto_select_cb SSL_CTX_set_next_proto_sel_cb +#undef ssl3_cbc_record_digest_supported +#define ssl3_cbc_record_digest_supported ssl3_cbc_record_digest_support +#undef ssl_check_clienthello_tlsext_late +#define ssl_check_clienthello_tlsext_late ssl_check_clihello_tlsext_late +#undef ssl_check_clienthello_tlsext_early +#define ssl_check_clienthello_tlsext_early ssl_check_clihello_tlsext_early /* Hack some long ENGINE names */ #undef ENGINE_get_default_BN_mod_exp_crt diff --git a/libs/openssl/crypto/x509/by_dir.c b/libs/openssl/crypto/x509/by_dir.c index 27ca5150..c6602dae 100644 --- a/libs/openssl/crypto/x509/by_dir.c +++ b/libs/openssl/crypto/x509/by_dir.c @@ -218,7 +218,7 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) s=dir; p=s; - for (;;p++) + do { if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0')) { @@ -264,9 +264,7 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) return 0; } } - if (*p == '\0') - break; - } + } while (*p++ != '\0'); return 1; } diff --git a/libs/openssl/crypto/x509/x509_vfy.c b/libs/openssl/crypto/x509/x509_vfy.c index 5195ffef..920066ae 100644 --- a/libs/openssl/crypto/x509/x509_vfy.c +++ b/libs/openssl/crypto/x509/x509_vfy.c @@ -1462,10 +1462,9 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) * a certificate was revoked. This has since been changed since * critical extension can change the meaning of CRL entries. */ - if (crl->flags & EXFLAG_CRITICAL) + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) + && (crl->flags & EXFLAG_CRITICAL)) { - if (ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) - return 1; ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; ok = ctx->verify_cb(0, ctx); if(!ok) diff --git a/libs/openssl/e_os.h b/libs/openssl/e_os.h index 79c13925..6a0aad1d 100644 --- a/libs/openssl/e_os.h +++ b/libs/openssl/e_os.h @@ -368,6 +368,13 @@ static unsigned int _strlen31(const char *str) # define DEFAULT_HOME "C:" # endif +/* Avoid Windows 8 SDK GetVersion deprecated problems */ +#if defined(_MSC_VER) && _MSC_VER>=1800 +# define check_winnt() (1) +#else +# define check_winnt() (GetVersion() < 0x80000000) +#endif + #else /* The non-microsoft world */ # ifdef OPENSSL_SYS_VMS diff --git a/libs/openssl/ssl/d1_both.c b/libs/openssl/ssl/d1_both.c index 7a5596a6..2e8cf681 100644 --- a/libs/openssl/ssl/d1_both.c +++ b/libs/openssl/ssl/d1_both.c @@ -1459,26 +1459,36 @@ dtls1_process_heartbeat(SSL *s) unsigned int payload; unsigned int padding = 16; /* Use minimum padding */ - /* Read type and payload length first */ - hbtype = *p++; - n2s(p, payload); - pl = p; - if (s->msg_callback) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, &s->s3->rrec.data[0], s->s3->rrec.length, s, s->msg_callback_arg); + /* Read type and payload length first */ + if (1 + 2 + 16 > s->s3->rrec.length) + return 0; /* silently discard */ + hbtype = *p++; + n2s(p, payload); + if (1 + 2 + payload + 16 > s->s3->rrec.length) + return 0; /* silently discard per RFC 6520 sec. 4 */ + pl = p; + if (hbtype == TLS1_HB_REQUEST) { unsigned char *buffer, *bp; + unsigned int write_length = 1 /* heartbeat type */ + + 2 /* heartbeat length */ + + payload + padding; int r; + if (write_length > SSL3_RT_MAX_PLAIN_LENGTH) + return 0; + /* Allocate memory for the response, size is 1 byte * message type, plus 2 bytes payload length, plus * payload, plus padding */ - buffer = OPENSSL_malloc(1 + 2 + payload + padding); + buffer = OPENSSL_malloc(write_length); bp = buffer; /* Enter response type, length and copy payload */ @@ -1489,11 +1499,11 @@ dtls1_process_heartbeat(SSL *s) /* Random padding */ RAND_pseudo_bytes(bp, padding); - r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding); + r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length); if (r >= 0 && s->msg_callback) s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT, - buffer, 3 + payload + padding, + buffer, write_length, s, s->msg_callback_arg); OPENSSL_free(buffer); diff --git a/libs/openssl/ssl/kssl.h b/libs/openssl/ssl/kssl.h index 8242fd5e..e4df8430 100644 --- a/libs/openssl/ssl/kssl.h +++ b/libs/openssl/ssl/kssl.h @@ -70,6 +70,15 @@ #include #include #include +#ifdef OPENSSL_SYS_WIN32 +/* These can sometimes get redefined indirectly by krb5 header files + * after they get undefed in ossl_typ.h + */ +#undef X509_NAME +#undef X509_EXTENSIONS +#undef OCSP_REQUEST +#undef OCSP_RESPONSE +#endif #ifdef __cplusplus extern "C" { diff --git a/libs/openssl/ssl/s23_clnt.c b/libs/openssl/ssl/s23_clnt.c index 84670b6c..2b93c639 100644 --- a/libs/openssl/ssl/s23_clnt.c +++ b/libs/openssl/ssl/s23_clnt.c @@ -283,7 +283,7 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len) send_time = (s->mode & SSL_MODE_SEND_CLIENTHELLO_TIME) != 0; if (send_time) { - unsigned long Time = time(NULL); + unsigned long Time = (unsigned long)time(NULL); unsigned char *p = result; l2n(Time, p); return RAND_pseudo_bytes(p, len-4); diff --git a/libs/openssl/ssl/s3_srvr.c b/libs/openssl/ssl/s3_srvr.c index 52efed32..9ac19c05 100644 --- a/libs/openssl/ssl/s3_srvr.c +++ b/libs/openssl/ssl/s3_srvr.c @@ -1830,7 +1830,7 @@ int ssl3_send_server_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); goto f_err; } - for (i=0; r[i] != NULL && i<4; i++) + for (i=0; i < 4 && r[i] != NULL; i++) { nr[i]=BN_num_bytes(r[i]); #ifndef OPENSSL_NO_SRP @@ -1866,7 +1866,7 @@ int ssl3_send_server_key_exchange(SSL *s) d=(unsigned char *)s->init_buf->data; p= &(d[4]); - for (i=0; r[i] != NULL && i<4; i++) + for (i=0; i < 4 && r[i] != NULL; i++) { #ifndef OPENSSL_NO_SRP if ((i == 2) && (type & SSL_kSRP)) diff --git a/libs/openssl/ssl/ssl.h b/libs/openssl/ssl/ssl.h index 0d0f4d26..4176cad1 100644 --- a/libs/openssl/ssl/ssl.h +++ b/libs/openssl/ssl/ssl.h @@ -915,7 +915,7 @@ struct ssl_ctx_st */ unsigned int max_send_fragment; -#ifndef OPENSSL_ENGINE +#ifndef OPENSSL_NO_ENGINE /* Engine to pass requests for client certs to */ ENGINE *client_cert_engine; diff --git a/libs/openssl/ssl/t1_enc.c b/libs/openssl/ssl/t1_enc.c index 56db8343..0c4cdded 100644 --- a/libs/openssl/ssl/t1_enc.c +++ b/libs/openssl/ssl/t1_enc.c @@ -986,7 +986,8 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) } else { - EVP_MD_CTX_copy(&hmac,hash); + if (!EVP_MD_CTX_copy(&hmac,hash)) + return -1; mac_ctx = &hmac; } diff --git a/libs/openssl/ssl/t1_lib.c b/libs/openssl/ssl/t1_lib.c index 33afdeba..bddffd92 100644 --- a/libs/openssl/ssl/t1_lib.c +++ b/libs/openssl/ssl/t1_lib.c @@ -662,6 +662,36 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } #endif +#ifdef TLSEXT_TYPE_padding + /* Add padding to workaround bugs in F5 terminators. + * See https://tools.ietf.org/html/draft-agl-tls-padding-03 + * + * NB: because this code works out the length of all existing + * extensions it MUST always appear last. + */ + { + int hlen = ret - (unsigned char *)s->init_buf->data; + /* The code in s23_clnt.c to build ClientHello messages includes the + * 5-byte record header in the buffer, while the code in s3_clnt.c does + * not. */ + if (s->state == SSL23_ST_CW_CLNT_HELLO_A) + hlen -= 5; + if (hlen > 0xff && hlen < 0x200) + { + hlen = 0x200 - hlen; + if (hlen >= 4) + hlen -= 4; + else + hlen = 0; + + s2n(TLSEXT_TYPE_padding, ret); + s2n(hlen, ret); + memset(ret, 0, hlen); + ret += hlen; + } + } +#endif + if ((extdatalen = ret-p-2)== 0) return p; @@ -1261,7 +1291,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } } else if (type == TLSEXT_TYPE_status_request && - s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb) + s->version != DTLS1_VERSION) { if (size < 5) @@ -2558,16 +2588,20 @@ tls1_process_heartbeat(SSL *s) unsigned int payload; unsigned int padding = 16; /* Use minimum padding */ - /* Read type and payload length first */ - hbtype = *p++; - n2s(p, payload); - pl = p; - if (s->msg_callback) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, &s->s3->rrec.data[0], s->s3->rrec.length, s, s->msg_callback_arg); + /* Read type and payload length first */ + if (1 + 2 + 16 > s->s3->rrec.length) + return 0; /* silently discard */ + hbtype = *p++; + n2s(p, payload); + if (1 + 2 + payload + 16 > s->s3->rrec.length) + return 0; /* silently discard per RFC 6520 sec. 4 */ + pl = p; + if (hbtype == TLS1_HB_REQUEST) { unsigned char *buffer, *bp; diff --git a/libs/openssl/ssl/tls1.h b/libs/openssl/ssl/tls1.h index c39c267f..c992091e 100644 --- a/libs/openssl/ssl/tls1.h +++ b/libs/openssl/ssl/tls1.h @@ -230,6 +230,12 @@ extern "C" { /* ExtensionType value from RFC5620 */ #define TLSEXT_TYPE_heartbeat 15 +/* ExtensionType value for TLS padding extension. + * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml + * http://tools.ietf.org/html/draft-agl-tls-padding-03 + */ +#define TLSEXT_TYPE_padding 21 + /* ExtensionType value from RFC4507 */ #define TLSEXT_TYPE_session_ticket 35 diff --git a/source/Console.cbproj b/source/Console.cbproj index c2cd8803..17c39db7 100644 --- a/source/Console.cbproj +++ b/source/Console.cbproj @@ -41,7 +41,7 @@ rtl.bpi;$(PackageImports) CppConsoleApplication true - CompanyName=Martin Prikryl;FileDescription=Console interface for WinSCP;FileVersion=4.0.3.0;InternalName=console;LegalCopyright=(c) 2000-2014 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.com;ProductName=WinSCP;ProductVersion=5.5.2.0;ReleaseType=stable;WWW=http://winscp.net/ + CompanyName=Martin Prikryl;FileDescription=Console interface for WinSCP;FileVersion=4.0.3.0;InternalName=console;LegalCopyright=(c) 2000-2014 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.com;ProductName=WinSCP;ProductVersion=5.5.3.0;ReleaseType=stable;WWW=http://winscp.net/ 1033 4 3 diff --git a/source/DragExt.cbproj b/source/DragExt.cbproj index 99a28833..c0db0c23 100644 --- a/source/DragExt.cbproj +++ b/source/DragExt.cbproj @@ -42,7 +42,7 @@ CppDynamicLibrary true true - CompanyName=Martin Prikryl;FileDescription=Drag&Drop shell extension for WinSCP (32-bit);FileVersion=1.2.1.0;InternalName=dragext32;LegalCopyright=(c) 2000-2014 Martin Prikryl;LegalTrademarks=;OriginalFilename=dragext.dll;ProductName=WinSCP;ProductVersion=5.5.2.0;ReleaseType=stable;WWW=http://winscp.net/ + CompanyName=Martin Prikryl;FileDescription=Drag&Drop shell extension for WinSCP (32-bit);FileVersion=1.2.1.0;InternalName=dragext32;LegalCopyright=(c) 2000-2014 Martin Prikryl;LegalTrademarks=;OriginalFilename=dragext.dll;ProductName=WinSCP;ProductVersion=5.5.3.0;ReleaseType=stable;WWW=http://winscp.net/ 1033 2 1 diff --git a/source/DragExt64.rc b/source/DragExt64.rc index 88c94346..551b2121 100644 --- a/source/DragExt64.rc +++ b/source/DragExt64.rc @@ -1,6 +1,6 @@ 1 VERSIONINFO FILEVERSION 1,2,1,0 -PRODUCTVERSION 5,5,2,0 +PRODUCTVERSION 5,5,3,0 FILEOS 0x4 FILETYPE 0x2 { @@ -16,7 +16,7 @@ FILETYPE 0x2 VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "dragext64.dll\0" VALUE "ProductName", "WinSCP\0" - VALUE "ProductVersion", "5.5.2.0\0" + VALUE "ProductVersion", "5.5.3.0\0" VALUE "ReleaseType", "stable\0" VALUE "WWW", "http://winscp.net/\0" } diff --git a/source/WinSCP.cbproj b/source/WinSCP.cbproj index d4b7a024..3e790612 100644 --- a/source/WinSCP.cbproj +++ b/source/WinSCP.cbproj @@ -54,11 +54,11 @@ CppVCLApplication true true - CompanyName=Martin Prikryl;FileDescription=WinSCP: SFTP, FTP and SCP client;FileVersion=5.5.2.0;InternalName=winscp;LegalCopyright=(c) 2000-2014 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.exe;ProductName=WinSCP;ProductVersion=5.5.2.0;ReleaseType=stable;WWW=http://winscp.net/ + CompanyName=Martin Prikryl;FileDescription=WinSCP: SFTP, FTP and SCP client;FileVersion=5.5.3.0;InternalName=winscp;LegalCopyright=(c) 2000-2014 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.exe;ProductName=WinSCP;ProductVersion=5.5.3.0;ReleaseType=stable;WWW=http://winscp.net/ 1033 5 5 - 2 + 3 true diff --git a/source/core/Common.cpp b/source/core/Common.cpp index 722abd35..eafbc600 100644 --- a/source/core/Common.cpp +++ b/source/core/Common.cpp @@ -1897,6 +1897,28 @@ UnicodeString __fastcall EncodeUrlString(UnicodeString S) return DoEncodeUrl(S, NonUrlChars()); } //--------------------------------------------------------------------------- +UnicodeString __fastcall AppendUrlParams(UnicodeString AURL, UnicodeString Params) +{ + // see also TWebHelpSystem::ShowHelp + const wchar_t FragmentSeparator = L'#'; + UnicodeString URL = ::CutToChar(AURL, FragmentSeparator, false); + + if (URL.Pos(L"?") == 0) + { + URL += L"?"; + } + else + { + URL += L"&"; + } + + URL += Params; + + AddToList(URL, AURL, FragmentSeparator); + + return URL; +} +//--------------------------------------------------------------------------- UnicodeString __fastcall EscapeHotkey(const UnicodeString & Caption) { return ReplaceStr(Caption, L"&", L"&&"); @@ -1997,6 +2019,14 @@ bool __fastcall IsWin7() return CheckWin32Version(6, 1); } //--------------------------------------------------------------------------- +bool __fastcall IsWine() +{ + HMODULE NtDll = GetModuleHandle(L"ntdll.dll"); + return + ALWAYS_TRUE(NtDll != NULL) && + (GetProcAddress(NtDll, "wine_get_version") != NULL); +} +//--------------------------------------------------------------------------- LCID __fastcall GetDefaultLCID() { return GetUserDefaultLCID(); diff --git a/source/core/Common.h b/source/core/Common.h index 11d14123..142f1ad5 100644 --- a/source/core/Common.h +++ b/source/core/Common.h @@ -86,6 +86,7 @@ bool __fastcall IsHex(wchar_t Ch); UnicodeString __fastcall DecodeUrlChars(UnicodeString S); UnicodeString __fastcall EncodeUrlChars(UnicodeString S, UnicodeString Ignore = L""); UnicodeString __fastcall EncodeUrlString(UnicodeString S); +UnicodeString __fastcall AppendUrlParams(UnicodeString AURL, UnicodeString Params); bool __fastcall RecursiveDeleteFile(const UnicodeString FileName, bool ToRecycleBin); void __fastcall DeleteFileChecked(const UnicodeString & FileName); unsigned int __fastcall CancelAnswer(unsigned int Answers); @@ -99,6 +100,7 @@ bool __fastcall CutToken(UnicodeString & Str, UnicodeString & Token, void __fastcall AddToList(UnicodeString & List, const UnicodeString & Value, const UnicodeString & Delimiter); bool __fastcall IsWinVista(); bool __fastcall IsWin7(); +bool __fastcall IsWine(); TLibModule * __fastcall FindModule(void * Instance); __int64 __fastcall Round(double Number); bool __fastcall TryRelativeStrToDateTime(UnicodeString S, TDateTime & DateTime); diff --git a/source/core/FtpFileSystem.cpp b/source/core/FtpFileSystem.cpp index 318b26d5..ee47b78b 100644 --- a/source/core/FtpFileSystem.cpp +++ b/source/core/FtpFileSystem.cpp @@ -3187,6 +3187,84 @@ UnicodeString __fastcall FormatValidityTime(const TFtpsCertificateData::TValidit (unsigned short)ValidityTime.Sec, 0)); } //--------------------------------------------------------------------------- +bool __fastcall VerifyNameMask(UnicodeString Name, UnicodeString Mask) +{ + bool Result = true; + int Pos; + while (Result && (Pos = Mask.Pos(L"*")) > 0) + { + // Pos will typically be 1 here, so not actual comparison is done + Result = SameText(Mask.SubString(1, Pos - 1), Name.SubString(1, Pos - 1)); + if (Result) + { + Mask.Delete(1, Pos); // including * + Name.Delete(1, Pos - 1); + // remove everything until the next dot + Pos = Name.Pos(L"."); + if (Pos == 0) + { + Pos = Name.Length() + 1; + } + Name.Delete(1, Pos - 1); + } + } + + if (Result) + { + Result = SameText(Mask, Name); + } + + return Result; +} +//--------------------------------------------------------------------------- +bool __fastcall TFTPFileSystem::VerifyCertificateHostName(const TFtpsCertificateData & Data) +{ + UnicodeString HostName = FTerminal->SessionData->HostNameExpanded; + + UnicodeString CommonName = Data.Subject.CommonName; + bool NoMask = CommonName.IsEmpty(); + bool Result = !NoMask && VerifyNameMask(HostName, CommonName); + if (Result) + { + FTerminal->LogEvent(FORMAT("Certificate common name \"%s\" matches hostname", (CommonName))); + } + else + { + if (!NoMask && (FTerminal->Configuration->ActualLogProtocol >= 1)) + { + FTerminal->LogEvent(FORMAT("Certificate common name \"%s\" does not match hostname", (CommonName))); + } + UnicodeString SubjectAltName = Data.SubjectAltName; + while (!Result && !SubjectAltName.IsEmpty()) + { + UnicodeString Entry = CutToChar(SubjectAltName, L',', true); + UnicodeString EntryName = CutToChar(Entry, L':', true); + if (SameText(EntryName, L"DNS")) + { + NoMask = false; + Result = VerifyNameMask(HostName, Entry); + if (Result) + { + FTerminal->LogEvent(FORMAT("Certificate subject alternative name \"%s\" matches hostname", (Entry))); + } + else + { + if (FTerminal->Configuration->ActualLogProtocol >= 1) + { + FTerminal->LogEvent(FORMAT("Certificate subject alternative name \"%s\" does not match hostname", (Entry))); + } + } + } + } + } + if (!Result && NoMask) + { + FTerminal->LogEvent("Certificate has no common name nor subject alternative name, not verifying hostname"); + Result = true; + } + return Result; +} +//--------------------------------------------------------------------------- bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate( const TFtpsCertificateData & Data, int & RequestResult) { @@ -3199,11 +3277,14 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate( FSessionInfo.CertificateFingerprint = BytesToHex(RawByteString((const char*)Data.Hash, Data.HashLen), false, L':'); + UnicodeString CertificateSubject = Data.Subject.Organization; + FTerminal->LogEvent(FORMAT(L"Verifying certificate for \"%s\" with fingerprint %s", (CertificateSubject, FSessionInfo.CertificateFingerprint))); + int VerificationResultStr; switch (Data.VerificationResult) { case X509_V_OK: - VerificationResultStr = CERT_OK; + VerificationResultStr = -1; break; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: VerificationResultStr = CERT_ERR_UNABLE_TO_GET_ISSUER_CERT; @@ -3267,10 +3348,15 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate( break; } - UnicodeString Summary = LoadStr(VerificationResultStr); - if (Data.VerificationResult != X509_V_OK) + UnicodeString Summary; + if (VerificationResultStr >= 0) + { + Summary = LoadStr(VerificationResultStr) + L" " + FMTLOAD(CERT_ERRDEPTH, (Data.VerificationDepth + 1)); + } + + if (!VerifyCertificateHostName(Data)) { - Summary += L" " + FMTLOAD(CERT_ERRDEPTH, (Data.VerificationDepth + 1)); + AddToList(Summary, FMTLOAD(CERT_NAME_MISMATCH, (FTerminal->SessionData->HostNameExpanded)), L"\n\n"); } FSessionInfo.Certificate = @@ -3284,21 +3370,30 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate( RequestResult = 0; - THierarchicalStorage * Storage = - FTerminal->Configuration->CreateScpStorage(false); - try + if (Summary.IsEmpty()) { - Storage->AccessMode = smRead; + RequestResult = 1; + } - if (Storage->OpenSubKey(CertificateStorageKey, false) && - Storage->ValueExists(FSessionInfo.CertificateFingerprint)) + if (RequestResult == 0) + { + THierarchicalStorage * Storage = + FTerminal->Configuration->CreateScpStorage(false); + try { - RequestResult = 1; + Storage->AccessMode = smRead; + + if (Storage->OpenSubKey(CertificateStorageKey, false) && + Storage->ValueExists(FSessionInfo.CertificateFingerprint)) + { + FTerminal->LogEvent(FORMAT(L"Certificate for \"%s\" matches cached fingerprint", (CertificateSubject))); + RequestResult = 1; + } + } + __finally + { + delete Storage; } - } - __finally - { - delete Storage; } if (RequestResult == 0) @@ -3316,6 +3411,7 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate( } else if (ExpectedKey == FSessionInfo.CertificateFingerprint) { + FTerminal->LogEvent(FORMAT(L"Certificate for \"%s\" matches configured fingerprint", (CertificateSubject))); RequestResult = 1; } } diff --git a/source/core/FtpFileSystem.h b/source/core/FtpFileSystem.h index 21dd9f14..922beb51 100644 --- a/source/core/FtpFileSystem.h +++ b/source/core/FtpFileSystem.h @@ -183,6 +183,7 @@ friend class TFileListHelper; void __fastcall SetLastCode(int Code); void __fastcall StoreLastResponse(const UnicodeString & Text); void __fastcall SetCPSLimit(TFileOperationProgressType * OperationProgress); + bool __fastcall VerifyCertificateHostName(const TFtpsCertificateData & Data); static bool __fastcall Unquote(UnicodeString & Str); static UnicodeString __fastcall ExtractStatusMessage(UnicodeString Status); diff --git a/source/core/Script.cpp b/source/core/Script.cpp index 2693d379..ce234e43 100644 --- a/source/core/Script.cpp +++ b/source/core/Script.cpp @@ -410,7 +410,7 @@ void __fastcall TScript::LogPendingLines(TTerminal * ATerminal) { // not using Log(), as we want to log to ATerminal, not Terminal, // what is different here, as we are called from TManagementScript::Connect() - ATerminal->Log->Add(llMessage, FORMAT(ScriptLogFormat, (L"Retrospectivelly logging previous script records:"))); + ATerminal->Log->Add(llMessage, FORMAT(ScriptLogFormat, (L"Retrospectively logging previous script records:"))); for (int Index = 0; Index < FPendingLogLines->Count; Index++) { diff --git a/source/filezilla/AsyncSslSocketLayer.cpp b/source/filezilla/AsyncSslSocketLayer.cpp index 848cbc95..00788bc8 100644 --- a/source/filezilla/AsyncSslSocketLayer.cpp +++ b/source/filezilla/AsyncSslSocketLayer.cpp @@ -1,4 +1,4 @@ -/* CAsyncSslSocketLayer by Tim Kosse +/* CAsyncSslSocketLayer by Tim Kosse mailto: tim.kosse@filezilla-project.org) Version 2.0 (2005-02-27) ------------------------------------------------------------- @@ -123,6 +123,7 @@ static char THIS_FILE[] = __FILE__; if (!p##n) \ bError = true; #endif +#include //The following functions from the SSL libraries are used: def(int, SSL_state, (const SSL *s)); @@ -1558,16 +1559,8 @@ void CAsyncSslSocketLayer::apps_ssl_info_callback(const SSL *s, int where, int r if (where & SSL_CB_HANDSHAKE_DONE) { int error = pSSL_get_verify_result(pLayer->m_ssl); - if (error) - { - pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_VERIFY_CERT, error); - pLayer->m_bBlocking = TRUE; - return; - } - pLayer->m_bSslEstablished = TRUE; - pLayer->PrintSessionInfo(); - pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_INFO, SSL_INFO_ESTABLISHED); - pLayer->TriggerEvents(); + pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_VERIFY_CERT, error); + pLayer->m_bBlocking = TRUE; } } @@ -1930,6 +1923,27 @@ BOOL CAsyncSslSocketLayer::GetPeerCertificateData(t_SslCertData &SslCertData, LP return FALSE; } + int subjectAltNamePos = X509_get_ext_by_NID(pX509, NID_subject_alt_name, -1); + if (subjectAltNamePos >= 0) + { + X509_EXTENSION * subjectAltNameExtension = X509_get_ext(pX509, subjectAltNamePos); + BIO * subjectAltNameBio = BIO_new(BIO_s_mem()); + + if (X509V3_EXT_print(subjectAltNameBio, subjectAltNameExtension, 0, 0) == 1) + { + USES_CONVERSION; + u_char *data; + int len = BIO_get_mem_data(subjectAltNameBio, &data); + char * buf = new char[len + 1]; + memcpy(buf, data, len); + buf[len] = '\0'; + _tcsncpy(SslCertData.subjectAltName, A2CT(buf), LENOF(SslCertData.subjectAltName)); + SslCertData.subjectAltName[LENOF(SslCertData.subjectAltName) - 1] = '\0'; + } + + BIO_vfree(subjectAltNameBio); + } + unsigned int length = 20; pX509_digest(pX509, pEVP_sha1(), SslCertData.hash, &length); diff --git a/source/filezilla/AsyncSslSocketLayer.h b/source/filezilla/AsyncSslSocketLayer.h index adb590eb..df89f98f 100644 --- a/source/filezilla/AsyncSslSocketLayer.h +++ b/source/filezilla/AsyncSslSocketLayer.h @@ -126,6 +126,8 @@ struct t_SslCertData int y,M,d,h,m,s; } validFrom, validUntil; + TCHAR subjectAltName[10240]; + unsigned char hash[20]; int verificationResult; diff --git a/source/filezilla/FileZillaIntf.cpp b/source/filezilla/FileZillaIntf.cpp index f63ec233..38811039 100644 --- a/source/filezilla/FileZillaIntf.cpp +++ b/source/filezilla/FileZillaIntf.cpp @@ -375,6 +375,7 @@ bool __fastcall TFileZillaIntf::HandleMessage(WPARAM wParam, LPARAM lParam) CopyContact(Data.Issuer, AData->pCertData->issuer); CopyValidityTime(Data.ValidFrom, AData->pCertData->validFrom); CopyValidityTime(Data.ValidUntil, AData->pCertData->validUntil); + Data.SubjectAltName = AData->pCertData->subjectAltName; Data.Hash = AData->pCertData->hash; Data.VerificationResult = AData->pCertData->verificationResult; Data.VerificationDepth = AData->pCertData->verificationDepth; diff --git a/source/filezilla/FileZillaIntf.h b/source/filezilla/FileZillaIntf.h index b1efab78..16c308ab 100644 --- a/source/filezilla/FileZillaIntf.h +++ b/source/filezilla/FileZillaIntf.h @@ -67,6 +67,8 @@ struct TFtpsCertificateData TValidityTime ValidFrom; TValidityTime ValidUntil; + const wchar_t * SubjectAltName; + const unsigned char * Hash; static const size_t HashLen = 20; diff --git a/source/forms/CustomScpExplorer.cpp b/source/forms/CustomScpExplorer.cpp index 4265a901..e4df5484 100644 --- a/source/forms/CustomScpExplorer.cpp +++ b/source/forms/CustomScpExplorer.cpp @@ -2017,7 +2017,11 @@ bool __fastcall TCustomScpExplorerForm::ExecuteFileOperation(TFileOperation Oper else if (Operation == foDelete) { assert(FileList->Count); - bool Alternative = bool(Param); + // We deliberately do not toggle alternative flag (Param), but use OR, + // because the Param is set only when command is invoked using Shift-Del/F8 keyboard + // shortcut of CurrentDeleteAlternativeAction + bool Alternative = + bool(Param) || UseAlternativeFunction(); bool Recycle; if (Side == osLocal) { diff --git a/source/forms/Login.cpp b/source/forms/Login.cpp index 5b7c4f80..ada33876 100644 --- a/source/forms/Login.cpp +++ b/source/forms/Login.cpp @@ -291,10 +291,15 @@ TTreeNode * __fastcall TLoginDialog::AddSession(TSessionData * Data) TTreeNode * Parent = AddSessionPath(UnixExtractFilePath(Data->Name), true, Data->IsWorkspace); TTreeNode * Node = SessionTree->Items->AddChild(Parent, UnixExtractFileName(Data->Name)); Node->Data = Data; - SetNodeImage(Node, GetSessionImageIndex(Data)); + UpdateNodeImage(Node); return Node; } +//--------------------------------------------------------------------------- +void __fastcall TLoginDialog::UpdateNodeImage(TTreeNode * Node) +{ + SetNodeImage(Node, GetSessionImageIndex(GetNodeSession(Node))); +} //--------------------------------------------------------------------- int __fastcall TLoginDialog::GetSessionImageIndex(TSessionData * Data) { @@ -380,12 +385,17 @@ void __fastcall TLoginDialog::NewSite() LoadContents(); } //--------------------------------------------------------------------------- -void __fastcall TLoginDialog::Default() +void __fastcall TLoginDialog::ResetNewSiteData() { if (ALWAYS_TRUE(StoredSessions != NULL)) { FNewSiteData->Assign(StoredSessions->DefaultSettings); } +} +//--------------------------------------------------------------------------- +void __fastcall TLoginDialog::Default() +{ + ResetNewSiteData(); NewSite(); } @@ -588,12 +598,6 @@ void __fastcall TLoginDialog::UpdateControls() UpdateButtonVisibility(EditButton); UpdateButtonVisibility(EditCancelButton); - TAction * SaveButtonAction = - SupportsSplitButton() ? SaveSessionAction : SaveAsSessionAction; - if (SaveButton->Action != SaveButtonAction) - { - SaveButton->Action = SaveButtonAction; - } SaveAsSessionMenuItem->Visible = FEditing; } } @@ -649,6 +653,19 @@ void __fastcall TLoginDialog::FormShow(TObject * /*Sender*/) // Explicit call is needed, as we get here during csRecreating phase, // when SessionTreeChange is not triggered, see initial method comment LoadContents(); + + if (FLocaleChanging) + { + TTreeNode * Node = SessionTree->Items->GetFirstNode(); + while (Node != NULL) + { + if (IsSiteNode(Node)) + { + UpdateNodeImage(Node); + } + Node = Node->GetNext(); + } + } } UpdateControls(); } @@ -879,6 +896,8 @@ void __fastcall TLoginDialog::SaveAsSession(bool ForceDialog) LoadContents(); UpdateControls(); + + ResetNewSiteData(); } } //--------------------------------------------------------------------------- @@ -2414,8 +2433,7 @@ void __fastcall TLoginDialog::PortNumberEditChange(TObject * Sender) //--------------------------------------------------------------------------- UnicodeString __fastcall TLoginDialog::ImportExportIniFilePath() { - UnicodeString PersonalDirectory; - ::SpecialFolderLocation(CSIDL_PERSONAL, PersonalDirectory); + UnicodeString PersonalDirectory = GetPersonalFolder(); UnicodeString FileName = IncludeTrailingBackslash(PersonalDirectory) + ExtractFileName(ExpandEnvironmentVariables(Configuration->IniFileStorageName)); return FileName; @@ -2745,7 +2763,7 @@ void __fastcall TLoginDialog::CancelEditing() { FEditing = false; // reset back the color - SetNodeImage(SessionTree->Selected, GetSessionImageIndex(GetNodeSession(SessionTree->Selected))); + UpdateNodeImage(SessionTree->Selected); } //--------------------------------------------------------------------------- void __fastcall TLoginDialog::CloneToNewSite() diff --git a/source/forms/Login.h b/source/forms/Login.h index d18ae244..9c239a4b 100644 --- a/source/forms/Login.h +++ b/source/forms/Login.h @@ -329,6 +329,7 @@ class TLoginDialog : public TForm bool __fastcall CanLogin(); bool __fastcall IsCloneToNewSiteDefault(); bool __fastcall IsDefaultResult(TModalResult Result); + void __fastcall UpdateNodeImage(TTreeNode * Node); int __fastcall GetSessionImageIndex(TSessionData * Data); void __fastcall SetNodeImage(TTreeNode * Node, int ImageIndex); void __fastcall CancelEditing(); @@ -336,6 +337,7 @@ class TLoginDialog : public TForm bool __fastcall IsEditable(); TSessionData * __fastcall CloneSelectedSession(); void __fastcall CloneToNewSite(); + void __fastcall ResetNewSiteData(); protected: void __fastcall Default(); diff --git a/source/forms/Preferences.cpp b/source/forms/Preferences.cpp index 312bc435..5b3c8cb4 100644 --- a/source/forms/Preferences.cpp +++ b/source/forms/Preferences.cpp @@ -105,10 +105,13 @@ __fastcall TPreferencesDialog::~TPreferencesDialog() SAFE_DESTROY(FEditorScrollOnDragOver); SAFE_DESTROY(FCopyParamScrollOnDragOver); SAFE_DESTROY(FCustomCommandsScrollOnDragOver); - delete FEditorFont; + SAFE_DESTROY(FEditorFont); delete FCustomCommandList; + FCustomCommandList = NULL; delete FCopyParamList; + FCopyParamList = NULL; delete FEditorList; + FEditorList = NULL; } //--------------------------------------------------------------------- bool __fastcall TPreferencesDialog::Execute(TPreferencesDialogData * DialogData) @@ -1188,29 +1191,32 @@ void __fastcall TPreferencesDialog::IconButtonClick(TObject *Sender) void __fastcall TPreferencesDialog::CustomCommandsViewData(TObject * /*Sender*/, TListItem * Item) { - assert(FCustomCommandList != NULL); - int Index = Item->Index; - assert(Index >= 0 && Index <= FCustomCommandList->Count); - const TCustomCommandType * Command = FCustomCommandList->Commands[Index]; - UnicodeString Caption = StripHotkey(Command->Name); - if (Command->ShortCut != 0) - { - Caption = FORMAT(L"%s (%s)", (Caption, ShortCutToText(Command->ShortCut))); - } - Item->Caption = Caption; - assert(!Item->SubItems->Count); - Item->SubItems->Add(Command->Command); - int Params = Command->Params; - Item->SubItems->Add(LoadStr( - FLAGSET(Params, ccLocal) ? CUSTOM_COMMAND_LOCAL : CUSTOM_COMMAND_REMOTE)); - UnicodeString ParamsStr; - #define ADDPARAM(PARAM, STR) \ - if (FLAGSET(Params, PARAM)) \ - ParamsStr += (ParamsStr.IsEmpty() ? L"" : L"/") + LoadStr(STR); - ADDPARAM(ccApplyToDirectories, CUSTOM_COMMAND_DIRECTORIES); - ADDPARAM(ccRecursive, CUSTOM_COMMAND_RECURSE); - #undef ADDPARAM - Item->SubItems->Add(ParamsStr); + // WORKAROUND We get here on Wine after destructor is called + if (FCustomCommandList != NULL) + { + int Index = Item->Index; + assert(Index >= 0 && Index <= FCustomCommandList->Count); + const TCustomCommandType * Command = FCustomCommandList->Commands[Index]; + UnicodeString Caption = StripHotkey(Command->Name); + if (Command->ShortCut != 0) + { + Caption = FORMAT(L"%s (%s)", (Caption, ShortCutToText(Command->ShortCut))); + } + Item->Caption = Caption; + assert(!Item->SubItems->Count); + Item->SubItems->Add(Command->Command); + int Params = Command->Params; + Item->SubItems->Add(LoadStr( + FLAGSET(Params, ccLocal) ? CUSTOM_COMMAND_LOCAL : CUSTOM_COMMAND_REMOTE)); + UnicodeString ParamsStr; + #define ADDPARAM(PARAM, STR) \ + if (FLAGSET(Params, PARAM)) \ + ParamsStr += (ParamsStr.IsEmpty() ? L"" : L"/") + LoadStr(STR); + ADDPARAM(ccApplyToDirectories, CUSTOM_COMMAND_DIRECTORIES); + ADDPARAM(ccRecursive, CUSTOM_COMMAND_RECURSE); + #undef ADDPARAM + Item->SubItems->Add(ParamsStr); + } } //--------------------------------------------------------------------------- void __fastcall TPreferencesDialog::ListViewSelectItem( @@ -1642,14 +1648,18 @@ void __fastcall TPreferencesDialog::UpdateEditorListView() void __fastcall TPreferencesDialog::EditorListView3Data(TObject * /*Sender*/, TListItem * Item) { - int Index = Item->Index; - assert(Index >= 0 && Index <= FEditorList->Count); - const TEditorPreferences * Editor = FEditorList->Editors[Index]; - Item->Caption = Editor->Name; - Item->SubItems->Add(Editor->Data->FileMask.Masks); - if (Editor->Data->Editor == edExternal) + // WORKAROUND We get here on Wine after destructor is called + if (FEditorList != NULL) { - Item->SubItems->Add(BooleanToStr(Editor->Data->ExternalEditorText)); + int Index = Item->Index; + assert(Index >= 0 && Index <= FEditorList->Count); + const TEditorPreferences * Editor = FEditorList->Editors[Index]; + Item->Caption = Editor->Name; + Item->SubItems->Add(Editor->Data->FileMask.Masks); + if (Editor->Data->Editor == edExternal) + { + Item->SubItems->Add(BooleanToStr(Editor->Data->ExternalEditorText)); + } } } //--------------------------------------------------------------------------- @@ -1822,23 +1832,27 @@ void __fastcall TPreferencesDialog::UpdateCopyParamListView() void __fastcall TPreferencesDialog::CopyParamListViewData(TObject * /*Sender*/, TListItem * Item) { - UnicodeString Name; - UnicodeString Rule; - - int Index = Item->Index; - if (Index == 0) - { - Name = StripHotkey(LoadStr(COPY_PARAM_DEFAULT)); - } - else + // WORKAROUND We get here on Wine after destructor is called + if (FCopyParamList != NULL) { - assert(Index >= 1 && Index <= 1 + FCopyParamList->Count); - Name = StripHotkey(FCopyParamList->Names[Index - 1]); - Rule = BooleanToStr(FCopyParamList->Rules[Index - 1] != NULL); - } + UnicodeString Name; + UnicodeString Rule; + + int Index = Item->Index; + if (Index == 0) + { + Name = StripHotkey(LoadStr(COPY_PARAM_DEFAULT)); + } + else + { + assert(Index >= 1 && Index <= 1 + FCopyParamList->Count); + Name = StripHotkey(FCopyParamList->Names[Index - 1]); + Rule = BooleanToStr(FCopyParamList->Rules[Index - 1] != NULL); + } - Item->Caption = Name; - Item->SubItems->Add(Rule); + Item->Caption = Name; + Item->SubItems->Add(Rule); + } } //--------------------------------------------------------------------------- void __fastcall TPreferencesDialog::HelpButtonClick(TObject * /*Sender*/) diff --git a/source/forms/Preferences.dfm b/source/forms/Preferences.dfm index 92ac9174..f0b1b345 100644 --- a/source/forms/Preferences.dfm +++ b/source/forms/Preferences.dfm @@ -2952,6 +2952,8 @@ object PreferencesDialog: TPreferencesDialog end object PanelLocalSheet: TTabSheet Tag = 22 + HelpType = htKeyword + HelpKeyword = 'ui_pref_panels_local' Caption = 'Local' ImageIndex = 20 TabVisible = False diff --git a/source/forms/Progress.cpp b/source/forms/Progress.cpp index bb454d1e..a9947269 100644 --- a/source/forms/Progress.cpp +++ b/source/forms/Progress.cpp @@ -118,53 +118,62 @@ void __fastcall TProgressForm::UpdateControls() if (FData.Operation != FLastOperation) { bool AVisible; - THandle ShellModule; - try + // Wine does have static text "Searching" instead of actual animations + if (!IsWine()) { - AVisible = true; - switch (FData.Operation) { - case foCopy: - case foMove: - case foRemoteMove: - case foRemoteCopy: - if (FData.Count == 1) Animate->CommonAVI = aviCopyFile; - else Animate->CommonAVI = aviCopyFiles; - break; - - case foDelete: - Animate->CommonAVI = (DeleteToRecycleBin ? aviRecycleFile : aviDeleteFile); - break; - - case foSetProperties: - case foGetProperties: - ShellModule = SafeLoadLibrary(L"shell32.dll"); - if (!ShellModule) - { - Abort(); - } - // workaround, VCL is not able to set both ResId and ResHandle otherwise - Animate->Active = false; - Animate->ResHandle = 0; - Animate->ComponentState << csLoading; - Animate->ResId = 165; - Animate->ResHandle = ShellModule; - Animate->ComponentState >> csLoading; - Animate->Active = true; - break; - - default: - assert(FData.Operation == foCustomCommand || - FData.Operation == foCalculateSize || - FData.Operation == foCalculateChecksum); - Animate->CommonAVI = aviNone; - AVisible = false; + try + { + THandle ShellModule; + AVisible = true; + switch (FData.Operation) { + case foCopy: + case foMove: + case foRemoteMove: + case foRemoteCopy: + if (FData.Count == 1) Animate->CommonAVI = aviCopyFile; + else Animate->CommonAVI = aviCopyFiles; + break; + + case foDelete: + Animate->CommonAVI = (DeleteToRecycleBin ? aviRecycleFile : aviDeleteFile); + break; + + case foSetProperties: + case foGetProperties: + ShellModule = SafeLoadLibrary(L"shell32.dll"); + if (!ShellModule) + { + Abort(); + } + // workaround, VCL is not able to set both ResId and ResHandle otherwise + Animate->Active = false; + Animate->ResHandle = 0; + Animate->ComponentState << csLoading; + Animate->ResId = 165; + Animate->ResHandle = ShellModule; + Animate->ComponentState >> csLoading; + Animate->Active = true; + break; + + default: + assert(FData.Operation == foCustomCommand || + FData.Operation == foCalculateSize || + FData.Operation == foCalculateChecksum); + Animate->CommonAVI = aviNone; + AVisible = false; + } } + catch (...) + { + AVisible = false; + }; } - catch (...) + else { + Animate->CommonAVI = aviNone; AVisible = false; - }; + } int Delta = 0; if (AVisible && !Animate->Visible) Delta = Animate->Height; @@ -173,7 +182,6 @@ void __fastcall TProgressForm::UpdateControls() MainPanel->Top = MainPanel->Top + Delta; TransferPanel->Top = TransferPanel->Top + Delta; - SpeedPanel->Top = SpeedPanel->Top + Delta; Animate->Visible = AVisible; Animate->Active = AVisible; @@ -181,7 +189,9 @@ void __fastcall TProgressForm::UpdateControls() else if (!TransferOperation && TransferPanel->Visible) Delta += -TransferPanel->Height; TransferPanel->Visible = TransferOperation; - SpeedPanel->Visible = TransferOperation; + // when animation is hidden for transfers (on wine) speed panel does not fit, + // so we hide it (temporary solution before window redesign) + SpeedPanel->Visible = TransferOperation && AVisible; ClientHeight = ClientHeight + Delta; diff --git a/source/forms/ScpCommander.cpp b/source/forms/ScpCommander.cpp index b423ece1..13d9837f 100644 --- a/source/forms/ScpCommander.cpp +++ b/source/forms/ScpCommander.cpp @@ -1774,7 +1774,7 @@ void __fastcall TScpCommanderForm::LocalPathComboUpdateDrives() Strings->Clear(); FLocalPathComboBoxPaths->Clear(); Strings->Add(LoadStr(SPECIAL_FOLDER_MY_DOCUMENTS)); - FLocalPathComboBoxPaths->AddObject(DriveInfo->SpecialFolder[CSIDL_PERSONAL]->Location, + FLocalPathComboBoxPaths->AddObject(GetPersonalFolder(), (TObject *)DriveInfo->SpecialFolder[CSIDL_PERSONAL]->ImageIndex); Strings->Add(LoadStr(SPECIAL_FOLDER_DESKTOP)); FLocalPathComboBoxPaths->AddObject(DriveInfo->SpecialFolder[CSIDL_DESKTOP]->Location, diff --git a/source/packages/my/PathLabel.pas b/source/packages/my/PathLabel.pas index 55e91777..eff97649 100644 --- a/source/packages/my/PathLabel.pas +++ b/source/packages/my/PathLabel.pas @@ -531,6 +531,7 @@ procedure TCustomPathLabel.DoDrawTextIntern(var Rect: TRect; Flags: Longint; S: end; FDisplayPath := FDisplayPath + Separator; + S := S + Separator; WidthMask := Canvas.TextWidth(FDisplayMask); if WidthMask > Width div 3 then @@ -582,7 +583,7 @@ procedure TCustomPathLabel.DoDrawTextIntern(var Rect: TRect; Flags: Longint; S: (WidthPath + WidthMask > Width); if not ShowHint then Hint := '' - else Hint := S + Separator + Mask; + else Hint := S + Mask; Str := FDisplayPath + FDisplayMask; if not Enabled then diff --git a/source/putty/SSH.C b/source/putty/SSH.C index 68e1c3c4..451efbc4 100644 --- a/source/putty/SSH.C +++ b/source/putty/SSH.C @@ -2563,7 +2563,9 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) if (conf_get_int(ssh->conf, CONF_sshbug_rsapad2) == FORCE_ON || (conf_get_int(ssh->conf, CONF_sshbug_rsapad2) == AUTO && (wc_match("OpenSSH_2.[5-9]*", imp) || - wc_match("OpenSSH_3.[0-2]*", imp)))) { + wc_match("OpenSSH_3.[0-2]*", imp) || + wc_match("mod_sftp/0.[0-8]*", imp) || + wc_match("mod_sftp/0.9.[0-8]", imp)))) { /* * These versions have the SSH-2 RSA padding bug. */ diff --git a/source/resource/TextsCore.h b/source/resource/TextsCore.h index 5e2098a1..629420e2 100644 --- a/source/resource/TextsCore.h +++ b/source/resource/TextsCore.h @@ -210,7 +210,6 @@ #define CERT_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 284 #define CERT_ERR_UNKNOWN 285 #define CERT_ERRDEPTH 286 -#define CERT_OK 287 #define MASK_ERROR 288 #define FTP_CANNOT_OPEN_ACTIVE_CONNECTION2 289 #define DELETE_LOCAL_FILE_ERROR 290 @@ -224,6 +223,7 @@ #define REPORT_ERROR 298 #define TLS_CERT_DECODE_ERROR 299 #define FIND_FILE_ERROR 700 +#define CERT_NAME_MISMATCH 701 #define CORE_CONFIRMATION_STRINGS 300 #define CONFIRM_PROLONG_TIMEOUT3 301 diff --git a/source/resource/TextsCore1.rc b/source/resource/TextsCore1.rc index 408e7c83..4a67f7ba 100644 --- a/source/resource/TextsCore1.rc +++ b/source/resource/TextsCore1.rc @@ -174,8 +174,7 @@ BEGIN CERT_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, "Unable to get local issuer certificate." CERT_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, "Unable to verify the first certificate." CERT_ERR_UNKNOWN, "Unknown certificate verification error." - CERT_ERRDEPTH, "The error occured at a depth of %d in the certificate chain." - CERT_OK, "The certificate seems to be valid." + CERT_ERRDEPTH, "The error occurred at a depth of %d in the certificate chain." MASK_ERROR, "Mask is invalid near '%s'." FTP_CANNOT_OPEN_ACTIVE_CONNECTION2, "The server cannot open connection in active mode. If you are behind a NAT router, you may need to specify an external IP address. Alternatively, consider switching to passive mode." DELETE_LOCAL_FILE_ERROR, "Error deleting file '%s'." @@ -189,6 +188,7 @@ BEGIN REPORT_ERROR, "%s\n\nPlease help us improving WinSCP by reporting the error on WinSCP support forum." TLS_CERT_DECODE_ERROR, "Error decoding TLS/SSL certificate (%s)." FIND_FILE_ERROR, "Error retrieving file list for \"%s\"." + CERT_NAME_MISMATCH, "Certificate was not issued for this server. You might be connecting to a server that is pretending to be \"%s\"." CORE_CONFIRMATION_STRINGS, "CORE_CONFIRMATION" CONFIRM_PROLONG_TIMEOUT3, "Host is not communicating for %d seconds.\n\nWait for another %0:d seconds?" @@ -372,7 +372,7 @@ BEGIN FILEZILLA_URL, "http://filezilla-project.org/" OPENSSL_BASED_ON, "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s." OPENSSL_COPYRIGHT, "Copyright © 1998-2014 The OpenSSL Project" - OPENSSL_VERSION, "1.0.1f" + OPENSSL_VERSION, "1.0.1g" OPENSSL_URL, "http://www.openssl.org/" PUTTY_LICENSE_URL, "http://www.chiark.greenend.org.uk/~sgtatham/putty/licence.html" MAIN_MSG_TAG, "**" diff --git a/source/resource/TextsWin1.rc b/source/resource/TextsWin1.rc index 2b775255..ec857260 100644 --- a/source/resource/TextsWin1.rc +++ b/source/resource/TextsWin1.rc @@ -139,7 +139,7 @@ BEGIN BOOKMARK_INFO_TIP, "Local: %s\nRemote: %s" CUSTOM_COMMAND_TOUCH, "&Touch" CUSTOM_COMMAND_EXECUTE, "&Execute" - ERROR_LIST_COUNT, "%d error(s) occured during last operation. Do you want to see it/them?" + ERROR_LIST_COUNT, "%d error(s) occurred during last operation. Do you want to see it/them?" ERROR_LIST_NUMBER, "Error %d of %d:\n%s" NO_NEW_VERSION, "You have the latest version." NEW_VERSION4, "New version %s was released." diff --git a/source/windows/GUITools.cpp b/source/windows/GUITools.cpp index 622d80bc..5c24e447 100644 --- a/source/windows/GUITools.cpp +++ b/source/windows/GUITools.cpp @@ -259,6 +259,39 @@ bool __fastcall SpecialFolderLocation(int PathID, UnicodeString & Path) return false; } //--------------------------------------------------------------------------- +UnicodeString __fastcall GetPersonalFolder() +{ + UnicodeString Result; + SpecialFolderLocation(CSIDL_PERSONAL, Result); + + if (IsWine()) + { + UnicodeString WineHostHome = GetEnvironmentVariable(L"WINE_HOST_HOME"); + if (!WineHostHome.IsEmpty()) + { + UnicodeString WineHome = L"Z:" + ToUnixPath(WineHostHome); + if (DirectoryExists(WineHome)) + { + Result = WineHome; + } + } + else + { + // Should we use WinAPI GetUserName() instead? + UnicodeString UserName = GetEnvironmentVariable(L"USERNAME"); + if (!UserName.IsEmpty()) + { + UnicodeString WineHome = L"Z:\\home\\" + UserName; + if (DirectoryExists(WineHome)) + { + Result = WineHome; + } + } + } + } + return Result; +} +//--------------------------------------------------------------------------- UnicodeString __fastcall ItemsFormatString(const UnicodeString SingleItemFormat, const UnicodeString MultiItemsFormat, int Count, const UnicodeString FirstItem) { @@ -311,7 +344,7 @@ UnicodeString __fastcall UniqTempDir(const UnicodeString BaseDir, const UnicodeS { TempDir += IncludeTrailingBackslash(FormatDateTime(L"nnzzz", Now())); }; - } + } while (!Mask && DirectoryExists(TempDir)); return TempDir; diff --git a/source/windows/GUITools.h b/source/windows/GUITools.h index 50aa78fd..270aaf73 100644 --- a/source/windows/GUITools.h +++ b/source/windows/GUITools.h @@ -30,6 +30,7 @@ bool __fastcall ExecuteShellAndWait(HWND Handle, const UnicodeString Command, void __fastcall OpenSessionInPutty(const UnicodeString PuttyPath, TSessionData * SessionData, UnicodeString UserName, UnicodeString Password); bool __fastcall SpecialFolderLocation(int PathID, UnicodeString & Path); +UnicodeString __fastcall GetPersonalFolder(); UnicodeString __fastcall ItemsFormatString(const UnicodeString SingleItemFormat, const UnicodeString MultiItemsFormat, int Count, const UnicodeString FirstItem); UnicodeString __fastcall ItemsFormatString(const UnicodeString SingleItemFormat, diff --git a/source/windows/Setup.cpp b/source/windows/Setup.cpp index 2c1a944a..535c9abe 100644 --- a/source/windows/Setup.cpp +++ b/source/windows/Setup.cpp @@ -763,6 +763,37 @@ UnicodeString __fastcall GetUsageData() return Configuration->Usage->Serialize(); } //--------------------------------------------------------------------------- +static UnicodeString __fastcall WantBetaUrl(UnicodeString URL, bool Force) +{ + bool Beta; + if (WinConfiguration->IsBeta) + { + Beta = true; + } + else + { + switch (WinConfiguration->Updates.BetaVersions) + { + case asAuto: + Beta = WinConfiguration->AnyBetaInVersionHistory; + break; + + case asOn: + Beta = true; + break; + + default: + Beta = false; + break; + } + } + if (Beta || Force) + { + URL = AppendUrlParams(URL, FORMAT(L"beta=%d", (Beta ? 1 : 0))); + } + return URL; +} +//--------------------------------------------------------------------------- void __fastcall QueryUpdates() { bool Complete = false; @@ -784,32 +815,7 @@ void __fastcall QueryUpdates() UnicodeString URL = LoadStr(UPDATES_URL) + FORMAT(L"?v=%s&lang=%s", (CurrentVersionStr, IntToHex(__int64(GUIConfiguration->Locale), 4))); - bool Beta; - if (WinConfiguration->IsBeta) - { - Beta = true; - } - else - { - switch (Updates.BetaVersions) - { - case asAuto: - Beta = WinConfiguration->AnyBetaInVersionHistory; - break; - - case asOn: - Beta = true; - break; - - default: - Beta = false; - break; - } - } - if (Beta) - { - URL += L"&beta=1"; - } + URL = WantBetaUrl(URL, false); URL += L"&dotnet=" + Updates.DotNetVersion; URL += L"&console=" + Updates.ConsoleVersion; UnicodeString Proxy; @@ -1099,7 +1105,10 @@ void __fastcall CheckForUpdates(bool CachedResults) if (New) { Configuration->Usage->Inc(L"UpdateDownloadOpens"); - OpenBrowser(LoadStr(UPGRADE_URL)); + UnicodeString UpgradeUrl = LoadStr(UPGRADE_URL); + UpgradeUrl = WantBetaUrl(UpgradeUrl, true); + UpgradeUrl = AppendUrlParams(UpgradeUrl, FORMAT(L"to=%s", (VersionStrFromCompoundVersion(Updates.Results.Version)))); + OpenBrowser(UpgradeUrl); } break; diff --git a/source/windows/TerminalManager.cpp b/source/windows/TerminalManager.cpp index f4539928..eb6bbc2a 100644 --- a/source/windows/TerminalManager.cpp +++ b/source/windows/TerminalManager.cpp @@ -650,7 +650,11 @@ void __fastcall TTerminalManager::UpdateAppTitle() } UnicodeString QueueProgressTitle; - if (!FProgressTitle.IsEmpty() && !ForegroundTask()) + if (!FForegroundProgressTitle.IsEmpty()) + { + NewTitle = FForegroundProgressTitle + L" - " + NewTitle; + } + else if (!FProgressTitle.IsEmpty() && !ForegroundTask()) { NewTitle = FProgressTitle + L" - " + NewTitle; } @@ -1013,9 +1017,10 @@ void __fastcall TTerminalManager::TerminalReadDirectoryProgress( ScpExplorer->LockWindow(); } FDirectoryReadingStart = Now(); - if (!FProgressTitle.IsEmpty()) + if (!FProgressTitle.IsEmpty() || !FForegroundProgressTitle.IsEmpty()) { FProgressTitle = L""; + FForegroundProgressTitle = L""; UpdateAppTitle(); } @@ -1040,6 +1045,7 @@ void __fastcall TTerminalManager::TerminalReadDirectoryProgress( } FProgressTitle = L""; + FForegroundProgressTitle = L""; UpdateAppTitle(); } } @@ -1055,7 +1061,7 @@ void __fastcall TTerminalManager::TerminalReadDirectoryProgress( if ((Now() - FDirectoryReadingStart) >= DirectoryReadingProgressDelay) { - FProgressTitle = FMTLOAD(DIRECTORY_READING_PROGRESS, (Progress)); + FForegroundProgressTitle = FMTLOAD(DIRECTORY_READING_PROGRESS, (Progress)); UpdateAppTitle(); } } diff --git a/source/windows/TerminalManager.h b/source/windows/TerminalManager.h index 458047a7..91e68778 100644 --- a/source/windows/TerminalManager.h +++ b/source/windows/TerminalManager.h @@ -91,6 +91,7 @@ class TTerminalManager : public TTerminalList TList * FQueues; TStrings * FTerminationMessages; UnicodeString FProgressTitle; + UnicodeString FForegroundProgressTitle; TDateTime FDirectoryReadingStart; TAuthenticateForm * FAuthenticateForm; TCriticalSection * FQueueSection; diff --git a/source/windows/Tools.cpp b/source/windows/Tools.cpp index 01e38994..a0ef9a9f 100644 --- a/source/windows/Tools.cpp +++ b/source/windows/Tools.cpp @@ -276,11 +276,16 @@ bool __fastcall ExecuteShellAndWait(const UnicodeString Command) &Application->ProcessMessages); } //--------------------------------------------------------------------------- -bool __fastcall OpenInNewWindow() +bool __fastcall UseAlternativeFunction() { return FLAGSET(GetAsyncKeyState(VK_SHIFT), 0x8000); } //--------------------------------------------------------------------------- +bool __fastcall OpenInNewWindow() +{ + return UseAlternativeFunction(); +} +//--------------------------------------------------------------------------- void __fastcall ExecuteNewInstance(const UnicodeString & Param) { UnicodeString Arg = Param; diff --git a/source/windows/Tools.h b/source/windows/Tools.h index 89f1a10a..2e75b5c2 100644 --- a/source/windows/Tools.h +++ b/source/windows/Tools.h @@ -11,6 +11,7 @@ void __fastcall CenterFormOn(TForm * Form, TControl * CenterOn); bool __fastcall ExecuteShellAndWait(const UnicodeString Path, const UnicodeString Params); bool __fastcall ExecuteShellAndWait(const UnicodeString Command); +bool __fastcall UseAlternativeFunction(); bool __fastcall OpenInNewWindow(); void __fastcall ExecuteNewInstance(const UnicodeString & Param); IShellLink * __fastcall CreateDesktopShortCut(const UnicodeString &Name, diff --git a/source/windows/UserInterface.cpp b/source/windows/UserInterface.cpp index da2362ca..538fb9a1 100644 --- a/source/windows/UserInterface.cpp +++ b/source/windows/UserInterface.cpp @@ -23,6 +23,7 @@ #include "Custom.h" #include "HelpWin.h" #include +#include //--------------------------------------------------------------------------- #pragma package(smart_init) //--------------------------------------------------------------------------- @@ -273,6 +274,9 @@ void __fastcall ConfigureInterface() { TBXSetTheme(WinConfiguration->Theme); } + // Has any effect on Wine only + // (otherwise initial UserDocumentDirectory is equivalent to GetPersonalFolder()) + UserDocumentDirectory = GetPersonalFolder(); } //--------------------------------------------------------------------------- // dummy function to force linking of TBXOfficeXPTheme.pas diff --git a/source/windows/WinConfiguration.cpp b/source/windows/WinConfiguration.cpp index b9fe5518..45b89557 100644 --- a/source/windows/WinConfiguration.cpp +++ b/source/windows/WinConfiguration.cpp @@ -552,9 +552,7 @@ void __fastcall TWinConfiguration::Default() PixelsPerInchToolbarValue; FScpExplorer.SessionsTabs = true; FScpExplorer.StatusBar = true; - UnicodeString PersonalFolder; - ::SpecialFolderLocation(CSIDL_PERSONAL, PersonalFolder); - FScpExplorer.LastLocalTargetDirectory = PersonalFolder; + FScpExplorer.LastLocalTargetDirectory = GetPersonalFolder(); FScpExplorer.ViewStyle = 0; /* vsIcon */ FScpExplorer.ShowFullAddress = true; FScpExplorer.DriveView = true; diff --git a/source/windows/WinMain.cpp b/source/windows/WinMain.cpp index ff33fd4f..c1a937c7 100644 --- a/source/windows/WinMain.cpp +++ b/source/windows/WinMain.cpp @@ -110,7 +110,7 @@ void __fastcall Download(TTerminal * Terminal, const UnicodeString FileName, UnicodeString LocalDirectory = ExpandFileName(Terminal->SessionData->LocalDirectory); if (LocalDirectory.IsEmpty()) { - ::SpecialFolderLocation(CSIDL_PERSONAL, LocalDirectory); + LocalDirectory = GetPersonalFolder(); } TargetDirectory = IncludeTrailingBackslash(LocalDirectory); @@ -321,12 +321,7 @@ void __fastcall UpdateStaticUsage() UnicodeString ExeName = ExpandFileName(Application->ExeName); bool InProgramFiles = AnsiSameText(ExeName.SubString(1, ProgramsFolder.Length()), ProgramsFolder); Configuration->Usage->Set(L"InProgramFiles", InProgramFiles); - - HMODULE NtDll = GetModuleHandle(L"ntdll.dll"); - bool Wine = - ALWAYS_TRUE(NtDll != NULL) && - (GetProcAddress(NtDll, "wine_get_version") != NULL); - Configuration->Usage->Set(L"Wine", Wine); + Configuration->Usage->Set(L"Wine", IsWine()); WinConfiguration->UpdateStaticUsage();