Commit 2971e0a7ea2114e4f338af2b36fa6b7d71f1918b

Authored by Perry Werneck
1 parent 23df3f64

Splitting windows HTTP download method.

@@ -80,7 +80,7 @@ case "$host" in @@ -80,7 +80,7 @@ case "$host" in
80 *-mingw32|*-pc-msys) 80 *-mingw32|*-pc-msys)
81 app_cv_osname="windows" 81 app_cv_osname="windows"
82 CFLAGS="$CFLAGS -pthread -D_WIN32_WINNT=0x0600" 82 CFLAGS="$CFLAGS -pthread -D_WIN32_WINNT=0x0600"
83 - LIBS="$LIBS -lws2_32 -lwtsapi32 -lcomdlg32" 83 + LIBS="$LIBS -lws2_32 -lwtsapi32 -lcomdlg32 -lwinhttp"
84 LDFLAGS="$LDFLAGS -pthread" 84 LDFLAGS="$LDFLAGS -pthread"
85 DLL_LDFLAGS="-shared -Wl,--output-def,\$(@D)/\$(LIBNAME).def" 85 DLL_LDFLAGS="-shared -Wl,--output-def,\$(@D)/\$(LIBNAME).def"
86 DLLEXT=".dll" 86 DLLEXT=".dll"
@@ -218,6 +218,9 @@ @@ -218,6 +218,9 @@
218 <Unit filename="src/core/windows/event_dispatcher.c"> 218 <Unit filename="src/core/windows/event_dispatcher.c">
219 <Option compilerVar="CC" /> 219 <Option compilerVar="CC" />
220 </Unit> 220 </Unit>
  221 + <Unit filename="src/core/windows/http.c">
  222 + <Option compilerVar="CC" />
  223 + </Unit>
