package Net::SSLLabs::EndpointDetails;

use strict;
use warnings;
use Net::SSLLabs::Cert();
use Net::SSLLabs::Suites();
use Net::SSLLabs::SimDetails();
use Net::SSLLabs::Protocol();
use Net::SSLLabs::Chain();
use Net::SSLLabs::Key();

our $VERSION = '0.07';

sub new {
    my ( $class, $json ) = @_;
    my $self = $json;
    bless $self, $class;
    $self->{key}  = Net::SSLLabs::Key->new( $self->{key} );
    $self->{cert} = Net::SSLLabs::Cert->new( $self->{cert} );
    my @protocols = @{ $self->{protocols} };
    $self->{protocols} = [];
    foreach my $protocol (@protocols) {
        push @{ $self->{protocols} }, Net::SSLLabs::Protocol->new($protocol);
    }
    $self->{suites} = Net::SSLLabs::Suites->new( $self->{suites} );
    $self->{sims}   = Net::SSLLabs::SimDetails->new( $self->{sims} );
    $self->{chain}  = Net::SSLLabs::Chain->new( $self->{chain} );
    return $self;
}

sub host_start_time {
    my ($self) = @_;
    return $self->{hostStartTime};
}

sub key {
    my ($self) = @_;
    return $self->{key};
}

sub cert {
    my ($self) = @_;
    return $self->{cert};
}

sub chain {
    my ($self) = @_;
    return $self->{chain};
}

sub protocols {
    my ($self) = @_;
    return @{ $self->{protocols} };
}

sub suites {
    my ($self) = @_;
    return $self->{suites};
}

sub server_signature {
    my ($self) = @_;
    return $self->{serverSignature};
}

sub prefix_delegation {
    my ($self) = @_;
    return $self->{prefixDelegation} ? 1 : 0;
}

sub non_prefix_delegation {
    my ($self) = @_;
    return $self->{nonPrefixDelegation} ? 1 : 0;
}

sub vuln_beast {
    my ($self) = @_;
    return $self->{vulnBeast} ? 1 : 0;
}

sub reneg_support {
    my ($self) = @_;
    return $self->{renegSupport};
}

sub sts_response_header {
    my ($self) = @_;
    return $self->{stsResponseHeader};
}

sub sts_max_age {
    my ($self) = @_;
    return $self->{stsMaxAge};
}

sub sts_subdomains {
    my ($self) = @_;
    return $self->{stsSubdomains} ? 1 : 0;
}

sub pkp_response_header {
    my ($self) = @_;
    return $self->{pkpResponseHeader};
}

sub session_resumption {
    my ($self) = @_;
    return $self->{sessionResumption};
}

sub compression_methods {
    my ($self) = @_;
    return $self->{compressionMethods};
}

sub supports_npn {
    my ($self) = @_;
    return $self->{supportsNpn} ? 1 : 0;
}

sub npn_protocols {
    my ($self) = @_;
    return $self->{npnProtocols};
}

sub session_tickets {
    my ($self) = @_;
    return $self->{sessionTickets};
}

sub ocsp_stapling {
    my ($self) = @_;
    return $self->{ocspStaplings};
}

sub stapling_revocation_status {
    my ($self) = @_;
    return $self->{staplingRevocationStatus};
}

sub stapling_revocation_error_message {
    my ($self) = @_;
    return $self->{staplingRevocationErrorMessage};
}

sub sni_required {
    my ($self) = @_;
    return $self->{sniRequired} ? 1 : 0;
}

sub http_status_code {
    my ($self) = @_;
    return $self->{httpStatusCode};
}

sub supports_rc4 {
    my ($self) = @_;
    return $self->{supportsRc4} ? 1 : 0;
}

sub forward_secrecy {
    my ($self) = @_;
    return $self->{forwardSecrecy};
}

sub rc4_with_modern {
    my ($self) = @_;
    return $self->{rc4WithModern} ? 1 : 0;
}

sub sims {
    my ($self) = @_;
    return $self->{sims};
}

sub heartbleed {
    my ($self) = @_;
    return $self->{heartbleed} ? 1 : 0;
}

sub heartbeat {
    my ($self) = @_;
    return $self->{heartbeat} ? 1 : 0;
}

