Wednesday, April 16, 2014

Is a strong caution about Heartbleed worth the disruption to distributions with a declared dependency on Crypt::SSLeay?

As I noted previously, distributions with a declared dependency on Crypt::SSLeay may not really need Crypt::SSLeay.

Heartbleed is a serious bug in OpenSSL that allows one side of a "secure" connection to read the memory of the process running on the other side of the connection. While the initial attention focused on clients being able to read confidential data from server processes, clients are also vulnerable.

In a nutshell, you might think your little robot is taking too long fetching stock quotes from remote, but it might just be sucking your memory in 64Kb blocks at a time (yes, there are some details I am glossing over). Host verification may not help you feel secure because, among other reasons, 1) Someone might actually have obtained the certificate for the server via previous attacks on that and might have tricked you into connecting to their server; 2) The server might have been taken over by a hostile party; and 3) The remote might have been legitimately using a self-signed certificate in the past, and you have disabled host verification.

Which means connecting to a remote with a vulnerable client is not safe.

I recently added a test to Crypt::SSLeay 0.65_13 to check for the version of the OpenSSL library it uses which required adding a litte XS to SSLeay.xs. This test fails if the OpenSSL library in use is a version that was revealed to be vulnerable to the Heartbleed bug.

As of 0.65_12, the only failures were coming from machines where IO::Socket::INET was automatically overridden by IO::Socket::IP.

For 0.65_13 version, the current failure rate on CPANTesters is about 75%.

If I leave this test in for the next release, systems with a vulnerable OpenSSL will not be able to automatically update. They will have to force install Crypt::SSLeay.

Now, they may not really need Crypt::SSLeay. LWP might be using IO::Socket::SSL under the covers, but either way, they are depending on OpenSSL to provide a secure communications channel. So, moving to a version of OpenSSL that is not vulnerable would be useful even if Crypt::SSLeay is a superfluous dependency.

Is it worth causing this kind of disruption by having make test for Crypt::SSLeay fail if it was built against a vulnerable OpenSSL?

Does your code really depend on Crypt::SSLeay?

I added the following section to the development version of Crypt::SSLeay:

Starting with version 6.02 of LWP, https support was unbundled into LWP::Protocol::https. This module specifies as one of its prerequisites IO::Socket::SSL which is automatically used by LWP::UserAgent unless this preference is overridden separately. IO::Socket::SSL is a more complete implementation, and, crucially, it allows hostname verification. Crypt::SSLeay does not support this. At this point, Crypt::SSLeay is maintained to support existing software that already depends on it.

However, it is possible that your software does not really depend on Crypt::SSLeay, only on the ability of LWP::UserAgent class to communicate with sites over SSL/TLS.

If are using version LWP 6.02 or later, and therefore have installed LWP::Protocol::https and its dependencies, and do not explicitly use Net::SSL before loading LWP::UserAgent, or override the default socket class, you are probably using IO::Socket::SSL and do not really need Crypt::SSLeay

If you have both Crypt::SSLeay and IO::Socket::SSL installed, and would like to force LWP::UserAgent to use Crypt::SSLeay, you can use:

use Net::HTTPS;
use LWP::UserAgent;


use LWP::UserAgent;


use Net::SSL;
use LWP::UserAgent;

For example, metacpan tells me Finance::Quote has a declared dependency on Crypt::SSLeay. But, when I look at the source, I see:

