OSDN Git Service

End the support for Windows XP and earlier.
[ffftp/ffftp.git] / socketwrapper.c
index d8db7aa..904624f 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,6 +37,9 @@ 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
@@ -50,18 +52,30 @@ typedef int (__cdecl* _X509_print_ex)(BIO*, X509*, unsigned long, unsigned long)
 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
@@ -75,6 +89,9 @@ _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
@@ -87,10 +104,23 @@ _X509_print_ex p_X509_print_ex;
 _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
@@ -122,10 +152,17 @@ BOOL LoadOpenSSL()
                return FALSE;\r
 #ifdef ENABLE_PROCESS_PROTECTION\r
        // 同梱するOpenSSLのバージョンに合わせてSHA1ハッシュ値を変更すること\r
-       // ssleay32.dll 1.0.1g\r
-       RegisterTrustedModuleSHA1Hash("\xCB\xBA\x62\x61\x3C\x44\x1E\x94\xD2\xF4\xAD\xD5\x03\x43\x6F\x26\xD2\xAF\x2F\x21");\r
-       // libeay32.dll 1.0.1g\r
-       RegisterTrustedModuleSHA1Hash("\x4E\x53\x29\xC4\x32\x1B\x17\xA5\x4D\x40\xDF\x6F\xF6\xD2\x53\x7E\xBC\x54\x69\x1B");\r
+#if defined(_M_IX86)\r
+       // ssleay32.dll 1.0.2d\r
+       RegisterTrustedModuleSHA1Hash("\xBF\x93\x28\xBE\x43\x04\x2D\x18\xA4\x02\x1B\xF3\x63\x0A\xC7\x1A\x94\xCF\xA6\x05");\r
+       // libeay32.dll 1.0.2d\r
+       RegisterTrustedModuleSHA1Hash("\xFA\xAE\x6D\x44\xC6\x91\xF3\xA1\x53\x4E\x3A\xFE\x0C\x3C\x8D\xF9\xF7\x2B\x87\xF9");\r
+#elif defined(_M_AMD64)\r
+       // ssleay32.dll 1.0.2d\r
+       RegisterTrustedModuleSHA1Hash("\xD8\x01\x0D\xBE\xEE\x6D\x73\x79\x57\x1A\xE8\xAC\x25\x1C\x96\xA1\x93\x9A\x90\x51");\r
+       // libeay32.dll 1.0.2d\r
+       RegisterTrustedModuleSHA1Hash("\x82\xCD\x9F\x91\xB4\x48\x13\x93\x46\x1B\xC2\x83\xDF\xBC\xE2\x14\x6B\x0A\xB7\xF9");\r
+#endif\r
 #endif\r
        g_hOpenSSL = LoadLibrary("ssleay32.dll");\r
        // バージョン固定のためlibssl32.dllの読み込みは脆弱性の原因になり得るので廃止\r
@@ -135,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
@@ -152,6 +188,9 @@ 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_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
@@ -172,10 +211,23 @@ BOOL LoadOpenSSL()
                || !(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_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_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
@@ -490,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
@@ -518,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
@@ -525,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
@@ -639,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
@@ -655,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
@@ -1074,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