Things break on Debian Wheezy with libssl-dev 1.0.1e-2+deb7u12 on 32bit.
Running the example in IO::Socket::SSL, which relies on this library the following behavior can be observed:
In the perl6-m REPL:
$ perl6
> use IO::Socket::SSL
> my $sock = IO::Socket::SSL.new(:host<google.com>, :port(443))
IO::Socket::SSL.new(encoding => "utf8", host => "google.com", port => 443, localhost => Str, localport => Int, certfile => Str, listen => Bool, input-line-separator => "\n", ins => 0, fd => 10, ssl => OpenSSL.new(ctx => SSL_CTX.new(method => SSL_METHOD.new(version => 769)), ssl => SSL.new(version => 769, type => 4096, method => SSL_METHOD.new(version => 769), rbio => BIO.new(method => BIO_METHOD.new(type => 1285, name => "socket"), cb_arg => Str, init => 0, shutdown => 1, flags => 0, retry_reason => 0, num => 0, ptr => OpaquePointer.new(10), next_bio => BIO, prev_bio => BIO, references => 0, num_read => 19181323943937, num_write => 353), wbio => BIO.new(method => BIO_METHOD.new(type => 1285, name => "socket"), cb_arg => Str, init => 0, shutdown => 1, flags => 0, retry_reason => 0, num => 0, ptr => OpaquePointer.new(10), next_bio => BIO, prev_bio => BIO, references => 0, num_read => 19181323943937, num_write => 353), bbio => BIO, rwstate => 1, in_handshake => 0, handshake_func => OpaquePointer.new(-1279529744), server => 0, new_session => 0, quiet_shutdown => 0, shutdown => 0, state => 3, rstate => 240), client => Bool::True))
> my $othersock = IO::Socket::SSL.new(:host<github.com>, :port(443))
Segmentation fault
$ perl6 --version
This is perl6 version 2014.07-157-g42dfe38 built on MoarVM version 2014.07-365-g29d2e7b
Run from a script:
$ cat github.pl6
use v6;
use IO::Socket::SSL;
my $ssl = IO::Socket::SSL.new(:host<github.com>, :port(443));
my $content = Buf.new;
$ssl.send("GET /\r\n\r\n");
while my $read = $ssl.recv {
$content ~= $read;
}
say $content;
psch@debvm:~/rakudo$ perl6 github.pl6
Buf:0x<>
psch@debvm:~/rakudo$ perl6 --version
This is perl6 version 2014.07-157-g42dfe38 built on MoarVM version 2014.07-365-g29d2e7b
I have added a very basic binding for liberr to try and see if there's an underlying library error that causes this, which I will open a PR for. With that patch, the string error message came out as follows:
error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac
This pointed me towards this debian bug, which in turns points to this bug in libssl. Further searching revealed this more current debian bug, which seems to indicate this is an issue upstream.
I consider it northworthy that the command to verify the behavior on the openssl ticket above works fine and disabling AES-NI as mentioned in the discussion on the openssl ticket did not have any effect.
PR #2 on this repository and this one for IO::Socket::SSL contain the code I used to obtain the error string.
Two corrections:
- It's not Debian Wheezy I'm failing on, but Debian Jessie.
- Thus, the libssl version is not 1.0.1e but a later one. I just now updated libssl to 1.0.1i and verified that the issue still exists.
Does this still exist?
I think you forgot to call .read( :bin ) since you are putting it into Buf $content and not Str $content;
# .read()
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -MIO::Socket::SSL -e 'use v6; my $ssl = IO::Socket::SSL.new(:host<github.com>, :port(443)); my $content = Buf.new; $ssl.send("GET /\r\n\r\n"); while my $read = $ssl.recv { $content ~= $read; }; say $content;'
Cannot use a Buf as a string, but you called the Stringy method on it
in method Stringy at src/gen/m-CORE.setting:6315
in sub infix:<~> at src/gen/m-CORE.setting:1561
in block <unit> at -e:1
# .read( :bin )
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -MIO::Socket::SSL -e 'use v6; my $ssl = IO::Socket::SSL.new(:host<github.com>, :port(443)); my $content = Buf.new; $ssl.send("GET /\r\n\r\n"); while my $read = $ssl.recv(:bin) { $content ~= $read; }; say $content;'
Buf:0x<48 54 54 50 2f 31 2e 31 20 33 30 31 20 4d 6f 76 65 64 20 50 65 72 6d 61 6e 65 6e 74 6c 79 0d 0a 43 6f 6e 74 65 6e 74 2d 6c 65 6e 67 74 68 3a 20 30 0d 0a 4c 6f 63 61 74 69 6f 6e 3a 20 68 74 74 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 63 6c 6f 73 65 0d 0a 0d 0a>
# .read.recv.perl
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -MIO::Socket::SSL -e 'use v6; my $ssl = IO::Socket::SSL.new(:host<github.com>, :port(443)); my $content = Buf.new; $ssl.send("GET /\r\n\r\n"); say $ssl.recv.perl'
"HTTP/1.1 301 Moved Permanently\r\nContent-length: 0\r\nLocation: https://github.com/\r\nConnection: close\r\n\r\n"
So from the 3rd example i'd guess this has to do with SSL forwarding in IO::Socket::SSL closing the socket, although that may be caused by the recent PR that uses IO::Socket::INET since that HTTP message should only be occuring when going to 'http://github.com' not 'https://github.com'
Calling .gist/.perl on the IO::Socket::SSL object also causes a segfault, which is why your REPL example segfaults:
# REPL, (segfaults)
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -MIO::Socket::SSL
> my $sock = IO::Socket::SSL.new(:host<google.com>, :port(443));
Segmentation fault
# -e, but call .perl method (segfaults)
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -MIO::Socket::SSL -e 'my $sock = IO::Socket::SSL.new(:host<google.com>, :port(443)); say $sock.perl'
Segmentation fault
# -e, just init the socket (ok)
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -MIO::Socket::SSL -e 'my $sock = IO::Socket::SSL.new(:host<google.com>, :port(443));'
# -e, list methods (ok)
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -MIO::Socket::SSL -e 'my $sock = IO::Socket::SSL.new(:host<google.com>, :port(443)); say $sock.^methods'
new recv send write get accept close <anon> <anon> <anon> <anon> <anon> <anon> <anon> <anon> <anon> <anon> <anon> <anon> <anon>
# since .perl causes the segfault, we can (correctly) guess that the `say $content`
# or the REPL trying to show the results of my $sock = IO::Socket::SSL.new( ... )
# from the original example caused a segfault when say forces .perl/.gist
# method call on IO::Socket::SSL
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -MIO::Socket::SSL -e 'my $sock = IO::Socket::SSL.new(:host<google.com>, :port(443)); say $sock;'
Segmentation fault
So I would guess that we need to add a .perl and .gist method
Here is my system info:
nickl@localhost:~/perl6/Perl6-Code--Walker$ openssl version -a
OpenSSL 1.0.1k 8 Jan 2015
built on: Thu Jan 8 19:58:08 2015
platform: debian-amd64
options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)
compiler: -I. -I.. -I../include -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -DTERMIO -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -Wl,-z,relro -Wa,--noexecstack -Wall -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM
OPENSSLDIR: "/usr/lib/ssl"
nickl@localhost:~/perl6/Perl6-Code--Walker$ cat /etc/*-release
PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
NAME="Debian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"
ID=debian
HOME_URL="http://www.debian.org/"
SUPPORT_URL="http://www.debian.org/support/"
BUG_REPORT_URL="https://bugs.debian.org/"
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -v
This is perl6 version 2015.01-67-g756a4ac built on MoarVM version 2015.01-22-g5cda8dc
nickl@localhost:~/perl6/Perl6-Code--Walker$ perl6 -MIO::Socket::SSL -e 'my $ssl = IO::Socket::SSL.new(:host<github.com>, :port(443)); my $content = Buf.new; $ssl.send("GET /\r\n\r\n"); while my $read = $ssl.recv( :bin) { $content ~= $read; }; say $content;'
Buf:0x<48 54 54 50 2f 31 2e 31 20 33 30 31 20 4d 6f 76 65 64 20 50 65 72 6d 61 6e 65 6e 74 6c 79 0d 0a 43 6f 6e 74 65 6e 74 2d 6c 65 6e 67 74 68 3a 20 30 0d 0a 4c 6f 63 61 74 69 6f 6e 3a 20 68 74 74 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 63 6c 6f 73 65 0d 0a 0d 0a>
nickl@localhost:~/perl6/io-socket-ssl$ perl6 -v
This is perl6 version 2015.01-67-g756a4ac built on MoarVM version 2015.01-22-g5cda8dc
I suspect the issue still exists on 32bit systems, considering there's still a problem with int sizes in NativeCall. On the other hand, ugexe's code demonstrates working behavior, so I suppose testing again on 32bit should be the next step. I don't have a 32bit VM available currently, though, but I'll try to set one up in the near future (unless someone beats me to it. :) )
The 32bit issues have fixed in NativeCall... So one would have to use int32 in P6 when C talks about int, and long when C talks about long.
I can reproduce on 64 bit/FreeBSD 10 and Debian Jessie and Wheezy.
Details for FreeBSD follow $ uname -a FreeBSD burpy.pl6anet.org 10.1-RELEASE-p10 FreeBSD 10.1-RELEASE-p10 #0: Wed May 13 06:54:13 UTC 2015 [email protected]:/usr/obj/usr/src/sys/GENERIC amd64
$ openssl version -a OpenSSL 1.0.1l-freebsd 15 Jan 2015 built on: date not available platform: FreeBSD-amd64 options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) idea(int) blowfish(idx) compiler: clang OPENSSLDIR: "/etc/ssl"
$ perl6 -v This is perl6 version 2015.05-80-g2cc3afe built on MoarVM version 2015.05
$ perl6
use IO::Socket::SSL my $sock = IO::Socket::SSL.new(:host<p6weekly.wordpress.com>, :port(443)) err code: 336130329 error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac
It looks like you are using the REPL, which is known to cause this problem regardless of OS as noted above
Oops I missed that.
But can confirm it also errors inside a script
steve@burpy:~/pl6anet $ cat test.pl use IO::Socket::SSL; my $sock = IO::Socket::SSL.new(:host<p6weekly.wordpress.com>, :port(443));
$ perl6 test.pl err code: 336130329 error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac
FWIW :host must be a string (although I don't think that will fix the issue)
:host should be visible now (I forgot to manually rewrite the angle brackets as html entities!)