diff --git a/configure.ac b/configure.ac index b3405fd..a9b5e9f 100644 --- a/configure.ac +++ b/configure.ac @@ -80,7 +80,7 @@ case "$host" in *-mingw32|*-pc-msys) app_cv_osname="windows" CFLAGS="$CFLAGS -pthread -D_WIN32_WINNT=0x0600" - LIBS="$LIBS -lws2_32 -lwtsapi32 -lcomdlg32" + LIBS="$LIBS -lws2_32 -lwtsapi32 -lcomdlg32 -lwinhttp" LDFLAGS="$LDFLAGS -pthread" DLL_LDFLAGS="-shared -Wl,--output-def,\$(@D)/\$(LIBNAME).def" DLLEXT=".dll" diff --git a/lib3270.cbp b/lib3270.cbp index c0f09cb..7a75759 100644 --- a/lib3270.cbp +++ b/lib3270.cbp @@ -218,6 +218,9 @@ + + diff --git a/src/core/windows/http.c b/src/core/windows/http.c new file mode 100644 index 0000000..713b596 --- /dev/null +++ b/src/core/windows/http.c @@ -0,0 +1,188 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + * References: + * + * https://docs.microsoft.com/en-us/windows/win32/winhttp/winhttp-autoproxy-api + * + */ + +/** + * @brief Implements CRL download using winhttp. + * + */ + +#include +#include +#include +#include +#include +#include + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static void lib3270_autoptr_cleanup_HINTERNET(HINTERNET **hInternet) +{ + if(*hInternet) + WinHttpCloseHandle(*hInternet); + *hInternet = 0; +} + +char * lib3270_get_from_url(H3270 *hSession, const char *url, size_t *length, const char **error_message) +{ + wchar_t wHostname[4096]; + wchar_t wPath[4096]; + + lib3270_trace_event(hSession,"Getting data from %s",url); + + { + // Strip URL + char * unescaped = lib3270_unescape(url); + + char *hostname = strstr(unescaped,"://"); + if(!hostname) + hostname = unescaped; + else + hostname += 3; + + char *path = strchr(hostname,'/'); + if(path) + *(path++) = 0; + + mbstowcs(wHostname, hostname, strlen(hostname)+1); + mbstowcs(wPath, path, strlen(path)+1); + + lib3270_free(unescaped); + + } + + // https://docs.microsoft.com/en-us/windows/desktop/api/winhttp/nf-winhttp-winhttpopenrequest + + // Open HTTP session + // https://docs.microsoft.com/en-us/windows/desktop/api/winhttp/nf-winhttp-winhttpopenrequest + static const char * userAgent = PACKAGE_NAME "/" PACKAGE_VERSION; + wchar_t wUserAgent[256]; + mbstowcs(wUserAgent, userAgent, strlen(userAgent)+1); + lib3270_autoptr(HINTERNET) httpSession = WinHttpOpen(wUserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ); + if(!httpSession) + { + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError()); + lib3270_write_log(hSession,"http","%s: %s",url, windows_error); + + *error_message = _( "Can't open HTTP session" ); + errno = EINVAL; + return NULL; + } + + // Connect to server + lib3270_autoptr(HINTERNET) hConnect = WinHttpConnect(httpSession, wHostname, INTERNET_DEFAULT_HTTP_PORT, 0); + if(!hConnect) + { + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError()); + lib3270_write_log(hSession,"http","%s: %s", url, windows_error); + + *error_message = _( "Can't connect to HTTP server." ); + + return NULL; + } + + // Create request. + lib3270_autoptr(HINTERNET) hRequest = WinHttpOpenRequest(hConnect, L"GET", wPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_ESCAPE_PERCENT); + if(!hConnect) + { + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError()); + lib3270_write_log(hSession,"http","%s: %s", url, windows_error); + + *error_message = _( "Can't create HTTP request." ); + + errno = EINVAL; + return NULL; + } + + WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0); + + // Send request. + if(!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) + { + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError()); + lib3270_write_log(hSession,"http","%s: %s", url, windows_error); + + *error_message = _( "Can't send HTTP request." ); + + errno = EINVAL; + return NULL; + } + + // Get response + if(!WinHttpReceiveResponse(hRequest, NULL)) + { + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError()); + lib3270_write_log(hSession,"http","%s: %s", url, windows_error); + + *error_message = _( "Error receiving HTTP response." ); + + errno = EINVAL; + return NULL; + + } + + DWORD szResponse = 0; + if(!WinHttpQueryDataAvailable(hRequest, &szResponse)) + { + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError()); + lib3270_write_log(hSession,"http","%s: %s", url, windows_error); + + *error_message = _( "Empty response from HTTP server." ); + + errno = EINVAL; + return NULL; + } + + char * httpText = lib3270_malloc(szResponse+1); + memset(httpText,0,szResponse+1); + + debug("Data block: %p",httpText); + debug("Response before: %u", (unsigned int) szResponse); + + if(!WinHttpReadData(hRequest,httpText,szResponse,&szResponse)){ + lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError()); + lib3270_write_log(hSession,"http","%s: %s", url, windows_error); + + *error_message = _( "Can't read HTTP response size." ); + + lib3270_free(httpText); + + errno = EINVAL; + return NULL; + } + + if(length) + *length = (size_t) szResponse; + + return httpText; + +} diff --git a/src/include/lib3270-internals.h b/src/include/lib3270-internals.h index 0527c22..cffce20 100644 --- a/src/include/lib3270-internals.h +++ b/src/include/lib3270-internals.h @@ -867,3 +867,13 @@ LIB3270_INTERNAL int non_blocking(H3270 *session, Boolean on); LIB3270_INTERNAL char * lib3270_get_user_name(); + /// @brief Query data from URL. + /// + /// @param hSession Handle of the TN3270 Session. + /// @param url The url to get. + /// @param length Pointer to the response lenght (can be NULL). + /// @param error_message Pointer to the error message. + /// + /// @return The data from URL (release it with lib3270_free) or NULL on error. + /// + LIB3270_INTERNAL char * lib3270_get_from_url(H3270 *hSession, const char *url, size_t *length, const char **error_message); diff --git a/src/ssl/windows/http.c b/src/ssl/windows/http.c index 6515413..76a8cbb 100644 --- a/src/ssl/windows/http.c +++ b/src/ssl/windows/http.c @@ -46,148 +46,23 @@ /*--[ Implement ]------------------------------------------------------------------------------------*/ -static void lib3270_autoptr_cleanup_HINTERNET(HINTERNET **hInternet) -{ - if(*hInternet) - WinHttpCloseHandle(*hInternet); - *hInternet = 0; -} - X509_CRL * get_crl_using_http(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) { - wchar_t wHostname[4096]; - wchar_t wPath[4096]; - - { - // Strip URL - char * url = lib3270_unescape(consturl); - - char *hostname = strstr(url,"://"); - if(!hostname) - hostname = url; - else - hostname += 3; - - char *path = strchr(hostname,'/'); - if(path) - *(path++) = 0; - - mbstowcs(wHostname, hostname, strlen(hostname)+1); - mbstowcs(wPath, path, strlen(path)+1); - - lib3270_free(url); - - } - - // https://docs.microsoft.com/en-us/windows/desktop/api/winhttp/nf-winhttp-winhttpopenrequest - - // Open HTTP session - // https://docs.microsoft.com/en-us/windows/desktop/api/winhttp/nf-winhttp-winhttpopenrequest - static const char * userAgent = PACKAGE_NAME "/" PACKAGE_VERSION; - wchar_t wUserAgent[256]; - mbstowcs(wUserAgent, userAgent, strlen(userAgent)+1); - lib3270_autoptr(HINTERNET) httpSession = WinHttpOpen(wUserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ); - if(!httpSession) - { - lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError()); - lib3270_write_log(hSession,"ssl","%s: %s",consturl, windows_error); - - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't open HTTP session" ); - debug("%s",message->text); - errno = EINVAL; - return NULL; - } - - // Connect to server - lib3270_autoptr(HINTERNET) hConnect = WinHttpConnect(httpSession, wHostname, INTERNET_DEFAULT_HTTP_PORT, 0); - if(!hConnect) - { - lib3270_autoptr(char) windows_error = lib3270_win32_translate_error_code(GetLastError()); - lib3270_write_log(hSession,"ssl","%s: %s",consturl, windows_error); - - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't connect to HTTP server." ); - debug("%s",message->text); - errno = EINVAL; - return NULL; - } - - // Create request. - lib3270_autoptr(HINTERNET) hRequest = WinHttpOpenRequest(hConnect, L"GET", wPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_ESCAPE_PERCENT); - if(!hConnect) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't create HTTP request." ); - debug("%s",message->text); - errno = EINVAL; - return NULL; - } - - WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0); - - // Send request. - if(!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't send HTTP request." ); - debug("%s",message->text); - errno = EINVAL; - return NULL; - } - - // Get response - if(!WinHttpReceiveResponse(hRequest, NULL)) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't receive HTTP response." ); - debug("%s",message->text); - errno = EINVAL; - return NULL; - } + size_t szResponse = 0; + lib3270_autoptr(char) httpText = lib3270_get_from_url(hSession, consturl, &szResponse, &message->text); - DWORD szResponse = 0; - if(!WinHttpQueryDataAvailable(hRequest, &szResponse)) + if(!httpText) { message->error = hSession->ssl.error = 0; message->title = _( "Security error" ); - message->text = _( "Empty response from HTTP server." ); - debug("%s",message->text); - errno = EINVAL; - return NULL; - } - - lib3270_autoptr(char) httpText = lib3270_malloc(szResponse+1); - memset(httpText,0,szResponse+1); - - debug("Data block: %p",httpText); - debug("Response before: %u", (unsigned int) szResponse); - - if(!WinHttpReadData(hRequest,httpText,szResponse,&szResponse)){ - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't read HTTP response." ); - debug("%s",message->text); - errno = EINVAL; return NULL; } - debug("Response after: %u", (unsigned int) szResponse); - - // - // Parse CRL - // - X509_CRL * x509_crl = NULL; - // Copy the pointer because d2i_X509_CRL changes the value!!! const unsigned char *crl_data = (const unsigned char *) httpText; - if(!d2i_X509_CRL(&x509_crl,&crl_data, szResponse)) + X509_CRL * x509_crl = NULL; + if(!d2i_X509_CRL(&x509_crl,&crl_data, (DWORD) szResponse)) { message->error = hSession->ssl.error = ERR_get_error(); message->title = _( "Security error" ); @@ -196,7 +71,6 @@ X509_CRL * get_crl_using_http(H3270 *hSession, SSL_ERROR_MESSAGE * message, cons return NULL; } - debug("**************URL:[%s]*********************",consturl); return x509_crl; } -- libgit2 0.21.2