221 <Unit filename="src/core/windows/log.c"> 224 <Unit filename="src/core/windows/log.c">
222 <Option compilerVar="CC" /> 225 <Option compilerVar="CC" />
223 </Unit> 226 </Unit>
src/core/windows/http.c 0 → 100644
@@ -0,0 +1,188 @@ @@ -0,0 +1,188 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como - e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + * References:
  29 + *
  30 + * https://docs.microsoft.com/en-us/windows/win32/winhttp/winhttp-autoproxy-api
  31 + *
  32 + */
  33 +
  34 +/**
  35 + * @brief Implements CRL download using winhttp.
  36 + *
  37 + */
  38 +
  39 +#include <config.h>
  40 +#include <lib3270-internals.h>
  41 +#include <lib3270/log.h>
  42 +#include <lib3270/trace.h>
  43 +#include <winhttp.h>
  44 +#include <utilc.h>
  45 +
  46 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  47 +
  48 +static void lib3270_autoptr_cleanup_HINTERNET(HINTERNET **hInternet)
  49 +{
  50 + if(*hInternet)
  51 + WinHttpCloseHandle(*hInternet);
  52 + *hInternet = 0;
  53 +}
  54 +
  55 +char * lib3270_get_from_url(H3270 *hSession, const char *url, size_t *length, const char **error_message)
  56 +{
  57 + wchar_t wHostname[4096];
  58 + wchar_t wPath[4096];
  59 +
  60 + lib3270_trace_event(hSession,"Getting data from %s",url);
  61 +
  62 + {
  63 + // Strip URL
  64 + char * unescaped = lib3270_unescape(url);
  65 +
  66 + char *hostname = strstr(unescaped,"://");
  67 + if(!hostname)
  68 + hostname = unescaped;
  69 + else
  70 + hostname += 3;
  71 +
  72 + char *path = strchr(hostname,'/');
  73 + if(path)
  74 + *(path++) = 0;
  75 +
  76 + mbstowcs(wHostname, hostname, strlen(hostname)+1);
  77 + mbstowcs(wPath, path, strlen(path)+1);
  78 +
  79 + lib3270_free(unescaped);
  80 +
  81 + }
  82 +
  83 + // https://docs.microsoft.com/en-us/windows/desktop/api/winhttp/nf-winhttp-winhttpopenrequest
  84 +
  85 + // Open HTTP session
  86 + // https://docs.microsoft.com/en-us/windows/desktop/api/winhttp/nf-winhttp-winhttpopenrequest
  87 + static const char * userAgent = PACKAGE_NAME "/" PACKAGE_VERSION;
  88 + wchar_t wUserAgent[256];
  89 + mbstowcs(wUserAgent, userAgent, strlen(userAgent)+1);
  90 + lib3270_autoptr(HINTERNET) httpSession = WinHttpOpen(wUserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );
  91 + if(!httpSession)
  92 + {
  93 + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError());
  94 + lib3270_write_log(hSession,"http","%s: %s",url, windows_error);
  95 +
  96 + *error_message = _( "Can't open HTTP session" );
  97 + errno = EINVAL;
  98 + return NULL;
  99 + }
  100 +
  101 + // Connect to server
  102 + lib3270_autoptr(HINTERNET) hConnect = WinHttpConnect(httpSession, wHostname, INTERNET_DEFAULT_HTTP_PORT, 0);
  103 + if(!hConnect)
  104 + {
  105 + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError());
  106 + lib3270_write_log(hSession,"http","%s: %s", url, windows_error);
  107 +
  108 + *error_message = _( "Can't connect to HTTP server." );
  109 +
  110 + return NULL;
  111 + }
  112 +
  113 + // Create request.
  114 + lib3270_autoptr(HINTERNET) hRequest = WinHttpOpenRequest(hConnect, L"GET", wPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_ESCAPE_PERCENT);
  115 + if(!hConnect)
  116 + {
  117 + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError());
  118 + lib3270_write_log(hSession,"http","%s: %s", url, windows_error);
  119 +
  120 + *error_message = _( "Can't create HTTP request." );
  121 +
  122 + errno = EINVAL;
  123 + return NULL;
  124 + }
  125 +
  126 + WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
  127 +
  128 + // Send request.
  129 + if(!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
  130 + {
  131 + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError());
  132 + lib3270_write_log(hSession,"http","%s: %s", url, windows_error);
  133 +
  134 + *error_message = _( "Can't send HTTP request." );
  135 +
  136 + errno = EINVAL;
  137 + return NULL;
  138 + }
  139 +
  140 + // Get response
  141 + if(!WinHttpReceiveResponse(hRequest, NULL))
  142 + {
  143 + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError());
  144 + lib3270_write_log(hSession,"http","%s: %s", url, windows_error);
  145 +
  146 + *error_message = _( "Error receiving HTTP response." );
  147 +
  148 + errno = EINVAL;
  149 + return NULL;
  150 +
  151 + }
  152 +
  153 + DWORD szResponse = 0;
  154 + if(!WinHttpQueryDataAvailable(hRequest, &szResponse))
  155 + {
  156 + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError());
  157 + lib3270_write_log(hSession,"http","%s: %s", url, windows_error);
  158 +
  159 + *error_message = _( "Empty response from HTTP server." );
  160 +
  161 + errno = EINVAL;
  162 + return NULL;
  163 + }
  164 +
  165 + char * httpText = lib3270_malloc(szResponse+1);
  166 + memset(httpText,0,szResponse+1);
  167 +
  168 + debug("Data block: %p",httpText);
  169 + debug("Response before: %u", (unsigned int) szResponse);
  170 +
  171 + if(!WinHttpReadData(hRequest,httpText,szResponse,&szResponse)){
  172 + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError());
  173 + lib3270_write_log(hSession,"http","%s: %s", url, windows_error);
  174 +
  175 + *error_message = _( "Can't read HTTP response size." );
  176 +
  177 + lib3270_free(httpText);
  178 +
  179 + errno = EINVAL;
  180 + return NULL;
  181 + }
  182 +
  183 + if(length)
  184 + *length = (size_t) szResponse;
  185 +
  186 + return httpText;
  187 +
  188 +}
