Imported Upstream version 1.052
Dominic Hargreaves
10 years ago
0 | 1.052 2014/01/16 | |
1 | - FTPS: reuse same SSL session for control and data channnel to work | |
2 | with default configuration of proftpd. | |
3 | ||
4 | 1.051 2014/01/10 | |
5 | - fixes to Net::FTP SSL support | |
6 | - examples/ftps-tests.pl has lots of tests for FTP against live server | |
7 | ||
8 | 1.05 2014/01/09 | |
9 | - added support for SSL+IPv6 in Net::FTP | |
10 | - new package Net::SSLGlue::Socket for a socket which combines plain,ssl,ipv6 | |
11 | - fixed some tests - some checks for bad certificates do not work anymore | |
12 | because these certs were fixed | |
13 | ||
0 | 14 | 1.04 2013/08/01 |
1 | 15 | replace Net::Cmd::getline via Net::SSLGlue::POP3 because it assumed, that it |
2 | 16 | just needs to wait for read events on the sockets - which is not the case for |
0 | Changes | |
1 | COPYRIGHT | |
2 | examples/ftps-direct.pl | |
3 | examples/ftps-starttls.pl | |
4 | examples/ftps-tests.pl | |
5 | examples/lwp.pl | |
6 | examples/lwp_post.pl | |
7 | examples/send-ssl-mail.pl | |
8 | examples/send-starttls-mail.pl | |
0 | 9 | lib/Net/SSLGlue.pm |
10 | lib/Net/SSLGlue/FTP.pm | |
1 | 11 | lib/Net/SSLGlue/LDAP.pm |
2 | 12 | lib/Net/SSLGlue/LWP.pm |
13 | lib/Net/SSLGlue/POP3.pm | |
3 | 14 | lib/Net/SSLGlue/SMTP.pm |
4 | lib/Net/SSLGlue/POP3.pm | |
15 | lib/Net/SSLGlue/Socket.pm | |
5 | 16 | Makefile.PL |
6 | 17 | MANIFEST This list of files |
18 | README | |
7 | 19 | t/01_load.t |
8 | 20 | t/external/02_smtp.t |
9 | 21 | t/external/03_lwp.t |
10 | 22 | t/external/04_pop3.t |
11 | TODO | |
12 | COPYRIGHT | |
13 | examples/lwp.pl | |
14 | examples/lwp_post.pl | |
15 | examples/send-ssl-mail.pl | |
16 | examples/send-starttls-mail.pl | |
17 | Changes | |
18 | README | |
23 | t/external/05_ftp.t | |
19 | 24 | META.yml Module meta-data (added by MakeMaker) |
0 | 0 | --- #YAML:1.0 |
1 | 1 | name: Net-SSLGlue |
2 | version: 1.04 | |
2 | version: 1.052 | |
3 | 3 | abstract: ~ |
4 | 4 | author: [] |
5 | 5 | license: unknown |
10 | 10 | ExtUtils::MakeMaker: 0 |
11 | 11 | requires: |
12 | 12 | IO::Socket::SSL: 1.19 |
13 | resources: | |
14 | repository: https://github.com/noxxi/p5-net-sslglue | |
13 | 15 | no_index: |
14 | 16 | directory: |
15 | 17 | - t |
0 | 0 | use ExtUtils::MakeMaker; |
1 | 1 | require 5.008; |
2 | 2 | my $xt = prompt( "Should I do external tests?\n". |
3 | "These tests will fail if there is no internet connection or if a firewall\n". | |
4 | "blocks some traffic.\n". | |
5 | "[y/N]", 'n' ); | |
3 | "These tests will fail if there is no internet connection or if a firewall\n". | |
4 | "blocks some traffic.\n". | |
5 | "[y/N]", 'n' ); | |
6 | 6 | WriteMakefile( |
7 | NAME => 'Net::SSLGlue', | |
8 | VERSION_FROM => 'lib/Net/SSLGlue.pm', | |
9 | PREREQ_PM => { | |
10 | 'IO::Socket::SSL' => 1.19, | |
7 | NAME => 'Net::SSLGlue', | |
8 | VERSION_FROM => 'lib/Net/SSLGlue.pm', | |
9 | PREREQ_PM => { | |
10 | 'IO::Socket::SSL' => 1.19, | |
11 | }, | |
12 | $xt =~m{^y}i ? ( test => { TESTS => 't/*.t t/external/*.t' }):(), | |
13 | META_MERGE => { | |
14 | resources => { | |
15 | repository => 'https://github.com/noxxi/p5-net-sslglue', | |
11 | 16 | }, |
12 | $xt =~m{^y}i ? ( test => { TESTS => 't/*.t t/external/*.t' }):(), | |
17 | }, | |
13 | 18 | ); |
0 | use strict; | |
1 | use warnings; | |
2 | use Net::SSLGlue::FTP; | |
3 | ||
4 | my $ftp = Net::FTP->new( 'ftp.example.com', | |
5 | SSL => 1, | |
6 | SSL_ca_path => '/etc/ssl/certs', | |
7 | Passive => 1, | |
8 | Debug => 1, | |
9 | ); | |
10 | $ftp->login('foo','bar'); | |
11 | print $ftp->ls; |
0 | use strict; | |
1 | use warnings; | |
2 | use Net::SSLGlue::FTP; | |
3 | ||
4 | my $ftp = Net::FTP->new( 'ftp.example.com', | |
5 | Passive => 1, | |
6 | Debug => 1, | |
7 | ); | |
8 | $ftp->starttls( SSL_ca_path => '/etc/ssl/certs' ) | |
9 | or die "tls upgrade failed"; | |
10 | $ftp->login('foo','bar'); | |
11 | print $ftp->ls; | |
12 | ||
13 | # change protection to clear | |
14 | $ftp->prot('C'); | |
15 | $ftp->ls; | |
16 | ||
17 | # stop TLS on control channel | |
18 | $ftp->stoptls; | |
19 | $ftp->ls; | |
20 |
0 | #!/usr/bin/perl | |
1 | use strict; | |
2 | use warnings; | |
3 | ||
4 | # This runs lots of tests with SSL against a test server | |
5 | # - plain | |
6 | # - with SSL upgrade and plain data connections | |
7 | # - with SSL upgrade and SSL data connections | |
8 | # - with SSL upgrade and downgrade after auth | |
9 | # - with direct SSL connection | |
10 | ||
11 | # setup stuff here | |
12 | # you need a server where you can write and read and create directories | |
13 | # SSL support is optional, but preferred | |
14 | # IPv6 support should be possible | |
15 | ||
16 | my $testhost = '127.0.0.1'; # where your test server is, IPv6 should be ok | |
17 | my $plain_port = 2021; # port where server listens for plain ftp | |
18 | my $user = 'foo'; # login as user | |
19 | my $pass = 'bar'; # with pass | |
20 | my $can_auth = 1; # does server support AUTH TLS | |
21 | my $ssl_port = 2090; # does server support direct SSL | |
22 | my %sslargs = ( | |
23 | # should be enabled if you want to verify certificates | |
24 | SSL_verify_mode => 1, | |
25 | # for CAs known to the system this might be maybe ommitted | |
26 | # otherwise set this or SSL_ca_path | |
27 | SSL_ca_file => 'ca.pem', | |
28 | # if the certificate has a different name then $testhost set it here | |
29 | SSL_verifycn_name => 'server.local', | |
30 | ); | |
31 | ||
32 | ||
33 | use Net::SSLGlue::FTP; | |
34 | use IO::Socket::SSL; | |
35 | use Carp 'croak'; | |
36 | ||
37 | my @test = ( | |
38 | # basic FTP server stuff | |
39 | { Passive => 0 }, | |
40 | { Passive => 1 }, | |
41 | $can_auth ? ( | |
42 | # SSL upgrade with data connections unprotected | |
43 | { Passive => 0, _starttls => 1, _prot => 'C' }, | |
44 | { Passive => 1, _starttls => 1, _prot => 'C' }, | |
45 | # SSL upgrade with data connections protected | |
46 | { Passive => 0, _starttls => 1 }, | |
47 | { Passive => 1, _starttls => 1 }, | |
48 | # SSL upgrade with SSL downgrade after auth | |
49 | { Passive => 0, _starttls => 1, _stoptls => 1 }, | |
50 | { Passive => 1, _starttls => 1, _stoptls => 1 }, | |
51 | ):(), | |
52 | # direct SSL on separate port | |
53 | $ssl_port ? ( | |
54 | { Passive => 0, SSL => 1, Port => $ssl_port }, | |
55 | { Passive => 1, SSL => 1, Port => $ssl_port }, | |
56 | ):(), | |
57 | ); | |
58 | ||
59 | my $testbase = sprintf("test-%04x%04x-",rand(2**16),rand(2**16)); | |
60 | for( my $i=0;$i<@test;$i++ ) { | |
61 | ||
62 | my %conf = %{$test[$i]}; | |
63 | my $starttls = delete $conf{_starttls}; | |
64 | my $stoptls = delete $conf{_stoptls}; | |
65 | my $prot = delete $conf{_prot}; | |
66 | my $dir = "$testbase$i"; | |
67 | ||
68 | print STDERR "------------ $dir\n"; | |
69 | my $ftp = Net::FTP->new( $testhost, | |
70 | Port => $plain_port, | |
71 | Debug => 1, | |
72 | %sslargs, | |
73 | %conf, | |
74 | ) or die "ftp connect failed"; | |
75 | ||
76 | my $ftperr = sub { | |
77 | my $msg = shift; | |
78 | croak "$msg failed (@_): ".$ftp->message; | |
79 | }; | |
80 | ||
81 | # upgrade to SSL | |
82 | $ftp->starttls or $ftperr->('auth tls', $SSL_ERROR) | |
83 | if $starttls; | |
84 | ||
85 | # login | |
86 | $ftp->login($user,$pass) or $ftperr->('login'); | |
87 | ||
88 | # downgrade from SSL | |
89 | $ftp->stoptls or $ftperr->('ccc') if $stoptls; | |
90 | ||
91 | # change protection level | |
92 | $ftp->prot($prot) or $ftperr->("PROT $prot") | |
93 | if $prot; | |
94 | ||
95 | # create directory for test and change into it | |
96 | $ftp->mkdir($dir) or $ftperr->('mkd'); | |
97 | $ftp->cwd($dir) or $ftperr->('cwd'); | |
98 | ||
99 | # check that dir is empty | |
100 | my @files = $ftp->ls; | |
101 | $ftp->ok or $ftperr->('nlst'); | |
102 | @files and die "directory should be empty"; | |
103 | ||
104 | # create a file in dir | |
105 | $ftp->put( _s2f( my $foo = 'foo' ,'<' ), 'foo.txt' ) | |
106 | or $ftperr->('stor'); | |
107 | # append some bytes to it | |
108 | $ftp->append( _s2f('bar'),'foo.txt' ) or $ftperr->('appe'); | |
109 | # check that it is there | |
110 | @files = $ftp->ls; | |
111 | "@files" eq 'foo.txt' or die "wrong ls: @files"; | |
112 | ||
113 | # retrieve file and verify content | |
114 | $ftp->get( 'foo.txt', _s2f( $foo = '','>' )); | |
115 | $foo eq 'foobar' or die "wrong data: 'foobar' != '$foo'"; | |
116 | ||
117 | $ftp->quit; | |
118 | } | |
119 | ||
120 | sub _s2f { | |
121 | open( my $fh,$_[1] || '<',\$_[0] ); | |
122 | return $fh | |
123 | } |
0 | ||
1 | package Net::SSLGlue::FTP; | |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use Carp 'croak'; | |
6 | use IO::Socket::SSL '$SSL_ERROR'; | |
7 | use Net::SSLGlue::Socket; | |
8 | use Socket 'AF_INET'; | |
9 | ||
10 | our $VERSION = 1.001; | |
11 | ||
12 | BEGIN { | |
13 | for my $class (qw(Net::FTP Net::FTP::dataconn)) { | |
14 | eval "require $class" or die "failed to load $class"; | |
15 | no strict 'refs'; | |
16 | my $fixed; | |
17 | for( @{ "${class}::ISA" } ) { | |
18 | $_ eq 'IO::Socket::INET' or next; | |
19 | $_ = 'Net::SSLGlue::Socket'; | |
20 | $fixed = 1; | |
21 | last; | |
22 | } | |
23 | die "cannot replace IO::Socket::INET with Net::SSLGlue::Socket in ${class}::ISA" | |
24 | if ! $fixed; | |
25 | } | |
26 | $Net::FTP::VERSION eq '2.77' | |
27 | or warn "Not tested with Net::FTP version $Net::FTP::VERSION"; | |
28 | } | |
29 | ||
30 | # redefine Net::FTP::new so that it understands SSL => 1 and connects directly | |
31 | # with SSL to the server | |
32 | { | |
33 | no warnings 'redefine'; | |
34 | my $onew = Net::FTP->can('new'); | |
35 | *Net::FTP::new = sub { | |
36 | my $class = shift; | |
37 | my %args = @_%2 ? ( Host => shift(), @_ ): @_; | |
38 | my %sslargs = map { $_ => delete $args{$_} } | |
39 | grep { m{^SSL_} } keys %args; | |
40 | ||
41 | my $self; | |
42 | if ( $args{SSL} ) { | |
43 | # go immediatly to SSL | |
44 | # Net::FTP::new gives only specific args to socket class | |
45 | $args{Port} ||= 990; | |
46 | local %Net::SSLGlue::Socket::ARGS = ( SSL => 1, %sslargs ); | |
47 | $self = $onew->($class,%args) or return; | |
48 | ${*$self}{net_ftp_tlstype} = 'P'; | |
49 | } else { | |
50 | $self = $onew->($class,%args) or return; | |
51 | } | |
52 | ${*$self}{net_ftp_tlsargs} = \%sslargs; | |
53 | return $self; | |
54 | }; | |
55 | } | |
56 | ||
57 | # add starttls method to upgrade connection to SSL: AUTH TLS | |
58 | sub Net::FTP::starttls { | |
59 | my $self = shift; | |
60 | $self->is_ssl and croak("called starttls within SSL session"); | |
61 | $self->_AUTH('TLS') == Net::FTP::CMD_OK or return; | |
62 | ||
63 | my $host = $self->host; | |
64 | # for name verification strip port from domain:port, ipv4:port, [ipv6]:port | |
65 | $host =~s{(?<!:):\d+$}{}; | |
66 | ||
67 | my %args = ( | |
68 | SSL_verify_mode => 1, | |
69 | SSL_verifycn_scheme => 'ftp', | |
70 | SSL_verifycn_name => $host, | |
71 | # reuse SSL session of control connection in data connections | |
72 | SSL_session_cache => Net::SSLGlue::FTP::SingleSessionCache->new, | |
73 | %{ ${*$self}{net_ftp_tlsargs}}, | |
74 | @_ | |
75 | ); | |
76 | ||
77 | $self->start_SSL(%args) or return; | |
78 | ${*$self}{net_ftp_tlsargs} = \%args; | |
79 | $self->prot('P'); | |
80 | return 1; | |
81 | } | |
82 | ||
83 | # add prot method to set protection level (PROT C|P) | |
84 | sub Net::FTP::prot { | |
85 | my ($self,$type) = @_; | |
86 | $type eq 'C' or $type eq 'P' or croak("type must by C or P"); | |
87 | $self->_PBSZ(0) or return; | |
88 | $self->_PROT($type) or return; | |
89 | ${*$self}{net_ftp_tlstype} = $type; | |
90 | return 1; | |
91 | } | |
92 | ||
93 | # add stoptls method to downgrade connection from SSL: CCC | |
94 | sub Net::FTP::stoptls { | |
95 | my $self = shift; | |
96 | $self->is_ssl or croak("called stoptls outside SSL session"); | |
97 | $self->_CCC() or return; | |
98 | $self->stop_SSL(); | |
99 | return 1; | |
100 | } | |
101 | ||
102 | # add EPSV for new style passive mode (incl. IPv6) | |
103 | sub Net::FTP::epsv { | |
104 | my $self = shift; | |
105 | @_ and croak 'usage: $ftp->epsv()'; | |
106 | delete ${*$self}{net_ftp_intern_port}; | |
107 | ||
108 | $self->_EPSV && $self->message =~ m{\(([\x33-\x7e])\1\1(\d+)\1\)} | |
109 | ? ${*$self}{'net_ftp_pasv'} = [ $self->peerhost, $2 ] | |
110 | : undef; | |
111 | } | |
112 | ||
113 | # redefine PASV so that it uses EPSV on IPv6 | |
114 | # also net_ftp_pasv contains now the parsed [ip,port] | |
115 | { | |
116 | no warnings 'redefine'; | |
117 | *Net::FTP::pasv = sub { | |
118 | my $self = shift; | |
119 | @_ and croak 'usage: $ftp->port()'; | |
120 | return $self->epsv if $self->sockdomain != AF_INET; | |
121 | delete ${*$self}{net_ftp_intern_port}; | |
122 | ||
123 | if ( $self->_PASV && | |
124 | $self->message =~ m{(\d+,\d+,\d+,\d+),(\d+),(\d+)} ) { | |
125 | my $port = 256 * $2 + $3; | |
126 | ( my $ip = $1 ) =~s{,}{.}g; | |
127 | return ${*$self}{'net_ftp_pasv'} = [ $ip,$port ]; | |
128 | } | |
129 | return; | |
130 | }; | |
131 | } | |
132 | ||
133 | # add EPRT for new style passive mode (incl. IPv6) | |
134 | sub Net::FTP::eprt { | |
135 | @_ == 1 || @_ == 2 or croak 'usage: $self->eprt([PORT])'; | |
136 | return _eprt('EPRT',@_); | |
137 | } | |
138 | ||
139 | # redefine PORT to use EPRT for IPv6 | |
140 | { | |
141 | no warnings 'redefine'; | |
142 | *Net::FTP::port = sub { | |
143 | @_ == 1 || @_ == 2 or croak 'usage: $self->port([PORT])'; | |
144 | return _eprt('PORT',@_); | |
145 | }; | |
146 | } | |
147 | ||
148 | sub _eprt { | |
149 | my ($cmd,$self,$port) = @_; | |
150 | delete ${*$self}{net_ftp_intern_port}; | |
151 | unless ($port) { | |
152 | my $listen = ${*$self}{net_ftp_listen} ||= Net::SSLGlue::Socket->new( | |
153 | Listen => 1, | |
154 | Timeout => $self->timeout, | |
155 | LocalAddr => $self->sockhost, | |
156 | ); | |
157 | ${*$self}{net_ftp_intern_port} = 1; | |
158 | my $fam = ($listen->sockdomain == AF_INET) ? 1:2; | |
159 | if ( $cmd eq 'EPRT' || $fam == 2 ) { | |
160 | $port = "|$fam|".$listen->sockhost."|".$listen->sockport."|"; | |
161 | $cmd = 'EPRT'; | |
162 | } else { | |
163 | my $p = $listen->sockport; | |
164 | $port = join(',',split(m{\.},$listen->sockhost),$p >> 8,$p & 0xff); | |
165 | } | |
166 | } | |
167 | my $ok = $cmd eq 'EPRT' ? $self->_EPRT($port) : $self->_PORT($port); | |
168 | ${*$self}{net_ftp_port} = $port if $ok; | |
169 | return $ok; | |
170 | } | |
171 | ||
172 | ||
173 | ||
174 | for my $cmd (qw(PBSZ PROT CCC EPRT EPSV)) { | |
175 | no strict 'refs'; | |
176 | *{"Net::FTP::_$cmd"} = sub { | |
177 | shift->command("$cmd @_")->response() == Net::FTP::CMD_OK | |
178 | } | |
179 | } | |
180 | ||
181 | # redefine _dataconn to | |
182 | # - support IPv6 | |
183 | # - upgrade data connection to SSL if PROT P | |
184 | { | |
185 | ||
186 | no warnings 'redefine'; | |
187 | *Net::FTP::_dataconn = sub { | |
188 | my $self = shift; | |
189 | my $pkg = "Net::FTP::" . $self->type; | |
190 | eval "require $pkg"; | |
191 | $pkg =~ s/ /_/g; | |
192 | delete ${*$self}{net_ftp_dataconn}; | |
193 | ||
194 | my $conn; | |
195 | if ( my $pasv = ${*$self}{net_ftp_pasv} ) { | |
196 | $conn = $pkg->new( | |
197 | PeerAddr => $pasv->[0], | |
198 | PeerPort => $pasv->[1], | |
199 | LocalAddr => ${*$self}{net_ftp_localaddr}, | |
200 | ) or return; | |
201 | } elsif (my $listen = delete ${*$self}{net_ftp_listen}) { | |
202 | $conn = $listen->accept($pkg) or return; | |
203 | close($listen); | |
204 | } | |
205 | ||
206 | if (( ${*$self}{net_ftp_tlstype} || '') eq 'P' | |
207 | && ! $conn->start_SSL( $self->is_ssl | |
208 | ? ( SSL_reuse_ctx => $self ) | |
209 | : ( %{${*$self}{net_ftp_tlsargs}} ) | |
210 | ) ) { | |
211 | croak("failed to ssl upgrade dataconn: $SSL_ERROR"); | |
212 | return; | |
213 | } | |
214 | ||
215 | $conn->timeout($self->timeout); | |
216 | ${*$self}{net_ftp_dataconn} = $conn; | |
217 | ${*$conn} = ""; | |
218 | ${*$conn}{net_ftp_cmd} = $self; | |
219 | ${*$conn}{net_ftp_blksize} = ${*$self}{net_ftp_blksize}; | |
220 | return $conn; | |
221 | }; | |
222 | } | |
223 | ||
224 | { | |
225 | # Session Cache with single entry | |
226 | # used to make sure that we reuse same session for control channel and data | |
227 | package Net::SSLGlue::FTP::SingleSessionCache; | |
228 | sub new { my $x; return bless \$x,shift } | |
229 | sub add_session { | |
230 | my ($self,$key,$session) = @_; | |
231 | Net::SSLeay::SESSION_free($$self) if $$self; | |
232 | $$self = $session; | |
233 | } | |
234 | sub get_session { | |
235 | my $self = shift; | |
236 | return $$self | |
237 | } | |
238 | sub DESTROY { | |
239 | my $self = shift; | |
240 | Net::SSLeay::SESSION_free($$self) if $$self; | |
241 | } | |
242 | } | |
243 | ||
244 | 1; | |
245 | ||
246 | =head1 NAME | |
247 | ||
248 | Net::SSLGlue::FTP - extend Net::FTP for FTPS (SSL) and IPv6 | |
249 | ||
250 | =head1 SYNOPSIS | |
251 | ||
252 | use Net::SSLGlue::FTP; | |
253 | # SSL right from start | |
254 | my $ftps = Net::FTP->new( $host, | |
255 | SSL => 1, | |
256 | SSL_ca_path => ... | |
257 | ); | |
258 | ||
259 | # SSL through upgrade of plain connection | |
260 | my $ftp = Net::FTP->new( $host ); | |
261 | $ftp->starttls( SSL_ca_path => ... ); | |
262 | ||
263 | # change protection mode to unencrypted|encrypted | |
264 | $ftp->prot('C'); # clear | |
265 | $ftp->prot('P'); # protected | |
266 | ||
267 | =head1 DESCRIPTION | |
268 | ||
269 | L<Net::SSLGlue::FTP> extends L<Net::FTP> so one can either start directly with | |
270 | SSL or switch later to SSL using starttls method (AUTH TLS command). | |
271 | If IO::Socket::IP or IO::Socket::INET6 are installed it will also transparently | |
272 | use IPv6. | |
273 | ||
274 | By default it will take care to verify the certificate according to the rules | |
275 | for FTP implemented in L<IO::Socket::SSL>. | |
276 | ||
277 | =head1 METHODS | |
278 | ||
279 | =over 4 | |
280 | ||
281 | =item new | |
282 | ||
283 | The method C<new> of L<Net::FTP> is now able to start directly with SSL when | |
284 | the argument C<<SSL => 1>> is given. One can give the usual C<SSL_*> parameter | |
285 | of L<IO::Socket::SSL> to C<Net::FTP::new>. | |
286 | ||
287 | =item starttls | |
288 | ||
289 | If the connection is not yet SSLified it will issue the "AUTH TLS" command and | |
290 | change the object, so that SSL will now be used. The usual C<SSL_*> parameter of | |
291 | L<IO::Socket::SSL> will be given. | |
292 | ||
293 | =item peer_certificate ... | |
294 | ||
295 | Once the SSL connection is established you can use this method to get | |
296 | information about the certificate. See the L<IO::Socket::SSL> documentation. | |
297 | ||
298 | =back | |
299 | ||
300 | All of these methods can take the C<SSL_*> parameter from L<IO::Socket::SSL> to | |
301 | change the behavior of the SSL connection. The following parameters are | |
302 | especially useful: | |
303 | ||
304 | =over 4 | |
305 | ||
306 | =item SSL_ca_path, SSL_ca_file | |
307 | ||
308 | Specifies the path or a file where the CAs used for checking the certificates | |
309 | are located. This is typically L</etc/ssl/certs> on UNIX systems. | |
310 | ||
311 | =item SSL_verify_mode | |
312 | ||
313 | If set to 0, verification of the certificate will be disabled. By default | |
314 | it is set to 1 which means that the peer certificate is checked. | |
315 | ||
316 | =item SSL_verifycn_name | |
317 | ||
318 | Usually the name given as the hostname in the constructor is used to verify the | |
319 | identity of the certificate. If you want to check the certificate against | |
320 | another name you can specify it with this parameter. | |
321 | ||
322 | =back | |
323 | ||
324 | =head1 SEE ALSO | |
325 | ||
326 | IO::Socket::SSL, Net::FTP, Net::SSLGlue::Socket | |
327 | ||
328 | =head1 COPYRIGHT | |
329 | ||
330 | This module is copyright (c) 2013, Steffen Ullrich. | |
331 | All Rights Reserved. | |
332 | This module is free software. It may be used, redistributed and/or modified | |
333 | under the same terms as Perl itself. |
0 | ||
1 | package Net::SSLGlue::Socket; | |
2 | our $VERSION = 1.001; | |
3 | ||
4 | use strict; | |
5 | use warnings; | |
6 | use Carp 'croak'; | |
7 | use Symbol 'gensym'; | |
8 | use IO::Socket::SSL; | |
9 | my $IPCLASS; | |
10 | BEGIN { | |
11 | for(qw(IO::Socket::IP IO::Socket::INET6 IO::Socket::INET)) { | |
12 | $IPCLASS = $_,last if eval "require $_"; | |
13 | } | |
14 | } | |
15 | ||
16 | # this can be overwritten (with local) to get arguments passed around | |
17 | # to strict calls of the socket class new | |
18 | our %ARGS; | |
19 | ||
20 | sub new { | |
21 | my $class = shift; | |
22 | my %args = @_>1 ? @_ : ( PeerAddr => shift() ); | |
23 | %args = ( %args, %ARGS ); | |
24 | ||
25 | my %sslargs; | |
26 | for(keys %args) { | |
27 | $sslargs{$_} = delete $args{$_} if m{^SSL_}; | |
28 | } | |
29 | ||
30 | my $ssl = delete $args{SSL}; | |
31 | my $sock = $ssl | |
32 | ? IO::Socket::SSL->new(%args,%sslargs) | |
33 | : $IPCLASS->new(%args) | |
34 | or return; | |
35 | ||
36 | my $self = gensym(); | |
37 | *$self = *$sock; # clone handle | |
38 | bless $self,$class; | |
39 | ${*$self}{sock} = $sock; | |
40 | ${*$self}{ssl} = $ssl; | |
41 | ${*$self}{sslargs} = \%sslargs; | |
42 | ||
43 | return $self; | |
44 | } | |
45 | ||
46 | for my $sub (qw( | |
47 | fileno sysread syswrite close connect fcntl | |
48 | read write readline print printf getc say eof getline getlines | |
49 | blocking autoflush timeout | |
50 | sockhost sockport peerhost peerport sockdomain | |
51 | truncate stat setbuf setvbuf fdopen ungetc send recv | |
52 | )) { | |
53 | no strict 'refs'; | |
54 | *$sub = sub { | |
55 | my $self = shift; | |
56 | my $sock = ${*$self}{sock} or return; | |
57 | my $sock_sub = $sock->can($sub) or croak("$sock does not support $sub"); | |
58 | unshift @_,$sock; | |
59 | # warn "*** $sub called"; | |
60 | goto &$sock_sub; | |
61 | }; | |
62 | } | |
63 | ||
64 | sub accept { | |
65 | my ($self,$class) = @_; | |
66 | my $sock = ${*$self}{sock} or return; | |
67 | my $conn = $sock->accept(); | |
68 | ||
69 | return bless $conn,$class | |
70 | if $class && ! $class->isa('Net::SSLGlue::Socket'); | |
71 | ||
72 | $class ||= ref($self); | |
73 | my $wrap = gensym; | |
74 | *$wrap = *$conn; # clone original handle | |
75 | bless $wrap, $class; | |
76 | ${*$wrap}{sock} = $conn; | |
77 | ${*$wrap}{ssl} = ${*$self}{ssl}; | |
78 | ${*$wrap}{sslargs} = ${*$self}{sslargs}; | |
79 | return $wrap; | |
80 | }; | |
81 | ||
82 | sub start_SSL { | |
83 | my $self = shift; | |
84 | croak("start_SSL called on SSL socket") if ${*$self}{ssl}; | |
85 | IO::Socket::SSL->start_SSL(${*$self}{sock},%{${*$self}{sslargs}},@_) | |
86 | or return; | |
87 | ${*$self}{ssl} = 1; | |
88 | return $self; | |
89 | } | |
90 | ||
91 | sub stop_SSL { | |
92 | my $self = shift; | |
93 | croak("stop_SSL called on plain socket") if ! ${*$self}{ssl}; | |
94 | ${*$self}{sock}->stop_SSL(@_) or return; | |
95 | ${*$self}{ssl} = 0; | |
96 | return $self; | |
97 | } | |
98 | ||
99 | sub can_read { | |
100 | my ($self,$timeout) = @_; | |
101 | return 1 if ${*$self}{ssl} && ${*$self}{sock}->pending; | |
102 | vec( my $vec,fileno(${*$self}{sock}),1) = 1; | |
103 | return select($vec,undef,undef,$timeout); | |
104 | } | |
105 | ||
106 | sub peer_certificate { | |
107 | my $self = shift; | |
108 | return ${*$self}{ssl} && ${*$self}{sock}->peer_certificate(@_); | |
109 | } | |
110 | ||
111 | sub is_ssl { | |
112 | my $self = shift; | |
113 | return ${*$self}{ssl} && ${*$self}{sock}; | |
114 | } | |
115 | ||
116 | 1; | |
117 | ||
118 | =head1 NAME | |
119 | ||
120 | Net::SSLGlue::Socket - socket which can be either SSL or plain IP (IPv4/IPv6) | |
121 | ||
122 | =head1 SYNOPSIS | |
123 | ||
124 | use Net::SSLGlue::Socket; | |
125 | # SSL right from start | |
126 | my $ssl = Net::SSLGlue::Socket->new( | |
127 | PeerHost => ..., # IPv4|IPv6 address | |
128 | PeerPort => ..., | |
129 | SSL => 1, | |
130 | SSL_ca_path => ... | |
131 | ); | |
132 | ||
133 | # SSL through upgrade of plain connection | |
134 | my $plain = Net::SSLGlue::Socket->new(...); | |
135 | $plain->start_SSL( SSL_ca_path => ... ); | |
136 | ... | |
137 | $plain->stop_SSL | |
138 | ||
139 | ||
140 | =head1 DESCRIPTION | |
141 | ||
142 | L<Net::SSLGlue::Socket> implements a socket which can be either plain or SSL. | |
143 | If IO::Socket::IP or IO::Socket::INET6 are installed it will also transparently | |
144 | handle IPv6 connections. | |
145 | ||
146 | A socket can be either start directly with SSL or it can be start plain and | |
147 | later be upgraded to SSL (because of a STARTTLS commando or similar) and also | |
148 | downgraded again. | |
149 | ||
150 | It is possible but not recommended to use the socket in non-blocking | |
151 | mode, because in this case special care must be taken with SSL (see | |
152 | documentation of L<IO::Socket::SSL>). | |
153 | ||
154 | Additionally to the usual socket methods the following methods are defined or | |
155 | extended: | |
156 | ||
157 | =head1 METHODS | |
158 | ||
159 | =over 4 | |
160 | ||
161 | =item new | |
162 | ||
163 | The method C<new> of L<Net::SSLGlue::Socket> can have the argument SSL. If this | |
164 | is true the SSL upgrade will be done immediatly. If not set any SSL_* args will | |
165 | still be saved and used at a later start_SSL call. | |
166 | ||
167 | =item start_SSL | |
168 | ||
169 | This will upgrade the plain socket to SSL. See L<IO::Socket::SSL> for | |
170 | arguments to C<start_SSL>. Any SSL_* arguments given to new will be applied | |
171 | here too. | |
172 | ||
173 | =item stop_SSL | |
174 | ||
175 | This will downgrade the socket from SSL to plain. | |
176 | ||
177 | =item peer_certificate ... | |
178 | ||
179 | Once the SSL connection is established you can use this method to get | |
180 | information about the certificate. See the L<IO::Socket::SSL> documentation. | |
181 | ||
182 | =item can_read(timeout) | |
183 | ||
184 | This will check for available data. For a plain socket this will only use | |
185 | C<select> to check the socket, but for SSL it will check if there are any | |
186 | pending data before trying a select. | |
187 | Because SSL needs to read the whole frame before decryption can be done, a | |
188 | successful return of can_read is no guarantee that data can be read | |
189 | immediatly, only that new data are either available or in the process of | |
190 | arriving. | |
191 | ||
192 | =back | |
193 | ||
194 | =head1 SEE ALSO | |
195 | ||
196 | IO::Socket::SSL | |
197 | ||
198 | =head1 COPYRIGHT | |
199 | ||
200 | This module is copyright (c) 2013, Steffen Ullrich. | |
201 | All Rights Reserved. | |
202 | This module is free software. It may be used, redistributed and/or modified | |
203 | under the same terms as Perl itself. |
0 | 0 | package Net::SSLGlue; |
1 | our $VERSION = '1.04'; | |
1 | our $VERSION = '1.052'; | |
2 | 2 | |
3 | 3 | =head1 NAME |
4 | 4 | |
20 | 20 | |
21 | 21 | =item Net::POP3 - add SSL from beginning or using STLS |
22 | 22 | |
23 | =item Net::FTP - add SSL and IPv6 support to Net::FTP | |
24 | ||
23 | 25 | =item Net::LDAP - add proper certificate checking |
24 | 26 | |
25 | 27 | =item LWP - add proper certificate checking |
26 | 28 | |
27 | 29 | =back |
30 | ||
31 | There is also a Net::SSLGlue::Socket package which combines ssl and non-ssl | |
32 | and ipv6 capabilities to make it easier to enhance modules based on | |
33 | IO::Socket::INET. | |
28 | 34 | |
29 | 35 | =head1 COPYRIGHT |
30 | 36 |
37 | 37 | exit |
38 | 38 | }; |
39 | 39 | |
40 | # ssl to the wrong host | |
41 | # the certificate mail.gmx.de returns is for mail.gmx.net | |
42 | diag( "connect ssl to mail.gmx.de:465" ); | |
43 | IO::Socket::SSL->new( | |
44 | PeerAddr => 'mail.gmx.de:465', | |
45 | SSL_ca_path => $capath, | |
46 | SSL_verify_mode => 1, | |
47 | SSL_verifycn_scheme => 'smtp' | |
48 | ) and do { | |
49 | print "1..0 # mail.gmx.de:465 reachable with SSL\n"; | |
50 | exit | |
51 | }; | |
52 | 40 | |
53 | print "1..6\n"; | |
41 | print "1..3\n"; | |
54 | 42 | |
55 | 43 | # first direct SSL |
56 | 44 | my $smtp = Net::SMTP->new( 'mail.gmx.net', |
66 | 54 | # check that we can talk on connection |
67 | 55 | print $smtp->quit ? "ok\n": "not ok # quit failed\n"; |
68 | 56 | |
69 | # against wrong host should fail | |
70 | $smtp = Net::SMTP->new( 'mail.gmx.de' ); # should succeed | |
71 | $ok = $smtp->starttls( SSL_ca_path => $capath ); | |
72 | print $ok ? "not ok # smtp starttls mail.gmx.de did not fail\n": "ok\n"; | |
73 | ||
74 | # but not if we specify the right SSL_verifycn_name | |
75 | $smtp = Net::SMTP->new( 'mail.gmx.de' ); # should succeed | |
76 | $ok = $smtp->starttls( SSL_ca_path => $capath, SSL_verifycn_name => 'mail.gmx.net' ); | |
77 | print $ok ? "ok\n" : "not ok # smtp starttls mail.gmx.de/net\n"; | |
78 | ||
79 | # or disable verification | |
80 | $smtp = Net::SMTP->new( 'mail.gmx.de' ); # should succeed | |
81 | $ok = $smtp->starttls( SSL_verify_mode => 0 ); | |
82 | print $ok ? "ok\n" : "not ok # smtp starttls mail.gmx.de\n"; | |
83 | 57 | |
84 | 58 | sub diag { |
85 | 59 | #print STDERR "@_\n" |
2 | 2 | use warnings; |
3 | 3 | |
4 | 4 | BEGIN { |
5 | eval "use LWP"; | |
6 | if ( $@ ) { | |
7 | print "1..0 # no LWP\n"; | |
8 | exit | |
9 | } | |
5 | eval "use LWP"; | |
6 | if ( $@ ) { | |
7 | print "1..0 # no LWP\n"; | |
8 | exit | |
9 | } | |
10 | 10 | } |
11 | 11 | |
12 | 12 | use Net::SSLGlue::LWP; |
13 | use IO::Socket::SSL; | |
13 | 14 | use LWP::Simple; |
15 | ||
16 | my $goodhost = 'google.de'; | |
17 | # this does not work any longer - will be skipped in test | |
18 | my $badhost = 'www.fedora.org'; | |
14 | 19 | |
15 | 20 | my $capath = '/etc/ssl/certs/'; # unix? |
16 | 21 | -d $capath or do { |
17 | print "1..0 # cannot find system CA-path\n"; | |
18 | exit | |
22 | print "1..0 # cannot find system CA-path\n"; | |
23 | exit | |
19 | 24 | }; |
20 | Net::SSLGlue::LWP->import( SSL_ca_path => $capath ); | |
25 | Net::SSLGlue::LWP->import( | |
26 | SSL_ca_path => $capath, | |
27 | # LWP might define SSL_ca_file - remove it to avoid conflict | |
28 | SSL_ca_file => undef | |
29 | ); | |
21 | 30 | |
22 | 31 | # |
23 | 32 | # first check everything directly with IO::Socket::SSL |
24 | 33 | # |
25 | 34 | |
26 | # signin.ebay.de has a certificate, which is for signin.ebay.com | |
27 | # but where signin.ebay.de is a subjectAltName | |
28 | IO::Socket::SSL->new( | |
29 | PeerAddr => 'signin.ebay.de:443', | |
35 | diag("connecting to $goodhost:443 with IO::Socket::INET"); | |
36 | my $sock = IO::Socket::INET->new( | |
37 | PeerAddr => "$goodhost:443", | |
38 | Timeout => 10 | |
39 | ) or do { | |
40 | print "1..0 # connect $goodhost failed: $!\n"; | |
41 | exit | |
42 | }; | |
43 | diag("ssl upgrade $goodhost"); | |
44 | IO::Socket::SSL->start_SSL( $sock, | |
45 | SSL_ca_path => $capath, | |
46 | SSL_verifycn_name => "$goodhost", | |
47 | SSL_verify_mode => 1, | |
48 | SSL_verifycn_scheme => 'http', | |
49 | ) or do { | |
50 | print "1..0 # ssl upgrade $goodhost failed: $SSL_ERROR\n"; | |
51 | exit | |
52 | }; | |
53 | ||
54 | diag("connecting to $badhost:443 with IO::Socket::INET"); | |
55 | if ( $sock = IO::Socket::INET->new( | |
56 | PeerAddr => "$badhost:443", | |
57 | Timeout => 10, | |
58 | )) { | |
59 | diag("upgrading to https - should fail because of bad certificate"); | |
60 | if ( IO::Socket::SSL->start_SSL( $sock, | |
30 | 61 | SSL_ca_path => $capath, |
31 | 62 | SSL_verify_mode => 1, |
32 | SSL_verifycn_scheme => 'http' | |
33 | ) or do { | |
34 | print "1..0 # ssl connect signin.ebay.de failed\n"; | |
35 | exit | |
36 | }; | |
37 | ||
38 | # www.fedora.org has a certificate which has nothing in common | |
39 | # with the hostname | |
40 | my $sock = IO::Socket::INET->new( 'www.fedora.org:443' ) or do { | |
41 | print "1..0 # connect to www.fedora.org failed\n"; | |
42 | exit | |
43 | }; | |
44 | IO::Socket::SSL->start_SSL( $sock, | |
45 | SSL_ca_path => $capath, | |
46 | SSL_verify_mode => 1, | |
47 | SSL_verifycn_scheme => 'http' | |
48 | ) and do { | |
49 | print "1..0 # certificate for www.fedora.org unexpectly correct\n"; | |
50 | exit | |
51 | }; | |
63 | )) { | |
64 | diag("certificate for $badhost unexpectly correct"); | |
65 | $badhost = undef; | |
66 | }; | |
67 | } else { | |
68 | diag("connect to $badhost failed: $!"); | |
69 | $badhost = undef; | |
70 | } | |
52 | 71 | |
53 | 72 | # |
54 | 73 | # and than check, that LWP uses the same checks |
55 | 74 | # |
56 | 75 | |
57 | print "1..3\n"; | |
76 | print "1..".( $badhost ? 3:1 )."\n"; | |
58 | 77 | |
59 | # signin.ebay.de -> should succeed | |
60 | my $content = get( 'https://signin.ebay.de' ); | |
61 | print $content ? "ok\n": "not ok # lwp connect signin.ebay.de: $@\n"; | |
78 | # $goodhost -> should succeed | |
79 | diag("connecting to $goodhost:443 with LWP"); | |
80 | my $content = get( "https://$goodhost" ); | |
81 | print $content ? "ok\n": "not ok # lwp connect $goodhost: $@\n"; | |
62 | 82 | |
63 | # www.fedora.org -> should fail | |
64 | $content = get( 'https://www.fedora.org' ); | |
65 | print $content ? "not ok # lwp ssl connect www.fedora.org should fail\n": "ok\n"; | |
83 | if ( $badhost ) { | |
84 | # $badhost -> should fail | |
85 | diag("connecting to $badhost:443 with LWP"); | |
86 | $content = get( 'https://$badhost' ); | |
87 | print $content ? "not ok # lwp ssl connect $badhost should fail\n": "ok\n"; | |
66 | 88 | |
67 | # www.fedora.org -> should succeed if verify mode is 0 | |
68 | { | |
89 | # $badhost -> should succeed if verify mode is 0 | |
90 | { | |
69 | 91 | local %Net::SSLGlue::LWP::SSLopts = %Net::SSLGlue::LWP::SSLopts; |
70 | 92 | $Net::SSLGlue::LWP::SSLopts{SSL_verify_mode} = 0; |
71 | $content = get( 'https://www.fedora.org' ); | |
72 | print $content ? "ok\n": "not ok # lwp ssl www.fedora.org w/o ssl verify\n"; | |
93 | $content = get( 'https://$badhost' ); | |
94 | print $content ? "ok\n": "not ok # lwp ssl $badhost w/o ssl verify\n"; | |
95 | } | |
73 | 96 | } |
74 | 97 | |
98 | sub diag { print "# @_\n" } |
37 | 37 | exit |
38 | 38 | }; |
39 | 39 | |
40 | # ssl to the wrong host | |
41 | # the certificate pop.gmx.de returns is for pop.gmx.net | |
42 | diag( "connect ssl to pop.gmx.de:995" ); | |
43 | IO::Socket::SSL->new( | |
44 | PeerAddr => 'pop.gmx.de:995', | |
45 | SSL_ca_path => $capath, | |
46 | SSL_verify_mode => 1, | |
47 | SSL_verifycn_scheme => 'smtp' | |
48 | ) and do { | |
49 | print "1..0 # pop.gmx.de:995 reachable with SSL\n"; | |
50 | exit | |
51 | }; | |
52 | 40 | |
53 | print "1..6\n"; | |
41 | print "1..3\n"; | |
54 | 42 | |
55 | 43 | # first direct SSL |
56 | 44 | my $smtp = Net::POP3->new( 'pop.gmx.net', |
66 | 54 | # check that we can talk on connection |
67 | 55 | print $smtp->quit ? "ok\n": "not ok # quit failed\n"; |
68 | 56 | |
69 | # against wrong host should fail | |
70 | $smtp = Net::POP3->new( 'pop.gmx.de' ); # should succeed | |
71 | $ok = $smtp->starttls( SSL_ca_path => $capath ); | |
72 | print $ok ? "not ok # smtp starttls pop.gmx.de did not fail\n": "ok\n"; | |
73 | ||
74 | # but not if we specify the right SSL_verifycn_name | |
75 | $smtp = Net::POP3->new( 'pop.gmx.de' ); # should succeed | |
76 | $ok = $smtp->starttls( SSL_ca_path => $capath, SSL_verifycn_name => 'pop.gmx.net' ); | |
77 | print $ok ? "ok\n" : "not ok # smtp starttls pop.gmx.de/net\n"; | |
78 | ||
79 | # or disable verification | |
80 | $smtp = Net::POP3->new( 'pop.gmx.de' ); # should succeed | |
81 | $ok = $smtp->starttls( SSL_verify_mode => 0 ); | |
82 | print $ok ? "ok\n" : "not ok # smtp starttls pop.gmx.de\n"; | |
83 | ||
84 | 57 | sub diag { |
85 | 58 | #print STDERR "@_\n" |
86 | 59 | } |
0 | ||
1 | use strict; | |
2 | use warnings; | |
3 | use Test::More; | |
4 | ||
5 | my $server = 'ftp.rebex.net'; | |
6 | my $debug = 0; | |
7 | ||
8 | BEGIN { | |
9 | eval "use Net::FTP"; | |
10 | if ( $@ ) { | |
11 | print "1..0 # no Net::FTP\n"; | |
12 | exit | |
13 | } | |
14 | } | |
15 | ||
16 | use Net::SSLGlue::FTP; | |
17 | use IO::Socket::SSL; | |
18 | use File::Temp; | |
19 | ||
20 | # first try to connect w/o ftp | |
21 | # plain | |
22 | diag( "connect inet to $server:21" ); | |
23 | IO::Socket::INET->new( "$server:21" ) or do { | |
24 | plan skip_all => "$server:21 not reachable"; | |
25 | }; | |
26 | ||
27 | # ssl to the right host | |
28 | diag( "connect inet to $server:990" ); | |
29 | my $sock = IO::Socket::INET->new( "$server:990") or do { | |
30 | plan skip_all => "$server:999 not reachable"; | |
31 | }; | |
32 | ||
33 | # now we need CAs | |
34 | my $cafh = File::Temp->new( UNLINK => 0, SUFFIX => '.crt' ); | |
35 | my %sslargs = ( SSL_ca_file => $cafh->filename ); | |
36 | print $cafh <DATA>; | |
37 | close($cafh); | |
38 | ||
39 | diag( "upgrade to ssl $server:990" ); | |
40 | IO::Socket::SSL->start_SSL($sock, | |
41 | %sslargs, | |
42 | SSL_verify_mode => 1, | |
43 | SSL_verifycn_name => $server, | |
44 | SSL_verifycn_scheme => 'ftp' | |
45 | ) or do { | |
46 | plan skip_all => "$server:999 not upgradable to SSL: $SSL_ERROR"; | |
47 | }; | |
48 | ||
49 | plan tests => 9; | |
50 | ||
51 | # first direct SSL | |
52 | diag( "connect ftp over ssl to $server" ); | |
53 | my $ftp = Net::FTP->new($server, | |
54 | SSL => 1, | |
55 | %sslargs, | |
56 | Debug => $debug, | |
57 | Passive => 1, | |
58 | ); | |
59 | ok($ftp,"ftp ssl connect $server"); | |
60 | $ftp->login("anonymous",'net-sslglue-ftp@test.perl') | |
61 | or die "login to $server failed"; | |
62 | diag("logged in"); | |
63 | # check that we can talk on connection | |
64 | ok(~~$ftp->ls,"directory listing protected"); | |
65 | $ftp->prot('C'); | |
66 | ok(~~$ftp->ls,"directory listing clear"); | |
67 | ||
68 | # then TLS upgrade inside plain connection | |
69 | $ftp = Net::FTP->new($server, Passive => 1, Debug => $debug); | |
70 | ok($ftp,"ftp plain connect $server"); | |
71 | my $ok = $ftp->starttls(%sslargs); | |
72 | ok($ok,"ssl upgrade"); | |
73 | $ftp->login("anonymous",'net-sslglue-ftp@test.perl') | |
74 | or die "login to $server failed"; | |
75 | diag("logged in"); | |
76 | # check that we can talk on connection | |
77 | ok(~~$ftp->ls,"directory listing protected"); | |
78 | $ftp->prot('C'); | |
79 | ok(~~$ftp->ls,"directory listing clear"); | |
80 | $ok = $ftp->stoptls; | |
81 | ok($ok,"ssl downgrade"); | |
82 | ok(~~$ftp->ls,"directory listing after downgrade"); | |
83 | ||
84 | ||
85 | __DATA__ | |
86 | # Subject: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Class 1 Primary Intermediate Server CA | |
87 | # Issuer: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Certification Authority | |
88 | -----BEGIN CERTIFICATE----- | |
89 | MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW | |
90 | MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg | |
91 | Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh | |
92 | dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB | |
93 | jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT | |
94 | IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0 | |
95 | YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB | |
96 | IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE | |
97 | gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA | |
98 | pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv | |
99 | kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/ | |
100 | ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5 | |
101 | xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID | |
102 | AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD | |
103 | VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul | |
104 | F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov | |
105 | L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0 | |
106 | YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3 | |
107 | dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0 | |
108 | c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu | |
109 | BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0 | |
110 | BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl | |
111 | LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp | |
112 | tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen | |
113 | xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw | |
114 | xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X | |
115 | t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI | |
116 | RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi | |
117 | YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L | |
118 | WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN | |
119 | SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD | |
120 | wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L | |
121 | p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un | |
122 | 0q6Dp6jOW6c= | |
123 | -----END CERTIFICATE----- | |
124 | # Subject: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Certification Authority | |
125 | # Issuer: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Certification Authority | |
126 | -----BEGIN CERTIFICATE----- | |
127 | MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW | |
128 | MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg | |
129 | Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh | |
130 | dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 | |
131 | MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi | |
132 | U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh | |
133 | cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA | |
134 | A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk | |
135 | pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf | |
136 | OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C | |
137 | Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT | |
138 | Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi | |
139 | HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM | |
140 | Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w | |
141 | +2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ | |
142 | Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 | |
143 | Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B | |
144 | 26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID | |
145 | AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD | |
146 | VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul | |
147 | F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC | |
148 | ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w | |
149 | ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk | |
150 | aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 | |
151 | YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg | |
152 | c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 | |
153 | aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 | |
154 | d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG | |
155 | CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 | |
156 | dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF | |
157 | wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS | |
158 | Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst | |
159 | 0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc | |
160 | pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl | |
161 | CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF | |
162 | P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK | |
163 | 1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm | |
164 | KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE | |
165 | JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ | |
166 | 8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm | |
167 | fyWl8kgAwKQB2j8= | |
168 | -----END CERTIFICATE----- |