OSDN Git Service

Modify copyrights.
[ffftp/ffftp.git] / socketwrapper.c
index 0c1be4a..71da863 100644 (file)
 typedef void (__cdecl* _SSL_load_error_strings)();\r
 typedef int (__cdecl* _SSL_library_init)();\r
 typedef SSL_METHOD* (__cdecl* _SSLv23_method)();\r
-typedef SSL_CTX* (__cdecl* _SSL_CTX_new)(SSL_METHOD*);\r
-typedef void (__cdecl* _SSL_CTX_free)(SSL_CTX*);\r
 typedef SSL* (__cdecl* _SSL_new)(SSL_CTX*);\r
 typedef void (__cdecl* _SSL_free)(SSL*);\r
+typedef long (__cdecl* _SSL_ctrl)(SSL*, int, long, void*);\r
 typedef int (__cdecl* _SSL_shutdown)(SSL*);\r
 typedef int (__cdecl* _SSL_get_fd)(SSL*);\r
 typedef int (__cdecl* _SSL_set_fd)(SSL*, int);\r
@@ -38,7 +37,11 @@ typedef X509* (__cdecl* _SSL_get_peer_certificate)(const SSL*);
 typedef long (__cdecl* _SSL_get_verify_result)(const SSL*);\r
 typedef SSL_SESSION* (__cdecl* _SSL_get_session)(SSL*);\r
 typedef int (__cdecl* _SSL_set_session)(SSL*, SSL_SESSION*);\r
+typedef int (__cdecl* _SSL_set_cipher_list)(SSL*, const char*);\r
+typedef SSL_CTX* (__cdecl* _SSL_CTX_new)(SSL_METHOD*);\r
+typedef void (__cdecl* _SSL_CTX_free)(SSL_CTX*);\r
 typedef X509_STORE* (__cdecl* _SSL_CTX_get_cert_store)(const SSL_CTX*);\r
+typedef long (__cdecl* _SSL_CTX_ctrl)(SSL_CTX*, int, long, void*);\r
 typedef BIO_METHOD* (__cdecl* _BIO_s_mem)();\r
 typedef BIO* (__cdecl* _BIO_new)(BIO_METHOD*);\r
 typedef int (__cdecl* _BIO_free)(BIO*);\r
@@ -48,16 +51,31 @@ typedef void (__cdecl* _X509_free)(X509*);
 typedef int (__cdecl* _X509_print_ex)(BIO*, X509*, unsigned long, unsigned long);\r
 typedef X509_NAME* (__cdecl* _X509_get_subject_name)(X509*);\r
 typedef int (__cdecl* _X509_NAME_print_ex)(BIO*, X509_NAME*, int, unsigned long);\r
+typedef void (__cdecl* _X509_CRL_free)(X509_CRL*);\r
+typedef EVP_PKEY* (__cdecl* _PEM_read_bio_PrivateKey)(BIO*, EVP_PKEY**, pem_password_cb*, void*);\r
+typedef EVP_PKEY* (__cdecl* _PEM_read_bio_PUBKEY)(BIO*, EVP_PKEY**, pem_password_cb*, void*);\r
 typedef X509* (__cdecl* _PEM_read_bio_X509)(BIO*, X509**, pem_password_cb*, void*);\r
+typedef X509_CRL* (__cdecl* _PEM_read_bio_X509_CRL)(BIO*, X509_CRL**, pem_password_cb*, void*);\r
 typedef int (__cdecl* _X509_STORE_add_cert)(X509_STORE*, X509*);\r
+typedef int (__cdecl* _X509_STORE_add_crl)(X509_STORE*, X509_CRL*);\r
+typedef void (__cdecl* _EVP_PKEY_free)(EVP_PKEY*);\r
+typedef RSA* (__cdecl* _EVP_PKEY_get1_RSA)(EVP_PKEY*);\r
+typedef void (__cdecl* _RSA_free)(RSA*);\r
+typedef int (__cdecl* _RSA_size)(const RSA*);\r
+typedef int (__cdecl* _RSA_private_encrypt)(int, const unsigned char*, unsigned char*, RSA*, int);\r
+typedef int (__cdecl* _RSA_public_decrypt)(int, const unsigned char*, unsigned char*, RSA*, int);\r
+typedef unsigned char* (__cdecl* _SHA1)(const unsigned char*, size_t, unsigned char*);\r
+typedef unsigned char* (__cdecl* _SHA224)(const unsigned char*, size_t, unsigned char*);\r
+typedef unsigned char* (__cdecl* _SHA256)(const unsigned char*, size_t, unsigned char*);\r
+typedef unsigned char* (__cdecl* _SHA384)(const unsigned char*, size_t, unsigned char*);\r
+typedef unsigned char* (__cdecl* _SHA512)(const unsigned char*, size_t, unsigned char*);\r
 \r
 _SSL_load_error_strings p_SSL_load_error_strings;\r
 _SSL_library_init p_SSL_library_init;\r
 _SSLv23_method p_SSLv23_method;\r
-_SSL_CTX_new p_SSL_CTX_new;\r
-_SSL_CTX_free p_SSL_CTX_free;\r
 _SSL_new p_SSL_new;\r
 _SSL_free p_SSL_free;\r
+_SSL_ctrl p_SSL_ctrl;\r
 _SSL_shutdown p_SSL_shutdown;\r
 _SSL_get_fd p_SSL_get_fd;\r
 _SSL_set_fd p_SSL_set_fd;\r
@@ -71,7 +89,11 @@ _SSL_get_peer_certificate p_SSL_get_peer_certificate;
 _SSL_get_verify_result p_SSL_get_verify_result;\r
 _SSL_get_session p_SSL_get_session;\r
 _SSL_set_session p_SSL_set_session;\r
