diff --git a/apacheconfig/__init__.py b/apacheconfig/__init__.py index 52d2f63..19f0061 100644 --- a/apacheconfig/__init__.py +++ b/apacheconfig/__init__.py @@ -8,6 +8,9 @@ from apacheconfig.loader import ApacheConfigLoader from apacheconfig.error import ApacheConfigError +from apacheconfig.wloader import parse_item, parse_block, parse_contents +from apacheconfig.wloader import ItemNode, BlockNode, ContentsNode + @contextmanager def make_loader(**options): @@ -18,5 +21,7 @@ def make_loader(**options): **options) -__all__ = ['make_lexer', 'make_parser', 'make_loader', 'ApacheConfigLoader', - 'ApacheConfigError'] +__all__ = ['parse_item', 'parse_block', 'parse_contents', + 'ItemNode', 'BlockNode', 'ContentsNode', + 'make_lexer', 'make_parser', 'make_loader', + 'ApacheConfigLoader', 'ApacheConfigError'] diff --git a/apacheconfig/wloader.py b/apacheconfig/wloader.py new file mode 100644 index 0000000..6702301 --- /dev/null +++ b/apacheconfig/wloader.py @@ -0,0 +1,303 @@ +# +# This file is part of apacheconfig software. +# +# Copyright (c) 2018-2019, Ilya Etingof +# License: https://github.com/etingof/apacheconfig/LICENSE.rst +# + + +from apacheconfig import make_parser +from apacheconfig import make_lexer + +import abc +import six + + +def _restore_original(word): + """If the `word` is a Quoted string, restores it to original. + """ + if getattr(word, 'is_single_quoted', False): + return "'%s'" % word + if getattr(word, 'is_double_quoted', False): + return '"%s"' % word + return word + + +@six.add_metaclass(abc.ABCMeta) +class Node(): + """Generic class containing data that represents a node in the config AST. + """ + + @abc.abstractmethod + def __str__(self): + raise NotImplementedError() + + @property + def type(self): + """A typestring as defined by the apacheconfig parser. + + A single *Node class can have multiple possible values for this. For + instance, ItemNode is a generic representation of any single directive + but has a couple different possible `type`s, including `comment`, + `statement`, and `include`-- depending on which the caller may + decide to treat ItemNode differently. + """ + if self._type is None: + raise NotImplementedError() + return self._type + + @property + def whitespace(self): + """Trailing or preceding whitespace. + + Each Item or BlockNode keeps track of the whitespace preceding it. + For the first element in the configuration file, there could be no + whitespace preceding it at all, in which case this should return the + empty string. + + ContentsNode is special in that it keeps track of the trailing white- + space. + """ + if self._whitespace is None: + raise NotImplementedError() + return self._whitespace + + @whitespace.setter + def whitespace(self, value): + if self._whitespace is None: + raise NotImplementedError() + self._whitespace = value + + +class ContentsNode(Node): + """Node representing an ordered list of BlockNodes and ItemNodes. + + Each BlockNode contains a ContentsNode, and every configuration's root is + a ContentsNode. + + Unlike other Nodes, the `whitespace` property of ContentsNode keeps track + of *trailing* whitespace, since the preceding whitespace in ContentsNode + will already be recorded by the first Item or Block in ContentsNode. + + For instance, the following valid configuration: + `\tkey value # comment\n` + will be processed into something like: + ContentsNode([ + ItemNode(['\t', 'key', ' ', 'value']), + ItemNode([' ', '# comment']), + '\n']) + where the `whitespace` property for contents would return '\n', not '\t'. + """ + def __init__(self, raw): + self._type = raw[0] + self._contents = [] + self._whitespace = "" + for elem in raw[1:]: + if isinstance(elem, str) and elem.isspace(): + self._whitespace = elem + elif elem[0] == "block": + self._contents.append(BlockNode(elem)) + else: + self._contents.append(ItemNode(elem)) + + def add(self, index, raw_str): + """Parses thing into an Item or Block Node, then adds to contents. + + Arguments: + raw_str: string to parse. The parser should be able to determine + whether it's a block or item. For instance: + `key value` + `` + whitespace: preceding whitespace to prepend to the item. + index: index of contents at which to insert the resulting node. + """ + parser = _create_parser({}, start='miditem') + raw = parser.parse(raw_str) + if raw[0] == "block": + node = BlockNode(raw) + else: + node = ItemNode(raw) + self._contents.insert(index, node) + if (index + 1 < len(self._contents) and + '\n' not in self._contents[index + 1].whitespace): + whitespace_after = self._contents[index + 1].whitespace + self._contents[index + 1].whitespace = '\n' + whitespace_after + return node + + def remove(self, index): + """Removes node/thing from supplied index. + + Arguments: + index: index of node to remove from contents. + """ + thing = self._contents[index] + del self._contents[index] + return thing + + def __len__(self): + return len(self._contents) + + def __iter__(self): + return iter(self._contents) + + def __str__(self): + return ("".join([str(item) for item in self._contents]) + + self.whitespace) + + +class ItemNode(Node): + """Contains data for a single configuration line. + + Also manages any preceding whitespace. Can represent a key/value option, + a comment, or an include/includeoptional directive. + + Construct this using raw AST data from parser. Generally, block data looks + like: + ['block', , + Examples of what raw AST data might look like for an ItemNode: + ['statement', 'option', ' ', 'value'] + ['include', 'include', ' ', 'relative/path/*'] + ['statement', '\n ', 'option', ' = ', 'value'] + ['comment', '# here is a comment'] + ['comment', '\n ', '# here is a comment'] + + Properties: + value: getter & setter for the final element in the raw AST. For + includes, this would be the path for include directives; for + comments, it's the comment body, and for key/value directives, + it's the value. + name: getter only. Retrieves the first non-whitespace element in the + raw AST. + """ + + def __init__(self, raw): + """Initializes ItemNode with raw data from AST + + Args: + raw: list from parser module's AST. + """ + self._type = raw[0] + self._raw = tuple(raw[1:]) + self._whitespace = "" + if len(raw) > 1 and raw[1].isspace(): + self._whitespace = raw[1] + self._raw = tuple(raw[2:]) + + @property + def name(self): + """Getter for the first non-whitespace token, semantically the "name" + of this directive. + + Useful for retrieving the key if this is a key/value directive. + """ + return self._raw[0] + + def has_value(self): + return len(self._raw) > 1 + + @property + def value(self): + """Getter for the last token, semantically the "value" of this item. + """ + if not self.has_value(): + return None + return self._raw[-1] + + @value.setter + def value(self, value): + """Setter for the value of this item. + TODO(sydli): convert `value` to quotedstring automagically if quoted + """ + if not self.has_value(): + self._raw = self._raw + (" ", value,) + self._raw = self._raw[0:-1] + (value,) + + def __str__(self): + return (self.whitespace + + "".join([_restore_original(word) for word in self._raw])) + + def __repr__(self): + return ("ItemNode(%s)" + % str([self._type] + + [_restore_original(word) for word in self._raw])) + + +class BlockNode(Node): + """Contains data for a block. + + Manages any preceding whitespace, and details of contents. + + Construct this using raw AST data from parser. Generally, block data looks + like: + ['block', , , , + ] + E.g., for the block " + + is represented with an empty contents object. + + The add/remove functions inherited from ContentsNode act on the contents + contained within this block. + + Properties: + tag: getter only. Retrieves the full tag name. + arguments: getter & setter for block arguments. + """ + + def __init__(self, raw): + self._whitespace = "" + self._type = raw[0] + start = 1 + if isinstance(raw[start], str) and raw[start].isspace(): + self._whitespace = raw[start] + start += 1 + self._full_tag = ItemNode(('statement',) + raw[start]) + self._close_tag = raw[-1] + self._contents = None + if len(raw[start+1]) > 0: + self._contents = ContentsNode(raw[start + 1]) + + @property + def tag(self): + return self._full_tag.name + + @property + def arguments(self): + return self._full_tag.value + + @arguments.setter + def arguments(self, arguments): + self._full_tag.value = arguments + + @property + def contents(self): + return self._contents + + def __str__(self): + if self._contents is None: + return "%s<%s/>" % (self.whitespace, str(self._full_tag)) + return "%s<%s>%s" % (self.whitespace, str(self._full_tag), + str(self._contents), self._close_tag) + + +def _create_parser(options={}, start='contents'): + options['preservewhitespace'] = True + options['disableemptyelementtags'] = True + options['multilinehashcomments'] = True + ApacheConfigLexer = make_lexer(**options) + ApacheConfigParser = make_parser(**options) + return ApacheConfigParser(ApacheConfigLexer(), start=start) + + +def parse_contents(raw_str, options={}): + parser = _create_parser(options, start='contents') + return ContentsNode(parser.parse(raw_str)) + + +def parse_item(raw_str, options={}): + parser = _create_parser(options, start='startitem') + return ItemNode(parser.parse(raw_str)) + + +def parse_block(raw_str, options={}): + parser = _create_parser(options, start='startitem') + return BlockNode(parser.parse(raw_str)) diff --git a/requirements.txt b/requirements.txt index fa55493..244aec8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -ply>=3.0 \ No newline at end of file +ply>=3.0 +six diff --git a/tests/integration/samples/apache-conf-files/1626-1531.conf b/tests/integration/samples/apache-conf-files/1626-1531.conf new file mode 100644 index 0000000..1622a57 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/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/integration/samples/apache-conf-files/README.modules b/tests/integration/samples/apache-conf-files/README.modules new file mode 100644 index 0000000..32c3ef0 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/README.modules @@ -0,0 +1,6 @@ +# Modules required to parse these conf files: +ssl +rewrite +macro +wsgi +deflate diff --git a/tests/integration/samples/apache-conf-files/anarcat-1531.conf b/tests/integration/samples/apache-conf-files/anarcat-1531.conf new file mode 100644 index 0000000..73a9b74 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/anarcat-1531.conf @@ -0,0 +1,14 @@ + + ServerAdmin root@localhost + ServerName anarcat.wiki.orangeseeds.org:80 + + + UserDir disabled + + RewriteEngine On + RewriteRule ^/(.*) http\:\/\/anarc\.at\/$1 [L,R,NE] + + ErrorLog /var/log/apache2/1531error.log + LogLevel warn + CustomLog /var/log/apache2/1531access.log combined + diff --git a/tests/integration/samples/apache-conf-files/comment-continuations-2050.conf b/tests/integration/samples/apache-conf-files/comment-continuations-2050.conf new file mode 100644 index 0000000..4c3fa2a --- /dev/null +++ b/tests/integration/samples/apache-conf-files/comment-continuations-2050.conf @@ -0,0 +1,428 @@ +# --------------------------------------------------------------- +# Core ModSecurity Rule Set ver.2.2.6 +# Copyright (C) 2006-2012 Trustwave All rights reserved. +# +# The OWASP ModSecurity Core Rule Set is distributed under +# Apache Software License (ASL) version 2 +# Please see the enclosed LICENCE file for full details. +# --------------------------------------------------------------- + + +# +# -- [[ Recommended Base Configuration ]] ------------------------------------------------- +# +# The configuration directives/settings in this file are used to control +# the OWASP ModSecurity CRS. These settings do **NOT** configure the main +# ModSecurity settings such as: +# +# - SecRuleEngine +# - SecRequestBodyAccess +# - SecAuditEngine +# - SecDebugLog +# +# You should use the modsecurity.conf-recommended file that comes with the +# ModSecurity source code archive. +# +# Ref: http://mod-security.svn.sourceforge.net/viewvc/mod-security/m2/trunk/modsecurity.conf-recommended +# + + +# +# -- [[ Rule Version ]] ------------------------------------------------------------------- +# +# Rule version data is added to the "Producer" line of Section H of the Audit log: +# +# - Producer: ModSecurity for Apache/2.7.0-rc1 (http://www.modsecurity.org/); OWASP_CRS/2.2.4. +# +# Ref: https://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual#SecComponentSignature +# +#SecComponentSignature "OWASP_CRS/2.2.6" + + +# +# -- [[ Modes of Operation: Self-Contained vs. Collaborative Detection ]] ----------------- +# +# Each detection rule uses the "block" action which will inherit the SecDefaultAction +# specified below. Your settings here will determine which mode of operation you use. +# +# -- [[ Self-Contained Mode ]] -- +# Rules inherit the "deny" disruptive action. The first rule that matches will block. +# +# -- [[ Collaborative Detection Mode ]] -- +# This is a "delayed blocking" mode of operation where each matching rule will inherit +# the "pass" action and will only contribute to anomaly scores. Transactional blocking +# can be applied +# +# -- [[ Alert Logging Control ]] -- +# You have three options - +# +# - To log to both the Apache error_log and ModSecurity audit_log file use: "log" +# - To log *only* to the ModSecurity audit_log file use: "nolog,auditlog" +# - To log *only* to the Apache error_log file use: "log,noauditlog" +# +# Ref: http://blog.spiderlabs.com/2010/11/advanced-topic-of-the-week-traditional-vs-anomaly-scoring-detection-modes.html +# Ref: https://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual#SecDefaultAction +# +#SecDefaultAction "phase:1,deny,log" + + +# +# -- [[ Collaborative Detection Severity Levels ]] ---------------------------------------- +# +# These are the default scoring points for each severity level. You may +# adjust these to you liking. These settings will be used in macro expansion +# in the rules to increment the anomaly scores when rules match. +# +# These are the default Severity ratings (with anomaly scores) of the individual rules - +# +# - 2: Critical - Anomaly Score of 5. +# Is the highest severity level possible without correlation. It is +# normally generated by the web attack rules (40 level files). +# - 3: Error - Anomaly Score of 4. +# Is generated mostly from outbound leakage rules (50 level files). +# - 4: Warning - Anomaly Score of 3. +# Is generated by malicious client rules (35 level files). +# - 5: Notice - Anomaly Score of 2. +# Is generated by the Protocol policy and anomaly files. +# +#SecAction \ + "id:'900001', \ + phase:1, \ + t:none, \ + setvar:tx.critical_anomaly_score=5, \ + setvar:tx.error_anomaly_score=4, \ + setvar:tx.warning_anomaly_score=3, \ + setvar:tx.notice_anomaly_score=2, \ + nolog, \ + pass" + + +# +# -- [[ Collaborative Detection Scoring Threshold Levels ]] ------------------------------ +# +# These variables are used in macro expansion in the 49 inbound blocking and 59 +# outbound blocking files. +# +# **MUST HAVE** ModSecurity v2.5.12 or higher to use macro expansion in numeric +# operators. If you have an earlier version, edit the 49/59 files directly to +# set the appropriate anomaly score levels. +# +# You should set the score to the proper threshold you would prefer. If set to "5" +# it will work similarly to previous Mod CRS rules and will create an event in the error_log +# file if there are any rules that match. If you would like to lessen the number of events +# generated in the error_log file, you should increase the anomaly score threshold to +# something like "20". This would only generate an event in the error_log file if +# there are multiple lower severity rule matches or if any 1 higher severity item matches. +# +#SecAction \ + "id:'900002', \ + phase:1, \ + t:none, \ + setvar:tx.inbound_anomaly_score_level=5, \ + nolog, \ + pass" + + +#SecAction \ + "id:'900003', \ + phase:1, \ + t:none, \ + setvar:tx.outbound_anomaly_score_level=4, \ + nolog, \ + pass" + + +# +# -- [[ Collaborative Detection Blocking ]] ----------------------------------------------- +# +# This is a collaborative detection mode where each rule will increment an overall +# anomaly score for the transaction. The scores are then evaluated in the following files: +# +# Inbound anomaly score - checked in the modsecurity_crs_49_inbound_blocking.conf file +# Outbound anomaly score - checked in the modsecurity_crs_59_outbound_blocking.conf file +# +# If you want to use anomaly scoring mode, then uncomment this line. +# +#SecAction \ + "id:'900004', \ + phase:1, \ + t:none, \ + setvar:tx.anomaly_score_blocking=on, \ + nolog, \ + pass" + + +# +# -- [[ GeoIP Database ]] ----------------------------------------------------------------- +# +# There are some rulesets that need to inspect the GEO data of the REMOTE_ADDR data. +# +# You must first download the MaxMind GeoIP Lite City DB - +# +# http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz +# +# You then need to define the proper path for the SecGeoLookupDb directive +# +# Ref: http://blog.spiderlabs.com/2010/10/detecting-malice-with-modsecurity-geolocation-data.html +# Ref: http://blog.spiderlabs.com/2010/11/detecting-malice-with-modsecurity-ip-forensics.html +# +#SecGeoLookupDb /opt/modsecurity/lib/GeoLiteCity.dat + +# +# -- [[ Regression Testing Mode ]] -------------------------------------------------------- +# +# If you are going to run the regression testing mode, you should uncomment the +# following rule. It will enable DetectionOnly mode for the SecRuleEngine and +# will enable Response Header tagging so that the client testing script can see +# which rule IDs have matched. +# +# You must specify the your source IP address where you will be running the tests +# from. +# +#SecRule REMOTE_ADDR "@ipMatch 192.168.1.100" \ + "id:'900005', \ + phase:1, \ + t:none, \ + ctl:ruleEngine=DetectionOnly, \ + setvar:tx.regression_testing=1, \ + nolog, \ + pass" + + +# +# -- [[ HTTP Policy Settings ]] ---------------------------------------------------------- +# +# Set the following policy settings here and they will be propagated to the 23 rules +# file (modsecurity_common_23_request_limits.conf) by using macro expansion. +# If you run into false positives, you can adjust the settings here. +# +# Only the max number of args is uncommented by default as there are a high rate +# of false positives. Uncomment the items you wish to set. +# +# +# -- Maximum number of arguments in request limited +#SecAction \ + "id:'900006', \ + phase:1, \ + t:none, \ + setvar:tx.max_num_args=255, \ + nolog, \ + pass" + +# +# -- Limit argument name length +#SecAction \ + "id:'900007', \ + phase:1, \ + t:none, \ + setvar:tx.arg_name_length=100, \ + nolog, \ + pass" + +# +# -- Limit value name length +#SecAction \ + "id:'900008', \ + phase:1, \ + t:none, \ + setvar:tx.arg_length=400, \ + nolog, \ + pass" + +# +# -- Limit arguments total length +#SecAction \ + "id:'900009', \ + phase:1, \ + t:none, \ + setvar:tx.total_arg_length=64000, \ + nolog, \ + pass" + +# +# -- Individual file size is limited +#SecAction \ + "id:'900010', \ + phase:1, \ + t:none, \ + setvar:tx.max_file_size=1048576, \ + nolog, \ + pass" + +# +# -- Combined file size is limited +#SecAction \ + "id:'900011', \ + phase:1, \ + t:none, \ + setvar:tx.combined_file_sizes=1048576, \ + nolog, \ + pass" + + +# +# Set the following policy settings here and they will be propagated to the 30 rules +# file (modsecurity_crs_30_http_policy.conf) by using macro expansion. +# If you run into false positives, you can adjust the settings here. +# +#SecAction \ + "id:'900012', \ + phase:1, \ + t:none, \ + setvar:'tx.allowed_methods=GET HEAD POST OPTIONS', \ + setvar:'tx.allowed_request_content_type=application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/x-amf', \ + setvar:'tx.allowed_http_versions=HTTP/0.9 HTTP/1.0 HTTP/1.1', \ + setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .resources/ .resx/ .sql/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/', \ + setvar:'tx.restricted_headers=/Proxy-Connection/ /Lock-Token/ /Content-Range/ /Translate/ /via/ /if/', \ + nolog, \ + pass" + + +# +# -- [[ Content Security Policy (CSP) Settings ]] ----------------------------------------- +# +# The purpose of these settings is to send CSP response headers to +# Mozilla FireFox users so that you can enforce how dynamic content +# is used. CSP usage helps to prevent XSS attacks against your users. +# +# Reference Link: +# +# https://developer.mozilla.org/en/Security/CSP +# +# Uncomment this SecAction line if you want use CSP enforcement. +# You need to set the appropriate directives and settings for your site/domain and +# and activate the CSP file in the experimental_rules directory. +# +# Ref: http://blog.spiderlabs.com/2011/04/modsecurity-advanced-topic-of-the-week-integrating-content-security-policy-csp.html +# +#SecAction \ + "id:'900013', \ + phase:1, \ + t:none, \ + setvar:tx.csp_report_only=1, \ + setvar:tx.csp_report_uri=/csp_violation_report, \ + setenv:'csp_policy=allow \'self\'; img-src *.yoursite.com; media-src *.yoursite.com; style-src *.yoursite.com; frame-ancestors *.yoursite.com; script-src *.yoursite.com; report-uri %{tx.csp_report_uri}', \ + nolog, \ + pass" + + +# +# -- [[ Brute Force Protection ]] --------------------------------------------------------- +# +# If you are using the Brute Force Protection rule set, then uncomment the following +# lines and set the following variables: +# - Protected URLs: resources to protect (e.g. login pages) - set to your login page +# - Burst Time Slice Interval: time interval window to monitor for bursts +# - Request Threshold: request # threshold to trigger a burst +# - Block Period: temporary block timeout +# +#SecAction \ + "id:'900014', \ + phase:1, \ + t:none, \ + setvar:'tx.brute_force_protected_urls=/login.jsp /partner_login.php', \ + setvar:'tx.brute_force_burst_time_slice=60', \ + setvar:'tx.brute_force_counter_threshold=10', \ + setvar:'tx.brute_force_block_timeout=300', \ + nolog, \ + pass" + + +# +# -- [[ DoS Protection ]] ---------------------------------------------------------------- +# +# If you are using the DoS Protection rule set, then uncomment the following +# lines and set the following variables: +# - Burst Time Slice Interval: time interval window to monitor for bursts +# - Request Threshold: request # threshold to trigger a burst +# - Block Period: temporary block timeout +# +#SecAction \ + "id:'900015', \ + phase:1, \ + t:none, \ + setvar:'tx.dos_burst_time_slice=60', \ + setvar:'tx.dos_counter_threshold=100', \ + setvar:'tx.dos_block_timeout=600', \ + nolog, \ + pass" + + +# +# -- [[ Check UTF encoding ]] ----------------------------------------------------------- +# +# We only want to apply this check if UTF-8 encoding is actually used by the site, otherwise +# it will result in false positives. +# +# Uncomment this line if your site uses UTF8 encoding +#SecAction \ + "id:'900016', \ + phase:1, \ + t:none, \ + setvar:tx.crs_validate_utf8_encoding=1, \ + nolog, \ + pass" + + +# +# -- [[ Enable XML Body Parsing ]] ------------------------------------------------------- +# +# The rules in this file will trigger the XML parser upon an XML request +# +# Initiate XML Processor in case of xml content-type +# +#SecRule REQUEST_HEADERS:Content-Type "text/xml" \ + "id:'900017', \ + phase:1, \ + t:none,t:lowercase, \ + nolog, \ + pass, \ + chain" + #SecRule REQBODY_PROCESSOR "!@streq XML" \ + "ctl:requestBodyProcessor=XML" + + +# +# -- [[ Global and IP Collections ]] ----------------------------------------------------- +# +# Create both Global and IP collections for rules to use +# There are some CRS rules that assume that these two collections +# have already been initiated. +# +#SecRule REQUEST_HEADERS:User-Agent "^(.*)$" \ + "id:'900018', \ + phase:1, \ + t:none,t:sha1,t:hexEncode, \ + setvar:tx.ua_hash=%{matched_var}, \ + nolog, \ + pass" + + +#SecRule REQUEST_HEADERS:x-forwarded-for "^\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b" \ + "id:'900019', \ + phase:1, \ + t:none, \ + capture, \ + setvar:tx.real_ip=%{tx.1}, \ + nolog, \ + pass" + + +#SecRule &TX:REAL_IP "!@eq 0" \ + "id:'900020', \ + phase:1, \ + t:none, \ + initcol:global=global, \ + initcol:ip=%{tx.real_ip}_%{tx.ua_hash}, \ + nolog, \ + pass" + + +#SecRule &TX:REAL_IP "@eq 0" \ + "id:'900021', \ + phase:1, \ + t:none, \ + initcol:global=global, \ + initcol:ip=%{remote_addr}_%{tx.ua_hash}, \ + nolog, \ + pass" diff --git a/tests/integration/samples/apache-conf-files/drupal-errordocument-arg-1724.conf b/tests/integration/samples/apache-conf-files/drupal-errordocument-arg-1724.conf new file mode 100644 index 0000000..4733ffa --- /dev/null +++ b/tests/integration/samples/apache-conf-files/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/integration/samples/apache-conf-files/drupal-htaccess-1531.conf b/tests/integration/samples/apache-conf-files/drupal-htaccess-1531.conf new file mode 100644 index 0000000..a1aab7a --- /dev/null +++ b/tests/integration/samples/apache-conf-files/drupal-htaccess-1531.conf @@ -0,0 +1,149 @@ +# +# 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 + +# Set the default handler. +DirectoryIndex index.php index.html index.htm + +# Override PHP settings that cannot be changed at runtime. See +# sites/default/default.settings.php and drupal_environment_initialize() in +# includes/bootstrap.inc for settings that can be changed at runtime. + +# PHP 5, Apache 1 and 2. + + php_flag magic_quotes_gpc off + php_flag magic_quotes_sybase off + php_flag register_globals off + php_flag session.auto_start off + php_value mbstring.http_input pass + php_value mbstring.http_output pass + php_flag mbstring.encoding_translation off + + +# 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 + + # Set "protossl" to "s" if we were accessed via https://. This is used later + # if you enable "www." stripping or enforcement, in order to ensure that + # you don't bounce between http and https. + RewriteRule ^ - [E=protossl] + RewriteCond %{HTTPS} on + RewriteRule ^ - [E=protossl:s] + + # Make sure Authorization HTTP header is available to PHP + # even when running as CGI or FastCGI. + RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + # Block access to "hidden" directories whose names begin with a period. This + # includes directories used by version control systems such as Subversion or + # Git to store control files. Files whose names begin with a period, as well + # as the control files used by CVS, are protected by the FilesMatch directive + # above. + # + # NOTE: This only works when mod_rewrite is loaded. Without mod_rewrite, it is + # not possible to block access to entire directories from .htaccess, because + # is not allowed here. + # + # If you do not have mod_rewrite installed, you should remove these + # directories from your webroot or otherwise protect them from being + # downloaded. + RewriteRule "(^|/)\." - [F] + + # 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/...) + # uncomment the following: + # RewriteCond %{HTTP_HOST} . + # RewriteCond %{HTTP_HOST} !^www\. [NC] + # RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [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 the following: + # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] + # RewriteRule ^ http%{ENV:protossl}://%1%{REQUEST_URI} [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 / + + # Pass all requests not referring directly to files in the filesystem to + # index.php. Clean URLs are handled in drupal_environment_initialize(). + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} !=/favicon.ico + RewriteRule ^ index.php [L] + + # Rules to correctly serve gzip compressed CSS and JS files. + # Requires both mod_rewrite and mod_headers to be enabled. + + # Serve gzip compressed CSS files if they exist and the client accepts gzip. + RewriteCond %{HTTP:Accept-encoding} gzip + RewriteCond %{REQUEST_FILENAME}\.gz -s + RewriteRule ^(.*)\.css $1\.css\.gz [QSA] + + # Serve gzip compressed JS files if they exist and the client accepts gzip. + RewriteCond %{HTTP:Accept-encoding} gzip + RewriteCond %{REQUEST_FILENAME}\.gz -s + RewriteRule ^(.*)\.js $1\.js\.gz [QSA] + + # Serve correct content types, and prevent mod_deflate double gzip. + RewriteRule .css.gz$ - [T=text/css,E=no-gzip:1] + RewriteRule .js.gz$ - [T=text/javascript,E=no-gzip:1] + + + # Serve correct encoding type. + Header set Content-Encoding gzip + # Force proxies to cache gzipped & non-gzipped css/js files separately. + Header append Vary Accept-Encoding + + + + +# Add headers to all responses. + + # Disable content sniffing, since it's an attack vector. + Header always set X-Content-Type-Options nosniff + diff --git a/tests/integration/samples/apache-conf-files/escaped-space-arguments-2735.conf b/tests/integration/samples/apache-conf-files/escaped-space-arguments-2735.conf new file mode 100644 index 0000000..1ea53df --- /dev/null +++ b/tests/integration/samples/apache-conf-files/escaped-space-arguments-2735.conf @@ -0,0 +1,2 @@ +RewriteCond %{HTTP:Content-Disposition} \.php [NC] +RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.+/trackback/?\ HTTP/ [NC] diff --git a/tests/integration/samples/apache-conf-files/example-1755.conf b/tests/integration/samples/apache-conf-files/example-1755.conf new file mode 100644 index 0000000..2600295 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/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/integration/samples/apache-conf-files/example-ssl.conf b/tests/integration/samples/apache-conf-files/example-ssl.conf new file mode 100644 index 0000000..31deb76 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/example-ssl.conf @@ -0,0 +1,136 @@ + + ServerName example.com + ServerAlias www.example.com + ServerAdmin webmaster@localhost + + DocumentRoot /var/www/html + + # 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 + + # SSL Engine Switch: + # Enable/Disable SSL for this virtual host. + SSLEngine on + + # A self-signed (snakeoil) certificate can be created by installing + # the ssl-cert package. See + # /usr/share/doc/apache2/README.Debian.gz for more info. + # If both key and certificate are stored in the same file, only the + # SSLCertificateFile directive is needed. + SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem + SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key + + # Server Certificate Chain: + # Point SSLCertificateChainFile at a file containing the + # concatenation of PEM encoded CA certificates which form the + # certificate chain for the server certificate. Alternatively + # the referenced file can be the same as SSLCertificateFile + # when the CA certificates are directly appended to the server + # certificate for convenience. + #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt + + # Certificate Authority (CA): + # Set the CA certificate verification path where to find CA + # certificates for client authentication or alternatively one + # huge file containing all of them (file must be PEM encoded) + # Note: Inside SSLCACertificatePath you need hash symlinks + # to point to the certificate files. Use the provided + # Makefile to update the hash symlinks after changes. + #SSLCACertificatePath /etc/ssl/certs/ + #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt + + # Certificate Revocation Lists (CRL): + # Set the CA revocation path where to find CA CRLs for client + # authentication or alternatively one huge file containing all + # of them (file must be PEM encoded) + # Note: Inside SSLCARevocationPath you need hash symlinks + # to point to the certificate files. Use the provided + # Makefile to update the hash symlinks after changes. + #SSLCARevocationPath /etc/apache2/ssl.crl/ + #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl + + # Client Authentication (Type): + # Client certificate verification type and depth. Types are + # none, optional, require and optional_no_ca. Depth is a + # number which specifies how deeply to verify the certificate + # issuer chain before deciding the certificate is not valid. + #SSLVerifyClient require + #SSLVerifyDepth 10 + + # SSL Engine Options: + # Set various options for the SSL engine. + # o FakeBasicAuth: + # Translate the client X.509 into a Basic Authorisation. This means that + # the standard Auth/DBMAuth methods can be used for access control. The + # user name is the `one line' version of the client's X.509 certificate. + # Note that no password is obtained from the user. Every entry in the user + # file needs this password: `xxj31ZMTZzkVA'. + # o ExportCertData: + # This exports two additional environment variables: SSL_CLIENT_CERT and + # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the + # server (always existing) and the client (only existing when client + # authentication is used). This can be used to import the certificates + # into CGI scripts. + # o StdEnvVars: + # This exports the standard SSL/TLS related `SSL_*' environment variables. + # Per default this exportation is switched off for performance reasons, + # because the extraction step is an expensive operation and is usually + # useless for serving static content. So one usually enables the + # exportation for CGI and SSI requests only. + # o OptRenegotiate: + # This enables optimized SSL connection renegotiation handling when SSL + # directives are used in per-directory context. + #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire + + SSLOptions +StdEnvVars + + + SSLOptions +StdEnvVars + + + # SSL Protocol Adjustments: + # The safe and default but still SSL/TLS standard compliant shutdown + # approach is that mod_ssl sends the close notify alert but doesn't wait for + # the close notify alert from client. When you need a different shutdown + # approach you can use one of the following variables: + # o ssl-unclean-shutdown: + # This forces an unclean shutdown when the connection is closed, i.e. no + # SSL close notify alert is send or allowed to received. This violates + # the SSL/TLS standard but is needed for some brain-dead browsers. Use + # this when you receive I/O errors because of the standard approach where + # mod_ssl sends the close notify alert. + # o ssl-accurate-shutdown: + # This forces an accurate shutdown when the connection is closed, i.e. a + # SSL close notify alert is send and mod_ssl waits for the close notify + # alert of the client. This is 100% SSL/TLS standard compliant, but in + # practice often causes hanging connections with brain-dead browsers. Use + # this only for browsers where you know that their SSL implementation + # works correctly. + # Notice: Most problems of broken clients are also related to the HTTP + # keep-alive facility, so you usually additionally want to disable + # keep-alive for those clients, too. Use variable "nokeepalive" for this. + # Similarly, one has to force some clients to use HTTP/1.0 to workaround + # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and + # "force-response-1.0" for this. + BrowserMatch "MSIE [2-6]" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + # MSIE 7 and newer should be able to use keepalive + BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown + + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/tests/integration/samples/apache-conf-files/example.conf b/tests/integration/samples/apache-conf-files/example.conf new file mode 100644 index 0000000..60bdeea --- /dev/null +++ b/tests/integration/samples/apache-conf-files/example.conf @@ -0,0 +1,32 @@ + + # 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 + + ServerAdmin webmaster@localhost + DocumentRoot /var/www/html + + # 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/integration/samples/apache-conf-files/finalize-1243.apache2.conf.txt b/tests/integration/samples/apache-conf-files/finalize-1243.apache2.conf.txt new file mode 100644 index 0000000..73dc642 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/finalize-1243.apache2.conf.txt @@ -0,0 +1,222 @@ +# This is the main Apache server configuration file. It contains the +# configuration directives that give the server its instructions. +# See http://httpd.apache.org/docs/2.4/ for detailed information about +# the directives and /usr/share/doc/apache2/README.Debian about Debian specific +# hints. +# +# +# Summary of how the Apache 2 configuration works in Debian: +# The Apache 2 web server configuration in Debian is quite different to +# upstream's suggested way to configure the web server. This is because Debian's +# default Apache2 installation attempts to make adding and removing modules, +# virtual hosts, and extra configuration directives as flexible as possible, in +# order to make automating the changes and administering the server as easy as +# possible. + +# It is split into several files forming the configuration hierarchy outlined +# below, all located in the /etc/apache2/ directory: +# +# /etc/apache2/ +# |-- apache2.conf +# | `-- ports.conf +# |-- mods-enabled +# | |-- *.load +# | `-- *.conf +# |-- conf-enabled +# | `-- *.conf +# `-- sites-enabled +# `-- *.conf +# +# +# * apache2.conf is the main configuration file (this file). It puts the pieces +# together by including all remaining configuration files when starting up the +# web server. +# +# * ports.conf is always included from the main configuration file. It is +# supposed to determine listening ports for incoming connections which can be +# customized anytime. +# +# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/ +# directories contain particular configuration snippets which manage modules, +# global configuration fragments, or virtual host configurations, +# respectively. +# +# They are activated by symlinking available configuration files from their +# respective *-available/ counterparts. These should be managed by using our +# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See +# their respective man pages for detailed information. +# +# * The binary is called apache2. Due to the use of environment variables, in +# the default configuration, apache2 needs to be started/stopped with +# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not +# work with the default configuration. + + +# Global configuration +# + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE! If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the Mutex documentation (available +# at ); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +#ServerRoot "/etc/apache2" + +# +# The accept serialization lock file MUST BE STORED ON A LOCAL DISK. +# +Mutex file:${APACHE_LOCK_DIR} default + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# This needs to be set in /etc/apache2/envvars +# +PidFile ${APACHE_PID_FILE} + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 5 + + +# These need to be set in /etc/apache2/envvars +User ${APACHE_RUN_USER} +Group ${APACHE_RUN_GROUP} + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog ${APACHE_LOG_DIR}/error.log + +# +# LogLevel: Control the severity of messages logged to the error_log. +# Available values: trace8, ..., trace1, debug, info, notice, warn, +# error, crit, alert, emerg. +# It is also possible to configure the log level for particular modules, e.g. +# "LogLevel info ssl:warn" +# +LogLevel warn + +# Include module configuration: +IncludeOptional mods-enabled/*.load +IncludeOptional mods-enabled/*.conf + +# Include list of ports to listen on +Include ports.conf + + +# Sets the default security model of the Apache2 HTTPD server. It does +# not allow access to the root filesystem outside of /usr/share and /var/www. +# The former is used by web applications packaged in Debian, +# the latter may be used for local directories served by the web server. If +# your system is serving content from a sub-directory in /srv you must allow +# access here, or in any related virtual host. + + Options FollowSymLinks + AllowOverride None + Require all denied + + + + AllowOverride None + Require all granted + + + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + + +# +# Options Indexes FollowSymLinks +# AllowOverride None +# Require all granted +# + +# AccessFileName: The name of the file to look for in each directory +# for additional configuration directives. See also the AllowOverride +# directive. +# +AccessFileName .htaccess + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all denied + + + +# +# The following directives define some format nicknames for use with +# a CustomLog directive. +# +# These deviate from the Common Log Format definitions in that they use %O +# (the actual bytes sent including headers) instead of %b (the size of the +# requested file), because the latter makes it impossible to detect partial +# requests. +# +# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended. +# Use mod_remoteip instead. +# +#LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined +LogFormat "%t \"%r\" %>s %O \"%{User-Agent}i\"" vhost_combined + +#LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined +#LogFormat "%h %l %u %t \"%r\" %>s %O" common +LogFormat "- %t \"%r\" %>s %b" noip + +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# Include of directories ignores editors' and dpkg's backup files, +# see README.Debian for details. + +# Include generic snippets of statements +IncludeOptional conf-enabled/*.conf + +# Include the virtual host configurations: +#IncludeOptional sites-enabled/*.conf + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/tests/integration/samples/apache-conf-files/finalize-1243.conf b/tests/integration/samples/apache-conf-files/finalize-1243.conf new file mode 100644 index 0000000..dbfae37 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/finalize-1243.conf @@ -0,0 +1,67 @@ +#LoadModule ssl_module modules/mod_ssl.so + +Listen 4443 + + # 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.eiserneketten.de + + SSLEngine on + ServerAdmin webmaster@localhost + DocumentRoot /var/www/html + + # 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 noip + + # 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 + + Options FollowSymLinks + AllowOverride None + Order Deny,Allow + #Deny from All + + + Alias / /eiserneketten/pages/eiserneketten.html +SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem +SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key +SSLCertificateChainFile /etc/ssl/certs/ssl-cert-snakeoil.pem +Include /etc/letsencrypt/options-ssl-apache.conf + + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet + +# +# Directives to allow use of AWStats as a CGI +# +Alias /awstatsclasses "/usr/local/awstats/wwwroot/classes/" +Alias /awstatscss "/usr/local/awstats/wwwroot/css/" +Alias /awstatsicons "/usr/local/awstats/wwwroot/icon/" +ScriptAlias /awstats/ "/usr/local/awstats/wwwroot/cgi-bin/" + +# +# This is to permit URL access to scripts/files in AWStats directory. +# + + Options None + AllowOverride None + Order allow,deny + Allow from all + + diff --git a/tests/integration/samples/apache-conf-files/graphite-quote-1934.conf b/tests/integration/samples/apache-conf-files/graphite-quote-1934.conf new file mode 100644 index 0000000..f257dd9 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/graphite-quote-1934.conf @@ -0,0 +1,21 @@ + + + WSGIDaemonProcess _graphite processes=5 threads=5 display-name='%{GROUP}' inactivity-timeout=120 user=www-data group=www-data + WSGIProcessGroup _graphite + WSGIImportScript /usr/share/graphite-web/graphite.wsgi process-group=_graphite application-group=%{GLOBAL} + WSGIScriptAlias / /usr/share/graphite-web/graphite.wsgi + + Alias /content/ /usr/share/graphite-web/static/ + + SetHandler None + + + ErrorLog ${APACHE_LOG_DIR}/graphite-web_error.log + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel warn + + CustomLog ${APACHE_LOG_DIR}/graphite-web_access.log combined + + diff --git a/tests/integration/samples/apache-conf-files/ipv6-1143.conf b/tests/integration/samples/apache-conf-files/ipv6-1143.conf new file mode 100644 index 0000000..ad988dc --- /dev/null +++ b/tests/integration/samples/apache-conf-files/ipv6-1143.conf @@ -0,0 +1,9 @@ + +DocumentRoot /tmp +ServerName example.com +ServerAlias www.example.com +CustomLog ${APACHE_LOG_DIR}/example.log combined + + AllowOverride All + + diff --git a/tests/integration/samples/apache-conf-files/ipv6-1143b.conf b/tests/integration/samples/apache-conf-files/ipv6-1143b.conf new file mode 100644 index 0000000..e2b4fd3 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/ipv6-1143b.conf @@ -0,0 +1,18 @@ + +DocumentRoot /tmp +ServerName example.com +ServerAlias www.example.com +CustomLog ${APACHE_LOG_DIR}/example.log combined + + AllowOverride All + + + SSLEngine on + + SSLHonorCipherOrder On + SSLProtocol all -SSLv2 -SSLv3 + SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH +aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS" + + SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem + SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key + diff --git a/tests/integration/samples/apache-conf-files/ipv6-1143c.conf b/tests/integration/samples/apache-conf-files/ipv6-1143c.conf new file mode 100644 index 0000000..f2d2ecb --- /dev/null +++ b/tests/integration/samples/apache-conf-files/ipv6-1143c.conf @@ -0,0 +1,9 @@ + +DocumentRoot /tmp +ServerName example.com +ServerAlias www.example.com +CustomLog ${APACHE_LOG_DIR}/example.log combined + + AllowOverride All + + diff --git a/tests/integration/samples/apache-conf-files/ipv6-1143d.conf b/tests/integration/samples/apache-conf-files/ipv6-1143d.conf new file mode 100644 index 0000000..f5b7a2b --- /dev/null +++ b/tests/integration/samples/apache-conf-files/ipv6-1143d.conf @@ -0,0 +1,18 @@ + +DocumentRoot /tmp +ServerName example.com +ServerAlias www.example.com +CustomLog ${APACHE_LOG_DIR}/example.log combined + + AllowOverride All + + + SSLEngine on + + SSLHonorCipherOrder On + SSLProtocol all -SSLv2 -SSLv3 + SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH +aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS" + + SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem + SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key + diff --git a/tests/integration/samples/apache-conf-files/missing-double-quote-1724.conf b/tests/integration/samples/apache-conf-files/missing-double-quote-1724.conf new file mode 100644 index 0000000..7d97b23 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/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/integration/samples/apache-conf-files/missing-quote-1724.conf b/tests/integration/samples/apache-conf-files/missing-quote-1724.conf new file mode 100644 index 0000000..7d97b23 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/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/integration/samples/apache-conf-files/modmacro-1385.conf b/tests/integration/samples/apache-conf-files/modmacro-1385.conf new file mode 100644 index 0000000..d327c94 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/modmacro-1385.conf @@ -0,0 +1,33 @@ + + + # 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 $host + + ServerAdmin webmaster@localhost + DocumentRoot $dir + + # 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 + + +Use Vhost goxogle.com 80 /var/www/goxogle/ +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/tests/integration/samples/apache-conf-files/multivhost-1093.conf b/tests/integration/samples/apache-conf-files/multivhost-1093.conf new file mode 100644 index 0000000..444f0da --- /dev/null +++ b/tests/integration/samples/apache-conf-files/multivhost-1093.conf @@ -0,0 +1,295 @@ + + AllowOverride None + Require all denied + + + + DocumentRoot /var/www/sjau.ch/web + + ServerName sjau.ch + ServerAlias www.sjau.ch + ServerAdmin webmaster@sjau.ch + + ErrorLog /var/log/ispconfig/httpd/sjau.ch/error.log + + Alias /error/ "/var/www/sjau.ch/web/error/" + ErrorDocument 400 /error/400.html + ErrorDocument 401 /error/401.html + ErrorDocument 403 /error/403.html + ErrorDocument 404 /error/404.html + ErrorDocument 405 /error/405.html + ErrorDocument 500 /error/500.html + ErrorDocument 502 /error/502.html + ErrorDocument 503 /error/503.html + + + + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + + + Options +ExecCGI + + RubyRequire apache/ruby-run + #RubySafeLevel 0 + AddType text/html .rb + AddType text/html .rbx + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + + + + + + SetHandler mod_python + + PythonHandler mod_python.publisher + PythonDebug On + + + + # cgi enabled + + Require all granted + + ScriptAlias /cgi-bin/ /var/www/clients/client1/web2/cgi-bin/ + + SetHandler cgi-script + + # suexec enabled + + SuexecUserGroup web2 client1 + + # php as fast-cgi enabled + # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html + + IdleTimeout 300 + ProcessLifeTime 3600 + # MaxProcessCount 1000 + DefaultMinClassProcessCount 0 + DefaultMaxClassProcessCount 100 + IPCConnectTimeout 3 + IPCCommTimeout 600 + BusyTimeout 3600 + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + # add support for apache mpm_itk + + AssignUserId web2 client1 + + + + # Do not execute PHP files in webdav directory + + + SecRuleRemoveById 960015 + SecRuleRemoveById 960032 + + + SetHandler None + + + DavLockDB /var/www/clients/client1/web2/tmp/DavLock + # DO NOT REMOVE THE COMMENTS! + # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE! + # WEBDAV BEGIN + # WEBDAV END + + + + + + DocumentRoot /var/www/sjau.ch/web + + ServerName sjau.ch + ServerAlias www.sjau.ch + ServerAdmin webmaster@sjau.ch + + ErrorLog /var/log/ispconfig/httpd/sjau.ch/error.log + + Alias /error/ "/var/www/sjau.ch/web/error/" + ErrorDocument 400 /error/400.html + ErrorDocument 401 /error/401.html + ErrorDocument 403 /error/403.html + ErrorDocument 404 /error/404.html + ErrorDocument 405 /error/405.html + ErrorDocument 500 /error/500.html + ErrorDocument 502 /error/502.html + ErrorDocument 503 /error/503.html + + + + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + + + Options +ExecCGI + + RubyRequire apache/ruby-run + #RubySafeLevel 0 + AddType text/html .rb + AddType text/html .rbx + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + + + + + + SetHandler mod_python + + PythonHandler mod_python.publisher + PythonDebug On + + + + # cgi enabled + + Require all granted + + ScriptAlias /cgi-bin/ /var/www/clients/client1/web2/cgi-bin/ + + SetHandler cgi-script + + # suexec enabled + + SuexecUserGroup web2 client1 + + # php as fast-cgi enabled + # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html + + IdleTimeout 300 + ProcessLifeTime 3600 + # MaxProcessCount 1000 + DefaultMinClassProcessCount 0 + DefaultMaxClassProcessCount 100 + IPCConnectTimeout 3 + IPCCommTimeout 600 + BusyTimeout 3600 + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + # add support for apache mpm_itk + + AssignUserId web2 client1 + + + + # Do not execute PHP files in webdav directory + + + SecRuleRemoveById 960015 + SecRuleRemoveById 960032 + + + SetHandler None + + + DavLockDB /var/www/clients/client1/web2/tmp/DavLock + # DO NOT REMOVE THE COMMENTS! + # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE! + # WEBDAV BEGIN + # WEBDAV END + + + + diff --git a/tests/integration/samples/apache-conf-files/multivhost-1093b.conf b/tests/integration/samples/apache-conf-files/multivhost-1093b.conf new file mode 100644 index 0000000..0388abc --- /dev/null +++ b/tests/integration/samples/apache-conf-files/multivhost-1093b.conf @@ -0,0 +1,593 @@ + + AllowOverride None + Require all denied + + + + DocumentRoot /var/www/ensemen.ch/web + + ServerName ensemen.ch + ServerAlias www.ensemen.ch + ServerAdmin webmaster@ensemen.ch + + ErrorLog /var/log/ispconfig/httpd/ensemen.ch/error.log + + Alias /error/ "/var/www/ensemen.ch/web/error/" + ErrorDocument 400 /error/400.html + ErrorDocument 401 /error/401.html + ErrorDocument 403 /error/403.html + ErrorDocument 404 /error/404.html + ErrorDocument 405 /error/405.html + ErrorDocument 500 /error/500.html + ErrorDocument 502 /error/502.html + ErrorDocument 503 /error/503.html + + + + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + + + Options +ExecCGI + + RubyRequire apache/ruby-run + #RubySafeLevel 0 + AddType text/html .rb + AddType text/html .rbx + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + + + + + + SetHandler mod_python + + PythonHandler mod_python.publisher + PythonDebug On + + + + # cgi enabled + + Require all granted + + ScriptAlias /cgi-bin/ /var/www/clients/client4/web17/cgi-bin/ + + SetHandler cgi-script + + # suexec enabled + + SuexecUserGroup web17 client4 + + # php as fast-cgi enabled + # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html + + IdleTimeout 300 + ProcessLifeTime 3600 + # MaxProcessCount 1000 + DefaultMinClassProcessCount 0 + DefaultMaxClassProcessCount 100 + IPCConnectTimeout 3 + IPCCommTimeout 600 + BusyTimeout 3600 + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + # add support for apache mpm_itk + + AssignUserId web17 client4 + + + + # Do not execute PHP files in webdav directory + + + SecRuleRemoveById 960015 + SecRuleRemoveById 960032 + + + SetHandler None + + + DavLockDB /var/www/clients/client4/web17/tmp/DavLock + # DO NOT REMOVE THE COMMENTS! + # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE! + # WEBDAV BEGIN + # WEBDAV END + + + + + + DocumentRoot /var/www/ensemen.ch/web + + ServerName ensemen.ch + ServerAlias www.ensemen.ch + ServerAdmin webmaster@ensemen.ch + + ErrorLog /var/log/ispconfig/httpd/ensemen.ch/error.log + + Alias /error/ "/var/www/ensemen.ch/web/error/" + ErrorDocument 400 /error/400.html + ErrorDocument 401 /error/401.html + ErrorDocument 403 /error/403.html + ErrorDocument 404 /error/404.html + ErrorDocument 405 /error/405.html + ErrorDocument 500 /error/500.html + ErrorDocument 502 /error/502.html + ErrorDocument 503 /error/503.html + + + SSLEngine on + SSLProtocol All -SSLv2 -SSLv3 + SSLCertificateFile /var/www/clients/client4/web17/ssl/ensemen.ch.crt + SSLCertificateKeyFile /var/www/clients/client4/web17/ssl/ensemen.ch.key + + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + + + Options +ExecCGI + + RubyRequire apache/ruby-run + #RubySafeLevel 0 + AddType text/html .rb + AddType text/html .rbx + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + + + + + + SetHandler mod_python + + PythonHandler mod_python.publisher + PythonDebug On + + + + # cgi enabled + + Require all granted + + ScriptAlias /cgi-bin/ /var/www/clients/client4/web17/cgi-bin/ + + SetHandler cgi-script + + # suexec enabled + + SuexecUserGroup web17 client4 + + # php as fast-cgi enabled + # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html + + IdleTimeout 300 + ProcessLifeTime 3600 + # MaxProcessCount 1000 + DefaultMinClassProcessCount 0 + DefaultMaxClassProcessCount 100 + IPCConnectTimeout 3 + IPCCommTimeout 600 + BusyTimeout 3600 + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + # add support for apache mpm_itk + + AssignUserId web17 client4 + + + + # Do not execute PHP files in webdav directory + + + SecRuleRemoveById 960015 + SecRuleRemoveById 960032 + + + SetHandler None + + + DavLockDB /var/www/clients/client4/web17/tmp/DavLock + # DO NOT REMOVE THE COMMENTS! + # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE! + # WEBDAV BEGIN + # WEBDAV END + + + + + + DocumentRoot /var/www/ensemen.ch/web + + ServerName ensemen.ch + ServerAlias www.ensemen.ch + ServerAdmin webmaster@ensemen.ch + + ErrorLog /var/log/ispconfig/httpd/ensemen.ch/error.log + + Alias /error/ "/var/www/ensemen.ch/web/error/" + ErrorDocument 400 /error/400.html + ErrorDocument 401 /error/401.html + ErrorDocument 403 /error/403.html + ErrorDocument 404 /error/404.html + ErrorDocument 405 /error/405.html + ErrorDocument 500 /error/500.html + ErrorDocument 502 /error/502.html + ErrorDocument 503 /error/503.html + + + + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + + + Options +ExecCGI + + RubyRequire apache/ruby-run + #RubySafeLevel 0 + AddType text/html .rb + AddType text/html .rbx + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + + + + + + SetHandler mod_python + + PythonHandler mod_python.publisher + PythonDebug On + + + + # cgi enabled + + Require all granted + + ScriptAlias /cgi-bin/ /var/www/clients/client4/web17/cgi-bin/ + + SetHandler cgi-script + + # suexec enabled + + SuexecUserGroup web17 client4 + + # php as fast-cgi enabled + # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html + + IdleTimeout 300 + ProcessLifeTime 3600 + # MaxProcessCount 1000 + DefaultMinClassProcessCount 0 + DefaultMaxClassProcessCount 100 + IPCConnectTimeout 3 + IPCCommTimeout 600 + BusyTimeout 3600 + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + # add support for apache mpm_itk + + AssignUserId web17 client4 + + + + # Do not execute PHP files in webdav directory + + + SecRuleRemoveById 960015 + SecRuleRemoveById 960032 + + + SetHandler None + + + DavLockDB /var/www/clients/client4/web17/tmp/DavLock + # DO NOT REMOVE THE COMMENTS! + # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE! + # WEBDAV BEGIN + # WEBDAV END + + + + + + DocumentRoot /var/www/ensemen.ch/web + + ServerName ensemen.ch + ServerAlias www.ensemen.ch + ServerAdmin webmaster@ensemen.ch + + ErrorLog /var/log/ispconfig/httpd/ensemen.ch/error.log + + Alias /error/ "/var/www/ensemen.ch/web/error/" + ErrorDocument 400 /error/400.html + ErrorDocument 401 /error/401.html + ErrorDocument 403 /error/403.html + ErrorDocument 404 /error/404.html + ErrorDocument 405 /error/405.html + ErrorDocument 500 /error/500.html + ErrorDocument 502 /error/502.html + ErrorDocument 503 /error/503.html + + + SSLEngine on + SSLProtocol All -SSLv2 -SSLv3 + SSLCertificateFile /var/www/clients/client4/web17/ssl/ensemen.ch.crt + SSLCertificateKeyFile /var/www/clients/client4/web17/ssl/ensemen.ch.key + + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + # Clear PHP settings of this website + + SetHandler None + + Options +FollowSymLinks + AllowOverride All + Require all granted + + + + + Options +ExecCGI + + RubyRequire apache/ruby-run + #RubySafeLevel 0 + AddType text/html .rb + AddType text/html .rbx + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + SetHandler ruby-object + RubyHandler Apache::RubyRun.instance + + + + + + + + SetHandler mod_python + + PythonHandler mod_python.publisher + PythonDebug On + + + + # cgi enabled + + Require all granted + + ScriptAlias /cgi-bin/ /var/www/clients/client4/web17/cgi-bin/ + + SetHandler cgi-script + + # suexec enabled + + SuexecUserGroup web17 client4 + + # php as fast-cgi enabled + # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html + + IdleTimeout 300 + ProcessLifeTime 3600 + # MaxProcessCount 1000 + DefaultMinClassProcessCount 0 + DefaultMaxClassProcessCount 100 + IPCConnectTimeout 3 + IPCCommTimeout 600 + BusyTimeout 3600 + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + SetHandler fcgid-script + + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4 + FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5 + Options +ExecCGI + AllowOverride All + Require all granted + + + + # add support for apache mpm_itk + + AssignUserId web17 client4 + + + + # Do not execute PHP files in webdav directory + + + SecRuleRemoveById 960015 + SecRuleRemoveById 960032 + + + SetHandler None + + + DavLockDB /var/www/clients/client4/web17/tmp/DavLock + # DO NOT REMOVE THE COMMENTS! + # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE! + # WEBDAV BEGIN + # WEBDAV END + + + + diff --git a/tests/integration/samples/apache-conf-files/owncloud-1264.conf b/tests/integration/samples/apache-conf-files/owncloud-1264.conf new file mode 100644 index 0000000..d0ac81f --- /dev/null +++ b/tests/integration/samples/apache-conf-files/owncloud-1264.conf @@ -0,0 +1,13 @@ +Alias /owncloud /usr/share/owncloud + + + Options +FollowSymLinks + AllowOverride All + + order allow,deny + allow from all + + = 2.3> + Require all granted + + diff --git a/tests/integration/samples/apache-conf-files/rewrite-quote-1960.conf b/tests/integration/samples/apache-conf-files/rewrite-quote-1960.conf new file mode 100644 index 0000000..26214e7 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/rewrite-quote-1960.conf @@ -0,0 +1,7 @@ + + RewriteEngine On + RewriteCond %{REQUEST_URI} ^.*(,|;|:|<|>|">|"<|/|\\\.\.\\).* [NC,OR] + RewriteCond %{REQUEST_URI} ^.*(\=|\@|\[|\]|\^|\`|\{|\}|\~).* [NC,OR] + RewriteCond %{REQUEST_URI} ^.*(\'|%0A|%0D|%27|%3C|%3E|%00).* [NC] + RewriteRule ^(.*)$ - [F,L] + diff --git a/tests/integration/samples/apache-conf-files/roundcube-1222.conf b/tests/integration/samples/apache-conf-files/roundcube-1222.conf new file mode 100644 index 0000000..72ced7f --- /dev/null +++ b/tests/integration/samples/apache-conf-files/roundcube-1222.conf @@ -0,0 +1,61 @@ +# Those aliases do not work properly with several hosts on your apache server +# Uncomment them to use it or adapt them to your configuration +# Alias /roundcube/program/js/tiny_mce/ /usr/share/tinymce/www/ +# Alias /roundcube /var/lib/roundcube + +# Access to tinymce files + + Options Indexes MultiViews FollowSymLinks + AllowOverride None + = 2.3> + Require all granted + + + Order allow,deny + Allow from all + + + + + Options +FollowSymLinks + # This is needed to parse /var/lib/roundcube/.htaccess. See its + # content before setting AllowOverride to None. + AllowOverride All + = 2.3> + Require all granted + + + Order allow,deny + Allow from all + + + +# Protecting basic directories: + + Options -FollowSymLinks + AllowOverride None + + + + Options -FollowSymLinks + AllowOverride None + = 2.3> + Require all denied + + + Order allow,deny + Deny from all + + + + + Options -FollowSymLinks + AllowOverride None + = 2.3> + Require all denied + + + Order allow,deny + Deny from all + + diff --git a/tests/integration/samples/apache-conf-files/section-continuations-2525.conf b/tests/integration/samples/apache-conf-files/section-continuations-2525.conf new file mode 100644 index 0000000..9dbcc17 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/section-continuations-2525.conf @@ -0,0 +1,7 @@ + + diff --git a/tests/integration/samples/apache-conf-files/section-empty-continuations-2731.conf b/tests/integration/samples/apache-conf-files/section-empty-continuations-2731.conf new file mode 100644 index 0000000..96107a1 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/section-empty-continuations-2731.conf @@ -0,0 +1,247 @@ +#ATTENTION! +# +#DO NOT MODIFY THIS FILE BECAUSE IT WAS GENERATED AUTOMATICALLY, +#SO ALL YOUR CHANGES WILL BE LOST THE NEXT TIME THE FILE IS GENERATED. + +NameVirtualHost 192.168.100.218:80 +NameVirtualHost 10.128.178.192:80 + +NameVirtualHost 192.168.100.218:443 +NameVirtualHost 10.128.178.192:443 + + +ServerName "254020-web1.example.com" +ServerAdmin "name@example.com" + +DocumentRoot "/tmp" + + + LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" plesklog + + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" plesklog + + + TraceEnable off + +ServerTokens ProductOnly + + + AllowOverride "All" + Options SymLinksIfOwnerMatch + Order allow,deny + Allow from all + + +php_admin_flag engine off + + + +php_admin_flag engine off + + + + + + AllowOverride All + Options SymLinksIfOwnerMatch + Order allow,deny + Allow from all + + php_admin_flag engine off + + + php_admin_flag engine off + + + + + Header add X-Powered-By PleskLin + + + + JkWorkersFile "/etc/httpd/conf/workers.properties" + JkLogFile /var/log/httpd/mod_jk.log + JkLogLevel info + + +#Include "/etc/httpd/conf/plesk.conf.d/ip_default/*.conf" + + +# +# ServerName "default" +# UseCanonicalName Off +# DocumentRoot "/tmp" +# ScriptAlias /cgi-bin/ "/var/www/vhosts/default/cgi-bin" +# +# +# +# SSLEngine off +# +# +# +# AllowOverride None +# Options None +# Order allow,deny +# Allow from all +# +# +# +# +# +# php_admin_flag engine on +# +# +# +# php_admin_flag engine on +# +# +# +# +# + + + +# +# ServerName "default-192_168_100_218" +# UseCanonicalName Off +# DocumentRoot "/tmp" +# ScriptAlias /cgi-bin/ "/var/www/vhosts/default/cgi-bin" +# +# +# SSLEngine on +# SSLVerifyClient none +# #SSLCertificateFile "/usr/local/psa/var/certificates/cert-9MgutN" +# +# #SSLCACertificateFile "/usr/local/psa/var/certificates/cert-s6Wx3P" +# +# +# AllowOverride None +# Options None +# Order allow,deny +# Allow from all +# +# +# +# +# +# php_admin_flag engine on +# +# +# +# php_admin_flag engine on +# +# +# +# +# +# +# ServerName "default-10_128_178_192" +# UseCanonicalName Off +# DocumentRoot "/tmp" +# ScriptAlias /cgi-bin/ "/var/www/vhosts/default/cgi-bin" +# +# +# SSLEngine on +# SSLVerifyClient none +# #SSLCertificateFile "/usr/local/psa/var/certificates/certxfb6025" +# +# +# +# AllowOverride None +# Options None +# Order allow,deny +# Allow from all +# +# +# +# +# +# php_admin_flag engine on +# +# +# +# php_admin_flag engine on +# +# +# +# +# + + + + +# +# DocumentRoot "/tmp" +# ServerName lists +# ServerAlias lists.* +# UseCanonicalName Off +# +# ScriptAlias "/mailman/" "/usr/lib/mailman/cgi-bin/" +# +# Alias "/icons/" "/var/www/icons/" +# Alias "/pipermail/" "/var/lib/mailman/archives/public/" +# +# +# SSLEngine off +# +# +# +# +# Options FollowSymLinks +# Order allow,deny +# Allow from all +# +# +# + + +# +# DocumentRoot "/tmp" +# ServerName lists +# ServerAlias lists.* +# UseCanonicalName Off +# +# ScriptAlias "/mailman/" "/usr/lib/mailman/cgi-bin/" +# +# Alias "/icons/" "/var/www/icons/" +# Alias "/pipermail/" "/var/lib/mailman/archives/public/" +# +# SSLEngine on +# SSLVerifyClient none +# #SSLCertificateFile "/usr/local/psa/var/certificates/certxfb6025" +# +# +# +# Options FollowSymLinks +# Order allow,deny +# Allow from all +# +# +# + + + + RPAFproxy_ips 192.168.100.218 10.128.178.192 + + + RPAFproxy_ips 192.168.100.218 10.128.178.192 + diff --git a/tests/integration/samples/apache-conf-files/semacode-1598.conf b/tests/integration/samples/apache-conf-files/semacode-1598.conf new file mode 100644 index 0000000..89e2fb2 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/semacode-1598.conf @@ -0,0 +1,44 @@ + + ServerName semacode.com + ServerAlias www.semacode.com + DocumentRoot /tmp/ + TransferLog /tmp/access + ErrorLog /tmp/error + Redirect /posts/rss http://semacode.com/feed + Redirect permanent /weblog http://semacode.com/blog + +#ProxyPreserveHost On +# ProxyPass /past http://old.semacode.com + #ProxyPassReverse /past http://old.semacode.com +# + # Order allow,deny + #Allow from all +# + + Redirect /stylesheets/inside.css http://old.semacode.com/stylesheets/inside.css + RedirectMatch /images/portal/(.*) http://old.semacode.com/images/portal/$1 + Redirect /images/invisible.gif http://old.semacode.com/images/invisible.gif + RedirectMatch /javascripts/(.*) http://old.semacode.com/javascripts/$1 + + RewriteEngine on + RewriteRule ^/past/(.*) http://old.semacode.com/past/$1 [L,P] + RewriteCond %{HTTP_HOST} !^semacode\.com$ [NC] + RewriteCond %{HTTP_HOST} !^$ + RewriteRule ^/(.*) http://semacode.com/$1 [L,R] + + + + + + ServerName old.semacode.com + ServerAlias www.old.semacode.com + DocumentRoot /home/simon/semacode-server/semacode/website/trunk/public + TransferLog /tmp/access-old + ErrorLog /tmp/error-old + + Options FollowSymLinks + AllowOverride None + Order allow,deny + Allow from all + + diff --git a/tests/integration/samples/apache-conf-files/sslrequire-wordlist-1827.htaccess b/tests/integration/samples/apache-conf-files/sslrequire-wordlist-1827.htaccess new file mode 100644 index 0000000..1c06d54 --- /dev/null +++ b/tests/integration/samples/apache-conf-files/sslrequire-wordlist-1827.htaccess @@ -0,0 +1 @@ +SSLRequire %{SSL_CLIENT_S_DN_CN} in {"foo@bar.com", "bar@foo.com"} diff --git a/tests/integration/test_apache_samples.py b/tests/integration/test_apache_samples.py new file mode 100644 index 0000000..c97c687 --- /dev/null +++ b/tests/integration/test_apache_samples.py @@ -0,0 +1,67 @@ +# +# This file is part of apacheconfig software. +# +# Copyright (c) 2018-2019, Ilya Etingof +# License: https://github.com/etingof/apacheconfig/LICENSE.rst +# +import sys +import os + +from apacheconfig import * + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +class PerlConfigGeneralTestCase(unittest.TestCase): + + def setUp(self): + options = {'preservewhitespace': True} + ApacheConfigLexer = make_lexer(**options) + self.lexer = ApacheConfigLexer() + ApacheConfigParser = make_parser(**options) + self.parser = ApacheConfigParser(self.lexer, start='contents') + + def _test_files(self, directory, perform_test, expected_errors=0): + errors = [] + for filename in os.listdir(directory): + text = "" + filepath = os.path.join(directory, filename) + if os.path.isdir(filepath): + continue + with open(filepath) as f: + text = f.read() + perform_test(text) + self.assertEqual(len(errors), expected_errors) + + def testLexFiles(self): + samples_dir = os.path.join( + os.path.dirname(__file__), + 'samples', 'apache-conf-files', + ) + self._test_files(samples_dir, self.lexer.tokenize) + + def testParseFiles(self): + samples_dir = os.path.join( + os.path.dirname(__file__), + 'samples', 'apache-conf-files', + ) + self._test_files(samples_dir, self.parser.parse) + + def _parse_and_write(self, text): + node = parse_contents(text) + self.assertEquals(str(node), text) + + def testParseAndWriteFiles(self): + samples_dir = os.path.join( + os.path.dirname(__file__), + 'samples', 'apache-conf-files', + ) + self._test_files(samples_dir, self._parse_and_write) + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/unit/test_wloader.py b/tests/unit/test_wloader.py new file mode 100644 index 0000000..7cf2f98 --- /dev/null +++ b/tests/unit/test_wloader.py @@ -0,0 +1,176 @@ +# +# This file is part of apacheconfig software. +# +# Copyright (c) 2018-2019, Ilya Etingof +# License: https://github.com/etingof/apacheconfig/LICENSE.rst +# +import os +import sys + +from apacheconfig import * + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +try: + from unittest import mock + +except ImportError: + + import mock + +class WLoaderTestCaseWrite(unittest.TestCase): + def testChangeItemValue(self): + cases = [ + ('option value', 'value2', 'option value2'), + ('\noption value', 'value2', '\noption value2'), + ('\noption =\\\n value', 'value2', '\noption =\\\n value2'), + ('option value', 'long value', 'option long value'), + ('option value', '"long value"', 'option "long value"'), + ('option', 'option2', 'option option2'), + ('include old/path/to/file', 'new/path/to/file', 'include new/path/to/file'), + ] + for raw, new_value, expected in cases: + node = parse_item(raw) + node.value = new_value + self.assertEqual(expected, str(node)) + + def testChangeBlockValue(self): + cases = [ + ("\n", "name2", "\n"), + ("\n", "name2", "\n"), + ] + for raw, new_value, expected in cases: + node = parse_block(raw) + node.arguments = new_value + self.assertEqual(expected, str(node)) + + def testAddToContents(self): + cases = [ + # Inserting statement middle or end + ("a b\nc d", 1, "\n1 2", "a b\n1 2\nc d"), + ("a b\nc d", 2, "\n1 2", "a b\nc d\n1 2"), + ("a b\n", 1, " ###", "a b ###\n"), + ("a b # comment\n", 1, "\n1 2", "a b\n1 2\n # comment\n"), + # Inserting option/value statement at beginning + ("a", 0, "\n1 2", "\n1 2\na"), + ("a\n", 0, "###", "###\na\n"), + (" a b", 0, "\n1 2", "\n1 2\n a b"), + ("\n", 0, "\n1 2", "\n1 2\n"), + ("# comment\n", 0, "\n1 2", "\n1 2\n# comment\n"), + ] + for raw, index, to_add, expected in cases: + node = parse_contents(raw) + node.add(index, to_add) + self.assertEqual(expected, str(node)) + + def testRemoveFromContents(self): + cases = [ + ("a b\nc d", 1, "a b"), + ("a b\nc d", 0, "\nc d"), + ("\na\n", 0, "\n"), + ("a # comment", 1, "a"), + ("a # comment", 0, " # comment") + ] + for raw, index, expected in cases: + node = parse_contents(raw) + node.remove(index) + self.assertEqual(expected, str(node)) + +class WLoaderTestCaseRead(unittest.TestCase): + def _test_item_cases(self, cases, expected_type, options={}): + for raw, expected_name, expected_value in cases: + node = parse_item(raw, options) + self.assertEqual(expected_name, node.name, + "Expected node('%s').name to be %s, got %s" % + (repr(raw), expected_name, node.name)) + self.assertEqual(expected_value, node.value, + "Expected node('%s').value to be %s, got %s" % + (repr(raw), expected_value, node.value)) + self.assertEqual(raw, str(node), + "Expected str(node('%s')) to be the same, but got '%s'" % + (repr(raw), str(node))) + self.assertEqual(expected_type, node.type, + "Expected node('%s').type to be '%s', but got '%s'" % + (repr(raw), expected_type, str(node.type))) + + def testLoadStatement(self): + cases = [ + ('option value', 'option', 'value'), + ('option', 'option', None), + (' option value', 'option', 'value'), + (' option = value', 'option', 'value'), + ('\noption value', 'option', 'value'), + ('option "dblquoted value"', 'option', 'dblquoted value'), + ("option 'sglquoted value'", "option", "sglquoted value"), + ] + self._test_item_cases(cases, 'statement') + + def testLoadComment(self): + comment = '# here is a silly comment' + cases = [ + (comment, comment, None), + ('\n' + comment, comment, None), + (' ' + comment, comment, None), + ] + self._test_item_cases(cases, 'comment') + + def testLoadApacheInclude(self): + cases = [ + ('include path', 'include', 'path'), + (' include path', 'include', 'path'), + ('\ninclude path', 'include', 'path'), + ] + self._test_item_cases(cases, 'include', + options={'useapacheinclude': True}) + + def testLoadContents(self): + cases = [ + ('a b\nc d', ('a b', '\nc d')), + (' \n', tuple()), + ('a b \n', ('a b',)), + ('a b # comment', ('a b', ' # comment')), + ('a b\n\n \n', ('a b', '\n\n')), + ] + for raw, expected in cases: + node = parse_contents(raw) + self.assertEqual(len(node), len(expected)) + for got, expected in zip(node, expected): + self.assertEqual(str(got), expected) + self.assertEqual(raw, str(node)) + + def testLoadBlocks(self): + cases = [ + ('\nhello there\nit me\n', None), + ('\n', 'name/'), + ('\n', None), + ('\n', 'name'), + ('\n', None), + ('\n\n', None), + ] + for (raw, value) in cases: + node = parse_block(raw) + self.assertEqual("b", node.tag) + self.assertEqual(value, node.arguments) + self.assertEqual(raw, str(node)) + + def testLoadWholeConfig(self): + text = """\ + +# a +a = b + + + a = b + +a b + +c "d d" + +# a +""" + node = parse_contents(text) + self.assertEqual(text, str(node))