sub open_ssl_ccs {
    my ($self) = @_;
    return $self->{openSslCcs};
}

sub poodle {
    my ($self) = @_;
    return $self->{poodle} ? 1 : 0;
}

sub poodle_tls {
    my ($self) = @_;
    return $self->{poodleTls};
}

sub fallback_scsv {
    my ($self) = @_;
    return $self->{fallbackScsv} ? 1 : 0;
}

sub freak {
    my ($self) = @_;
    return $self->{freak} ? 1 : 0;
}

sub has_sct {
    my ($self) = @_;
    return $self->{hasSct};
}

sub dh_primes {
    my ($self) = @_;
    return @{ $self->{dhPrimes} };
}

sub dh_uses_known_primes {
    my ($self) = @_;
    return $self->{dhUsesKnownPrimes};
}

sub dh_ys_reuse {
    my ($self) = @_;
    return $self->{dhYsReuse};
}

sub logjam {
    my ($self) = @_;
    return $self->{logjam};
}

1;
__END__

=head1 NAME

Net::SSLLabs::EndpointDetails - EndpointDetails object

=head1 VERSION

Version 0.07

=head1 SUBROUTINES/METHODS

=head2 new

a new C<Net::SSLLabs::EndpointDetails> object, accepts a hash ref as it's parameter.

=head2 host_start_time

endpoint assessment starting time, in milliseconds since 1970. This field is useful when test results are retrieved in several HTTP invocations. Then, you should check that the hostStartTime value matches the startTime value of the host.

=head2 key

returns the connected L<Net::SSLLabs::Key|Net::SSLLabs::Key> object

=head2 cert

returns the connected L<Net::SSLLabs::Cert|Net::SSLLabs::Cert> object

=head2 chain

returns the connected L<Net::SSLLabs::Chain|Net::SSLLabs::Chain> object

=head2 protocols

returns the list of supported protocols as L<Net::SSLLabs::Protocol|Net::SSLLabs::Protocol> objects

=head2 suites

returns the L<Net::SSLLabs::Suites|Net::SSLLabs::Suites> object

=head2 server_signature

Contents of the HTTP Server response header when known. This field could be absent for one of two reasons: 1) the HTTP request failed (check httpStatusCode) or 2) there was no Server response header returned.

=head2 prefix_delegation

true if this endpoint is reachable via a hostname with the www prefix

=head2 non_prefix_delegation

true if this endpoint is reachable via a hostname without the www prefix

=head2 vuln_beast

true if the endpoint is vulnerable to the BEAST attack

=head2 reneg_support

this is an integer value that describes the endpoint support for renegotiation:

=over 2

=item bit 0 (1) - set if insecure client-initiated renegotiation is supported

=item bit 1 (2) - set if secure renegotiation is supported

=item bit 2 (4) - set if secure client-initiated renegotiation is supported

=item bit 3 (8) - set if the server requires secure renegotiation support

=back

=head2 sts_response_header

the contents of the Strict-Transport-Security (STS) response header, if seen

=head2 sts_max_age

the maxAge parameter extracted from the STS parameters;
 
=over 2

=item undef if STS not seen, 

=item -1 if the specified value is invalid (e.g., not a zero or a positive integer; the maximum value currently supported is 2,147,483,647)

=back

=head2 sts_subdomains

true if the includeSubDomains STS parameter is set; undef if STS not seen

=head2 pkp_response_header

the contents of the Public-Key-Pinning response header, if seen

=head2 session_resumption

this is an integer value that describes endpoint support for session resumption. The possible values are:

=over 2

=item 0 - session resumption is not enabled and we're seeing empty session IDs

=item 1 - endpoint returns session IDs, but sessions are not resumed

=item 2 - session resumption is enabled

=back

=head2 compression_methods

integer value that describes supported compression methods

=over 2

=item bit 0 is set for DEFLATE

=back

=head2 supports_npn

true if the server supports NPN

=head2 npn_protocols

space separated list of supported protocols

=head2 session_tickets

indicates support for Session Tickets

=over 2

=item bit 0 (1) - set if session tickets are supported

=item bit 1 (2) - set if the implementation is faulty [not implemented]

=item bit 2 (4) - set if the server is intolerant to the extension

=back

=head2 ocsp_stapling

true if OCSP stapling is deployed on the server