my $ua;
    $ua = Finance::Quote::UserAgent->new;
  } else {
    $ua = LWP::UserAgent->new;

The other dependencies it declares are:

 "LWP::UserAgent" => 0,
    "Mozilla::CA" => 0,

That means, installing this module would pull in the latest LWP. Given that Crypt::SSLeay depends on LWP::Protocol::https, and that pulls in IO::Socket::SSL.

Since Finance::Quote does not seem to explicitly override the choice of plumbing, unless a user of the module set the environment variable PERL_NET_HTTPS_SSL_SOCKET_CLASS to Net::SSL.

See what I mean?

In conclusion, it is entirely possible that your code has been running without actually using Crypt::SSLeay for the past few years. Given the advantages of IO::Socket::SSL over Crypt::SSLeay, it is probably a good idea to ask yourself whether you really need to declare a dependency on Crypt::SSLeay.

Maybe all you need is a dependency on LWP::Protocol::https.

The updates I make to Crypt::SSLeay are mostly limited to build processes etc. They are not very frequent. The places that really depend on Crypt::SSLeay tend to have in place much older ecosystems. It is hard to diagnose problems in those environments if I break something. On the other hand, in more modern environments, your code that uses LWP::UserAgent to communicate over HTTPS is probably not touching anything within Crypt::SSLeay.

So, maybe it's time to remove that declared dependency in your Makefile.PL.

Monday, April 14, 2014

Why does Crypt::SSLeay fail to build under Strawberry Perl?

After a comment on my blog attracted my attention to some interesting failures when trying to build Crypt::SSLeay with Strawberry Perl, I was perplexed.

I don't really use Strawberry. I have always used either ActivePerl, or built my own perl, depending on my taste for experimentation. So, I went over to Strawberry Perl's web site, and downloaded their latest portable 64-bit distribution, unzipped, and tried to install Crypt::SSLeay.

And, I got a similar failure at link stage:

dlltool --def SSLeay.def --output-exp dll.exp
g++.exe -o blib\arch\auto\Crypt\SSLeay\SSLeay.dll -Wl,
    --base-file -Wl,dll.base -
mdll -s -L"C:\…\strawberry\perl\lib\CORE"
    -L"C:\…\strawberry\c\lib" SSLeay.o
 undefined reference to `X509_get_issuer_name'
 undefined reference to `X509_NAME_oneline'
 undefined reference to `CRYPTO_free'
 undefined reference to `X509_get_subject_name'
 undefined reference to `X509_NAME_oneline'
 undefined reference to `CRYPTO_free'
 undefined reference to `X509_free'
 undefined reference to `d2i_PKCS12_fp'
 undefined reference to `PKCS12_parse'
: undefined reference to `EVP_PKEY_free'
 undefined reference to `X509_free'
 undefined reference to `PKCS12_free'
 undefined reference to `RAND_load_file'
 undefined reference to `OPENSSL_add_all_algorithms_noconf'
 undefined reference to `ERR_load_crypto_strings'
 undefined reference to `RAND_seed'
 undefined reference to `ERR_get_error'
 undefined reference to `ERR_get_error'
 undefined reference to `ERR_error_string'


So, the libraries we want to link to are there, but …

I mean, at this point, I am actually using Devel::CheckLib to check if compiling programs against the requested libraries succeeds, so I know the libraries are there. Why is linking failing?

I mean, look at this:

C:\…\strawberry\c\lib> strings libeay32.a 
   | perl -ne "print if /X509_NAME_oneline/"

So, at least superficially, it looks like everything is there. Why the failures?

Also, it turns out the January 2014 release of Strawberry Perl (/w perl 5.18) comes with OpenSSL 1.0.1e. Is there a better excuse to build OpenSSL from scratch?

But, that would require putting together a whole MinGW environment.

Of course, don't use outdated versions of OpenSSL. But, the solution to the linking problem was much simpler. The candidate library list I am using was ssl crypto ssl32 ssleay32 libeay32 z. Well, using GCC, libeay32.a would be linked by specifying -leay32. If you use -llibeay32, the linker will look for liblibeay32.a.

Therefore, changing that list of libraries to ssl crypto ssl32 ssleay32 eay32 z works for Strawberry. It does, however, fail when I try it using Windows SDK 7.1 build environment. Therefore, the new list of candidate libraries is ssl crypto ssl32 ssleay32 eay32 libeay32 z. I'll push the change to CPAN and GitHub.

Thursday, April 10, 2014

Building OpenSSL 1.0.1g on 64-bit Windows Pro 8.1 with Windows SDK 7.1

This, actually, turned out to be surprisingly straightforward.

I admit, nothing is really straightforward when it comes to OpenSSL, but as such things go, this simply involved:

  1. Download the latest source distribution
  2. Open up a SDK command prompt
  3. Optionally, get zlib, build DLL
  4. Get nasm and build executable
  5. If you did ask for zlib, add directories to INCLUDE and LIB:

    C:\…\openssl-1.0.1g> set INCLUDE=%INCLUDE%;C:\…\zlib-1.2.8
    C:\…\openssl-1.0.1g> set LIB=%LIB%;C:\…\zlib-1.2.8
  6. Run C:\…\openssl-1.0.1g> perl Configure VC-WIN64A zlib-dynamic --openssldir=C:\opt\OpenSSL
  7. Run C:\…\openssl-1.0.1g> ms\do_win64a
  8. Run C:\…\openssl-1.0.1g> nmake -f ms\ntdll.mak
  9. Wait … well, at least on my machine ;-)
  10. cd to out32dll, and run ..\ms\test
  11. Make sure all tests pass:

  12. Install by doing:

    C:\…\openssl-1.0.1g\out32dll> cd ..
    C:\…\openssl-1.0.1g> nmake -f ms\ntdll.mak install

Now, if you want to compile and link against OpenSSL, you will need to make sure C:\opt\OpenSSL\include and C:\opt\OpenSSL\lib are added to the INCLUDE and LIB paths, respectively. To run code linked against this OpenSSL build, you will also need to make sure programs built against it can located the DLLs. I put the files from both in a common location, say, C:\opt\bin which is then added to my %PATH%.

I want that extra bit of protection for C:\opt\bin, so it is only writable by an admin user. So, fire up an admin command window, and do:

C:\…> xcopy C:\opt\OpenSSL\bin\* C:\opt\bin
 3 File(s) copied


C:\…> xcopy \users\sinan\src\zlib-1.2.8\zlib1.dll c:\opt\bin

How can we test this actually worked?

Well, let's try building Crypt::SSLeay:

C:\…\src> git clone

C:\…\src> cd Crypt-SSLeay

C:\…\Crypt-SSLeay> perl Makefile.PL --libpath=C:\opt\OpenSSL\lib --incpath=C:\opt\OpenSSL\include --live-tests --no-verbose

C:\…\Crypt-SSLeay> nmake test

which should yield:

t/00-basic.t .... ok
t/01-connect.t .. ok
t/02-live.t ..... # Reading configuration from 'test.config' on MSWin32
# network_tests : 1
t/02-live.t ..... 5/? # [RT #73755] Cheat by disabling LWP::UserAgent host verification
t/02-live.t ..... ok
All tests successful.
Files=3, Tests=29,  6 wallclock secs ( 0.06 usr +  0.02 sys =  0.08 CPU)
Result: PASS

Now, do an nmake install. Then, switch to a new, non-SDK command window to make sure that things work outside of the development environment as well. Try running the following script:

use strict;
use warnings;
use Test::More;

# Make sure LWP uses Crypt::SSLeay, not IO::Socket::SSL
# IO::Socket::SSL is better, but this is testing Crypt::SSLeay
use Net::HTTPS;

use HTTP::Request;
use LWP::UserAgent;

my $method = 'HEAD';
my $uri = '';

my $ua = LWP::UserAgent->new(
    ssl_opts => { verify_hostname => 0 },

my $req = HTTP::Request->new;


my $test_name = "$method '$uri'";

my $res = $ua->request($req);

if ($res->is_success) {
    my $socket_class = $res->header('Client-SSL-Socket-Class');
    # Make sure *WE* succeded ;-)
    if ( isa_ok($socket_class, 'Net::SSL') ) {
        pass $test_name;
    else {
        fail $test_name;
        diag "Request succeded but UA used '$socket_class'";
else {
    fail $test_name;
    diag "HTTP status = ", $res->status_line ;


Which produces:

C:\…\Temp> perl
ok 1 - The class (or class-like) 'Net::SSL' isa 'Net::SSL'
ok 2 - HEAD ''

Keep in mind that IO::Socket::SSL is the better module. If you have upgraded to LWP 6.xx and also installed LWP::Protocol::https, your LWP::UserAgent object is very likely using IO::Socket::SSL. Only force the use of Crypt::SSLeay if you have a specific need.

Tuesday, April 8, 2014

Building and Installing gVim on Windows 8.1 Pro

Vim (most often gVim, but I am fine in the terminal as well) is the only editor that I am really used to using. So, when I installed Windows 8.1 on my trusty old laptop, I immediately wanted to build a brand spanking new 64-bit version (yeah, and this thing can't deal with 2x2GB properly, but why not?) with all the latest patches. That means, building from source. When I had XP SP3 on this thing, I had set up nice little environments for building every little thing I liked to build from source. On this new OS which really, desperately wants to run on a phone, I did not know how things were going to work (I have heard that things were even worse with 8.0).

After a few false starts (such as trying to do this with Visual Studio 2013 Express Edition for Windows Desktop), I realized the right tool to use is the Windows SDK 7.1.

I installed TortoiseHG and cloned the source:

I realize, green just is not my color … I seriously miss the way you could customize the GUI in XP. But, I digress …

Vim comes with a makefile, Make_mvc.mak for Microsoft's compiler. I noticed the cl that came with SDK 7.1 supported an optimization option called /favor:INTEL64, so I added that to the OPTFLAG variable right around line 481 and entered:

C:\…\vim\src> nmake -f Make_mvc.mak OPTIMIZE=SPACE CPU=AMD64 NETBANS=no GETTEXT=no GUI=yes

And, within about 30 seconds, the executable was built.

What now?

The file INSTALLpc.txt has a lot of information, and tells you what you need to do next, in section 10, at the end of the file:

C:\…\vim\src> mkdir c:\opt\vim\vim74

C:\…\vim\src> copy *.exe c:\opt\vim\vim74
        4 file(s) copied.

C:\…\vim\src> copy GvimExt\gvimext.dll c:\opt\vim\vim74
        1 file(s) copied.

C:\…\vim\src> copy xxd\xxd.exe c:\opt\vim\vim74
        1 file(s) copied.

C:\…\vim\src> xcopy ..\runtime\* c:\opt\vim\vim74 /e

Then I changed my directory to c:\opt\vim\vim74, and typed install. You get a funky text based menu where you enter item numbers to select and toggle options. I think this is what they call old school, but then I grew up with it, but I admit it might be daunting at first:

Originally, I had made a mistake, and staged the vim74 directory in %temp%. I promptly realized I had made a mistake: I needed those files in a better place, not in my %temp%. I moved the vim74 directory to c:\opt\vim\vim74, and typed install again.

I really don't want those batch files. So, I typed the digit 1 and pressed enter. The program listed a bunch of directories in my %path% giving me the option to create batch files in one of those directories. The last option, in my case 12, was not to create any batch files, and that's the one I went with.

I am also trying to be a disciplined Vim user, so I disabled the mapping of CTRL-C, CTRL-V … etc in the default _vimrc to be created. Of course, I had saved my trusted _vimrc, and that's going in my %userprofile% directory.

Finally, I disabled the creation of various icons on the desktop:

Finally, type d, press Enter, and there you have your "Edit with Vim" context-menu entry.

Hope this helps!

PS: If you also want vim.exe for console use, do an nmake -f Make_mvc.mak … GUI=yes clean and then repeat the nmake command without GUI=yes. You can simply copy the resulting vim.exe alongside gvim.exe.

Link with the 64-bit libraries, Luke!

I had some trouble building perl 5.18.2 after upgrading to Windows 8.1 Pro.

While the test failures seemed to be confined to Module::Build and ExtUtils::ParseXS, the fact that the failed tests involved XS and dynamic libraries meant I could not simply ignore them.

As my first step towards solving the issue, I removed everything related to Visual Studio Express 2013 from my system. I also uninstalled all SDKs other than the Windows 7.1 SDK which does come with a 64-bit command line build environment.

My first attempt at rebuilding resulted in exactly the same test failures.

The failures persisted after installing the distribution, and trying to build the modules from the command line.

Something was so borken that I was getting LNK 2001 errors for even TerminateProcess … I had initially focused on the more interesting __security_cookie, but that was a red herring.

Looking over the bundled win32\Makefile, I realized the problem (and therefore also the solution) was staring me right in the face. The original win32\Makefile has:

CCHOME          = $(MSVCDIR)
CCINCDIR        = $(CCHOME)\include
CCLIBDIR        = $(CCHOME)\lib

The SDK command prompt does not set %MSVCDIR%, so I had set that to C:\Program Files\Microsoft SDKs\Windows\v7.1.

Well, there is that small matter of linking with the correct libraries, which happen to be in the lib\x64 under that!

After changing those to:

CCHOME          = C:\Program Files\Microsoft SDKs\Windows\v7.1
CCINCDIR        = $(CCHOME)\include
CCLIBDIR        = $(CCHOME)\lib\x64

nmake test went without a hitch.

Then, just to make sure, I downloaded ExtUtils::ParseXS, and did a perl Makefile.PL, nmake test, with the following results:

Microsoft (R) Program Maintenance Utility Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

cp lib/ExtUtils/ParseXS/ blib\lib\ExtUtils\ParseXS\
cp lib/ExtUtils/ParseXS/ blib\lib\ExtUtils\ParseXS\
cp lib/ExtUtils/Typemaps/ blib\lib\ExtUtils\Typemaps\
cp lib/ExtUtils/Typemaps/ blib\lib\ExtUtils\Typemaps\
cp lib/ExtUtils/ParseXS.pod blib\lib\ExtUtils\ParseXS.pod
cp lib/ExtUtils/ blib\lib\ExtUtils\
cp lib/ExtUtils/ParseXS/ blib\lib\ExtUtils\ParseXS\
cp lib/ExtUtils/Typemaps/ blib\lib\ExtUtils\Typemaps\
cp lib/ExtUtils/ParseXS/ blib\lib\ExtUtils\ParseXS\
cp lib/ExtUtils/xsubpp blib\lib\ExtUtils\xsubpp
cp lib/ExtUtils/Typemaps/ blib\lib\ExtUtils\Typemaps\
cp lib/ExtUtils/ blib\lib\ExtUtils\
        C:\opt\perl-5.18.2\bin\perl.exe -MExtUtils::Command -e cp -- lib/ExtUtil
s/xsubpp blib\script\xsubpp
        pl2bat.bat blib\script\xsubpp
        C:\opt\perl-5.18.2\bin\perl.exe "-MExtUtils::Command::MM" "-e" "test_har
ness(0, 'blib\lib', 'blib\arch')" t/*.t
t/001-basic.t ............................ ok
t/002-more.t ............................. ok
t/003-usage.t ............................ ok
t/101-standard_typemap_locations.t ....... ok
t/102-trim_whitespace.t .................. ok
t/103-tidy_type.t ........................ ok
t/104-map_type.t ......................... ok
t/105-valid_proto_string.t ............... ok
t/106-process_typemaps.t ................. ok
t/108-map_type.t ......................... ok
t/109-standard_XS_defs.t ................. ok
t/110-assign_func_args.t ................. ok
t/111-analyze_preprocessor_statements.t .. ok
t/112-set_cond.t ......................... ok
t/113-check_cond_preproc_statements.t .... ok
t/114-blurt_death_Warn.t ................. ok
t/115-avoid-noise.t ...................... ok
t/501-t-compile.t ........................ ok
t/510-t-bare.t ........................... ok
t/511-t-whitespace.t ..................... ok
t/512-t-file.t ........................... ok
t/513-t-merge.t .......................... ok
t/514-t-embed.t .......................... ok
t/515-t-cmd.t ............................ ok
t/516-t-clone.t .......................... ok
t/517-t-targetable.t ..................... ok
t/600-t-compat.t ......................... ok
All tests successful.
Files=27, Tests=265, 10 wallclock secs ( 0.19 usr +  0.14 sys =  0.33 CPU)
Result: PASS

PS: FYI, I used CCTYPE = MSVC100 with this SDK.

Monday, April 7, 2014

Why did Extutils::ParseXS fail tests after building perl on Windows 8.1?

After installing Windows 8.1, the first thing I wanted to build was Gvim. I am not a Vim expert by any means, but it is the only editor that makes me feel "at home" on multiple systems. When I was using Windows XP, building Gvim using MSVC 2010 Express had been a breeze, so, without much thinking or research, I figured installing MS Visual Studio 2013 Express for Windows Desktop applications would be the way to go. It turned out it wasn't. Instead, I had to download the SDK for Windows 7 to build Gvim.

But, when that worked, including the installation of the shell extension, I was emboldened to build perl. Seemed straightforward enough as it was something I had done before. Lo and behold, everything seemed to go OK, but a bunch of tests for Module::Build and ExtUtils::ParseXS failed. The failures in Module::Build tests were also related to XS.

Hmmmmm …

The good news is I don't think there is anything wrong with Extutils::ParseXS.

A little manual playing around revealed that creating a dynamic library was failing. And, while the error messages were those shown in this Microsoft Knowledgebase article, the build environment is not the same, and in fact, there doesn't seem to be a bufferoverflowU.lib file under the Windows 7 SDK tree. Where is one under the Windows 8 SDK, but that one does not actually provide a command line environment and you have to use the VS 2013 Express tools which had failed me earlier.

The problem could be in the tools I used. Or, it might be related to how Extutils::CBuilder works with those tools.

I think a little bit of environmental cleanup is in order before I try this from scratch again.

PS: Or, I could just use Strawberry Perl, but my goals do not just consist of "install a perl and go" at this point ;-)