aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_external.py
blob: 0628d96ade3d5a0c55227352b1f7218f78ad2602 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""These tests rely on replies from public internet services

TODO: reimplement with local stubs
"""
import httplib2
import os
import pytest
import ssl
import sys
import tests


def test_get_301_via_https():
    # Google always redirects to http://google.com
    http = httplib2.Http()
    response, content = http.request("https://code.google.com/apis/", "GET")
    assert response.status == 200
    assert response.previous.status == 301


def test_get_via_https():
    # Test that we can handle HTTPS
    http = httplib2.Http()
    response, content = http.request("https://google.com/adsense/", "GET")
    assert response.status == 200


def test_get_via_https_spec_violation_on_location():
    # Test that we follow redirects through HTTPS
    # even if they violate the spec by including
    # a relative Location: header instead of an
    # absolute one.
    http = httplib2.Http()
    response, content = http.request("https://google.com/adsense", "GET")
    assert response.status == 200
    assert response.previous is not None


def test_get_via_https_key_cert():
    #  At this point I can only test
    #  that the key and cert files are passed in
    #  correctly to httplib. It would be nice to have
    #  a real https endpoint to test against.
    http = httplib2.Http(timeout=2)
    http.add_certificate("akeyfile", "acertfile", "bitworking.org")
    try:
        http.request("https://bitworking.org", "GET")
    except AttributeError:
        assert http.connections["https:bitworking.org"].key_file == "akeyfile"
        assert http.connections["https:bitworking.org"].cert_file == "acertfile"
    except IOError:
        # Skip on 3.2
        pass

    try:
        http.request("https://notthere.bitworking.org", "GET")
    except httplib2.ServerNotFoundError:
        assert http.connections["https:notthere.bitworking.org"].key_file is None
        assert http.connections["https:notthere.bitworking.org"].cert_file is None
    except IOError:
        # Skip on 3.2
        pass


def test_ssl_invalid_ca_certs_path():
    # Test that we get an ssl.SSLError when specifying a non-existent CA
    # certs file.
    http = httplib2.Http(ca_certs="/nosuchfile")
    with tests.assert_raises(IOError):
        http.request("https://www.google.com/", "GET")


@pytest.mark.xfail(
    sys.version_info <= (3,),
    reason=(
        "FIXME: for unknown reason Python 2.7.10 validates www.google.com "
        "against dummy CA www.example.com"
    ),
)
def test_ssl_wrong_ca():
    # Test that we get a SSLHandshakeError if we try to access
    # https://www.google.com, using a CA cert file that doesn't contain
    # the CA Google uses (i.e., simulating a cert that's not signed by a
    # trusted CA).
    other_ca_certs = os.path.join(
        os.path.dirname(os.path.abspath(httplib2.__file__)), "test", "other_cacerts.txt"
    )
    assert os.path.exists(other_ca_certs)
    http = httplib2.Http(ca_certs=other_ca_certs)
    http.follow_redirects = False
    with tests.assert_raises(ssl.SSLError):
        http.request("https://www.google.com/", "GET")


def test_sni_hostname_validation():
    # TODO: make explicit test server with SNI validation
    http = httplib2.Http()
    http.request("https://google.com/", method="GET")


@pytest.mark.skipif(
    os.environ.get("TRAVIS_PYTHON_VERSION") in ("2.7", "pypy"),
    reason="Python 2.7 doesn't support TLS min/max"
)
def test_min_tls_version():
    # skip on Python versions that don't support TLS min
    if not hasattr(ssl.SSLContext(), 'minimum_version'):
        return
    # BadSSL server that supports max TLS 1.1,
    # forcing 1.2 should always fail
    http = httplib2.Http(tls_minimum_version="TLSv1_2")
    with tests.assert_raises(ssl.SSLError):
        http.request("https://tls-v1-1.badssl.com:1011/")


@pytest.mark.skipif(
    os.environ.get("TRAVIS_PYTHON_VERSION") in ("2.7", "pypy"),
    reason="Python 2.7 doesn't support TLS min/max"
)
def test_max_tls_version():
    # skip on Python versions that don't support TLS max
    if not hasattr(ssl.SSLContext(), 'maximum_version'):
        return
    # Google supports TLS 1.2+, confirm we can force down to 1.0
    # this may break whenever Google disables TLSv1
    http = httplib2.Http(tls_maximum_version="TLSv1")
    http.request("https://google.com")
    _, tls_ver, _ = http.connections['https:google.com'].sock.cipher()
    assert tls_ver == "TLSv1.0"