From 88311f50312f97115cd85e31abc9adb68098a704 Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Tue, 29 Jan 2019 10:39:48 -0200 Subject: [PATCH] Adding "quick and dirty" workaround for possible bug in libcurl for windows. --- .gitignore | 3 ++- src/lib3270/ssl/linux/getcrl.c | 100 ++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------- src/lib3270/ssl/windows/getcrl.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- src/lib3270/testprogram/testprogram.c | 21 ++++++++++++++++++++- src/lib3270/trace_ds.c | 9 +++++---- 5 files changed, 140 insertions(+), 77 deletions(-) diff --git a/.gitignore b/.gitignore index 5883eec..c065e67 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,8 @@ versions ChangeLog* Makefile aclocal.m4 -configure +configure* +*.trace autom4te.cache makegtkruntime.sh copydeps.sh diff --git a/src/lib3270/ssl/linux/getcrl.c b/src/lib3270/ssl/linux/getcrl.c index 6202797..a18063d 100644 --- a/src/lib3270/ssl/linux/getcrl.c +++ b/src/lib3270/ssl/linux/getcrl.c @@ -252,71 +252,40 @@ X509_CRL * lib3270_get_X509_CRL(H3270 *hSession, SSL_ERROR_MESSAGE * message) } #ifdef HAVE_LDAP - else if(strncasecmp(consturl,"ldap",4) == 0) + else if(strncasecmp(consturl,"ldap://",7) == 0 && strlen(consturl) > 8) { int rc; lib3270_autoptr(char) url = strdup(consturl); - + char * base = strchr(url+7,'/'); char * attrs[] = { NULL, NULL }; - char * base = NULL; - const struct _args + if(!base) { - const char * name; - char ** value; + message->error = hSession->ssl.error = 0; + message->title = N_( "Security error" ); + message->text = N_( "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" ); + return NULL; } - args[] = - { - { "attr", &attrs[0] }, - { "base", &base } - }; - - // Get arguments - size_t arg; - char * ptr = strchr(url,'?'); - while(ptr) - { - *(ptr++) = 0; - char *value = strchr(ptr,'='); - if(!value) - { - message->error = hSession->ssl.error = 0; - message->title = N_( "Security error" ); - message->text = N_( "Invalid argument format" ); - message->description = "The URL argument should be in the format name=value"; - return NULL; - } - - *(value++) = 0; - - debug("%s=%s",ptr,value); - for(arg = 0; arg < (sizeof(args)/sizeof(args[0])); arg++) - { - if(!strcasecmp(ptr,args[arg].name)) - { - *args[arg].value = value; - debug("%s=\"%s\"",args[arg].name,*args[arg].value); - } - } - - ptr = strchr(value,'&'); - } + *(base++) = 0; + attrs[0] = strchr(base,'?'); - // Do we get all the required arguments? - for(arg = 0; arg < (sizeof(args)/sizeof(args[0])); arg++) + if(!base) { - if(!*args[arg].value) - { - message->error = hSession->ssl.error = 0; - message->title = N_( "Security error" ); - message->text = N_( "Can't set LDAP query" ); - message->description = N_("Insuficient arguments"); - lib3270_write_log(hSession,"ssl","%s: Required argument \"%s\" is missing",url, args[arg].name); - return NULL; - } + message->error = hSession->ssl.error = 0; + message->title = N_( "Security error" ); + message->text = N_( "No LDAP attribute on the URL" ); + message->description = _( "The URL argument should be in the format ldap://[HOST]/[DN]?attribute" ); + 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; @@ -401,6 +370,16 @@ X509_CRL * lib3270_get_X509_CRL(H3270 *hSession, SSL_ERROR_MESSAGE * message) return NULL; } + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + lib3270_trace_data( + hSession, + "CRL Data received from LDAP server", + (const 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; @@ -485,7 +464,18 @@ X509_CRL * lib3270_get_X509_CRL(H3270 *hSession, SSL_ERROR_MESSAGE * message) return NULL; } - debug("content-type: %s",ct); + /* + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + lib3270_autoptr(char) msg = lib3270_strdup_printf("CRL Data received with content-type \"%s\"", (ct ? ct : "undefined")); + lib3270_trace_data( + hSession, + msg, + (const char *) crl_data->contents, + crl_data->length + ); + } + */ if(ct) { @@ -526,8 +516,6 @@ X509_CRL * lib3270_get_X509_CRL(H3270 *hSession, SSL_ERROR_MESSAGE * message) } data += 3; - debug("\n%s\nlength=%u",data,(unsigned int) strlen(data)); - lib3270_autoptr(BIO) bio = BIO_new_mem_buf(data,-1); BIO * b64 = BIO_new(BIO_f_base64()); diff --git a/src/lib3270/ssl/windows/getcrl.c b/src/lib3270/ssl/windows/getcrl.c index 70e2527..f61b8b6 100644 --- a/src/lib3270/ssl/windows/getcrl.c +++ b/src/lib3270/ssl/windows/getcrl.c @@ -292,6 +292,19 @@ X509_CRL * lib3270_get_X509_CRL(H3270 *hSession, SSL_ERROR_MESSAGE * message) return NULL; } + /* + if(lib3270_get_toggle(data->hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + lib3270_autoptr(msg) = lib3270_vsprintf("CRL Data received with content-type \"%s\"", (ct ? ct : "undefined")); + lib3270_trace_data( + data->hSession, + msg, + (const char *) crl_data->contents, + crl_data->length + ); + } + */ + if(ct) { const unsigned char * data = crl_data->contents; @@ -321,35 +334,76 @@ X509_CRL * lib3270_get_X509_CRL(H3270 *hSession, SSL_ERROR_MESSAGE * message) } else if(strncasecmp(consturl,"ldap://",7) == 0) { - // It's an LDAP query, assumes a base64 data. - trace_ssl(crl_data->hSession, "No mime-type, assuming LDAP/BASE64"); + // LDAP Query on curl for windows returns an unprocessed response instead of a base64 data. + char * attr = strchr(consturl,'?'); + if(!attr) + { + message->error = hSession->ssl.error = 0; + message->title = N_( "Security error" ); + message->text = N_( "No attribute in LDAP search URL" ); + return NULL; + } + + attr++; + + // + // There's something odd on libcurl for windows! For some reason it's not converting the LDAP response values to + // base64, because of this I've to extract the BER directly. + // + // This is an ugly solution, I know! + // + + lib3270_autoptr(char) text = lib3270_strdup_printf("No mime-type, extracting \"%s\" directly from LDAP response\n",attr); + trace_ssl(crl_data->hSession, text); + + lib3270_autoptr(char) key = lib3270_strdup_printf("%s: ",attr); + char *ptr = strstr((char *) crl_data->contents, key); + + debug("key=\"%s\" ptr=%p",key,ptr) - char * data = strstr((char *) crl_data->contents,":: "); - if(!data) + if(!ptr) { - message->error = hSession->ssl.error = ERR_get_error(); + message->error = hSession->ssl.error = 0; message->title = N_( "Security error" ); - message->text = N_( "Got an invalid CRL from LDAP server" ); + message->text = N_( "Can't find attribute in LDAP response" ); return NULL; } - data += 3; - debug("\n%s\nlength=%u",data,(unsigned int) strlen(data)); + ptr += strlen(key); + size_t length = crl_data->length - (ptr - ((char *) crl_data->contents)); + size_t ix; - lib3270_autoptr(BIO) bio = BIO_new_mem_buf(data,-1); + for(ix = 0; ix < (length-1); ix++) + { + if(ptr[ix] == '\n' && ptr[ix+1] == '\n') + break; + } - BIO * b64 = BIO_new(BIO_f_base64()); - bio = BIO_push(b64, bio); + debug("length=%u ix=%u", (unsigned int) length, (unsigned int) ix); - BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + if(ix >= length) + { + message->error = hSession->ssl.error = 0; + message->title = N_( "Security error" ); + message->text = N_( "Can't find attribute end in LDAP response" ); + return NULL; + } + + length = ix; + + lib3270_trace_data( + hSession, + "CRL Data received from LDAP server", + (const char *) ptr, + length + ); - if(!d2i_X509_CRL_bio(bio, &crl)) + if(!d2i_X509_CRL(&crl, (const unsigned char **) &ptr, length)) { message->error = hSession->ssl.error = ERR_get_error(); message->title = N_( "Security error" ); - message->text = N_( "Got an invalid CRL from server" ); + message->text = N_( "Can't get CRL from LDAP Search" ); lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); - return NULL; } } diff --git a/src/lib3270/testprogram/testprogram.c b/src/lib3270/testprogram/testprogram.c index 21ccef0..bba32a9 100644 --- a/src/lib3270/testprogram/testprogram.c +++ b/src/lib3270/testprogram/testprogram.c @@ -6,9 +6,22 @@ #include #include +#include #define MAX_ARGS 10 +const char *trace_file = "test.trace"; + +static void write_trace(H3270 *session, void *userdata, const char *fmt, va_list args) +{ + FILE *out = fopen(trace_file,"a"); + if(out) + { + vfprintf(out,fmt,args); + fclose(out); + } +} + int main(int argc, char *argv[]) { // #pragma GCC diagnostic push @@ -16,6 +29,7 @@ int main(int argc, char *argv[]) static struct option options[] = { { "crl", required_argument, 0, 'C' }, { "url", required_argument, 0, 'U' }, + { "tracefile", required_argument, 0, 't' }, { 0, 0, 0, 0} @@ -32,7 +46,7 @@ int main(int argc, char *argv[]) int long_index =0; int opt; - while((opt = getopt_long(argc, argv, "C:U:", options, &long_index )) != -1) { + while((opt = getopt_long(argc, argv, "C:U:t:", options, &long_index )) != -1) { switch(opt) { case 'U': lib3270_set_url(h,optarg); @@ -41,6 +55,11 @@ int main(int argc, char *argv[]) case 'C': lib3270_set_crl_url(h,optarg); break; + + case 't': + trace_file = optarg; + lib3270_set_trace_handler(h,write_trace,NULL); + break; } } diff --git a/src/lib3270/trace_ds.c b/src/lib3270/trace_ds.c index f70f949..f1840ad 100644 --- a/src/lib3270/trace_ds.c +++ b/src/lib3270/trace_ds.c @@ -31,9 +31,8 @@ */ -/* - * trace_ds.c - * 3270 data stream tracing. +/** + * @brief 3270 data stream tracing. * */ @@ -193,7 +192,9 @@ void trace_ssl(H3270 *session, const char *fmt, ...) } -/* Write to the trace file. */ +/** + * @brief Write to the trace file. + */ static void wtrace(H3270 *session, const char *fmt, ...) { va_list args; -- libgit2 0.21.2