+_SSL_set_cipher_list p_SSL_set_cipher_list;\r
+_SSL_CTX_new p_SSL_CTX_new;\r
+_SSL_CTX_free p_SSL_CTX_free;\r
 _SSL_CTX_get_cert_store p_SSL_CTX_get_cert_store;\r
+_SSL_CTX_ctrl p_SSL_CTX_ctrl;\r
 _BIO_s_mem p_BIO_s_mem;\r
 _BIO_new p_BIO_new;\r
 _BIO_free p_BIO_free;\r
@@ -81,8 +103,24 @@ _X509_free p_X509_free;
 _X509_print_ex p_X509_print_ex;\r
 _X509_get_subject_name p_X509_get_subject_name;\r
 _X509_NAME_print_ex p_X509_NAME_print_ex;\r
+_X509_CRL_free p_X509_CRL_free;\r
+_PEM_read_bio_PrivateKey p_PEM_read_bio_PrivateKey;\r
+_PEM_read_bio_PUBKEY p_PEM_read_bio_PUBKEY;\r
 _PEM_read_bio_X509 p_PEM_read_bio_X509;\r
+_PEM_read_bio_X509_CRL p_PEM_read_bio_X509_CRL;\r
 _X509_STORE_add_cert p_X509_STORE_add_cert;\r
+_X509_STORE_add_crl p_X509_STORE_add_crl;\r
+_EVP_PKEY_free p_EVP_PKEY_free;\r
+_EVP_PKEY_get1_RSA p_EVP_PKEY_get1_RSA;\r
+_RSA_free p_RSA_free;\r
+_RSA_size p_RSA_size;\r
+_RSA_private_encrypt p_RSA_private_encrypt;\r
+_RSA_public_decrypt p_RSA_public_decrypt;\r
+_SHA1 p_SHA1;\r
+_SHA224 p_SHA224;\r
+_SHA256 p_SHA256;\r
+_SHA384 p_SHA384;\r
+_SHA512 p_SHA512;\r
 \r
 #define MAX_SSL_SOCKET 16\r
 \r
@@ -114,10 +152,17 @@ BOOL LoadOpenSSL()
                return FALSE;\r
 #ifdef ENABLE_PROCESS_PROTECTION\r
        // 同梱するOpenSSLのバージョンに合わせてSHA1ハッシュ値を変更すること\r
-       // ssleay32.dll 1.0.1c\r
-       RegisterTrustedModuleSHA1Hash("\x8A\xB5\x6D\x5E\x0B\x31\x80\x5E\x21\x55\x2D\x6E\x4F\xAF\xB1\x47\x7B\xD3\xB5\x23");\r
-       // libeay32.dll 1.0.1c\r
-       RegisterTrustedModuleSHA1Hash("\xB4\x88\x17\x2E\x5C\x26\x9D\x62\x83\x65\x3A\xC1\x1B\xC9\x6E\x70\x1A\x8D\x6E\x76");\r
+#if defined(_M_IX86)\r
+       // ssleay32.dll 1.0.1j\r
+       RegisterTrustedModuleSHA1Hash("\x57\x83\x70\x2D\x44\x8F\x1F\xB3\x83\xC2\xC1\x93\xB5\x92\xC8\x14\xFE\x2B\x31\x59");\r
+       // libeay32.dll 1.0.1j\r
+       RegisterTrustedModuleSHA1Hash("\x66\x15\x03\xCA\xFB\x5C\x08\x96\x4B\x80\x9A\x55\x14\xDB\x1F\x12\x4A\x9C\x53\x52");\r
+#elif defined(_M_AMD64)\r
+       // ssleay32.dll 1.0.1j\r
+       RegisterTrustedModuleSHA1Hash("\x4C\xBD\xC5\x05\xB5\xB2\x48\xA8\xC2\x0B\xE4\xB3\x17\x02\x9C\x32\xE2\x84\x87\xA9");\r
+       // libeay32.dll 1.0.1j\r
+       RegisterTrustedModuleSHA1Hash("\xF7\x31\xBF\xF6\x2C\x51\xBA\x00\x38\x7E\x76\x2F\x8B\xB3\xF9\x52\x5D\xED\xA4\xE6");\r
+#endif\r
 #endif\r
        g_hOpenSSL = LoadLibrary("ssleay32.dll");\r
        // バージョン固定のためlibssl32.dllの読み込みは脆弱性の原因になり得るので廃止\r
@@ -127,10 +172,9 @@ BOOL LoadOpenSSL()
                || !(p_SSL_load_error_strings = (_SSL_load_error_strings)GetProcAddress(g_hOpenSSL, "SSL_load_error_strings"))\r
                || !(p_SSL_library_init = (_SSL_library_init)GetProcAddress(g_hOpenSSL, "SSL_library_init"))\r
                || !(p_SSLv23_method = (_SSLv23_method)GetProcAddress(g_hOpenSSL, "SSLv23_method"))\r
-               || !(p_SSL_CTX_new = (_SSL_CTX_new)GetProcAddress(g_hOpenSSL, "SSL_CTX_new"))\r
-               || !(p_SSL_CTX_free = (_SSL_CTX_free)GetProcAddress(g_hOpenSSL, "SSL_CTX_free"))\r
                || !(p_SSL_new = (_SSL_new)GetProcAddress(g_hOpenSSL, "SSL_new"))\r
                || !(p_SSL_free = (_SSL_free)GetProcAddress(g_hOpenSSL, "SSL_free"))\r
+               || !(p_SSL_ctrl = (_SSL_ctrl)GetProcAddress(g_hOpenSSL, "SSL_ctrl"))\r
                || !(p_SSL_shutdown = (_SSL_shutdown)GetProcAddress(g_hOpenSSL, "SSL_shutdown"))\r
                || !(p_SSL_get_fd = (_SSL_get_fd)GetProcAddress(g_hOpenSSL, "SSL_get_fd"))\r
                || !(p_SSL_set_fd = (_SSL_set_fd)GetProcAddress(g_hOpenSSL, "SSL_set_fd"))\r
