Merge branch 'master' into ecdsa

This commit is contained in:
osirisinferi 2017-04-30 13:24:55 +02:00
commit 692227d824
No known key found for this signature in database
GPG key ID: 590297AD5FAE2134
27 changed files with 516 additions and 56 deletions

259
AUTHORS.md Normal file
View file

@ -0,0 +1,259 @@
Authors
=======
* [Aaron Zirbes](https://github.com/aaronzirbes)
* Aaron Zuehlke
* Ada Lovelace
* [Adam Woodbeck](https://github.com/awoodbeck)
* [Aidin Gharibnavaz](https://github.com/aidin36)
* [AJ ONeal](https://github.com/coolaj86)
* [Alcaro](https://github.com/Alcaro)
* [Alexander Mankuta](https://github.com/pointlessone)
* [Alex Bowers](https://github.com/alexbowers)
* [Alex Conlin](https://github.com/alexconlin)
* [Alex Gaynor](https://github.com/alex)
* [Alex Halderman](https://github.com/jhalderm)
* [Alex Jordan](https://github.com/strugee)
* [Amjad Mashaal](https://github.com/TheNavigat)
* [Andrew Murray](https://github.com/radarhere)
* [Anselm Levskaya](https://github.com/levskaya)
* [Antoine Jacoutot](https://github.com/ajacoutot)
* [asaph](https://github.com/asaph)
* [Axel Beckert](https://github.com/xtaran)
* [Bas](https://github.com/Mechazawa)
* [benbankes](https://github.com/benbankes)
* [Ben Irving](https://github.com/benileo)
* [Benjamin Kerensa](https://github.com/bkerensa)
* [Benjamin Neff](https://github.com/SuperTux88)
* [Benjamin Piouffle](https://github.com/Betree)
* [Ben Ubois](https://github.com/benubois)
* [Ben Wolfe](https://github.com/bwolfe)
* [Bigfish](https://github.com/bwolfe)
* [Blake Griffith](https://github.com/cowlicks)
* [Brad Warren](https://github.com/bmw)
* [Brandon Kraft](https://github.com/kraftbj)
* [Brandon Kreisel](https://github.com/kraftbj)
* [Ceesjan Luiten](https://github.com/quinox)
* [Chad Whitacre](https://github.com/whit537)
* [Chhatoi Pritam Baral](https://github.com/pritambaral)
* [Chris Johns](https://github.com/ter0)
* [Chris Lamb](https://github.com/lamby)
* [chrismarget](https://github.com/chrismarget)
* [Christian Gärtner](https://github.com/ChristianGaertner)
* [Christian Rosentreter](https://github.com/the-real-tokai)
* [Christopher Brown](https://github.com/chbrown)
* [Christopher Manning](https://github.com/christophermanning)
* [Christoph Kisfeld](https://github.com/chk1)
* [Clif Houck](https://github.com/ClifHouck)
* [Cooper Quintin](https://github.com/cooperq)
* [Corey Farwell](https://github.com/frewsxcv)
* [Craig Smith](https://github.com/dashaxiong)
* [Damian Poddebniak](https://github.com/duesee)
* [Damien Nozay](https://github.com/dnozay)
* [Damien Tournoud](https://github.com/damz)
* [DanCld](https://github.com/DanCld)
* [Daniel Albers](https://github.com/AID)
* [Daniel Aleksandersen](https://github.com/da2x)
* [Daniel Convissor](https://github.com/convissor)
* [Daniel Huang](https://github.com/dhuang)
* [Dave Guarino](https://github.com/daguar)
* [David cz](https://github.com/dave-cz)
* [David Dworken](https://github.com/ddworken)
* [David Kreitschmann](https://kreitschmann.de)
* [David Xia](https://github.com/davidxia)
* [Devin Howard](https://github.com/devvmh)
* [dokazaki](https://github.com/dokazaki)
* [Dominic Cleal](https://github.com/domcleal)
* [Dominic Lüchinger](https://github.com/dol)
* [Douglas José](https://github.com/douglasjose)
* [Erica Portnoy](https://github.com/ohemorange)
* [Eric Engestrom](https://github.com/1ace)
* [Eric Rescorla](https://github.com/ekr)
* [Eric Wustrow](https://github.com/ewust)
* [Erik Rose](https://github.com/erikrose)
* [Eugene Kazakov](https://github.com/xgin)
* [Fabian](https://github.com/faerbit)
* [Faidon Liambotis](https://github.com/paravoid)
* [Fan Jiang](https://github.com/tcz001)
* [Felix Schwarz](https://github.com/FelixSchwarz)
* [Felix Yan](https://github.com/felixonmars)
* [Filip Ochnik](https://github.com/filipochnik)
* [Francois Marier](https://github.com/fmarier)
* [Frank](https://github.com/Frankkkkk)
* [Frederic BLANC](https://github.com/fblanc)
* [Garrett Robinson](https://github.com/garrettr)
* [Gene Wood](https://github.com/gene1wood)
* [Geoffroy Doucet](https://www.geoffroydoucet.com)
* [Gian Carlo Pace](https://github.com/gicappa)
* [Gilles Pietri](https://github.com/gilou)
* [Giovanni Pellerano](https://github.com/evilaliv3)
* [Giovanni Toraldo](https://github.com/gionn)
* [Gordin](https://github.com/Gordin)
* [Gregor Dschung](https://github.com/chkpnt)
* [Gregory L. Dietsche](https://github.com/farmergreg)
* [Greg Osuri](https://github.com/gosuri)
* [Guillaume Boudreau](https://github.com/gboudreau)
* [Harlan Lieberman-Berg](https://github.com/hlieberman)
* [Henri Salo](https://github.com/fgeek)
* [Henry Chen](https://github.com/henrychen95)
* [Ingolf Becker](https://github.com/watercrossing)
* [Jaap Eldering](https://github.com/eldering)
* [Jacob Hoffman-Andrews](https://github.com/jsha)
* [Jacob Sachs](https://github.com/jsachs)
* [Jairo Llopis](https://github.com/Yajo)
* [Jakub Warmuz](https://github.com/kuba)
* [James Kasten](https://github.com/jdkasten)
* [Jason Grinblat](https://github.com/ptychomancer)
* [Jay Faulkner](https://github.com/jayofdoom)
* [J.C. Jones](https://github.com/jcjones)
* [Jeff Hodges](https://github.com/jmhodges)
* [Jeremy Gillula](https://github.com/jgillula)
* [Jeroen Ketelaar](https://github.com/JKetelaar)
* [Jeroen Pluimers](https://github.com/jpluimers)
* [j](https://github.com/bit)
* [Jim Tittsler](https://github.com/jimt)
* [Joe Ranweiler](https://github.com/ranweiler)
* [Joerg Sonnenberger](https://github.com/jsonn)
* [John Leach](https://github.com/johnl)
* [John Reed](https://github.com/leerspace)
* [Jonas Berlin](https://github.com/xkr47)
* [Jonathan Herlin](https://github.com/Jonher937)
* [Jon Walsh](https://github.com/code-tree)
* [Joona Hoikkala](https://github.com/joohoi)
* [Josh Soref](https://github.com/jsoref)
* [Joubin Jabbari](https://github.com/joubin)
* [Juho Juopperi](https://github.com/jkjuopperi)
* [Kane York](https://github.com/riking)
* [Kenneth Skovhede](https://github.com/kenkendk)
* [Kevin Burke](https://github.com/kevinburke)
* [Kevin London](https://github.com/kevinlondon)
* [Kubilay Kocak](https://github.com/koobs)
* [LeCoyote](https://github.com/LeCoyote)
* [Lee Watson](https://github.com/TheReverend403)
* [Leo Famulari](https://github.com/lfam)
* [lf](https://github.com/lf-)
* [Liam Marshall](https://github.com/liamim)
* [Lior Sabag](https://github.com/liorsbg)
* [Lipis](https://github.com/lipis)
* [lord63](https://github.com/lord63)
* [Luca Beltrame](https://github.com/lbeltrame)
* [Luca Ebach](https://github.com/lucebac)
* [Luca Olivetti](https://github.com/olivluca)
* [Luke Rogers](https://github.com/lukeroge)
* [Maarten](https://github.com/mrtndwrd)
* [Maikel Martens](https://github.com/krukas)
* [Malte Janduda](https://github.com/MalteJ)
* [Mantas Mikulėnas](https://github.com/grawity)
* [Marcel Krüger](https://github.com/zauguin)
* [Marcos Caceres](https://github.com/marcoscaceres)
* [Marek Viger](https://github.com/freezy-sk)
* [Mario Villaplana](https://github.com/supermari0)
* [Marius Gedminas](https://github.com/mgedmin)
* [Martey Dodoo](https://github.com/martey)
* [Martijn Bastiaan](https://github.com/martijnbastiaan)
* [Martijn Braam](https://github.com/MartijnBraam)
* [Martin Brugger](https://github.com/mbrugger)
* [Mathieu Leduc-Hamel](https://github.com/mlhamel)
* [Matt Bostock](https://github.com/mattbostock)
* [Matthew Ames](https://github.com/SuperMatt)
* [Michael Schumacher](https://github.com/schumaml)
* [Michael Strache](https://github.com/Jarodiv)
* [Michael Sverdlin](https://github.com/sveder)
* [Michal Moravec](https://github.com/https://github.com/Majkl578)
* [Michal Papis](https://github.com/mpapis)
* [Minn Soe](https://github.com/MinnSoe)
* [Min RK](https://github.com/minrk)
* [Miquel Ruiz](https://github.com/miquelruiz)
* [Môshe van der Sterre](https://github.com/moshevds)
* [mrstanwell](https://github.com/mrstanwell)
* [Nav Aulakh](https://github.com/Nav)
* [Nelson Elhage](https://github.com/nelhage)
* [Nick Fong](https://github.com/nickfong)
* [Nick Le Mouton](https://github.com/NoodlesNZ)
* [Nikos Roussos](https://github.com/comzeradd)
* [Noah Swartz](https://github.com/swartzcr)
* [Ola Bini](https://github.com/olabini)
* [Ondřej Súkup](https://github.com/mimi1vx)
* [Ondřej Surý](https://github.com/oerdnj)
* [osirisinferi](https://github.com/osirisinferi)
* Patrick Figel
* [Patrick Heppler](https://github.com/PatrickHeppler)
* [Paul Feitzinger](https://github.com/pfeyz)
* [Pavan Gupta](https://github.com/pavgup)
* [Pavel Pavlov](https://github.com/ghost355)
* [Peter Conrad](https://github.com/pconrad-fb)
* [Peter Eckersley](https://github.com/pde)
* [Peter Mosmans](https://github.com/PeterMosmans)
* [Philippe Langlois](https://github.com/langloisjp)
* [Philipp Spitzer](https://github.com/spitza)
* [Piero Steinger](https://github.com/Jadaw1n)
* [Pierre Jaury](https://github.com/kaiyou)
* [Piotr Kasprzyk](https://github.com/kwadrat)
* [Prayag Verma](https://github.com/pra85)
* [Reinaldo de Souza Jr](https://github.com/juniorz)
* [Remi Rampin](https://github.com/remram44)
* [Rémy HUBSCHER](https://github.com/Natim)
* [Rémy Léone](https://github.com/sieben)
* [Richard Barnes](https://github.com/r-barnes)
* [Richard Panek](https://github.com/kernelpanek)
* [Robert Buchholz](https://github.com/rbu)
* [Robert Habermann](https://github.com/frennkie)
* [Robert Xiao](https://github.com/nneonneo)
* [Roland Shoemaker](https://github.com/rolandshoemaker)
* [Roy Wellington Ⅳ](https://github.com/thanatos)
* [rugk](https://github.com/rugk)
* [Sachi King](https://github.com/nakato)
* [Sagi Kedmi](https://github.com/sagi)
* [Sam Lanning](https://github.com/samlanning)
* [sapics](https://github.com/sapics)
* [Scott Barr](https://github.com/scottjbarr)
* [Scott Merrill](https://github.com/skpy)
* [Sebastian Bögl](https://github.com/TheBoegl)
* [Sebastian Wagner](https://github.com/sebix)
* [sedrubal](https://github.com/sedrubal)
* [Seppe Stas](https://github.com/seppestas)
* [Sergey Nuzdhin](https://github.com/lwolf)
* [Seth Schoen](https://github.com/schoen)
* [Sharif Nassar](https://github.com/mrwacky42)
* [Shaun Cummiskey](https://github.com/ampersign)
* [Shiloh Heurich](https://github.com/sheurich)
* [silverwind](https://github.com/silverwind)
* [Sorvani](https://github.com/sorvani)
* [Spencer Bliven](https://github.com/sbliven)
* [Stacey Sheldon](https://github.com/solidgoldbomb)
* [Stavros Korokithakis](https://github.com/skorokithakis)
* [Stefan Weil](https://github.com/stweil)
* [Steve Desmond](https://github.com/stevedesmond-ca)
* [Tan Jay Jun](https://github.com/jayjun)
* [Tapple Gao](https://github.com/tapple)
* [Telepenin Nikolay](https://github.com/telepenin)
* [Thomas Cottier](https://github.com/tcottier-enalean)
* [Thomas Mayer](https://github.com/thomaszbz)
* [Thomas Waldmann](https://github.com/ThomasWaldmann)
* [Thom Wiggers](https://github.com/thomwiggers)
* [Till Maas](https://github.com/tyll)
* [Timothy Guan-tin Chien](https://github.com/timdream)
* [Torsten Bögershausen](https://github.com/tboegi)
* [Travis Raines](https://github.com/rainest)
* [Trung Ngo](https://github.com/Ngo-The-Trung)
* [Valentin](https://github.com/e00E)
* [venyii](https://github.com/venyii)
* [Viktor Szakats](https://github.com/vszakats)
* [Ville Skyttä](https://github.com/scop)
* [Vinney Cavallo](https://github.com/vcavallo)
* [Vladimir Rutsky](https://github.com/rutsky)
* [Wang Yu](https://github.com/wyhitcs)
* [Ward Vandewege](https://github.com/cure)
* [Whyfoo](https://github.com/whyfoo)
* [Wilfried Teiken](https://github.com/wteiken)
* [Willem Fibbe](https://github.com/fibbers)
* [William Budington](https://github.com/Hainish)
* [Will Newby](https://github.com/willnewby)
* [Will Oller](https://github.com/willoller)
* [Yan](https://github.com/diracdeltas)
* [Yen Chi Hsuan](https://github.com/yan12125)
* [Yomna](https://github.com/ynasser)
* [Yoni Jah](https://github.com/yonjah)
* [YourDaddyIsHere](https://github.com/YourDaddyIsHere)
* [Zach Shepherd](https://github.com/zjs)
* [陈三](https://github.com/chenxsan)

View file

@ -8,7 +8,6 @@ version = '0.14.0.dev0'
# Please update tox.ini when modifying dependency version requirements
install_requires = [
'argparse',
# load_pem_private/public_key (>=0.6)
# rsa_recover_prime_factors (>=0.8)
'cryptography>=0.8',
@ -28,6 +27,10 @@ install_requires = [
'six',
]
# env markers cause problems with older pip and setuptools
if sys.version_info < (2, 7):
install_requires.append('argparse')
dev_extras = [
'nose',
'tox',
@ -59,6 +62,7 @@ setup(
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Security',
],

2
certbot-apache/setup.cfg Normal file
View file

@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1

View file

@ -42,6 +42,11 @@ setup(
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Security',
'Topic :: System :: Installation/Setup',

View file

@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1

View file

@ -42,6 +42,11 @@ setup(
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Security',
],

View file

@ -110,7 +110,7 @@ class NginxParser(object):
srv = servers[filename] # workaround undefined loop var in lambdas
# Find all the server blocks
_do_for_subarray(tree, lambda x: x[0] == ['server'],
_do_for_subarray(tree, lambda x: len(x) >= 2 and x[0] == ['server'],
lambda x, y: srv.append((x[1], y)))
# Find 'include' statements in server blocks and append their trees

View file

@ -125,13 +125,13 @@ class NginxParserTest(util.NginxTest):
False, True,
set(['localhost',
r'~^(www\.)?(example|bar)\.']),
[], [9, 1, 9])
[], [10, 1, 9])
vhost2 = obj.VirtualHost(nparser.abs_path('nginx.conf'),
[obj.Addr('somename', '8080', False, False),
obj.Addr('', '8000', False, False)],
False, True,
set(['somename', 'another.alias', 'alias']),
[], [9, 1, 12])
[], [10, 1, 12])
vhost3 = obj.VirtualHost(nparser.abs_path('sites-enabled/example.com'),
[obj.Addr('69.50.225.155', '9000',
False, False),
@ -186,7 +186,7 @@ class NginxParserTest(util.NginxTest):
None, None, None,
set(['localhost',
r'~^(www\.)?(example|bar)\.']),
None, [9, 1, 9])
None, [10, 1, 9])
nparser.add_server_directives(mock_vhost,
[['foo', 'bar'], ['\n ', 'ssl_certificate', ' ',
'/etc/ssl/cert.pem']],

View file

@ -14,6 +14,9 @@ events {
worker_connections 1024;
}
empty {
}
include foo.conf;
http {

View file

@ -100,9 +100,13 @@ class NginxTlsSni01(common.TLSSNI01):
if line[0] == ['http']:
body = line[1]
found_bucket = False
posn = 0
for inner_line in body:
if inner_line[0] == bucket_directive[1]:
if int(inner_line[1]) < int(bucket_directive[3]):
body[posn] = bucket_directive
found_bucket = True
posn += 1
if not found_bucket:
body.insert(0, bucket_directive)
if include_directive not in body:

2
certbot-nginx/setup.cfg Normal file
View file

@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1

View file

@ -42,6 +42,11 @@ setup(
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Security',
'Topic :: System :: Installation/Setup',

View file

@ -1115,10 +1115,13 @@ def _create_subparsers(helpful):
helpful.add(
None, "--user-agent", default=None,
help="Set a custom user agent string for the client. User agent strings allow "
"the CA to collect high level statistics about success rates by OS and "
"plugin. If you wish to hide your server OS version from the Let's "
"the CA to collect high level statistics about success rates by OS, "
"plugin and use case, and to know when to deprecate support for past Python "
"versions and flags. If you wish to hide this information from the Let's "
'Encrypt server, set this to "". '
'(default: {0})'.format(sample_user_agent()))
'(default: {0}). The flags encoded in the user agent are: '
'--duplicate, --force-renew, --allow-subset-of-names, -n, and '
'whether any hooks are set.'.format(sample_user_agent()))
helpful.add("certonly",
"--csr", type=read_file,
help="Path to a Certificate Signing Request (CSR) in DER or PEM format."

View file

@ -1,6 +1,7 @@
"""Certbot client API."""
import logging
import os
import platform
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
@ -53,21 +54,49 @@ def determine_user_agent(config):
"""
if config.user_agent is None:
ua = "CertbotACMEClient/{0} ({1}) Authenticator/{2} Installer/{3}"
ua = ua.format(certbot.__version__, util.get_os_info_ua(),
config.authenticator, config.installer)
ua = ("CertbotACMEClient/{0} ({1}; {2}) Authenticator/{3} Installer/{4} "
"({5}; flags: {6}) Py/{7}")
ua = ua.format(certbot.__version__, cli.cli_command, util.get_os_info_ua(),
config.authenticator, config.installer, config.verb,
ua_flags(config), platform.python_version())
else:
ua = config.user_agent
return ua
def ua_flags(config):
"Turn some very important CLI flags into clues in the user agent."
if isinstance(config, DummyConfig):
return "FLAGS"
flags = []
if config.duplicate:
flags.append("dup")
if config.renew_by_default:
flags.append("frn")
if config.allow_subset_of_names:
flags.append("asn")
if config.noninteractive_mode:
flags.append("n")
hook_names = ("pre", "post", "renew", "manual_auth", "manual_cleanup")
hooks = [getattr(config, h + "_hook") for h in hook_names]
if any(hooks):
flags.append("hook")
return " ".join(flags)
class DummyConfig(object):
"Shim for computing a sample user agent."
def __init__(self):
self.authenticator = "XXX"
self.installer = "YYY"
self.user_agent = None
self.verb = "SUBCOMMAND"
def __getattr__(self, name):
"Any config properties we might have are None."
return None
def sample_user_agent():
"Document what this Certbot's user agent string will be like."
class DummyConfig(object):
"Shim for computing a sample user agent."
def __init__(self):
self.authenticator = "XXX"
self.installer = "YYY"
self.user_agent = None
return determine_user_agent(DummyConfig())

View file

@ -50,13 +50,13 @@ def save_key(key_pem, key_dir, keyname="key-certbot.pem"):
config.strict_permissions)
if config.dry_run:
key_path = None
logger.info("Dry run, not saving private key to file")
logger.debug("Dry run, not saving private key to file")
else:
key_f, key_path = util.unique_file(
os.path.join(key_dir, keyname), 0o600, "wb")
with key_f:
key_f.write(key_pem)
logger.info("Saving private key: %s", key_path)
logger.debug("Saving private key: %s", key_path)
return util.Key(key_path, key_pem)
@ -85,13 +85,13 @@ def init_save_csr(privkey, names, path):
config.strict_permissions)
if config.dry_run:
csr_filename = None
logger.info("Creating CSR: not saving to file")
logger.debug("Creating CSR: not saving to file")
else:
csr_f, csr_filename = util.unique_file(
os.path.join(path, "csr-certbot.pem"), 0o644, "wb")
with csr_f:
csr_f.write(csr_pem)
logger.info("Creating CSR: %s", csr_filename)
logger.debug("Creating CSR: %s", csr_filename)
return util.CSR(csr_filename, csr_pem, "pem")

View file

@ -289,3 +289,60 @@ def _gen_https_names(domains):
domains[-1])
return ""
def _get_validated(method, validator, message, default=None, **kwargs):
if default is not None:
try:
validator(default)
except errors.Error as error:
logger.debug('Encountered invalid default value "%s" when prompting for "%s"',
default,
message,
exc_info=True)
raise AssertionError('Invalid default "{0}"'.format(default))
while True:
code, raw = method(message, default=default, **kwargs)
if code == display_util.OK:
try:
validator(raw)
return code, raw
except errors.Error as error:
logger.debug('Validator rejected "%s" when prompting for "%s"',
raw,
message,
exc_info=True)
zope.component.getUtility(interfaces.IDisplay).notification(str(error), pause=False)
else:
return code, raw
def validated_input(validator, *args, **kwargs):
"""Like `~certbot.interfaces.IDisplay.input`, but with validation.
:param callable validator: A method which will be called on the
supplied input. If the method raises a `errors.Error`, its
text will be displayed and the user will be re-prompted.
:param list *args: Arguments to be passed to `~certbot.interfaces.IDisplay.input`
:param dict **kwargs: Arguments to be passed to `~certbot.interfaces.IDisplay.input`
:return: as `~certbot.interfaces.IDisplay.input`
:rtype: tuple
"""
return _get_validated(zope.component.getUtility(interfaces.IDisplay).input,
validator, *args, **kwargs)
def validated_directory(validator, *args, **kwargs):
"""Like `~certbot.interfaces.IDisplay.directory_select`, but with validation.
:param callable validator: A method which will be called on the
supplied input. If the method raises a `errors.Error`, its
text will be displayed and the user will be re-prompted.
:param list *args: Arguments to be passed to `~certbot.interfaces.IDisplay.directory_select`
:param dict **kwargs: Arguments to be passed to `~certbot.interfaces.IDisplay.directory_select`
:return: as `~certbot.interfaces.IDisplay.directory_select`
:rtype: tuple
"""
return _get_validated(zope.component.getUtility(interfaces.IDisplay).directory_select,
validator, *args, **kwargs)

View file

@ -123,7 +123,6 @@ class FileDisplay(object):
def input(self, message, default=None,
cli_flag=None, force_interactive=False, **unused_kwargs):
# pylint: disable=no-self-use
"""Accept input from the user.
:param str message: message to display to the user

View file

@ -16,6 +16,7 @@ from certbot import cli
from certbot import errors
from certbot import interfaces
from certbot.display import util as display_util
from certbot.display import ops
from certbot.plugins import common
@ -136,22 +137,17 @@ to serve all files under specified web root ({0})."""
return None if index == 0 else known_webroots[index - 1]
def _prompt_for_new_webroot(self, domain):
display = zope.component.getUtility(interfaces.IDisplay)
while True:
code, webroot = display.directory_select(
"Input the webroot for {0}:".format(domain),
force_interactive=True)
if code == display_util.HELP:
# Displaying help is not currently implemented
return None
elif code == display_util.CANCEL:
return None
else: # code == display_util.OK
try:
return _validate_webroot(webroot)
except errors.PluginError as error:
display.notification(str(error), pause=False)
code, webroot = ops.validated_directory(
_validate_webroot,
"Input the webroot for {0}:".format(domain),
force_interactive=True)
if code == display_util.HELP:
# Displaying help is not currently implemented
return None
elif code == display_util.CANCEL or code == display_util.ESC:
return None
else: # code == display_util.OK
return _validate_webroot(webroot)
def _create_challenge_dirs(self):
path_map = self.conf("map")

View file

@ -100,22 +100,16 @@ class AuthenticatorTest(unittest.TestCase):
self.config.webroot_path = []
self.config.webroot_map = {}
imaginary_dir = os.path.join(os.sep, "imaginary", "dir")
mock_display = mock_get_utility()
mock_display.menu.return_value = (display_util.OK, 0,)
mock_display.directory_select.side_effect = (
(display_util.HELP, -1,), (display_util.CANCEL, -1,),
(display_util.OK, imaginary_dir,), (display_util.OK, self.path,),)
self.auth.perform([self.achall])
with mock.patch('certbot.display.ops.validated_directory') as m:
m.side_effect = ((display_util.HELP, -1),
(display_util.CANCEL, -1),
(display_util.OK, self.path,))
self.assertTrue(mock_display.notification.called)
for call in mock_display.notification.call_args_list:
self.assertTrue(imaginary_dir in call[0][0])
self.auth.perform([self.achall])
self.assertTrue(mock_display.directory_select.called)
for call in mock_display.directory_select.call_args_list:
self.assertTrue(self.achall.domain in call[0][0])
self.assertEqual(self.config.webroot_map[self.achall.domain], self.path)
def test_perform_missing_root(self):
self.config.webroot_path = None

View file

@ -14,6 +14,7 @@ from certbot import account
from certbot import errors
from certbot.display import util as display_util
from certbot.display import ops
import certbot.tests.util as test_util
@ -112,7 +113,6 @@ class ChooseAccountTest(test_util.TempDirTestCase):
@classmethod
def _call(cls, accounts):
from certbot.display import ops
return ops.choose_account(accounts)
@test_util.patch_get_utility("certbot.display.ops.z_util")
@ -405,5 +405,77 @@ class SuccessRevocationTest(unittest.TestCase):
os.linesep), pause=False)
self.assertTrue(path in mock_util().notification.call_args[0][0])
class ValidatorTests(unittest.TestCase):
"""Tests for `validated_input` and `validated_directory`."""
__ERROR = "Must be non-empty"
valid_input = "asdf"
valid_directory = "/var/www/html"
@staticmethod
def __validator(m):
if m == "":
raise errors.PluginError(ValidatorTests.__ERROR)
@test_util.patch_get_utility()
def test_input_blank_with_validator(self, mock_util):
mock_util().input.side_effect = [(display_util.OK, ""),
(display_util.OK, ""),
(display_util.OK, ""),
(display_util.OK, self.valid_input)]
returned = ops.validated_input(self.__validator, "message", force_interactive=True)
self.assertEqual(ValidatorTests.__ERROR, mock_util().notification.call_args[0][0])
self.assertEqual(returned, (display_util.OK, self.valid_input))
@test_util.patch_get_utility()
def test_input_validation_with_default(self, mock_util):
mock_util().input.side_effect = [(display_util.OK, self.valid_input)]
returned = ops.validated_input(self.__validator, "msg", default="other")
self.assertEqual(returned, (display_util.OK, self.valid_input))
@test_util.patch_get_utility()
def test_input_validation_with_bad_default(self, mock_util):
mock_util().input.side_effect = [(display_util.OK, self.valid_input)]
self.assertRaises(AssertionError,
ops.validated_input,
self.__validator, "msg", default="")
@test_util.patch_get_utility()
def test_input_cancel_with_validator(self, mock_util):
mock_util().input.side_effect = [(display_util.CANCEL, "")]
code, unused_raw = ops.validated_input(self.__validator, "message", force_interactive=True)
self.assertEqual(code, display_util.CANCEL)
@test_util.patch_get_utility()
def test_directory_select_validation(self, mock_util):
mock_util().directory_select.side_effect = [(display_util.OK, ""),
(display_util.OK, self.valid_directory)]
returned = ops.validated_directory(self.__validator, "msg", force_interactive=True)
self.assertEqual(ValidatorTests.__ERROR, mock_util().notification.call_args[0][0])
self.assertEqual(returned, (display_util.OK, self.valid_directory))
@test_util.patch_get_utility()
def test_directory_select_validation_with_default(self, mock_util):
mock_util().directory_select.side_effect = [(display_util.OK, self.valid_directory)]
returned = ops.validated_directory(self.__validator, "msg", default="other")
self.assertEqual(returned, (display_util.OK, self.valid_directory))
@test_util.patch_get_utility()
def test_directory_select_validation_with_bad_default(self, mock_util):
mock_util().directory_select.side_effect = [(display_util.OK, self.valid_directory)]
self.assertRaises(AssertionError,
ops.validated_directory,
self.__validator, "msg", default="")
if __name__ == "__main__":
unittest.main() # pragma: no cover

View file

@ -22,8 +22,8 @@ your system.
System Requirements
===================
Certbot currently requires Python 2.6 or 2.7. By default, it requires root
access in order to write to ``/etc/letsencrypt``,
Certbot currently requires Python 2.6, 2.7, or 3.3+. By default, it requires
root access in order to write to ``/etc/letsencrypt``,
``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to ports 80 and 443
(if you use the ``standalone`` plugin) and to read and modify webserver
configurations (if you use the ``apache`` or ``nginx`` plugins). If none of

View file

@ -68,7 +68,8 @@ In Fedora 23+.
FreeBSD
-------
- https://svnweb.freebsd.org/ports/head/security/py-certbot/
- https://www.freshports.org/security/py-acme/
- https://www.freshports.org/security/py-certbot/
Gentoo
------

View file

@ -182,7 +182,7 @@ The ``http`` challenge will ask you to place a file with a specific name and
specific content in the ``/.well-known/acme-challenge/`` directory directly
in the top-level directory (“web root”) containing the files served by your
webserver. In essence it's the same as the webroot_ plugin, but not automated.
When using the ``dns`` plugin, ``certbot`` will ask you to place a TXT DNS
When using the ``dns`` challenge, ``certbot`` will ask you to place a TXT DNS
record with specific contents under the domain name consisting of the hostname
for which you want a certificate issued, prepended by ``_acme-challenge``.

View file

@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1

View file

@ -33,6 +33,11 @@ setup(
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Security',
'Topic :: System :: Installation/Setup',

View file

@ -1,3 +1,6 @@
[bdist_wheel]
universal = 1
[easy_install]
zip_ok = false

View file

@ -36,7 +36,6 @@ version = meta['version']
# https://github.com/pypa/pip/issues/988 for more info.
install_requires = [
'acme=={0}'.format(version),
'argparse',
# We technically need ConfigArgParse 0.10.0 for Python 2.6 support, but
# saying so here causes a runtime error against our temporary fork of 0.9.3
# in which we added 2.6 support (see #2243), so we relax the requirement.
@ -56,6 +55,10 @@ install_requires = [
'zope.interface',
]
# env markers cause problems with older pip and setuptools
if sys.version_info < (2, 7):
install_requires.append('argparse')
dev_extras = [
# Pin astroid==1.3.5, pylint==1.4.2 as a workaround for #289
'astroid==1.3.5',
@ -94,6 +97,11 @@ setup(
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Security',
'Topic :: System :: Installation/Setup',