From 43db012c224e25e341888e856f82c3985d68c8f4 Mon Sep 17 00:00:00 2001 From: André Breves Date: Wed, 15 Apr 2020 19:35:31 -0300 Subject: [PATCH] Improves macOS support --- configure.ac | 5 +++-- src/core/macos/connect.c | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/macos/curl.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/macos/event_dispatcher.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/macos/log.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/macos/util.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/include/localdefs.h | 6 +++++- src/ssl/macos/getcrl.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/macos/init.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/macos/ldap.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/macos/private.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/macos/url.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 1723 insertions(+), 3 deletions(-) create mode 100644 src/core/macos/connect.c create mode 100644 src/core/macos/curl.c create mode 100644 src/core/macos/event_dispatcher.c create mode 100644 src/core/macos/log.c create mode 100644 src/core/macos/util.c create mode 100644 src/ssl/macos/getcrl.c create mode 100644 src/ssl/macos/init.c create mode 100644 src/ssl/macos/ldap.c create mode 100644 src/ssl/macos/private.h create mode 100644 src/ssl/macos/url.c diff --git a/configure.ac b/configure.ac index 790471b..0c3fc4b 100644 --- a/configure.ac +++ b/configure.ac @@ -107,14 +107,15 @@ case "$host" in *-apple-darwin*) CFLAGS="$CFLAGS -pthread -DCONFDIR=\$(confdir) -DDATADIR=\$(datadir) -DLOCALEDIR=\$(localedir)" LDFLAGS="$LDFLAGS -pthread" - app_cv_osname="linux" + LIBS="$LIBS -framework CoreFoundation" + app_cv_osname="macos" LOGDIR="/var/log" DLLEXT=".so" DLL_LDFLAGS="-shared -Wl,-install_name,\$(@F)" INSTALL_PACKAGES="linux-lib ${INSTALL_PACKAGES}" - app_cv_static='yes' + app_cv_static='no' ;; diff --git a/src/core/macos/connect.c b/src/core/macos/connect.c new file mode 100644 index 0000000..c8d6478 --- /dev/null +++ b/src/core/macos/connect.c @@ -0,0 +1,312 @@ +/* + * "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) + * + */ + +#include +#include +#include +#include +#include +#include "kybdc.h" + +#include +#include +#include +#include +#include +#include +#include + +#define SOCK_CLOSE(s) close(s->connection.sock); s->connection.sock = -1; + +#include + +#include "hostc.h" +#include "trace_dsc.h" +#include "telnetc.h" +#include "screen.h" + +#include +#include +#include + +/*---[ Implement ]-------------------------------------------------------------------------------*/ + + +static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG GNUC_UNUSED(flag), void GNUC_UNUSED(*dunno)) +{ + int err; + socklen_t len = sizeof(err); + + if(hSession->xio.write) { + trace("%s write=%p",__FUNCTION__,hSession->xio.write); + lib3270_remove_poll(hSession, hSession->xio.write); + hSession->xio.write = NULL; + } + + if(getsockopt(hSession->connection.sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len) < 0) + { + lib3270_disconnect(hSession); + lib3270_popup_dialog( + hSession, + LIB3270_NOTIFY_ERROR, + _( "Network error" ), + _( "Unable to get connection state." ), + _( "%s" ), strerror(errno) + ); + return; + } + else if(err) + { + char buffer[4096]; + + snprintf(buffer,4095,_( "Can't connect to %s" ), lib3270_get_url(hSession) ); + + lib3270_disconnect(hSession); + lib3270_popup_dialog( + hSession, + LIB3270_NOTIFY_ERROR, + _( "Connection failed" ), + buffer, + _( "%s" ), strerror(err) + ); + return; + } + + hSession->xio.except = lib3270_add_poll_fd(hSession,hSession->connection.sock,LIB3270_IO_FLAG_EXCEPTION,net_exception,0); + hSession->xio.read = lib3270_add_poll_fd(hSession,hSession->connection.sock,LIB3270_IO_FLAG_READ,net_input,0); + +#if defined(HAVE_LIBSSL) + if(hSession->ssl.con && hSession->ssl.state == LIB3270_SSL_UNDEFINED) + { + if(ssl_negotiate(hSession)) + return; + } +#endif + + lib3270_setup_session(hSession); + lib3270_set_connected_initial(hSession); + +} + + struct resolver + { + const char * message; + }; + + static int background_connect(H3270 *hSession, void *host) + { + + struct addrinfo hints; + struct addrinfo * result = NULL; + struct addrinfo * rp = NULL; + + memset(&hints,0,sizeof(hints)); + hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6 + hints.ai_socktype = SOCK_STREAM; // Stream socket + hints.ai_flags = AI_PASSIVE; // For wildcard IP address + hints.ai_protocol = 0; // Any protocol + + status_resolving(hSession); + + int rc = getaddrinfo(hSession->host.current, hSession->host.srvc, &hints, &result); + if(rc != 0) + { + ((struct resolver *) host)->message = gai_strerror(rc); + return -1; + } + + status_connecting(hSession); + + for(rp = result; hSession->connection.sock < 0 && rp != NULL; rp = rp->ai_next) + { + hSession->connection.sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if(hSession->connection.sock < 0) + { + ((struct resolver *) host)->message = strerror(errno); + continue; + } + + // Connected! + if(connect(hSession->connection.sock, rp->ai_addr, rp->ai_addrlen)) + { + SOCK_CLOSE(hSession); + ((struct resolver *) host)->message = strerror(errno); + continue; + } + + } + + freeaddrinfo(result); + + return 0; + + } + + int net_reconnect(H3270 *hSession, int seconds) + { + struct resolver host; + memset(&host,0,sizeof(host)); + + // Connect to host + if(lib3270_run_task(hSession, background_connect, &host) || hSession->connection.sock < 0) + { + char buffer[4096]; + snprintf(buffer,4095,_( "Can't connect to %s:%s"), hSession->host.current, hSession->host.srvc); + + lib3270_popup_dialog( hSession, + LIB3270_NOTIFY_ERROR, + _( "Connection error" ), + buffer, + "%s", + host.message); + + lib3270_set_disconnected(hSession); + return errno = ENOTCONN; + } + + /* don't share the socket with our children */ + (void) fcntl(hSession->connection.sock, F_SETFD, 1); + + hSession->ever_3270 = False; + +#if defined(HAVE_LIBSSL) + debug("%s: TLS/SSL is %s",__FUNCTION__,hSession->ssl.enabled ? "ENABLED" : "DISABLED") + trace_dsn(hSession,"TLS/SSL is %s\n", hSession->ssl.enabled ? "enabled" : "disabled" ); + if(hSession->ssl.enabled) + { + hSession->ssl.host = 1; + if(ssl_init(hSession)) + return errno = ENOTCONN; + + } +#endif // HAVE_LIBSSL + + // set options for inline out-of-band data and keepalives + int optval = 1; + if (setsockopt(hSession->connection.sock, SOL_SOCKET, SO_OOBINLINE, (char *)&optval,sizeof(optval)) < 0) + { + int rc = errno; + lib3270_popup_dialog( hSession, + LIB3270_NOTIFY_ERROR, + _( "Connection error" ), + _( "setsockopt(SO_OOBINLINE) has failed" ), + "%s", + strerror(rc)); + SOCK_CLOSE(hSession); + return rc; + } + + optval = lib3270_get_toggle(hSession,LIB3270_TOGGLE_KEEP_ALIVE) ? 1 : 0; + if (setsockopt(hSession->connection.sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) < 0) + { + int rc = errno; + + char buffer[4096]; + snprintf(buffer,4095,_( "Can't %s network keep-alive" ), optval ? _( "enable" ) : _( "disable" )); + + lib3270_popup_dialog( hSession, + LIB3270_NOTIFY_ERROR, + _( "Connection error" ), + buffer, + "%s", + strerror(rc)); + SOCK_CLOSE(hSession); + return rc; + } + else + { + trace_dsn(hSession,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" ); + } + + + /* +#if defined(OMTU) + else if (setsockopt(hSession->sock, SOL_SOCKET, SO_SNDBUF, (char *)&mtu,sizeof(mtu)) < 0) + { + popup_a_sockerr(hSession, _( "setsockopt(%s)" ), "SO_SNDBUF"); + SOCK_CLOSE(hSession); + } +#endif + + */ + + // Connecting, set callbacks, wait for connection + lib3270_set_cstate(hSession, LIB3270_PENDING); + lib3270_st_changed(hSession, LIB3270_STATE_HALF_CONNECT, True); + + hSession->xio.write = lib3270_add_poll_fd(hSession,hSession->connection.sock,LIB3270_IO_FLAG_WRITE,net_connected,0); + // hSession->ns_write_id = AddOutput(hSession->sock, hSession, net_connected); + + trace("%s: Connection in progress",__FUNCTION__); + + if(seconds) + { + time_t end = time(0)+seconds; + + while(time(0) < end) + { + lib3270_main_iterate(hSession,1); + + switch(hSession->connection.state) + { + case LIB3270_PENDING: + case LIB3270_CONNECTED_INITIAL: + case LIB3270_CONNECTED_ANSI: + case LIB3270_CONNECTED_3270: + case LIB3270_CONNECTED_INITIAL_E: + case LIB3270_CONNECTED_NVT: + case LIB3270_CONNECTED_SSCP: + case LIB3270_RESOLVING: + break; + + case LIB3270_NOT_CONNECTED: + return errno = ENOTCONN; + + case LIB3270_CONNECTED_TN3270E: + if(!hSession->starting) + return 0; + break; + + default: + lib3270_write_log(hSession,"connect", "%s: State changed to unexpected state %d",__FUNCTION__,hSession->connection.state); + return errno = EINVAL; + } + + } + + lib3270_disconnect(hSession); + lib3270_write_log(hSession,"connect", "%s: %s",__FUNCTION__,strerror(ETIMEDOUT)); + + return errno = ETIMEDOUT; + } + + return 0; + + } + diff --git a/src/core/macos/curl.c b/src/core/macos/curl.c new file mode 100644 index 0000000..7704724 --- /dev/null +++ b/src/core/macos/curl.c @@ -0,0 +1,231 @@ +/* + * "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) + * + */ + +#include + +#if defined(HAVE_LIBCURL) + +#include +#include +#include +#include +#include + +#define CRL_DATA_LENGTH 2048 + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static inline void lib3270_autoptr_cleanup_CURL(CURL **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + curl_easy_cleanup(*ptr); + *ptr = NULL; +} + +typedef struct _curldata +{ + size_t length; + H3270 * hSession; + char errbuf[CURL_ERROR_SIZE]; + struct { + size_t length; + unsigned char * contents; + } data; +} CURLDATA; + +static inline void lib3270_autoptr_cleanup_CURLDATA(CURLDATA **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + { + CURLDATA *cdata = *ptr; + + if(cdata->data.contents) { + lib3270_free(cdata->data.contents); + cdata->data.contents = NULL; + } + lib3270_free(cdata); + } + *ptr = NULL; +} + +static size_t internal_curl_write_callback(void *contents, size_t size, size_t nmemb, void *userp) +{ + CURLDATA * data = (CURLDATA *) userp; + + debug("%s",__FUNCTION__); + + size_t realsize = size * nmemb; + + debug("%s size=%d data->length=%d crldatalength=%d",__FUNCTION__,(int) size, (int) data->length, CRL_DATA_LENGTH); + + if((realsize + data->length) > data->data.length) + { + data->data.length += (CRL_DATA_LENGTH + realsize); + data->data.contents = lib3270_realloc(data->data.contents,data->data.length); + memset(&(data->data.contents[data->length]),0,data->data.length-data->length); + } + + debug("%s",__FUNCTION__); + + if(lib3270_get_toggle(data->hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + lib3270_trace_data( + data->hSession, + "Received", + (const unsigned char *) contents, + realsize + ); + } + + debug("%s",__FUNCTION__); + + memcpy(&(data->data.contents[data->length]),contents,realsize); + data->length += realsize; + + debug("%s",__FUNCTION__); + + return realsize; +} + +static int internal_curl_trace_callback(CURL GNUC_UNUSED(*handle), curl_infotype type, char *data, size_t size, void *userp) +{ + const char * text = NULL; + + switch (type) { + case CURLINFO_TEXT: + lib3270_write_log(((CURLDATA *) userp)->hSession,"curl","%s",data); + return 0; + + case CURLINFO_HEADER_OUT: + text = "=> Send header"; + break; + + case CURLINFO_DATA_OUT: + text = "=> Send data"; + break; + + case CURLINFO_SSL_DATA_OUT: + text = "=> Send SSL data"; + break; + + case CURLINFO_HEADER_IN: + text = "<= Recv header"; + break; + + case CURLINFO_DATA_IN: + text = "<= Recv data"; + break; + + case CURLINFO_SSL_DATA_IN: + text = "<= Recv SSL data"; + break; + + default: + return 0; + + } + + lib3270_trace_data( + ((CURLDATA *) userp)->hSession, + text, + (const unsigned char *) data, + size + ); + + return 0; +} + +char * lib3270_get_from_url(H3270 *hSession, const char *url, size_t *length, const char **error_message) +{ + lib3270_write_event_trace(hSession,"Getting data from %s",url); + + // Use CURL to download the CRL + lib3270_autoptr(CURLDATA) crl_data = lib3270_malloc(sizeof(CURLDATA)); + lib3270_autoptr(CURL) hCurl = curl_easy_init(); + + memset(crl_data,0,sizeof(CURLDATA)); + crl_data->hSession = hSession; + crl_data->data.length = CRL_DATA_LENGTH; + crl_data->data.contents = lib3270_malloc(crl_data->data.length); + + if(!hCurl) + { + *error_message= _( "Can't initialize curl operation" ); + errno = EINVAL; + return NULL; + } + + CURLcode res; + + curl_easy_setopt(hCurl, CURLOPT_URL, url); + curl_easy_setopt(hCurl, CURLOPT_FOLLOWLOCATION, 1L); + + curl_easy_setopt(hCurl, CURLOPT_ERRORBUFFER, crl_data->errbuf); + + curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, internal_curl_write_callback); + curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (void *) crl_data); + + curl_easy_setopt(hCurl, CURLOPT_USERNAME, ""); + + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + curl_easy_setopt(hCurl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(hCurl, CURLOPT_DEBUGFUNCTION, internal_curl_trace_callback); + curl_easy_setopt(hCurl, CURLOPT_DEBUGDATA, (void *) crl_data); + } + + res = curl_easy_perform(hCurl); + + if(res != CURLE_OK) + { + if(crl_data->errbuf[0]) + lib3270_write_log(hSession,"curl","%s: %s",url, crl_data->errbuf); + + *error_message = curl_easy_strerror(res); + + lib3270_write_log(hSession,"curl","%s: %s",url, *error_message); + errno = EINVAL; + return NULL; + + } + + if(length) + *length = (size_t) crl_data->length; + + char * httpText = lib3270_malloc(crl_data->length+1); + memset(httpText,0,crl_data->length+1); + memcpy(httpText,crl_data->data.contents,crl_data->length); + + return httpText; + +} + +#endif // HAVE_LIBCURL diff --git a/src/core/macos/event_dispatcher.c b/src/core/macos/event_dispatcher.c new file mode 100644 index 0000000..9b9b7d8 --- /dev/null +++ b/src/core/macos/event_dispatcher.c @@ -0,0 +1,231 @@ +/* + * "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) + * + */ + + /** + * @brief Implements the default event dispatcher for linux. + * + */ + +#include +#include +#include +#include +#include + +#define MILLION 1000000L +#define TN (timeout_t *)NULL + +/*---[ Implement ]------------------------------------------------------------------------------------------*/ + +/** + * @brief lib3270's default event dispatcher. + * + * @param hSession TN3270 session to process. + * @param block If non zero, the method blocks waiting for event. + * + */ +int lib3270_default_event_dispatcher(H3270 *hSession, int block) +{ + int ns; + struct timeval now, twait, *tp; + int events; + + fd_set rfds, wfds, xfds; + + input_t *ip; + int processed_any = 0; + +retry: + + hSession->input.changed = 0; + + // If we've processed any input, then don't block again. + if(processed_any) + block = 0; + + events = 0; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&xfds); + + for (ip = (input_t *) hSession->input.list.first; ip != (input_t *)NULL; ip = (input_t *) ip->next) + { + if(!ip->enabled) + { + debug("Socket %d is disabled",ip->fd); + continue; + } + + if(ip->flag & LIB3270_IO_FLAG_READ) + { + FD_SET(ip->fd, &rfds); + events++; + } + + if(ip->flag & LIB3270_IO_FLAG_WRITE) + { + FD_SET(ip->fd, &wfds); + events++; + } + + if(ip->flag & LIB3270_IO_FLAG_EXCEPTION) + { + FD_SET(ip->fd, &xfds); + events++; + } + } + + if (block) + { + if (hSession->timeouts.first) + { + (void) gettimeofday(&now, (void *)NULL); + twait.tv_sec = ((timeout_t *) hSession->timeouts.first)->tv.tv_sec - now.tv_sec; + twait.tv_usec = ((timeout_t *) hSession->timeouts.first)->tv.tv_usec - now.tv_usec; + if (twait.tv_usec < 0L) { + twait.tv_sec--; + twait.tv_usec += MILLION; + } + if (twait.tv_sec < 0L) + twait.tv_sec = twait.tv_usec = 0L; + tp = &twait; + } + else + { + twait.tv_sec = 1; + twait.tv_usec = 0L; + tp = &twait; + } + } + else + { + twait.tv_sec = 0; + twait.tv_usec = 10L; + tp = &twait; + + if(!events) + return processed_any; + } + + ns = select(FD_SETSIZE, &rfds, &wfds, &xfds, tp); + + if (ns < 0 && errno != EINTR) + { + lib3270_popup_dialog( hSession, + LIB3270_NOTIFY_ERROR, + _( "Network error" ), + _( "Select() failed when processing for events." ), + "%s", + strerror(errno)); + } + else + { + for (ip = (input_t *) hSession->input.list.first; ip != (input_t *) NULL; ip = (input_t *) ip->next) + { + if((ip->flag & LIB3270_IO_FLAG_READ) && FD_ISSET(ip->fd, &rfds)) + { + (*ip->call)(hSession,ip->fd,LIB3270_IO_FLAG_READ,ip->userdata); + processed_any = True; + if (hSession->input.changed) + goto retry; + } + + if((ip->flag & LIB3270_IO_FLAG_WRITE) && FD_ISSET(ip->fd, &wfds)) + { + (*ip->call)(hSession,ip->fd,LIB3270_IO_FLAG_WRITE,ip->userdata); + processed_any = True; + if (hSession->input.changed) + goto retry; + } + + if((ip->flag & LIB3270_IO_FLAG_EXCEPTION) && FD_ISSET(ip->fd, &xfds)) + { + (*ip->call)(hSession,ip->fd,LIB3270_IO_FLAG_EXCEPTION,ip->userdata); + processed_any = True; + if (hSession->input.changed) + goto retry; + } + } + } + + // See what's expired. + if (hSession->timeouts.first) + { + struct timeout *t; + (void) gettimeofday(&now, (void *)NULL); + + while(hSession->timeouts.first) + { + t = (struct timeout *) hSession->timeouts.first; + + if (t->tv.tv_sec < now.tv_sec ||(t->tv.tv_sec == now.tv_sec && t->tv.tv_usec < now.tv_usec)) + { + t->in_play = True; + (*t->proc)(hSession); + processed_any = True; + + lib3270_linked_list_delete_node(&hSession->timeouts,t); + + } + else + { + break; + } + + } + + /* + + while ((t = ((timeout_t *) hSession->timeouts.first)) != TN) + { + if (t->tv.tv_sec < now.tv_sec ||(t->tv.tv_sec == now.tv_sec && t->tv.tv_usec < now.tv_usec)) + { + t->in_play = True; + (*t->proc)(t->session); + processed_any = True; + + lib3270_linked_list_delete_node(&hSession->timeouts,t); + + } + else + { + break; + } + } + + */ + } + + if (hSession->input.changed) + goto retry; + + return processed_any; + +} diff --git a/src/core/macos/log.c b/src/core/macos/log.c new file mode 100644 index 0000000..6e8001d --- /dev/null +++ b/src/core/macos/log.c @@ -0,0 +1,92 @@ +/* + * "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. 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) + * + */ + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYSLOG + #include +#endif // HAVE_SYSLOG + +/*---[ Implementacao ]--------------------------------------------------------------------------------------*/ + + int use_syslog = 0; + + void default_log_writer(H3270 GNUC_UNUSED(*session), const char *module, int GNUC_UNUSED(rc), const char *fmt, va_list arg_ptr) + { +#ifdef HAVE_SYSLOG + if(use_syslog) + { + vsyslog(LOG_INFO, fmt, arg_ptr); + } + else + { + printf("%s:\t",module); + vprintf(fmt,arg_ptr); + printf("\n"); + fflush(stdout); + } +#else + printf("%s:\t",module); + vprintf(fmt,arg_ptr); + printf("\n"); + fflush(stdout); +#endif + } + + LIB3270_EXPORT int lib3270_set_syslog(int flag) + { +#ifdef HAVE_SYSLOG + if(flag) + { + if(!use_syslog) + { + openlog(LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME), LOG_CONS, LOG_USER); + use_syslog = 1; + } + } + else + { + if(use_syslog) + { + closelog(); + use_syslog = 0; + } + } + + return 0; + +#else + return errno = ENOENT; +#endif // HAVE_SYSLOG + } diff --git a/src/core/macos/util.c b/src/core/macos/util.c new file mode 100644 index 0000000..03bed2f --- /dev/null +++ b/src/core/macos/util.c @@ -0,0 +1,169 @@ +/* + * "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. 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) + * + */ + +/** + * @brief Linux Utility functions. + */ + + +#include +#include +#include +#include +#include +#include +#include + +static char * concat(char *path, const char *name, size_t *length) +{ + size_t szCurrent = strlen(path); + + if(szCurrent > 1 && path[szCurrent-1] != '/') + strcat(path,"/"); + + szCurrent += strlen(name); + + if(szCurrent >= *length) + { + *length += (szCurrent + 1024); + path = lib3270_realloc(path,*length); + } + + strcat(path,name); + + return path; +} + +static char * build_filename(const char *root, const char *str, va_list args) +{ + size_t szFilename = 1024 + strlen(root); + char * filename = (char *) lib3270_malloc(szFilename); + + strcpy(filename,root); + + while(str) { + filename = concat(filename,str,&szFilename); + str = va_arg(args, const char *); + } + + return (char *) lib3270_realloc(filename,strlen(filename)+1); +} + +char * lib3270_build_data_filename(const char *str, ...) +{ + va_list args; + va_start (args, str); + + char *filename; + CFBundleRef mainBundle = CFBundleGetMainBundle(); + if (mainBundle) { + CFURLRef url = CFBundleCopyBundleURL(mainBundle); + if (url) { + size_t szPath = PATH_MAX; + char *path = (char *) lib3270_malloc(szPath); + CFURLGetFileSystemRepresentation(url, true, path, szPath); + CFRelease(url); + path = concat(path, "Contents/Resources", &szPath); + filename = build_filename(path, str, args); + lib3270_free(path); + } else { + filename = build_filename(LIB3270_STRINGIZE_VALUE_OF(DATADIR), str, args); + } + } else { + filename = build_filename(LIB3270_STRINGIZE_VALUE_OF(DATADIR), str, args); + } + + va_end (args); + + return filename; +} + +char * lib3270_build_config_filename(const char *str, ...) +{ + va_list args; + va_start (args, str); + + char *filename = build_filename(LIB3270_STRINGIZE_VALUE_OF(CONFDIR), str, args); + + va_end (args); + + return filename; +} + +char * lib3270_build_filename(const char *str, ...) +{ + size_t szFilename = 1024; + char * filename = (char *) lib3270_malloc(szFilename); + char * tempname; + + // First build the base filename + memset(filename,0,szFilename); + + va_list args; + va_start (args, str); + while(str) { + filename = concat(filename,str,&szFilename); + str = va_arg(args, const char *); + } + va_end (args); + + // Check paths + size_t ix; + + static const char * paths[] = + { + LIB3270_STRINGIZE_VALUE_OF(DATADIR), + LIB3270_STRINGIZE_VALUE_OF(CONFDIR), + "." + }; + + for(ix = 0; ix < (sizeof(paths)/sizeof(paths[0])); ix++) + { + tempname = lib3270_strdup_printf("%s/%s",paths[ix],filename); + + if(access(tempname, F_OK) == 0) + { + lib3270_free(filename); + return tempname; + } + + lib3270_free(tempname); + + } + + // Not found! Force the standard data dir + + tempname = lib3270_strdup_printf("%s/%s",paths[0],filename); + lib3270_free(filename); + + return tempname; + +} + diff --git a/src/include/localdefs.h b/src/include/localdefs.h index b1226b4..4e13d5b 100644 --- a/src/include/localdefs.h +++ b/src/include/localdefs.h @@ -36,7 +36,11 @@ //typedef void *XtPointer; // typedef void *Widget; // typedef void *XEvent; -typedef char Boolean; +#ifdef __APPLE__ + typedef unsigned char Boolean; +#else + typedef char Boolean; +#endif typedef char *String; // typedef unsigned int Cardinal; typedef unsigned long KeySym; diff --git a/src/ssl/macos/getcrl.c b/src/ssl/macos/getcrl.c new file mode 100644 index 0000000..99ec938 --- /dev/null +++ b/src/ssl/macos/getcrl.c @@ -0,0 +1,131 @@ +/* + * "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: + * + * http://www.openssl.org/docs/ssl/ + * https://stackoverflow.com/questions/4389954/does-openssl-automatically-handle-crls-certificate-revocation-lists-now + * + */ + +#include "private.h" + +#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK) + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static inline void lib3270_autoptr_cleanup_FILE(FILE **file) +{ + if(*file) + fclose(*file); +} + +X509_CRL * lib3270_download_crl(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) +{ + X509_CRL * x509_crl = NULL; + + if(!(consturl && *consturl)) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't open CRL File" ); + message->description = _("The URL for the CRL is undefined or empty"); + errno = ENOENT; + return NULL; + } + + if(strncasecmp(consturl,"file://",7) == 0) + { + lib3270_autoptr(FILE) hCRL = fopen(consturl+7,"r"); + + if(!hCRL) + { + // Can't open CRL File. + int err = errno; + + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't open CRL File" ); + message->description = strerror(err); + trace_ssl(hSession,"Can't open %s: %s\n",consturl,message->description); + return NULL; + + } + + trace_ssl(hSession,"Loading CRL from %s\n",consturl+7); + if(d2i_X509_CRL_fp(hCRL, &x509_crl)) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Can't decode CRL" ); + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); + return NULL; + } + + + + } +#ifdef HAVE_LDAP + else if(strncasecmp(consturl,"ldap://",7) == 0 && strlen(consturl) > 8) + { + return get_crl_using_ldap(hSession, message, consturl); + + } +#endif // HAVE_LDAP + else + { +#ifdef HAVE_LIBCURL + + return get_crl_using_url(hSession, message, consturl); + +#else + // Can't get CRL. + + message->error = hSession->ssl.error = 0; + + if(!(message->text && message->description)) + message->title = _( "Security error" ); + + if(!message->text) + message->text = _( "Unexpected or invalid CRL URL" ); + + if(!message->description) + message->description = _("The URL scheme is unknown"); + + trace_ssl(hSession,"%s: The URL scheme is unknown",consturl); + + errno = EINVAL; + return NULL; +#endif // HAVE_LIBCURL + } + + return x509_crl; + +} + +#endif // HAVE_LIBSSL && SSL_ENABLE_CRL_CHECK diff --git a/src/ssl/macos/init.c b/src/ssl/macos/init.c new file mode 100644 index 0000000..80b9181 --- /dev/null +++ b/src/ssl/macos/init.c @@ -0,0 +1,118 @@ +/* + * "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: + * + * http://www.openssl.org/docs/ssl/ + * https://stackoverflow.com/questions/4389954/does-openssl-automatically-handle-crls-certificate-revocation-lists-now + * + */ + +/** + * @brief OpenSSL initialization for linux. + * + */ + +#include + +#if defined(HAVE_LIBSSL) + +#include +#include +#include + +#ifndef SSL_ST_OK + #define SSL_ST_OK 3 +#endif // !SSL_ST_OK + +#include +#include +#include +#include +#include +#include +#include "trace_dsc.h" + +#ifdef SSL_ENABLE_CRL_CHECK + #include +#endif // SSL_ENABLE_CRL_CHECK + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +/** + * @brief Initialize openssl library. + * + * @return 0 if ok, non zero if fails. + * + */ +int ssl_ctx_init(H3270 *hSession, SSL_ERROR_MESSAGE * message) +{ + debug("%s ssl_ctx=%p",__FUNCTION__,ssl_ctx); + + if(ssl_ctx) + return 0; + + trace_ssl(hSession,"Initializing SSL context.\n"); + + SSL_load_error_strings(); + SSL_library_init(); + + ssl_ctx = SSL_CTX_new(SSLv23_method()); + if(ssl_ctx == NULL) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Cant initialize the SSL context." ); + return -1; + } + + SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL); + SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback); + + SSL_CTX_set_default_verify_paths(ssl_ctx); + + ssl_3270_ex_index = SSL_get_ex_new_index(0,NULL,NULL,NULL,NULL); + +#ifdef SSL_ENABLE_CRL_CHECK + + // Enable CRL check + X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx); + X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); + X509_STORE_set1_param(store, param); + X509_VERIFY_PARAM_free(param); + + trace_ssl(hSession,"CRL CHECK was enabled\n"); + +#endif // SSL_ENABLE_CRL_CHECK + + return 0; + +} + +#endif // HAVE_LIBSSL diff --git a/src/ssl/macos/ldap.c b/src/ssl/macos/ldap.c new file mode 100644 index 0000000..2762c89 --- /dev/null +++ b/src/ssl/macos/ldap.c @@ -0,0 +1,241 @@ +/* + * "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: + * + * http://www.openssl.org/docs/ssl/ + * https://stackoverflow.com/questions/4389954/does-openssl-automatically-handle-crls-certificate-revocation-lists-now + * + */ + +#include +#include +#include +#include +#include + +#include "utilc.h" + +#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LDAP) + +#include +#include +#include +#include + +#define LDAP_DEPRECATED 1 +#include + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static inline void lib3270_autoptr_cleanup_LDAPMessage(LDAPMessage **message) +{ + debug("%s(%p)",__FUNCTION__,*message); + if(message) + ldap_msgfree(*message); + *message = NULL; +} + +static inline void lib3270_autoptr_cleanup_LDAP(LDAP **ld) +{ + debug("%s(%p)",__FUNCTION__,*ld); + if(*ld) + ldap_unbind_ext(*ld, NULL, NULL); + *ld = NULL; +} + +static inline void lib3270_autoptr_cleanup_BerElement(BerElement **ber) +{ + debug("%s(%p)",__FUNCTION__,*ber); + if(*ber) + ber_free(*ber, 0); + *ber = NULL; +} + +static inline void lib3270_autoptr_cleanup_LDAPPTR(char **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + ldap_memfree(*ptr); + *ptr = NULL; +} + +LIB3270_INTERNAL X509_CRL * get_crl_using_ldap(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) +{ + X509_CRL * x509_crl = NULL; + + int rc; + lib3270_autoptr(char) url = lib3270_unescape(consturl); + char * base = strchr(url+7,'/'); + char * attrs[] = { NULL, NULL }; + + if(!base) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "No DN of the entry at which to start the search on the URL" ); + message->description = _( "The URL argument should be in the format ldap://[HOST]/[DN]?attribute" ); + errno = EINVAL; + return NULL; + } + + *(base++) = 0; + attrs[0] = strchr(base,'?'); + + if(!base) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "No LDAP attribute on the URL" ); + message->description = _( "The URL argument should be in the format ldap://[HOST]/[DN]?attribute" ); + errno = EINVAL; + return NULL; + } + + *(attrs[0]++) = 0; + + debug("host: \"%s\"",url); + debug("Base: \"%s\"",base); + debug("Attr: \"%s\"",attrs[0]); + + // Do LDAP Query + LDAP __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_LDAP))) *ld = NULL; + BerElement __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_BerElement))) * ber = NULL; + + rc = ldap_initialize(&ld, url); + if(rc != LDAP_SUCCESS) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't initialize LDAP" ); + message->description = ldap_err2string(rc); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + return NULL; + } + + unsigned long version = LDAP_VERSION3; + rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,(void *) &version); + if(rc != LDAP_SUCCESS) { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't set LDAP protocol version" ); + message->description = ldap_err2string(rc); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + return NULL; + } + + rc = ldap_simple_bind_s(ld, "", ""); + if(rc != LDAP_SUCCESS) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't bind to LDAP server" ); + message->description = ldap_err2string(rc); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + return NULL; + } + + lib3270_autoptr(LDAPMessage) results = NULL; + rc = ldap_search_ext_s( + ld, // Specifies the LDAP pointer returned by a previous call to ldap_init(), ldap_ssl_init(), or ldap_open(). + base, // Specifies the DN of the entry at which to start the search. + LDAP_SCOPE_BASE, // Specifies the scope of the search. + NULL, // Specifies a string representation of the filter to apply in the search. + (char **) &attrs, // Specifies a null-terminated array of character string attribute types to return from entries that match filter. + 0, // Should be set to 1 to request attribute types only. Set to 0 to request both attributes types and attribute values. + NULL, + NULL, + NULL, + 0, + &results + ); + + if(rc != LDAP_SUCCESS) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't search LDAP server" ); + message->description = ldap_err2string(rc); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + return NULL; + } + + char __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_LDAPPTR))) *attr = ldap_first_attribute(ld, results, &ber); + if(!attr) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't get LDAP attribute" ); + message->description = _("Search did not produce any attributes."); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + errno = ENOENT; + return NULL; + } + + struct berval ** value = ldap_get_values_len(ld, results, attr); + if(!value) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't get LDAP attribute" ); + message->description = _("Search did not produce any values."); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + errno = ENOENT; + return NULL; + } + + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + lib3270_trace_data( + hSession, + "CRL Data received from LDAP server", + (const unsigned char *) value[0]->bv_val, + value[0]->bv_len + ); + } + + // Precisa salvar uma cópia porque d2i_X509_CRL modifica o ponteiro. + const unsigned char *crl_data = (const unsigned char *) value[0]->bv_val; + + if(!d2i_X509_CRL(&x509_crl, &crl_data, value[0]->bv_len)) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Can't decode certificate revocation list" ); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->text); + ldap_value_free_len(value); + return NULL; + } + + ldap_value_free_len(value); + + return x509_crl; + +} + +#endif // HAVE_LIBSSL && SSL_ENABLE_CRL_CHECK && HAVE_LDAP diff --git a/src/ssl/macos/private.h b/src/ssl/macos/private.h new file mode 100644 index 0000000..e3096e7 --- /dev/null +++ b/src/ssl/macos/private.h @@ -0,0 +1,63 @@ +/* + * "Software G3270, 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 ', 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 private.h e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas de Mendonça) + * + */ + +#ifndef LIB3270_LINUX_SSL_PRIVATE_H_INCLUDED + + #define LIB3270_LINUX_SSL_PRIVATE_H_INCLUDED + + #include + + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + #ifdef HAVE_LDAP + + /// @brief Use libldap to get CRL. + LIB3270_INTERNAL X509_CRL * get_crl_using_ldap(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl); + + #endif // HAVE_LDAP + + #ifdef HAVE_LIBCURL + + /// @brief Use libcurl to get CRL. + LIB3270_INTERNAL X509_CRL * get_crl_using_url(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl); + + #endif // HAVE_LIBCURL + + +#endif // !LIB3270_LINUX_SSL_PRIVATE_H_INCLUDED diff --git a/src/ssl/macos/url.c b/src/ssl/macos/url.c new file mode 100644 index 0000000..18bfe54 --- /dev/null +++ b/src/ssl/macos/url.c @@ -0,0 +1,127 @@ +/* + * "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: + * + * http://www.openssl.org/docs/ssl/ + * https://stackoverflow.com/questions/4389954/does-openssl-automatically-handle-crls-certificate-revocation-lists-now + * + */ + +#include + +#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LIBCURL) + +#include "private.h" +#include +#include + +#define CRL_DATA_LENGTH 2048 + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static inline void lib3270_autoptr_cleanup_BIO(BIO **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + BIO_free_all(*ptr); + *ptr = NULL; +} + +LIB3270_INTERNAL X509_CRL * get_crl_using_url(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) +{ + X509_CRL * x509_crl = NULL; + + size_t szText = 0; + lib3270_autoptr(char) httpText = lib3270_get_from_url(hSession, consturl, &szText, &message->description); + + if(!httpText) + { + message->title = _( "Security error" ); + message->text = _( "Error getting certificate revocation list" ); + return NULL; + } + + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + lib3270_trace_data(hSession,"CRL Data",(const unsigned char *) httpText, (unsigned int) szText); + + if(strncasecmp(consturl,"ldap://",7) == 0) + { + // It's an LDAP query, assumes a base64 data. + char * data = strstr((char *) httpText,":: "); + if(!data) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Got a bad formatted certificate revocation list from LDAP server" ); + lib3270_write_log(hSession,"ssl","%s: invalid format:\n%s\n", consturl, httpText); + errno = EINVAL; + return NULL; + } + data += 3; + + lib3270_autoptr(BIO) bio = BIO_new_mem_buf(httpText,-1); + + BIO * b64 = BIO_new(BIO_f_base64()); + bio = BIO_push(b64, bio); + + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + + if(!d2i_X509_CRL_bio(bio, &x509_crl)) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Can't decode certificate revocation list got from LDAP server" ); + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); + errno = EINVAL; + return NULL; + } + + } + else + { + // CRL File, convert it + // 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, szText)) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Can't decode certificate revocation list" ); + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); + return NULL; + } + + } + + return x509_crl; + +} + +#endif // HAVE_LIBSSL && SSL_ENABLE_CRL_CHECK && HAVE_LIBCURL -- libgit2 0.21.2