src/include/lib3270-internals.h
@@ -867,3 +867,13 @@ LIB3270_INTERNAL int non_blocking(H3270 *session, Boolean on); @@ -867,3 +867,13 @@ LIB3270_INTERNAL int non_blocking(H3270 *session, Boolean on);
867 867
868 LIB3270_INTERNAL char * lib3270_get_user_name(); 868 LIB3270_INTERNAL char * lib3270_get_user_name();
869 869
  870 + /// @brief Query data from URL.
  871 + ///
  872 + /// @param hSession Handle of the TN3270 Session.
  873 + /// @param url The url to get.
  874 + /// @param length Pointer to the response lenght (can be NULL).
  875 + /// @param error_message Pointer to the error message.
  876 + ///
  877 + /// @return The data from URL (release it with lib3270_free) or NULL on error.
  878 + ///
  879 + LIB3270_INTERNAL char * lib3270_get_from_url(H3270 *hSession, const char *url, size_t *length, const char **error_message);
src/ssl/windows/http.c
@@ -46,148 +46,23 @@ @@ -46,148 +46,23 @@
46 46
47 /*--[ Implement ]------------------------------------------------------------------------------------*/ 47 /*--[ Implement ]------------------------------------------------------------------------------------*/
48 48
49 -static void lib3270_autoptr_cleanup_HINTERNET(HINTERNET **hInternet)  
50 -{  
51 - if(*hInternet)  
52 - WinHttpCloseHandle(*hInternet);  
53 - *hInternet = 0;  
54 -}  
55 -  
56 X509_CRL * get_crl_using_http(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) 49 X509_CRL * get_crl_using_http(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl)
57 { 50 {
58 - wchar_t wHostname[4096];  
59 - wchar_t wPath[4096];  
60 -  
61 - {  
62 - // Strip URL  
63 - char * url = lib3270_unescape(consturl);  
64 -  
65 - char *hostname = strstr(url,"://");  
66 - if(!hostname)  
67 - hostname = url;  
68 - else  
69 - hostname += 3;  
70 -  
71 - char *path = strchr(hostname,'/');  
72 - if(path)  
73 - *(path++) = 0;  
74 -  
75 - mbstowcs(wHostname, hostname, strlen(hostname)+1);  
76 - mbstowcs(wPath, path, strlen(path)+1);  
77 -  
78 - lib3270_free(url);  
79 -  
80 - }  
81 -  
82 - // https://docs.microsoft.com/en-us/windows/desktop/api/winhttp/nf-winhttp-winhttpopenrequest  
83 -  
84 - // Open HTTP session  
85 - // https://docs.microsoft.com/en-us/windows/desktop/api/winhttp/nf-winhttp-winhttpopenrequest  
86 - static const char * userAgent = PACKAGE_NAME "/" PACKAGE_VERSION;  
87 - wchar_t wUserAgent[256];  
88 - mbstowcs(wUserAgent, userAgent, strlen(userAgent)+1);  
89 - lib3270_autoptr(HINTERNET) httpSession = WinHttpOpen(wUserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );  
90 - if(!httpSession)  
91 - {  
92 - lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError());  
93 - lib3270_write_log(hSession,"ssl","%s: %s",consturl, windows_error);  
94 -  
95 - message->error = hSession->ssl.error = 0;  
96 - message->title = _( "Security error" );  
97 - message->text = _( "Can't open HTTP session" );  
98 - debug("%s",message->text);  
99 - errno = EINVAL;  
100 - return NULL;  
101 - }  
102 -  
103 - // Connect to server  
104 - lib3270_autoptr(HINTERNET) hConnect = WinHttpConnect(httpSession, wHostname, INTERNET_DEFAULT_HTTP_PORT, 0);  
105 - if(!hConnect)  
106 - {  
107 - lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError());  
108 - lib3270_write_log(hSession,"ssl","%s: %s",consturl, windows_error);  
109 -  
110 - message->error = hSession->ssl.error = 0;  
111 - message->title = _( "Security error" );  
112 - message->text = _( "Can't connect to HTTP server." );  
113 - debug("%s",message->text);  
114 - errno = EINVAL;  
115 - return NULL;  
116 - }  
117 -  
118 - // Create request.  
119 - lib3270_autoptr(HINTERNET) hRequest = WinHttpOpenRequest(hConnect, L"GET", wPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_ESCAPE_PERCENT);  
120 - if(!hConnect)  
121 - {  
122 - message->error = hSession->ssl.error = 0;  
123 - message->title = _( "Security error" );  
124 - message->text = _( "Can't create HTTP request." );  
125 - debug("%s",message->text);  
126 - errno = EINVAL;  
127 - return NULL;  
128 - }  
129 -  
130 - WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);  
131 -  
132 - // Send request.  
133 - if(!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0))  
134 - {  
135 - message->error = hSession->ssl.error = 0;  
136 - message->title = _( "Security error" );  
137 - message->text = _( "Can't send HTTP request." );  
138 - debug("%s",message->text);  
139 - errno = EINVAL;  
140 - return NULL;  
141 - }  
142 -  
143 - // Get response  
144 - if(!WinHttpReceiveResponse(hRequest, NULL))  
145 - {  
146 - message->error = hSession->ssl.error = 0;  
147 - message->title = _( "Security error" );  
148 - message->text = _( "Can't receive HTTP response." );  
149 - debug("%s",message->text);  
150 - errno = EINVAL;  
151 - return NULL;  
152 - } 51 + size_t szResponse = 0;
  52 + lib3270_autoptr(char) httpText = lib3270_get_from_url(hSession, consturl, &szResponse, &message->text);
