diff --git a/docs/using.rst b/docs/using.rst index 51426183d..687901191 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -224,21 +224,23 @@ The following files are available: ``cert.pem`` Server certificate only. - This is what Apache needs for `SSLCertificateFile + This is what Apache < 2.4.8 needs for `SSLCertificateFile `_. ``chain.pem`` All certificates that need to be served by the browser **excluding** server certificate, i.e. root and intermediate certificates only. - This is what Apache needs for `SSLCertificateChainFile + This is what Apache < 2.4.8 needs for `SSLCertificateChainFile `_. ``fullchain.pem`` All certificates, **including** server certificate. This is concatenation of ``chain.pem`` and ``cert.pem``. - This is what nginx needs for `ssl_certificate + This is what Apache >= 2.4.8 needs for `SSLCertificateFile + `_, + and what nginx needs for `ssl_certificate `_. diff --git a/letsencrypt-apache/letsencrypt_apache/augeas_lens/httpd.aug b/letsencrypt-apache/letsencrypt_apache/augeas_lens/httpd.aug index 0669896a0..d665ea7a7 100644 --- a/letsencrypt-apache/letsencrypt_apache/augeas_lens/httpd.aug +++ b/letsencrypt-apache/letsencrypt_apache/augeas_lens/httpd.aug @@ -51,7 +51,7 @@ let sep_osp = Sep.opt_space let sep_eq = del /[ \t]*=[ \t]*/ "=" let nmtoken = /[a-zA-Z:_][a-zA-Z0-9:_.-]*/ -let word = /[a-zA-Z][a-zA-Z0-9._-]*/ +let word = /[a-z][a-z0-9._-]*/i let comment = Util.comment let eol = Util.doseol @@ -68,6 +68,9 @@ let cl = /\\\\\n/ let dquot = let no_dquot = /[^"\\\r\n]/ in /"/ . (no_dquot|cdot|cl)* . /"/ +let dquot_msg = + let no_dquot = /([^ \t"\\\r\n]|[^"\\\r\n]+[^ \t"\\\r\n])/ + in /"/ . (no_dquot|cdot|cl)* let squot = let no_squot = /[^'\\\r\n]/ in /'/ . (no_squot|cdot|cl)* . /'/ @@ -78,6 +81,8 @@ let comp = /[<>=]?=/ *****************************************************************) let arg_dir = [ label "arg" . store (char_arg_dir+|dquot|squot) ] +(* message argument starts with " but ends at EOL *) +let arg_dir_msg = [ label "arg" . store dquot_msg ] let arg_sec = [ label "arg" . store (char_arg_sec+|comp|dquot|squot) ] let arg_wl = [ label "arg" . store (char_arg_wl+|dquot|squot) ] @@ -90,8 +95,10 @@ let arg_wordlist = let argv (l:lens) = l . (sep_spc . l)* -let directive = [ indent . label "directive" . store word . - (sep_spc . argv (arg_dir|arg_wordlist))? . eol ] +let directive = + (* arg_dir_msg may be the last or only argument *) + let dir_args = (argv (arg_dir|arg_wordlist) . (sep_spc . arg_dir_msg)?) | arg_dir_msg + in [ indent . label "directive" . store word . (sep_spc . dir_args)? . eol ] let section (body:lens) = (* opt_eol includes empty lines *) diff --git a/letsencrypt-apache/letsencrypt_apache/tests/testdata/debian_apache_2_4/two_vhost_80/apache2/conf-available/bad_conf_file.conf b/letsencrypt-apache/letsencrypt_apache/tests/testdata/debian_apache_2_4/two_vhost_80/apache2/conf-available/bad_conf_file.conf index 1aad6a9f4..8e9178803 100644 --- a/letsencrypt-apache/letsencrypt_apache/tests/testdata/debian_apache_2_4/two_vhost_80/apache2/conf-available/bad_conf_file.conf +++ b/letsencrypt-apache/letsencrypt_apache/tests/testdata/debian_apache_2_4/two_vhost_80/apache2/conf-available/bad_conf_file.conf @@ -1,5 +1,3 @@ ServerName invalid.net - - diff --git a/letsencrypt/cli.py b/letsencrypt/cli.py index 69a259d5b..ca92595d7 100644 --- a/letsencrypt/cli.py +++ b/letsencrypt/cli.py @@ -759,6 +759,14 @@ class HelpfulArgumentParser(object): parsed_args = self.parser.parse_args(self.args) parsed_args.func = self.VERBS[self.verb] + # Do any post-parsing homework here + + # argparse seemingly isn't flexible enough to give us this behaviour easily... + if parsed_args.staging: + if parsed_args.server not in (flag_default("server"), constants.STAGING_URI): + raise errors.Error("--server value conflicts with --staging") + parsed_args.server = constants.STAGING_URI + return parsed_args @@ -1103,6 +1111,10 @@ def _paths_parser(helpful): help="Logs directory.") add("paths", "--server", default=flag_default("server"), help=config_help("server")) + # overwrites server, handled in HelpfulArgumentParser.parse_args() + add("testing", "--test-cert", "--staging", action='store_true', dest='staging', + help='Use the staging server to obtain test (invalid) certs; equivalent' + ' to --server ' + constants.STAGING_URI) def _plugins_parsing(helpful, plugins): diff --git a/letsencrypt/constants.py b/letsencrypt/constants.py index 40155abd7..a1dccd1ea 100644 --- a/letsencrypt/constants.py +++ b/letsencrypt/constants.py @@ -30,8 +30,9 @@ CLI_DEFAULTS = dict( auth_chain_path="./chain.pem", strict_permissions=False, ) -"""Defaults for CLI flags and `.IConfig` attributes.""" +STAGING_URI = "https://acme-staging.api.letsencrypt.org/directory" +"""Defaults for CLI flags and `.IConfig` attributes.""" RENEWER_DEFAULTS = dict( renewer_enabled="yes", diff --git a/letsencrypt/le_util.py b/letsencrypt/le_util.py index fe63c70af..64295a80f 100644 --- a/letsencrypt/le_util.py +++ b/letsencrypt/le_util.py @@ -10,6 +10,8 @@ import stat import subprocess import sys +import configargparse + from letsencrypt import errors @@ -278,9 +280,11 @@ def add_deprecated_argument(add_argument, argument_name, nargs): sys.stderr.write( "Use of {0} is deprecated.\n".format(option_string)) + configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE.add(ShowWarning) add_argument(argument_name, action=ShowWarning, help=argparse.SUPPRESS, nargs=nargs) + def check_domain_sanity(domain): """Method which validates domain value and errors out if the requirements are not met. diff --git a/letsencrypt/plugins/standalone.py b/letsencrypt/plugins/standalone.py index 8b8612fd1..4319e51f9 100644 --- a/letsencrypt/plugins/standalone.py +++ b/letsencrypt/plugins/standalone.py @@ -2,7 +2,6 @@ import argparse import collections import logging -import random import socket import threading @@ -108,7 +107,7 @@ class ServerManager(object): in six.iteritems(self._instances)) -SUPPORTED_CHALLENGES = set([challenges.TLSSNI01, challenges.HTTP01]) +SUPPORTED_CHALLENGES = [challenges.TLSSNI01, challenges.HTTP01] def supported_challenges_validator(data): @@ -166,16 +165,16 @@ class Authenticator(common.Plugin): @classmethod def add_parser_arguments(cls, add): - add("supported-challenges", help="Supported challenges, " - "order preferences are randomly chosen.", - type=supported_challenges_validator, default=",".join( - sorted(chall.typ for chall in SUPPORTED_CHALLENGES))) + add("supported-challenges", + help="Supported challenges. Preferred in the order they are listed.", + type=supported_challenges_validator, + default=",".join(chall.typ for chall in SUPPORTED_CHALLENGES)) @property def supported_challenges(self): """Challenges supported by this plugin.""" - return set(challenges.Challenge.TYPES[name] for name in - self.conf("supported-challenges").split(",")) + return [challenges.Challenge.TYPES[name] for name in + self.conf("supported-challenges").split(",")] @property def _necessary_ports(self): @@ -198,9 +197,7 @@ class Authenticator(common.Plugin): def get_chall_pref(self, domain): # pylint: disable=unused-argument,missing-docstring - chall_pref = list(self.supported_challenges) - random.shuffle(chall_pref) # 50% for each challenge - return chall_pref + return self.supported_challenges def perform(self, achalls): # pylint: disable=missing-docstring if any(util.already_listening(port) for port in self._necessary_ports): diff --git a/letsencrypt/plugins/standalone_test.py b/letsencrypt/plugins/standalone_test.py index 26a040c2e..1e39dee57 100644 --- a/letsencrypt/plugins/standalone_test.py +++ b/letsencrypt/plugins/standalone_test.py @@ -98,17 +98,27 @@ class AuthenticatorTest(unittest.TestCase): def test_supported_challenges(self): self.assertEqual(self.auth.supported_challenges, - set([challenges.TLSSNI01, challenges.HTTP01])) + [challenges.TLSSNI01, challenges.HTTP01]) + + def test_supported_challenges_configured(self): + self.config.standalone_supported_challenges = "tls-sni-01" + self.assertEqual(self.auth.supported_challenges, + [challenges.TLSSNI01]) def test_more_info(self): self.assertTrue(isinstance(self.auth.more_info(), six.string_types)) def test_get_chall_pref(self): - self.assertEqual(set(self.auth.get_chall_pref(domain=None)), - set([challenges.TLSSNI01, challenges.HTTP01])) + self.assertEqual(self.auth.get_chall_pref(domain=None), + [challenges.TLSSNI01, challenges.HTTP01]) + + def test_get_chall_pref_configured(self): + self.config.standalone_supported_challenges = "tls-sni-01" + self.assertEqual(self.auth.get_chall_pref(domain=None), + [challenges.TLSSNI01]) @mock.patch("letsencrypt.plugins.standalone.util") - def test_perform_alredy_listening(self, mock_util): + def test_perform_already_listening(self, mock_util): for chall, port in ((challenges.TLSSNI01.typ, 1234), (challenges.HTTP01.typ, 4321)): mock_util.already_listening.return_value = True diff --git a/letsencrypt/plugins/webroot.py b/letsencrypt/plugins/webroot.py index 0b81d45b5..0679bc349 100644 --- a/letsencrypt/plugins/webroot.py +++ b/letsencrypt/plugins/webroot.py @@ -2,7 +2,6 @@ import errno import logging import os -import stat import zope.interface @@ -59,24 +58,38 @@ to serve all files under specified web root ({0}).""" logger.debug("Creating root challenges validation dir at %s", self.full_roots[name]) + + # Change the permissions to be writable (GH #1389) + # Umask is used instead of chmod to ensure the client can also + # run as non-root (GH #1795) + old_umask = os.umask(0o022) + try: - os.makedirs(self.full_roots[name]) - # Set permissions as parent directory (GH #1389) - # We don't use the parameters in makedirs because it - # may not always work + # This is coupled with the "umask" call above because + # os.makedirs's "mode" parameter may not always work: # https://stackoverflow.com/questions/5231901/permission-problems-when-creating-a-dir-with-os-makedirs-python - stat_path = os.stat(path) - filemode = stat.S_IMODE(stat_path.st_mode) - os.chmod(self.full_roots[name], filemode) - # Set owner and group, too - os.chown(self.full_roots[name], stat_path.st_uid, - stat_path.st_gid) + os.makedirs(self.full_roots[name], 0o0755) + + # Set owner as parent directory if possible + try: + stat_path = os.stat(path) + os.chown(self.full_roots[name], stat_path.st_uid, + stat_path.st_gid) + except OSError as exception: + if exception.errno == errno.EACCES: + logger.debug("Insufficient permissions to change owner and uid - ignoring") + else: + raise errors.PluginError( + "Couldn't create root for {0} http-01 " + "challenge responses: {1}", name, exception) except OSError as exception: if exception.errno != errno.EEXIST: raise errors.PluginError( "Couldn't create root for {0} http-01 " "challenge responses: {1}", name, exception) + finally: + os.umask(old_umask) def perform(self, achalls): # pylint: disable=missing-docstring assert self.full_roots, "Webroot plugin appears to be missing webroot map" @@ -87,26 +100,26 @@ to serve all files under specified web root ({0}).""" path = self.full_roots[achall.domain] except IndexError: raise errors.PluginError("Missing --webroot-path for domain: {1}" - .format(achall.domain)) + .format(achall.domain)) if not os.path.exists(path): raise errors.PluginError("Mysteriously missing path {0} for domain: {1}" - .format(path, achall.domain)) + .format(path, achall.domain)) return os.path.join(path, achall.chall.encode("token")) def _perform_single(self, achall): response, validation = achall.response_and_validation() + path = self._path_for_achall(achall) logger.debug("Attempting to save validation to %s", path) - with open(path, "w") as validation_file: - validation_file.write(validation.encode()) - # Set permissions as parent directory (GH #1389) - parent_path = self.full_roots[achall.domain] - stat_parent_path = os.stat(parent_path) - filemode = stat.S_IMODE(stat_parent_path.st_mode) - # Remove execution bit (not needed for this file) - os.chmod(path, filemode & ~stat.S_IEXEC) - os.chown(path, stat_parent_path.st_uid, stat_parent_path.st_gid) + # Change permissions to be world-readable, owner-writable (GH #1795) + old_umask = os.umask(0o022) + + try: + with open(path, "w") as validation_file: + validation_file.write(validation.encode()) + finally: + os.umask(old_umask) return response diff --git a/letsencrypt/plugins/webroot_test.py b/letsencrypt/plugins/webroot_test.py index e7f96b50d..9f5b6bba8 100644 --- a/letsencrypt/plugins/webroot_test.py +++ b/letsencrypt/plugins/webroot_test.py @@ -1,9 +1,10 @@ """Tests for letsencrypt.plugins.webroot.""" +import errno import os import shutil +import stat import tempfile import unittest -import stat import mock @@ -35,7 +36,6 @@ class AuthenticatorTest(unittest.TestCase): self.config = mock.MagicMock(webroot_path=self.path, webroot_map={"thing.com": self.path}) self.auth = Authenticator(self.config, "webroot") - self.auth.prepare() def tearDown(self): shutil.rmtree(self.path) @@ -48,7 +48,7 @@ class AuthenticatorTest(unittest.TestCase): def test_add_parser_arguments(self): add = mock.MagicMock() self.auth.add_parser_arguments(add) - self.assertEqual(0, add.call_count) # became 0 when we moved the args to cli.py! + self.assertEqual(0, add.call_count) # args moved to cli.py! def test_prepare_bad_root(self): self.config.webroot_path = os.path.join(self.path, "null") @@ -70,17 +70,33 @@ class AuthenticatorTest(unittest.TestCase): self.assertRaises(errors.PluginError, self.auth.prepare) os.chmod(self.path, 0o700) + @mock.patch("letsencrypt.plugins.webroot.os.chown") + def test_failed_chown_eacces(self, mock_chown): + mock_chown.side_effect = OSError(errno.EACCES, "msg") + self.auth.prepare() # exception caught and logged + + @mock.patch("letsencrypt.plugins.webroot.os.chown") + def test_failed_chown_not_eacces(self, mock_chown): + mock_chown.side_effect = OSError() + self.assertRaises(errors.PluginError, self.auth.prepare) + def test_prepare_permissions(self): + self.auth.prepare() # Remove exec bit from permission check, so that it # matches the file self.auth.perform([self.achall]) - parent_permissions = (stat.S_IMODE(os.stat(self.path).st_mode) & - ~stat.S_IEXEC) + path_permissions = stat.S_IMODE(os.stat(self.validation_path).st_mode) + self.assertEqual(path_permissions, 0o644) - actual_permissions = stat.S_IMODE(os.stat(self.validation_path).st_mode) + # Check permissions of the directories + + for dirpath, dirnames, _ in os.walk(self.path): + for directory in dirnames: + full_path = os.path.join(dirpath, directory) + dir_permissions = stat.S_IMODE(os.stat(full_path).st_mode) + self.assertEqual(dir_permissions, 0o755) - self.assertEqual(parent_permissions, actual_permissions) parent_gid = os.stat(self.path).st_gid parent_uid = os.stat(self.path).st_uid @@ -88,6 +104,7 @@ class AuthenticatorTest(unittest.TestCase): self.assertEqual(os.stat(self.validation_path).st_uid, parent_uid) def test_perform_cleanup(self): + self.auth.prepare() responses = self.auth.perform([self.achall]) self.assertEqual(1, len(responses)) self.assertTrue(os.path.exists(self.validation_path)) diff --git a/letsencrypt/tests/cli_test.py b/letsencrypt/tests/cli_test.py index 433671b38..e865099e8 100644 --- a/letsencrypt/tests/cli_test.py +++ b/letsencrypt/tests/cli_test.py @@ -15,6 +15,7 @@ from acme import jose from letsencrypt import account from letsencrypt import cli from letsencrypt import configuration +from letsencrypt import constants from letsencrypt import crypto_util from letsencrypt import errors from letsencrypt import le_util @@ -343,6 +344,19 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods namespace = cli.prepare_and_parse_args(plugins, long_args) self.assertEqual(namespace.domains, ['example.com', 'another.net']) + def test_parse_server(self): + plugins = disco.PluginsRegistry.find_all() + short_args = ['--server', 'example.com'] + namespace = cli.prepare_and_parse_args(plugins, short_args) + self.assertEqual(namespace.server, 'example.com') + + short_args = ['--staging'] + namespace = cli.prepare_and_parse_args(plugins, short_args) + self.assertEqual(namespace.server, constants.STAGING_URI) + + short_args = ['--staging', '--server', 'example.com'] + self.assertRaises(errors.Error, cli.prepare_and_parse_args, plugins, short_args) + def test_parse_webroot(self): plugins = disco.PluginsRegistry.find_all() webroot_args = ['--webroot', '-w', '/var/www/example', @@ -537,6 +551,11 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods self.assertEqual(path, os.path.abspath(path)) self.assertEqual(contents, test_contents) + def test_agree_dev_preview_config(self): + with MockedVerb('run') as mocked_run: + self._call(['-c', test_util.vector_path('cli.ini')]) + self.assertTrue(mocked_run.called) + class DetermineAccountTest(unittest.TestCase): """Tests for letsencrypt.cli._determine_account.""" diff --git a/letsencrypt/tests/testdata/cli.ini b/letsencrypt/tests/testdata/cli.ini new file mode 100644 index 000000000..8ef506071 --- /dev/null +++ b/letsencrypt/tests/testdata/cli.ini @@ -0,0 +1 @@ +agree-dev-preview = True diff --git a/tests/apache-conf-files/failing/missing-double-quote-1724.conf b/tests/apache-conf-files/failing/missing-double-quote-1724.conf new file mode 100644 index 000000000..7d97b23d0 --- /dev/null +++ b/tests/apache-conf-files/failing/missing-double-quote-1724.conf @@ -0,0 +1,52 @@ + + ServerAdmin webmaster@localhost + ServerAlias www.example.com + ServerName example.com + DocumentRoot /var/www/example.com/www/ + SSLEngine on + + SSLProtocol all -SSLv2 -SSLv3 + SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRS$ + SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem + SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key + + + Options FollowSymLinks + AllowOverride All + + + Options Indexes FollowSymLinks MultiViews + AllowOverride All + Order allow,deny + allow from all + # This directive allows us to have apache2's default start page + # in /apache2-default/, but still have / go to the right place + + + ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ + + AllowOverride None + Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch + Order allow,deny + Allow from all + + + ErrorLog /var/log/apache2/error.log + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel warn + + CustomLog /var/log/apache2/access.log combined + ServerSignature On + + Alias /apache_doc/ "/usr/share/doc/" + + Options Indexes MultiViews FollowSymLinks + AllowOverride None + Order deny,allow + Deny from all + Allow from 127.0.0.0/255.0.0.0 ::1/128 + + + diff --git a/tests/apache-conf-files/hackish-apache-test b/tests/apache-conf-files/hackish-apache-test new file mode 100755 index 000000000..c6663551e --- /dev/null +++ b/tests/apache-conf-files/hackish-apache-test @@ -0,0 +1,28 @@ +#!/bin/bash + +# A hackish script to see if the client is behaving as expected +# with each of the "passing" conf files. + +# TODO presently this requires interaction and human judgement to +# assess, but it should be automated +export EA=/etc/apache2/ +TESTDIR="`dirname $0`" +LEROOT="`realpath \"$TESTDIR/../../\"`" +cd $TESTDIR/passing + +function CleanupExit() { + echo control c, exiting tests... + if [ "$f" != "" ] ; then + sudo rm /etc/apache2/sites-{enabled,available}/"$f" + fi + exit 1 +} + +trap CleanupExit INT +for f in *.conf ; do + echo testing "$f" + sudo cp "$f" "$EA"/sites-available/ + sudo ln -s "$EA/sites-available/$f" "$EA/sites-enabled/$f" + sudo "$LEROOT"/venv/bin/letsencrypt --apache certonly -t + sudo rm /etc/apache2/sites-{enabled,available}/"$f" +done diff --git a/tests/apache-conf-files/passing/1626-1531.conf b/tests/apache-conf-files/passing/1626-1531.conf new file mode 100644 index 000000000..1622a57df --- /dev/null +++ b/tests/apache-conf-files/passing/1626-1531.conf @@ -0,0 +1,37 @@ + + ServerAdmin denver@ossguy.com + ServerName c-beta.ossguy.com + + Alias /robots.txt /home/denver/www/c-beta.ossguy.com/static/robots.txt + Alias /favicon.ico /home/denver/www/c-beta.ossguy.com/static/favicon.ico + + AliasMatch /(.*\.css) /home/denver/www/c-beta.ossguy.com/static/$1 + AliasMatch /(.*\.js) /home/denver/www/c-beta.ossguy.com/static/$1 + AliasMatch /(.*\.png) /home/denver/www/c-beta.ossguy.com/static/$1 + AliasMatch /(.*\.gif) /home/denver/www/c-beta.ossguy.com/static/$1 + AliasMatch /(.*\.jpg) /home/denver/www/c-beta.ossguy.com/static/$1 + + WSGIScriptAlias / /home/denver/www/c-beta.ossguy.com/django.wsgi + WSGIDaemonProcess c-beta-ossguy user=www-data group=www-data home=/var/www processes=5 threads=10 maximum-requests=1000 umask=0007 display-name=c-beta-ossguy + WSGIProcessGroup c-beta-ossguy + WSGIApplicationGroup %{GLOBAL} + + DocumentRoot /home/denver/www/c-beta.ossguy.com/static + + + Options -Indexes +FollowSymLinks -MultiViews + Require all granted + AllowOverride None + + + + Options +Indexes +FollowSymLinks -MultiViews + Require all granted + AllowOverride None + + + # Custom log file locations + LogLevel warn + ErrorLog /tmp/error.log + CustomLog /tmp/access.log combined + diff --git a/tests/apache-conf-files/passing/README.modules b/tests/apache-conf-files/passing/README.modules index 9c5853061..7edbd3e84 100644 --- a/tests/apache-conf-files/passing/README.modules +++ b/tests/apache-conf-files/passing/README.modules @@ -3,3 +3,5 @@ Modules required to parse these conf files: ssl rewrite macro +wsgi +deflate diff --git a/tests/apache-conf-files/passing/drupal-errordocument-arg-1724.conf b/tests/apache-conf-files/passing/drupal-errordocument-arg-1724.conf new file mode 100644 index 000000000..4733ffa4a --- /dev/null +++ b/tests/apache-conf-files/passing/drupal-errordocument-arg-1724.conf @@ -0,0 +1,116 @@ +# +# Apache/PHP/Drupal settings: +# + +# Protect files and directories from prying eyes. + + Order allow,deny + + +# Don't show directory listings for URLs which map to a directory. +Options -Indexes + +# Follow symbolic links in this directory. +Options +FollowSymLinks + +# Make Drupal handle any 404 errors. +ErrorDocument 404 /index.php + +# Force simple error message for requests for non-existent favicon.ico. + + # There is no end quote below, for compatibility with Apache 1.3. + ErrorDocument 404 "The requested file favicon.ico was not found. + + +# Set the default handler. +DirectoryIndex index.php + +# Override PHP settings. More in sites/default/settings.php +# but the following cannot be changed at runtime. + +# PHP 4, Apache 1. + + php_value magic_quotes_gpc 0 + php_value register_globals 0 + php_value session.auto_start 0 + php_value mbstring.http_input pass + php_value mbstring.http_output pass + php_value mbstring.encoding_translation 0 + + +# PHP 4, Apache 2. + + php_value magic_quotes_gpc 0 + php_value register_globals 0 + php_value session.auto_start 0 + php_value mbstring.http_input pass + php_value mbstring.http_output pass + php_value mbstring.encoding_translation 0 + + +# PHP 5, Apache 1 and 2. + + php_value magic_quotes_gpc 0 + php_value register_globals 0 + php_value session.auto_start 0 + php_value mbstring.http_input pass + php_value mbstring.http_output pass + php_value mbstring.encoding_translation 0 + + +# Requires mod_expires to be enabled. + + # Enable expirations. + ExpiresActive On + + # Cache all files for 2 weeks after access (A). + ExpiresDefault A1209600 + + + # Do not allow PHP scripts to be cached unless they explicitly send cache + # headers themselves. Otherwise all scripts would have to overwrite the + # headers set by mod_expires if they want another caching behavior. This may + # fail if an error occurs early in the bootstrap process, and it may cause + # problems if a non-Drupal PHP file is installed in a subdirectory. + ExpiresActive Off + + + +# Various rewrite rules. + + RewriteEngine on + + # If your site can be accessed both with and without the 'www.' prefix, you + # can use one of the following settings to redirect users to your preferred + # URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option: + # + # To redirect all users to access the site WITH the 'www.' prefix, + # (http://example.com/... will be redirected to http://www.example.com/...) + # adapt and uncomment the following: + # RewriteCond %{HTTP_HOST} ^example\.com$ [NC] + # RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301] + # + # To redirect all users to access the site WITHOUT the 'www.' prefix, + # (http://www.example.com/... will be redirected to http://example.com/...) + # uncomment and adapt the following: + # RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC] + # RewriteRule ^(.*)$ http://example.com/$1 [L,R=301] + + # Modify the RewriteBase if you are using Drupal in a subdirectory or in a + # VirtualDocumentRoot and the rewrite rules are not working properly. + # For example if your site is at http://example.com/drupal uncomment and + # modify the following line: + # RewriteBase /drupal + # + # If your site is running in a VirtualDocumentRoot at http://example.com/, + # uncomment the following line: + # RewriteBase / + + # Rewrite URLs of the form 'x' to the form 'index.php?q=x'. + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} !=/favicon.ico + RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] + + +# $Id$ diff --git a/tests/apache-conf-files/passing/example-1755.conf b/tests/apache-conf-files/passing/example-1755.conf new file mode 100644 index 000000000..260029576 --- /dev/null +++ b/tests/apache-conf-files/passing/example-1755.conf @@ -0,0 +1,36 @@ + + # The ServerName directive sets the request scheme, hostname and port that + # the server uses to identify itself. This is used when creating + # redirection URLs. In the context of virtual hosts, the ServerName + # specifies what hostname must appear in the request's Host: header to + # match this virtual host. For the default virtual host (this file) this + # value is not decisive as it is used as a last resort host regardless. + # However, you must set it for any further virtual host explicitly. + ServerName www.example.com + ServerAlias example.com +SetOutputFilter DEFLATE +# Do not attempt to compress the following extensions +SetEnvIfNoCase Request_URI \ +\.(?:gif|jpe?g|png|swf|flv|zip|gz|tar|mp3|mp4|m4v)$ no-gzip dont-vary + + ServerAdmin webmaster@localhost + DocumentRoot /var/www/proof + + # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, + # error, crit, alert, emerg. + # It is also possible to configure the loglevel for particular + # modules, e.g. + #LogLevel info ssl:warn + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + # For most configuration files from conf-available/, which are + # enabled or disabled at a global level, it is possible to + # include a line for only one particular virtual host. For example the + # following line enables the CGI configuration for this host only + # after it has been globally disabled with "a2disconf". + #Include conf-available/serve-cgi-bin.conf + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/tests/apache-conf-files/passing/missing-quote-1724.conf b/tests/apache-conf-files/passing/missing-quote-1724.conf new file mode 100644 index 000000000..7d97b23d0 --- /dev/null +++ b/tests/apache-conf-files/passing/missing-quote-1724.conf @@ -0,0 +1,52 @@ + + ServerAdmin webmaster@localhost + ServerAlias www.example.com + ServerName example.com + DocumentRoot /var/www/example.com/www/ + SSLEngine on + + SSLProtocol all -SSLv2 -SSLv3 + SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRS$ + SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem + SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key + + + Options FollowSymLinks + AllowOverride All + + + Options Indexes FollowSymLinks MultiViews + AllowOverride All + Order allow,deny + allow from all + # This directive allows us to have apache2's default start page + # in /apache2-default/, but still have / go to the right place + + + ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ + + AllowOverride None + Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch + Order allow,deny + Allow from all + + + ErrorLog /var/log/apache2/error.log + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel warn + + CustomLog /var/log/apache2/access.log combined + ServerSignature On + + Alias /apache_doc/ "/usr/share/doc/" + + Options Indexes MultiViews FollowSymLinks + AllowOverride None + Order deny,allow + Deny from all + Allow from 127.0.0.0/255.0.0.0 ::1/128 + + + diff --git a/tests/apache-conf-files/passing/sslrequire-wordlist.conf b/tests/apache-conf-files/passing/sslrequire-wordlist-1827.htaccess similarity index 100% rename from tests/apache-conf-files/passing/sslrequire-wordlist.conf rename to tests/apache-conf-files/passing/sslrequire-wordlist-1827.htaccess