=head2 stapling_revocation_status

same as Cert.revocationStatus, but for the stapled OCSP response.

=head2 stapling_revocation_error_message

description of the problem with the stapled OCSP response, if any.

=head2 sni_required

if SNI support is required to access the web site.

=head2 http_status_code

status code of the final HTTP response seen. When submitting HTTP requests, redirections are followed, but only if they lead to the same hostname. If this field is not available, that means the HTTP request failed.

=head2 http_forwarding

available on a server that responded with a redirection to some other hostname.

=head2 supports_rc4

true if the server supports at least one RC4 suite.

=head2 forward_secrecy

indicates support for Forward Secrecy

=over 2

=item bit 0 (1) - set if at least one browser from our simulations negotiated a Forward Secrecy suite.

=item bit 1 (2) - set based on Simulator results if FS is achieved with modern clients. For example, the server supports ECDHE suites, but not DHE.

=item bit 2 (4) - set if all simulated clients achieve FS. In other words, this requires an ECDHE + DHE combination to be supported.

=back

=head2 rc4_with_modern

true if RC4 is used with modern clients.

=head2 sims

instance of L<Net::SSLLabs::SimDetails|Net::SSLLabs::SimDetails>.

=head2 heartbleed

true if the server is vulnerable to the Heartbleed attack.

=head2 heartbeat

true if the server supports the Heartbeat extension.

=head2 open_ssl_ccs

results of the CVE-2014-0224 test:

=over 2

=item -1 - test failed

=item 0 - unknown

=item 1 - not vulnerable

=item 2 - possibly vulnerable, but not exploitable

=item 3 - vulnerable and exploitable

=back

=head2 poodle

true if the endpoint is vulnerable to POODLE; false otherwise

=head2 poodle_tls

results of the POODLE TLS test:

=over 2

=item -1 - test failed

=item 0 - unknown

=item 1 - not vulnerable

=item 2 - vulnerable

=back

=head2 fallback_scsv

true if the server supports TLS_FALLBACK_SCSV, false if it doesn't. This field will not be available if the server's support for TLS_FALLBACK_SCSV can't be tested because it supports only one protocol version (e.g., only TLS 1.2).

=head2 freak

true of the server is vulnerable to the FREAK attack, meaning it supports 512-bit key exchange.

=head2 has_sct

information about the availability of certificate transparency information (embedded SCTs):

=over 2

=item bit 0 (1) - SCT in certificate

=item bit 1 (2) - SCT in the stapled OCSP response

=item bit 2 (4) - SCT in the TLS extension (ServerHello)

=back

=head2 dh_primes

list of hex-encoded DH primes used by the server

=head2 dh_uses_known_primes

whether the server uses known DH primes:

=over 2

=item 0 - no

=item 1 - yes, but they're not weak

=item 2 - yes and they're weak

=back

=head2 dh_ys_reuse

true if the DH ephemeral server value is reused.

=head2 logjam

true if the server uses DH parameters weaker than 1024 bits.

=head1 DIAGNOSTICS

None

=head1 CONFIGURATION AND ENVIRONMENT

Net::SSLLabs::EndpointDetails requires no configuration files or environment variables.

=head1 DEPENDENCIES

Net::SSLLabs::EndpointDetails requires no non-core modules

=head1 INCOMPATIBILITIES

None reported

=head1 BUGS AND LIMITATIONS

Please report any bugs or feature requests to C<bug-net-ssllabs at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-SSLLabs>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.

=head1 AUTHOR

David Dick, C<< <ddick at cpan.org> >>

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Net::SSLLabs::EndpointDetails


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-SSLLabs>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/Net-SSLLabs>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/Net-SSLLabs>

=item * Search CPAN

L<http://search.cpan.org/dist/Net-SSLLabs/>

=back


=head1 ACKNOWLEDGEMENTS

Thanks to Ivan Ristic and the team at L<https://www.qualys.com> for providing the service at L<https://www.ssllabs.com>

POD was extracted from the API help at L<https://github.com/ssllabs/ssllabs-scan/blob/stable/ssllabs-api-docs.md>

=head1 LICENSE AND COPYRIGHT

Copyright 2015 David Dick.

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See L<http://dev.perl.org/licenses/> for more information.