153 53
154 - DWORD szResponse = 0;  
155 - if(!WinHttpQueryDataAvailable(hRequest, &szResponse)) 54 + if(!httpText)
156 { 55 {
157 message->error = hSession->ssl.error = 0; 56 message->error = hSession->ssl.error = 0;
158 message->title = _( "Security error" ); 57 message->title = _( "Security error" );
159 - message->text = _( "Empty response from HTTP server." );  
160 - debug("%s",message->text);  
161 - errno = EINVAL;  
162 - return NULL;  
163 - }  
164 -  
165 - lib3270_autoptr(char) httpText = lib3270_malloc(szResponse+1);  
166 - memset(httpText,0,szResponse+1);  
167 -  
168 - debug("Data block: %p",httpText);  
169 - debug("Response before: %u", (unsigned int) szResponse);  
170 -  
171 - if(!WinHttpReadData(hRequest,httpText,szResponse,&szResponse)){  
172 - message->error = hSession->ssl.error = 0;  
173 - message->title = _( "Security error" );  
174 - message->text = _( "Can't read HTTP response." );  
175 - debug("%s",message->text);  
176 - errno = EINVAL;  
177 return NULL; 58 return NULL;
178 } 59 }
179 60
180 - debug("Response after: %u", (unsigned int) szResponse);  
181 -  
182 - //  
183 - // Parse CRL  
184 - //  
185 - X509_CRL * x509_crl = NULL;  
186 -  
187 // Copy the pointer because d2i_X509_CRL changes the value!!! 61 // Copy the pointer because d2i_X509_CRL changes the value!!!
188 const unsigned char *crl_data = (const unsigned char *) httpText; 62 const unsigned char *crl_data = (const unsigned char *) httpText;
189 63
190 - if(!d2i_X509_CRL(&x509_crl,&crl_data, szResponse)) 64 + X509_CRL * x509_crl = NULL;
  65 + if(!d2i_X509_CRL(&x509_crl,&crl_data, (DWORD) szResponse))
191 { 66 {
192 message->error = hSession->ssl.error = ERR_get_error(); 67 message->error = hSession->ssl.error = ERR_get_error();
193 message->title = _( "Security error" ); 68 message->title = _( "Security error" );
@@ -196,7 +71,6 @@ X509_CRL * get_crl_using_http(H3270 *hSession, SSL_ERROR_MESSAGE * message, cons @@ -196,7 +71,6 @@ X509_CRL * get_crl_using_http(H3270 *hSession, SSL_ERROR_MESSAGE * message, cons
196 return NULL; 71 return NULL;
197 } 72 }
198 73
199 - debug("**************URL:[%s]*********************",consturl);  
200 return x509_crl; 74 return x509_crl;
201 75
202 } 76 }