Skip to content

Commit 7de54a6

Browse files
authored
Merge pull request #162 from dhs-ncats/develop
Pulling develop into master
2 parents 4e9505d + 41f6f94 commit 7de54a6

File tree

7 files changed

+59
-32
lines changed

7 files changed

+59
-32
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ language: python
33
sudo: false
44

55
python:
6-
- '2.7'
76
- '3.4'
87
- '3.5'
98
- '3.6'

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
## Pushing HTTPS :lock:
22

3+
[![Latest Version](https://img.shields.io/pypi/v/pshtt.svg)](https://pypi.python.org/pypi/pshtt/)
34
[![Coverage Status](https://coveralls.io/repos/github/dhs-ncats/pshtt/badge.svg)](https://coveralls.io/github/dhs-ncats/pshtt)
4-
55
[![Build Status](https://travis-ci.org/dhs-ncats/pshtt.svg?branch=master)](https://travis-ci.org/dhs-ncats/pshtt)
66

77
`pshtt` (_"pushed"_) is a tool to scan domains for HTTPS best practices. It saves its results to a CSV (or JSON) file.
@@ -12,6 +12,8 @@
1212

1313
## Getting Started
1414

15+
`pshtt` requires **Python 3.4+**. Python 2 is not supported.
16+
1517
`pshtt` can be installed as a module, or run directly from the repository.
1618

1719
#### Installed as a module
@@ -124,9 +126,9 @@ The following values are returned in `results.csv`:
124126
* `HSTS Max Age` - A domain's HSTS max-age is its canonical endpoint's max-age.
125127
* `HSTS Entire Domain` - A domain has HSTS enabled for the entire domain if its **root HTTPS endpoint** (_not the canonical HTTPS endpoint_) has HSTS enabled and uses the HSTS `includeSubDomains` flag.
126128
* `HSTS Preload Ready` - A domain is HSTS "preload ready" if its **root HTTPS endpoint** (_not the canonical HTTPS endpoint_) has HSTS enabled, has a max-age of at least 18 weeks, and uses the `includeSubDomains` and `preload` flag.
127-
* `HSTS Preload Pending` - A domain is "preload pending" when it appears in the [Chrome preload pending list](https://hstspreload.org/api/v2/pending).
128-
* `HSTS Preloaded` - A domain is HSTS preloaded if its domain name appears in the [Chrome preload list](https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json), regardless of what header is present on any endpoint.
129-
* `Base Domain HSTS Preloaded` - A domain's base domain is HSTS preloaded. This is subtly different from `HSTS Entire Domain`, which inpects headers on the base domain to see if HSTS is set correctly to encompass the entire zone. This checks the preload list directly.
129+
* `HSTS Preload Pending` - A domain is "preload pending" when it appears in the [Chrome preload pending list](https://hstspreload.org/api/v2/pending) with the `include_subdomains` flag equal to `true`. The intent of `pshtt` is to make sure that the user is _fully_ protected, so it only counts domains as HSTS preloaded if they are _fully_ HSTS preloaded (meaning that all subdomains are included as well).
130+
* `HSTS Preloaded` - A domain is HSTS preloaded if its domain name appears in the [Chrome preload list](https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json) with the `include_subdomains` flag equal to `true`, regardless of what header is present on any endpoint. The intent of `pshtt` is to make sure that the user is _fully_ protected, so it only counts domains as HSTS preloaded if they are _fully_ HSTS preloaded (meaning that all subdomains are included as well).
131+
* `Base Domain HSTS Preloaded` - A domain's base domain is HSTS preloaded if its base domain appears in the [Chrome preload list](https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json) with the `include_subdomains` flag equal to `true`. This is subtly different from `HSTS Entire Domain`, which inpects headers on the base domain to see if HSTS is set correctly to encompass the entire zone.
130132

131133
#### Scoring
132134

bump_version.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#/usr/bin/env bash
2+
3+
# bump_version.sh (show|major|minor|patch|prerelease|build)
4+
5+
VERSION_FILE=pshtt/__init__.py
6+
7+
HELP_INFORMATION="bump_version.sh (show|major|minor|patch|prerelease|build|finalize)"
8+
9+
old_version=$(sed "s/__version__ = '\(.*\)'/\1/" $VERSION_FILE)
10+
11+
if [[ $# -ne 1 ]]
12+
then
13+
echo $HELP_INFORMATION
14+
else
15+
case $1 in
16+
major|minor|patch|prerelease|build)
17+
new_version=$(python -c "import semver; print(semver.bump_$1('$old_version'))")
18+
echo Changing version from $old_version to $new_version
19+
sed -i "s/$old_version/$new_version/" $VERSION_FILE
20+
;;
21+
finalize)
22+
new_version=$(python -c "import semver; print(semver.finalize_version('$old_version'))")
23+
echo Changing version from $old_version to $new_version
24+
sed -i "s/$old_version/$new_version/" $VERSION_FILE
25+
;;
26+
show)
27+
echo $old_version
28+
;;
29+
*)
30+
echo $HELP_INFORMATION
31+
;;
32+
esac
33+
fi

pshtt/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.4.0-dev'
1+
__version__ = '0.4.1'

pshtt/pshtt.py

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from urllib2 import URLError
2727

2828
import sslyze
29+
from sslyze.server_connectivity_tester import ServerConnectivityTester, ServerConnectivityError
2930
import sslyze.synchronous_scanner
3031

3132
# We're going to be making requests with certificate validation disabled.
@@ -335,7 +336,6 @@ def basic_check(endpoint):
335336
base_immediate = parent_domain_for(subdomain_immediate)
336337

337338
endpoint.redirect_immediately_to = immediate
338-
endpoint.redirect_immediately_to_www = (re.match(r'^https?://www\.', immediate) is not None)
339339
endpoint.redirect_immediately_to_https = immediate.startswith("https://")
340340
endpoint.redirect_immediately_to_http = immediate.startswith("http://")
341341
endpoint.redirect_immediately_to_external = (base_original != base_immediate)
@@ -344,6 +344,13 @@ def basic_check(endpoint):
344344
(subdomain_original != subdomain_immediate)
345345
)
346346

347+
# We're interested in whether an endpoint redirects to the www version
348+
# of itself (not whether it redirects to www prepended to any other
349+
# hostname, even within the same parent domain).
350+
endpoint.redirect_immediately_to_www = (
351+
subdomain_immediate == ("www.%s" % subdomain_original)
352+
)
353+
347354
if ultimate_req is not None:
348355
# For ultimate destination, use the URL we arrived at,
349356
# not Location header. Auto-resolves relative redirects.
@@ -442,17 +449,10 @@ def https_check(endpoint):
442449
# remove the https:// from prefix for sslyze
443450
try:
444451
hostname = endpoint.url[8:]
445-
server_info = sslyze.server_connectivity.ServerConnectivityInfo(hostname=hostname, port=443)
446-
except Exception as err:
447-
endpoint.unknown_error = True
448-
logging.warn("Unknown exception when checking server connectivity info with sslyze.")
449-
utils.debug("{0}".format(err))
450-
return
451-
452-
try:
453-
server_info.test_connectivity_to_server()
454-
except sslyze.server_connectivity.ServerConnectivityError as err:
455-
logging.warn("Error in sslyze server connectivity check")
452+
server_tester = ServerConnectivityTester(hostname=hostname, port=443)
453+
server_info = server_tester.perform()
454+
except ServerConnectivityError as err:
455+
logging.warn("Error in sslyze server connectivity check when connecting to {}".format(err.server_info.hostname))
456456
utils.debug("{0}".format(err))
457457
return
458458
except Exception as err:
@@ -592,12 +592,6 @@ def root_down(endpoint):
592592
)
593593
)
594594

595-
def goes_to_www(endpoint):
596-
return (
597-
endpoint.redirect_immediately_to_www and
598-
(not endpoint.redirect_immediately_to_external)
599-
)
600-
601595
all_roots_unused = root_unused(https) and root_unused(http)
602596

603597
all_roots_down = root_down(https) and root_down(http)
@@ -606,8 +600,8 @@ def goes_to_www(endpoint):
606600
at_least_one_www_used and
607601
all_roots_unused and (
608602
all_roots_down or
609-
goes_to_www(https) or
610-
goes_to_www(http)
603+
https.redirect_immediately_to_www or
604+
http.redirect_immediately_to_www
611605
)
612606
)
613607

setup.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@
4444

4545
# Specify the Python versions you support here. In particular, ensure
4646
# that you indicate whether you support Python 2, Python 3 or both.
47-
'Programming Language :: Python :: 2',
48-
'Programming Language :: Python :: 2.7',
4947
'Programming Language :: Python :: 3',
5048
'Programming Language :: Python :: 3.4',
5149
'Programming Language :: Python :: 3.5',
@@ -59,7 +57,7 @@
5957

6058
install_requires=[
6159
'requests>=2.18.4',
62-
'sslyze>=1.1.0',
60+
'sslyze>=1.4.1',
6361
'wget>=3.2',
6462
'docopt',
6563
'pytablereader',
@@ -70,9 +68,10 @@
7068

7169
extras_require={
7270
# 'dev': ['check-manifest'],
73-
'test': [
71+
'dev': [
72+
'pytest',
73+
'semver',
7474
'tox',
75-
'pytest'
7675
],
7776
},
7877

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tox]
2-
envlist = py27,py34,py35,py36,flake8
2+
envlist = py34,py35,py36,flake8
33
skip_missing_interpreters = true
44
; usedevelop = true
55

0 commit comments

Comments
 (0)