@@ -144,7 +188,11 @@ BOOL LoadOpenSSL()
                || !(p_SSL_get_verify_result = (_SSL_get_verify_result)GetProcAddress(g_hOpenSSL, "SSL_get_verify_result"))\r
                || !(p_SSL_get_session = (_SSL_get_session)GetProcAddress(g_hOpenSSL, "SSL_get_session"))\r
                || !(p_SSL_set_session = (_SSL_set_session)GetProcAddress(g_hOpenSSL, "SSL_set_session"))\r
-               || !(p_SSL_CTX_get_cert_store = (_SSL_CTX_get_cert_store)GetProcAddress(g_hOpenSSL, "SSL_CTX_get_cert_store")))\r
+               || !(p_SSL_set_cipher_list = (_SSL_set_cipher_list)GetProcAddress(g_hOpenSSL, "SSL_set_cipher_list"))\r
+               || !(p_SSL_CTX_new = (_SSL_CTX_new)GetProcAddress(g_hOpenSSL, "SSL_CTX_new"))\r
+               || !(p_SSL_CTX_free = (_SSL_CTX_free)GetProcAddress(g_hOpenSSL, "SSL_CTX_free"))\r
+               || !(p_SSL_CTX_get_cert_store = (_SSL_CTX_get_cert_store)GetProcAddress(g_hOpenSSL, "SSL_CTX_get_cert_store"))\r
+               || !(p_SSL_CTX_ctrl = (_SSL_CTX_ctrl)GetProcAddress(g_hOpenSSL, "SSL_CTX_ctrl")))\r
        {\r
                if(g_hOpenSSL)\r
                        FreeLibrary(g_hOpenSSL);\r
@@ -162,8 +210,24 @@ BOOL LoadOpenSSL()
                || !(p_X509_print_ex = (_X509_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_print_ex"))\r
                || !(p_X509_get_subject_name = (_X509_get_subject_name)GetProcAddress(g_hOpenSSLCommon, "X509_get_subject_name"))\r
                || !(p_X509_NAME_print_ex = (_X509_NAME_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_NAME_print_ex"))\r
+               || !(p_X509_CRL_free = (_X509_CRL_free)GetProcAddress(g_hOpenSSLCommon, "X509_CRL_free"))\r
+               || !(p_PEM_read_bio_PrivateKey = (_PEM_read_bio_PrivateKey)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_PrivateKey"))\r
+               || !(p_PEM_read_bio_PUBKEY = (_PEM_read_bio_PUBKEY)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_PUBKEY"))\r
                || !(p_PEM_read_bio_X509 = (_PEM_read_bio_X509)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_X509"))\r
-               || !(p_X509_STORE_add_cert = (_X509_STORE_add_cert)GetProcAddress(g_hOpenSSLCommon, "X509_STORE_add_cert")))\r
+               || !(p_PEM_read_bio_X509_CRL = (_PEM_read_bio_X509_CRL)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_X509_CRL"))\r
+               || !(p_X509_STORE_add_cert = (_X509_STORE_add_cert)GetProcAddress(g_hOpenSSLCommon, "X509_STORE_add_cert"))\r
+               || !(p_X509_STORE_add_crl = (_X509_STORE_add_crl)GetProcAddress(g_hOpenSSLCommon, "X509_STORE_add_crl"))\r
+               || !(p_EVP_PKEY_free = (_EVP_PKEY_free)GetProcAddress(g_hOpenSSLCommon, "EVP_PKEY_free"))\r
+               || !(p_EVP_PKEY_get1_RSA = (_EVP_PKEY_get1_RSA)GetProcAddress(g_hOpenSSLCommon, "EVP_PKEY_get1_RSA"))\r
+               || !(p_RSA_free = (_RSA_free)GetProcAddress(g_hOpenSSLCommon, "RSA_free"))\r
+               || !(p_RSA_size = (_RSA_size)GetProcAddress(g_hOpenSSLCommon, "RSA_size"))\r
+               || !(p_RSA_private_encrypt = (_RSA_private_encrypt)GetProcAddress(g_hOpenSSLCommon, "RSA_private_encrypt"))\r
+               || !(p_RSA_public_decrypt = (_RSA_public_decrypt)GetProcAddress(g_hOpenSSLCommon, "RSA_public_decrypt"))\r
+               || !(p_SHA1 = (_SHA1)GetProcAddress(g_hOpenSSLCommon, "SHA1"))\r
+               || !(p_SHA224 = (_SHA224)GetProcAddress(g_hOpenSSLCommon, "SHA224"))\r
+               || !(p_SHA256 = (_SHA256)GetProcAddress(g_hOpenSSLCommon, "SHA256"))\r
+               || !(p_SHA384 = (_SHA384)GetProcAddress(g_hOpenSSLCommon, "SHA384"))\r
+               || !(p_SHA512 = (_SHA512)GetProcAddress(g_hOpenSSLCommon, "SHA512")))\r
        {\r
                if(g_hOpenSSL)\r
                        FreeLibrary(g_hOpenSSL);\r
@@ -338,14 +402,19 @@ BOOL SetSSLRootCertificate(const void* pData, DWORD Length)
        BYTE* p;\r
        BYTE* pBegin;\r
        BYTE* pEnd;\r
+       DWORD Left;\r
        BIO* pBIO;\r
        X509* pX509;\r
+       X509_CRL* pX509_CRL;\r
        if(!g_bOpenSSLLoaded)\r
                return FALSE;\r
        r = FALSE;\r
        EnterCriticalSection(&g_OpenSSLLock);\r
        if(!g_pOpenSSLCTX)\r
+       {\r
                g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
+               p_SSL_CTX_ctrl(g_pOpenSSLCTX, SSL_CTRL_MODE, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY, NULL);\r
+       }\r
        if(g_pOpenSSLCTX)\r
        {\r
                if(pStore = p_SSL_CTX_get_cert_store(g_pOpenSSLCTX))\r
@@ -353,18 +422,19 @@ BOOL SetSSLRootCertificate(const void* pData, DWORD Length)
                        p = (BYTE*)pData;\r
                        pBegin = NULL;\r
                        pEnd = NULL;\r
-                       while(Length > 0)\r
+                       Left = Length;\r
+                       while(Left > 0)\r
                        {\r
                                if(!pBegin)\r
                                {\r
-                                       if(Length < 27)\r
+                                       if(Left < 27)\r
                                                break;\r
                                        if(memcmp(p, "-----BEGIN CERTIFICATE-----", 27) == 0)\r
                                                pBegin = p;\r
                                }\r
                                else if(!pEnd)\r
                                {\r
-                                       if(Length < 25)\r
+                                       if(Left < 25)\r
                                                break;\r
                                        if(memcmp(p, "-----END CERTIFICATE-----", 25) == 0)\r
                                                pEnd = p + 25;\r
@@ -385,7 +455,45 @@ BOOL SetSSLRootCertificate(const void* pData, DWORD Length)
                                        pEnd = NULL;\r
                                }\r
                                p++;\r
-                               Length--;\r
+                               Left--;\r
+                       }\r
+                       p = (BYTE*)pData;\r
+                       pBegin = NULL;\r
+                       pEnd = NULL;\r
+                       Left = Length;\r
+                       while(Left > 0)\r
+                       {\r
+                               if(!pBegin)\r
+                               {\r
+                                       if(Left < 24)\r
+                                               break;\r
+                                       if(memcmp(p, "-----BEGIN X509 CRL-----", 24) == 0)\r
+                                               pBegin = p;\r
+                               }\r
+                               else if(!pEnd)\r
+                               {\r
+                                       if(Left < 22)\r
+                                               break;\r
+                                       if(memcmp(p, "-----END X509 CRL-----", 22) == 0)\r
+                                               pEnd = p + 22;\r
+                               }\r
+                               if(pBegin && pEnd)\r
+                               {\r
+                                       if(pBIO = p_BIO_new_mem_buf(pBegin, (int)((size_t)pEnd - (size_t)pBegin)))\r
+                                       {\r
+                                               if(pX509_CRL = p_PEM_read_bio_X509_CRL(pBIO, NULL, NULL, NULL))\r
+                                               {\r
+                                                       if(p_X509_STORE_add_crl(pStore, pX509_CRL) == 1)\r
+                                                               r = TRUE;\r
+                                                       p_X509_CRL_free(pX509_CRL);\r
+                                               }\r
+                                               p_BIO_free(pBIO);\r
+                                       }\r
+                                       pBegin = NULL;\r
+                                       pEnd = NULL;\r
+                               }\r
+                               p++;\r
+                               Left--;\r
                        }\r
                }\r
        }\r
@@ -434,12 +542,131 @@ BOOL IsHostNameMatched(LPCSTR HostName, LPCSTR CommonName)
        return bResult;\r
 }\r
 \r
+#pragma warning(push)\r
+#pragma warning(disable:4090)\r
+\r
+// RSA暗号化\r
+BOOL EncryptSignature(const char* PrivateKey, const char* Password, const void* pIn, DWORD InLength, void* pOut, DWORD OutLength, DWORD* pOutLength)\r
+{\r
+       BOOL bResult;\r
+       BIO* pBIO;\r
+       EVP_PKEY* pPKEY;\r
+       RSA* pRSA;\r
+       int i;\r
+       if(!g_bOpenSSLLoaded)\r
+               return FALSE;\r
+       bResult = FALSE;\r
+       if(pBIO = p_BIO_new_mem_buf((void*)PrivateKey, sizeof(char) * strlen(PrivateKey)))\r
+       {\r
+               if(pPKEY = p_PEM_read_bio_PrivateKey(pBIO, NULL, NULL, (void*)Password))\r
+               {\r
+                       if(pRSA = p_EVP_PKEY_get1_RSA(pPKEY))\r
+                       {\r
+                               if(p_RSA_size(pRSA) <= (int)OutLength)\r
+                               {\r
+                                       i = p_RSA_private_encrypt((int)InLength, (const unsigned char*)pIn, (unsigned char*)pOut, pRSA, RSA_PKCS1_PADDING);\r
+                                       if(i >= 0)\r
+                                       {\r
+                                               *pOutLength = (DWORD)i;\r
+                                               bResult = TRUE;\r
+                                       }\r
+                               }\r
+                               p_RSA_free(pRSA);\r
+                       }\r
+                       p_EVP_PKEY_free(pPKEY);\r
+               }\r
+               p_BIO_free(pBIO);\r
+       }\r
+       return bResult;\r
+}\r
+\r
+// RSA復号化\r
+// 主に自動更新ファイルのハッシュの改竄確認\r
+BOOL DecryptSignature(const char* PublicKey, const char* Password, const void* pIn, DWORD InLength, void* pOut, DWORD OutLength, DWORD* pOutLength)\r
+{\r
+       BOOL bResult;\r
+       BIO* pBIO;\r
+       EVP_PKEY* pPKEY;\r
+       RSA* pRSA;\r
+       int i;\r
+       if(!g_bOpenSSLLoaded)\r
+               return FALSE;\r
+       bResult = FALSE;\r
+       if(pBIO = p_BIO_new_mem_buf((void*)PublicKey, sizeof(char) * strlen(PublicKey)))\r
+       {\r
+               if(pPKEY = p_PEM_read_bio_PUBKEY(pBIO, NULL, NULL, Password))\r
+               {\r
+                       if(pRSA = p_EVP_PKEY_get1_RSA(pPKEY))\r
+                       {\r
+                               if(p_RSA_size(pRSA) <= (int)OutLength)\r
+                               {\r
+                                       i = p_RSA_public_decrypt((int)InLength, (const unsigned char*)pIn, (unsigned char*)pOut, pRSA, RSA_PKCS1_PADDING);\r
+                                       if(i >= 0)\r
+                                       {\r
+                                               *pOutLength = (DWORD)i;\r
+                                               bResult = TRUE;\r
+                                       }\r
+                               }\r
+                               p_RSA_free(pRSA);\r
+                       }\r
+                       p_EVP_PKEY_free(pPKEY);\r
+               }\r
+               p_BIO_free(pBIO);\r
+       }\r
+       return bResult;\r
+}\r
+\r
+#pragma warning(pop)\r
+\r
+// ハッシュ計算\r
+// 他にも同等の関数はあるが主にマルウェア対策のための冗長化\r
+BOOL GetHashSHA1(const void* pData, DWORD Size, void* pHash)\r
+{\r
+       if(!g_bOpenSSLLoaded)\r
+               return FALSE;\r
+       p_SHA1((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
+       return TRUE;\r
+}\r
+\r
+BOOL GetHashSHA224(const void* pData, DWORD Size, void* pHash)\r
+{\r
+       if(!g_bOpenSSLLoaded)\r
+               return FALSE;\r
+       p_SHA224((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
+       return TRUE;\r
+}\r
+\r
+BOOL GetHashSHA256(const void* pData, DWORD Size, void* pHash)\r
+{\r
+       if(!g_bOpenSSLLoaded)\r
+               return FALSE;\r
+       p_SHA256((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
+       return TRUE;\r
+}\r
+\r
+BOOL GetHashSHA384(const void* pData, DWORD Size, void* pHash)\r
+{\r
+       if(!g_bOpenSSLLoaded)\r
+               return FALSE;\r
+       p_SHA384((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
+       return TRUE;\r
+}\r
+\r
+BOOL GetHashSHA512(const void* pData, DWORD Size, void* pHash)\r
+{\r
+       if(!g_bOpenSSLLoaded)\r
+               return FALSE;\r
+       p_SHA512((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
+       return TRUE;\r
+}\r
+\r
 // SSLセッションを開始\r
-BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted)\r
+BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted, BOOL bStrengthen)\r
 {\r
        BOOL r;\r
        DWORD Time;\r
        SSL** ppSSL;\r
+       BOOL bInherited;\r
        SSL** ppSSLParent;\r
        SSL_SESSION* pSession;\r
        int Return;\r
@@ -450,7 +677,10 @@ BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted)
        Time = timeGetTime();\r
        EnterCriticalSection(&g_OpenSSLLock);\r
        if(!g_pOpenSSLCTX)\r
+       {\r
                g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
+               p_SSL_CTX_ctrl(g_pOpenSSLCTX, SSL_CTRL_MODE, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY, NULL);\r
+       }\r
        if(g_pOpenSSLCTX)\r
        {\r
                if(ppSSL = GetUnusedSSLPointer())\r
@@ -459,6 +689,7 @@ BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted)
                        {\r
                                if(p_SSL_set_fd(*ppSSL, s) != 0)\r
                                {\r
+                                       bInherited = FALSE;\r
                                        if(parent != INVALID_SOCKET)\r
                                        {\r
                                                if(ppSSLParent = FindSSLPointerFromSocket(parent))\r
@@ -466,11 +697,18 @@ BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted)
                                                        if(pSession = p_SSL_get_session(*ppSSLParent))\r
                                                        {\r
                                                                if(p_SSL_set_session(*ppSSL, pSession) == 1)\r
-                                                               {\r
-                                                               }\r
+                                                                       bInherited = TRUE;\r
                                                        }\r
                                                }\r
                                        }\r
+                                       if(!bInherited)\r
+                                       {\r
+                                               if(bStrengthen)\r
+                                               {\r
+                                                       p_SSL_ctrl(*ppSSL, SSL_CTRL_OPTIONS, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3, NULL);\r
+                                                       p_SSL_set_cipher_list(*ppSSL, "HIGH");\r
+                                               }\r
+                                       }\r
                                        // SSLのネゴシエーションには時間がかかる場合がある\r
                                        r = TRUE;\r
                                        while(r)\r
@@ -580,7 +818,7 @@ SOCKET FTPS_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
        BOOL bAborted;\r
        r = accept(s, addr, addrlen);\r
        bAborted = FALSE;\r
-       if(!AttachSSL(r, INVALID_SOCKET, &bAborted))\r
+       if(!AttachSSL(r, INVALID_SOCKET, &bAborted, TRUE))\r
        {\r
                closesocket(r);\r
                return INVALID_SOCKET;\r
@@ -596,7 +834,7 @@ int FTPS_connect(SOCKET s, const struct sockaddr *name, int namelen)
        BOOL bAborted;\r
        r = connect(s, name, namelen);\r
        bAborted = FALSE;\r
-       if(!AttachSSL(r, INVALID_SOCKET, &bAborted))\r
+       if(!AttachSSL(r, INVALID_SOCKET, &bAborted, TRUE))\r
                return SOCKET_ERROR;\r
        return r;\r
 }\r
@@ -611,6 +849,7 @@ int FTPS_closesocket(SOCKET s)
 // send相当の関数\r
 int FTPS_send(SOCKET s, const char * buf, int len, int flags)\r
 {\r
+       int r;\r
        SSL** ppSSL;\r
        if(!g_bOpenSSLLoaded)\r
                return send(s, buf, len, flags);\r
@@ -619,12 +858,16 @@ int FTPS_send(SOCKET s, const char * buf, int len, int flags)
        LeaveCriticalSection(&g_OpenSSLLock);\r
        if(!ppSSL)\r
                return send(s, buf, len, flags);\r
-       return p_SSL_write(*ppSSL, buf, len);\r
+       r = p_SSL_write(*ppSSL, buf, len);\r
+       if(r < 0)\r
+               return SOCKET_ERROR;\r
+       return r;\r
 }\r
 \r
 // recv相当の関数\r
 int FTPS_recv(SOCKET s, char * buf, int len, int flags)\r
 {\r
+       int r;\r
        SSL** ppSSL;\r
        if(!g_bOpenSSLLoaded)\r
                return recv(s, buf, len, flags);\r
@@ -634,8 +877,12 @@ int FTPS_recv(SOCKET s, char * buf, int len, int flags)
        if(!ppSSL)\r
                return recv(s, buf, len, flags);\r
        if(flags & MSG_PEEK)\r
-               return p_SSL_peek(*ppSSL, buf, len);\r
-       return p_SSL_read(*ppSSL, buf, len);\r
+               r = p_SSL_peek(*ppSSL, buf, len);\r
+       else\r
+               r = p_SSL_read(*ppSSL, buf, len);\r
+       if(r < 0)\r
+               return SOCKET_ERROR;\r
+       return r;\r
 }\r
 \r
 // IPv6対応\r
@@ -776,6 +1023,16 @@ int WSACancelAsyncRequestIPv6(HANDLE hAsyncTaskHandle)
        return Result;\r
 }\r
 \r
+char* AddressToStringIPv4(char* str, void* in)\r
+{\r
+       char* pResult;\r
+       unsigned char* p;\r
+       pResult = str;\r
+       p = (unsigned char*)in;\r
+       sprintf(str, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);\r
+       return pResult;\r
+}\r
+\r
 char* AddressToStringIPv6(char* str, void* in6)\r
 {\r
        char* pResult;\r
@@ -996,349 +1253,3 @@ HANDLE WSAAsyncGetHostByNameIPv6M(HWND hWnd, u_int wMsg, const char * name, char
        return r;\r
 }\r
 \r
-// SFTP対応\r
-\r
-typedef void* (__cdecl* _SFTP_Create)();\r
-typedef void (__cdecl* _SFTP_Destroy)(void*);\r
-typedef BOOL (__cdecl* _SFTP_IsExited)(void*);\r
-typedef BOOL (__cdecl* _SFTP_SetTimeoutCallback)(void*, void*);\r
-typedef size_t (__cdecl* _SFTP_PeekStdOut)(void*, void*, size_t);\r
-typedef size_t (__cdecl* _SFTP_ReadStdOut)(void*, void*, size_t);\r
-typedef size_t (__cdecl* _SFTP_WriteStdIn)(void*, const void*, size_t);\r
-typedef size_t (__cdecl* _SFTP_PeekDataOut)(void*, void*, size_t);\r
-typedef size_t (__cdecl* _SFTP_ReadDataOut)(void*, void*, size_t);\r
-typedef size_t (__cdecl* _SFTP_WriteDataIn)(void*, const void*, size_t);\r
-typedef BOOL (__cdecl* _SFTP_SetFilePosition)(void*, LONGLONG);\r
-\r
-_SFTP_Create p_SFTP_Create;\r
-_SFTP_Destroy p_SFTP_Destroy;\r
-_SFTP_IsExited p_SFTP_IsExited;\r
-_SFTP_SetTimeoutCallback p_SFTP_SetTimeoutCallback;\r
-_SFTP_PeekStdOut p_SFTP_PeekStdOut;\r
-_SFTP_ReadStdOut p_SFTP_ReadStdOut;\r
-_SFTP_WriteStdIn p_SFTP_WriteStdIn;\r
-_SFTP_PeekDataOut p_SFTP_PeekDataOut;\r
-_SFTP_ReadDataOut p_SFTP_ReadDataOut;\r
-_SFTP_WriteDataIn p_SFTP_WriteDataIn;\r
-_SFTP_SetFilePosition p_SFTP_SetFilePosition;\r
-\r
-typedef struct\r
-{\r
-       SOCKET Control;\r
-       SOCKET Data;\r
-       void* Handle;\r
-       char Host[1024];\r
-       int Port;\r
-       char User[1024];\r
-       char Password[1024];\r
-} SFTPDATA;\r
-\r
-#define MAX_SFTP_SOCKET 16\r
-\r
-BOOL g_bPuTTYLoaded;\r
-HMODULE g_hPuTTY;\r
-CRITICAL_SECTION g_PuTTYLock;\r
-SFTPDATA g_SFTPData[MAX_SFTP_SOCKET];\r
-\r
-// PuTTYを初期化\r
-BOOL LoadPuTTY()\r
-{\r
-       int i;\r
-       if(g_bPuTTYLoaded)\r
-               return FALSE;\r
-#ifdef ENABLE_PROCESS_PROTECTION\r
-       // ビルドしたputty.dllに合わせてSHA1ハッシュ値を変更すること\r
-       RegisterTrustedModuleSHA1Hash("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");\r
-#endif\r
-       // デバッグ用\r
-#ifdef _DEBUG\r
-       {\r
-               char Path[MAX_PATH];\r
-               GetModuleFileName(NULL, Path, MAX_PATH);\r
-               strcpy(strrchr(Path, '\\'), "\\..\\putty\\Debug\\PuTTY.dll");\r
-               g_hPuTTY = LoadLibrary(Path);\r
-       }\r
-#else\r
-       g_hPuTTY = LoadLibrary("putty.dll");\r
-#endif\r
-       if(!g_hPuTTY\r
-               || !(p_SFTP_Create = (_SFTP_Create)GetProcAddress(g_hPuTTY, "SFTP_Create"))\r
-               || !(p_SFTP_Destroy = (_SFTP_Destroy)GetProcAddress(g_hPuTTY, "SFTP_Destroy"))\r
-               || !(p_SFTP_IsExited = (_SFTP_IsExited)GetProcAddress(g_hPuTTY, "SFTP_IsExited"))\r
-               || !(p_SFTP_SetTimeoutCallback = (_SFTP_SetTimeoutCallback)GetProcAddress(g_hPuTTY, "SFTP_SetTimeoutCallback"))\r
-               || !(p_SFTP_PeekStdOut = (_SFTP_PeekStdOut)GetProcAddress(g_hPuTTY, "SFTP_PeekStdOut"))\r
-               || !(p_SFTP_ReadStdOut = (_SFTP_ReadStdOut)GetProcAddress(g_hPuTTY, "SFTP_ReadStdOut"))\r
-               || !(p_SFTP_WriteStdIn = (_SFTP_WriteStdIn)GetProcAddress(g_hPuTTY, "SFTP_WriteStdIn"))\r
-               || !(p_SFTP_PeekDataOut = (_SFTP_PeekDataOut)GetProcAddress(g_hPuTTY, "SFTP_PeekDataOut"))\r
-               || !(p_SFTP_ReadDataOut = (_SFTP_ReadDataOut)GetProcAddress(g_hPuTTY, "SFTP_ReadDataOut"))\r
-               || !(p_SFTP_WriteDataIn = (_SFTP_WriteDataIn)GetProcAddress(g_hPuTTY, "SFTP_WriteDataIn"))\r
-               || !(p_SFTP_SetFilePosition = (_SFTP_SetFilePosition)GetProcAddress(g_hPuTTY, "SFTP_SetFilePosition")))\r
-       {\r
-               if(g_hPuTTY)\r
-                       FreeLibrary(g_hPuTTY);\r
-               g_hPuTTY = NULL;\r
-               return FALSE;\r
-       }\r
-       for(i = 0; i < MAX_SFTP_SOCKET; i++)\r
-       {\r
-               g_SFTPData[i].Control = INVALID_SOCKET;\r
-               g_SFTPData[i].Data = INVALID_SOCKET;\r
-       }\r
-       InitializeCriticalSection(&g_PuTTYLock);\r
-       g_bPuTTYLoaded = TRUE;\r
-       return TRUE;\r
-}\r
-\r
-// PuTTYを解放\r
-void FreePuTTY()\r
-{\r
-       int i;\r
-       if(!g_bPuTTYLoaded)\r
-               return;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       for(i = 0; i < MAX_SFTP_SOCKET; i++)\r
-       {\r
-               if(g_SFTPData[i].Control != INVALID_SOCKET)\r
-               {\r
-                       closesocket(g_SFTPData[i].Control);\r
-                       g_SFTPData[i].Control = INVALID_SOCKET;\r
-                       p_SFTP_Destroy(g_SFTPData[i].Handle);\r
-               }\r
-               if(g_SFTPData[i].Data != INVALID_SOCKET)\r
-               {\r
-                       closesocket(g_SFTPData[i].Data);\r
-                       g_SFTPData[i].Data = INVALID_SOCKET;\r
-               }\r
-       }\r
-       FreeLibrary(g_hPuTTY);\r
-       g_hPuTTY = NULL;\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       DeleteCriticalSection(&g_PuTTYLock);\r
-       g_bPuTTYLoaded = FALSE;\r
-}\r
-\r
-// PuTTYが使用可能かどうか確認\r
-BOOL IsPuTTYLoaded()\r
-{\r
-       return g_bPuTTYLoaded;\r
-}\r
-\r
-SFTPDATA* GetUnusedSFTPData()\r
-{\r
-       int i;\r
-       for(i = 0; i < MAX_SFTP_SOCKET; i++)\r
-       {\r
-               if(g_SFTPData[i].Control == INVALID_SOCKET)\r
-               {\r
-                       memset(&g_SFTPData[i], 0, sizeof(SFTPDATA));\r
-                       return &g_SFTPData[i];\r
-               }\r
-       }\r
-       return NULL;\r
-}\r
-\r
-SFTPDATA* FindSFTPDataFromSocket(SOCKET s)\r
-{\r
-       int i;\r
-       for(i = 0; i < MAX_SFTP_SOCKET; i++)\r
-       {\r
-               if(g_SFTPData[i].Control == s || g_SFTPData[i].Data == s)\r
-                       return &g_SFTPData[i];\r
-       }\r
-       return NULL;\r
-}\r
-\r
-// SFTPとしてマークされているか確認\r
-// マークされていればTRUEを返す\r
-BOOL IsSFTPAttached(SOCKET s)\r
-{\r
-       SFTPDATA* pSFTPData;\r
-       if(!g_bPuTTYLoaded)\r
-               return FALSE;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       pSFTPData = FindSFTPDataFromSocket(s);\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       if(!pSFTPData)\r
-               return FALSE;\r
-       return TRUE;\r
-}\r
-\r
-// コントロール用の仮想的なソケットを取得\r
-// 識別子としてダミーのソケットを返す\r
-SOCKET SFTP_socket(int af, int type, int protocol)\r
-{\r
-       SOCKET r;\r
-       SFTPDATA* pSFTPData;\r
-       if(!g_bPuTTYLoaded)\r
-               return INVALID_SOCKET;\r
-       r = INVALID_SOCKET;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       if(pSFTPData = GetUnusedSFTPData())\r
-       {\r
-               r = socket(af, type, protocol);\r
-               pSFTPData->Control = r;\r
-               pSFTPData->Data = INVALID_SOCKET;\r
-               pSFTPData->Handle = p_SFTP_Create();\r
-       }\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       return r;\r
-}\r
-\r
-int SFTP_bind(SOCKET s, const struct sockaddr *addr, int namelen)\r
-{\r
-       return SOCKET_ERROR;\r
-}\r
-\r
-int SFTP_listen(SOCKET s, int backlog)\r
-{\r
-       return SOCKET_ERROR;\r
-}\r
-\r
-// accept相当の関数\r
-SOCKET SFTP_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
-{\r
-       return INVALID_SOCKET;\r
-}\r
-\r
-// connect相当の関数\r
-int SFTP_connect(SOCKET s, const struct sockaddr *name, int namelen)\r
-{\r
-       SFTPDATA* pSFTPData;\r
-       if(!g_bPuTTYLoaded)\r
-               return SOCKET_ERROR;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       pSFTPData = FindSFTPDataFromSocket(s);\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       if(!pSFTPData)\r
-               return SOCKET_ERROR;\r
-       if(namelen == sizeof(struct sockaddr_in))\r
-       {\r
-       }\r
-       else if(namelen == sizeof(struct sockaddr_in6))\r
-       {\r
-       }\r
-       else\r
-               return SOCKET_ERROR;\r
-       return 0;\r
-}\r
-\r
-// closesocket相当の関数\r
-int SFTP_closesocket(SOCKET s)\r
-{\r
-       SFTPDATA* pSFTPData;\r
-       if(!g_bPuTTYLoaded)\r
-               return SOCKET_ERROR;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       if(pSFTPData = FindSFTPDataFromSocket(s))\r
-       {\r
-               if(pSFTPData->Control == s)\r
-               {\r
-                       pSFTPData->Control = INVALID_SOCKET;\r
-                       p_SFTP_Destroy(pSFTPData->Handle);\r
-               }\r
-               if(pSFTPData->Data == s)\r
-                       pSFTPData->Data = INVALID_SOCKET;\r
-       }\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       return closesocket(s);\r
-}\r
-\r
-// send相当の関数\r
-int SFTP_send(SOCKET s, const char * buf, int len, int flags)\r
-{\r
-       int r;\r
-       SFTPDATA* pSFTPData;\r
-       if(!g_bPuTTYLoaded)\r
-               return SOCKET_ERROR;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       pSFTPData = FindSFTPDataFromSocket(s);\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       if(!pSFTPData)\r
-               return SOCKET_ERROR;\r
-       if(p_SFTP_IsExited(pSFTPData->Handle))\r
-               return SOCKET_ERROR;\r
-       r = SOCKET_ERROR;\r
-       if(pSFTPData->Control == s)\r
-               r = (int)p_SFTP_WriteStdIn(pSFTPData->Handle, buf, len);\r
-       else if(pSFTPData->Data == s)\r
-               r = (int)p_SFTP_WriteDataIn(pSFTPData->Handle, buf, len);\r
-       return r;\r
-}\r
-\r
-// recv相当の関数\r
-int SFTP_recv(SOCKET s, char * buf, int len, int flags)\r
-{\r
-       int r;\r
-       SFTPDATA* pSFTPData;\r
-       if(!g_bPuTTYLoaded)\r
-               return SOCKET_ERROR;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       pSFTPData = FindSFTPDataFromSocket(s);\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       if(!pSFTPData)\r
-               return SOCKET_ERROR;\r
-       if(p_SFTP_IsExited(pSFTPData->Handle))\r
-               return SOCKET_ERROR;\r
-       r = SOCKET_ERROR;\r
-       if(pSFTPData->Control == s)\r
-       {\r
-               if(flags & MSG_PEEK)\r
-                       r = (int)p_SFTP_PeekStdOut(pSFTPData->Handle, buf, len);\r
-               else\r
-                       r = (int)p_SFTP_ReadStdOut(pSFTPData->Handle, buf, len);\r
-       }\r
-       else if(pSFTPData->Data == s)\r
-       {\r
-               if(flags & MSG_PEEK)\r
-                       r = (int)p_SFTP_PeekDataOut(pSFTPData->Handle, buf, len);\r
-               else\r
-                       r = (int)p_SFTP_ReadDataOut(pSFTPData->Handle, buf, len);\r
-       }\r
-       return r;\r
-}\r
-\r
-BOOL SFTP_SetTimeoutCallback(SOCKET s, void* pCallback)\r
-{\r
-       SFTPDATA* pSFTPData;\r
-       if(!g_bPuTTYLoaded)\r
-               return FALSE;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       pSFTPData = FindSFTPDataFromSocket(s);\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       if(!pSFTPData)\r
-               return FALSE;\r
-       return p_SFTP_SetTimeoutCallback(pSFTPData->Handle, pCallback);\r
-}\r
-\r
-// データ用の仮想的なソケットを取得\r
-// 識別子としてダミーのソケットを返す\r
-SOCKET SFTP_GetDataHandle(SOCKET s, int af, int type, int protocol)\r
-{\r
-       SOCKET r;\r
-       SFTPDATA* pSFTPData;\r
-       if(!g_bPuTTYLoaded)\r
-               return INVALID_SOCKET;\r
-       r = INVALID_SOCKET;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       if(pSFTPData = FindSFTPDataFromSocket(s))\r
-       {\r
-               r = socket(af, type, protocol);\r
-               pSFTPData->Data = r;\r
-       }\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       return r;\r
-}\r
-\r
-BOOL SFTP_SetFilePosition(SOCKET s, LONGLONG Position)\r
-{\r
-       SFTPDATA* pSFTPData;\r
-       if(!g_bPuTTYLoaded)\r
-               return FALSE;\r
-       EnterCriticalSection(&g_PuTTYLock);\r
-       pSFTPData = FindSFTPDataFromSocket(s);\r
-       LeaveCriticalSection(&g_PuTTYLock);\r
-       if(!pSFTPData)\r
-               return FALSE;\r
-       return p_SFTP_SetFilePosition(pSFTPData->Handle, Position);\r
-}\r
-\r