Skip to content

Commit 1fc84c8

Browse files
authored
Merge pull request certbot#3234 from sagi/rewrite
Comment out corresponding RewriteConds for filtered RewriteRule
2 parents 031b41a + 0e96223 commit 1fc84c8

File tree

2 files changed

+114
-13
lines changed

2 files changed

+114
-13
lines changed

certbot-apache/certbot_apache/configurator.py

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ def _get_ssl_vhost_path(self, non_ssl_vh_fp):
821821
else:
822822
return non_ssl_vh_fp + self.conf("le_vhost_ext")
823823

824-
def _sift_line(self, line):
824+
def _sift_rewrite_rule(self, line):
825825
"""Decides whether a line should be copied to a SSL vhost.
826826
827827
A canonical example of when sifting a line is required:
@@ -872,18 +872,62 @@ def _copy_create_ssl_vhost_skeleton(self, avail_fp, ssl_fp):
872872
with open(avail_fp, "r") as orig_file:
873873
with open(ssl_fp, "w") as new_file:
874874
new_file.write("<IfModule mod_ssl.c>\n")
875+
876+
comment = ("# Some rewrite rules in this file were "
877+
"disabled on your HTTPS site,\n"
878+
"# because they have the potential to create "
879+
"redirection loops.\n")
880+
875881
for line in orig_file:
876-
if self._sift_line(line):
882+
A = line.lstrip().startswith("RewriteCond")
883+
B = line.lstrip().startswith("RewriteRule")
884+
885+
if not (A or B):
886+
new_file.write(line)
887+
continue
888+
889+
# A RewriteRule that doesn't need filtering
890+
if B and not self._sift_rewrite_rule(line):
891+
new_file.write(line)
892+
continue
893+
894+
# A RewriteRule that does need filtering
895+
if B and self._sift_rewrite_rule(line):
877896
if not sift:
878-
new_file.write(
879-
"# Some rewrite rules in this file were "
880-
"were disabled on your HTTPS site,\n"
881-
"# because they have the potential to "
882-
"create redirection loops.\n")
897+
new_file.write(comment)
883898
sift = True
884899
new_file.write("# " + line)
885-
else:
886-
new_file.write(line)
900+
continue
901+
902+
# We save RewriteCond(s) and their corresponding
903+
# RewriteRule in 'chunk'.
904+
# We then decide whether we comment out the entire
905+
# chunk based on its RewriteRule.
906+
chunk = []
907+
if A:
908+
chunk.append(line)
909+
line = next(orig_file)
910+
911+
# RewriteCond(s) must be followed by one RewriteRule
912+
while not line.lstrip().startswith("RewriteRule"):
913+
chunk.append(line)
914+
line = next(orig_file)
915+
916+
# Now, current line must start with a RewriteRule
917+
chunk.append(line)
918+
919+
if self._sift_rewrite_rule(line):
920+
if not sift:
921+
new_file.write(comment)
922+
sift = True
923+
924+
new_file.write(''.join(
925+
['# ' + l for l in chunk]))
926+
continue
927+
else:
928+
new_file.write(''.join(chunk))
929+
continue
930+
887931
new_file.write("</IfModule>\n")
888932
except IOError:
889933
logger.fatal("Error writing/reading to file in make_vhost_ssl")

certbot-apache/certbot_apache/tests/configurator_test.py

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,16 +1110,19 @@ def test_create_own_redirect_for_old_apache_version(self):
11101110
self.config._enable_redirect(self.vh_truth[1], "")
11111111
self.assertEqual(len(self.config.vhosts), 9)
11121112

1113-
def test_sift_line(self):
1113+
def test_sift_rewrite_rule(self):
11141114
# pylint: disable=protected-access
11151115
small_quoted_target = "RewriteRule ^ \"http://\""
1116-
self.assertFalse(self.config._sift_line(small_quoted_target))
1116+
self.assertFalse(self.config._sift_rewrite_rule(small_quoted_target))
11171117

11181118
https_target = "RewriteRule ^ https://satoshi"
1119-
self.assertTrue(self.config._sift_line(https_target))
1119+
self.assertTrue(self.config._sift_rewrite_rule(https_target))
11201120

11211121
normal_target = "RewriteRule ^/(.*) http://www.a.com:1234/$1 [L,R]"
1122-
self.assertFalse(self.config._sift_line(normal_target))
1122+
self.assertFalse(self.config._sift_rewrite_rule(normal_target))
1123+
1124+
not_rewriterule = "NotRewriteRule ^ ..."
1125+
self.assertFalse(self.config._sift_rewrite_rule(not_rewriterule))
11231126

11241127
@mock.patch("certbot_apache.configurator.zope.component.getUtility")
11251128
def test_make_vhost_ssl_with_existing_rewrite_rule(self, mock_get_utility):
@@ -1148,7 +1151,61 @@ def test_make_vhost_ssl_with_existing_rewrite_rule(self, mock_get_utility):
11481151
"[L,QSA,R=permanent]")
11491152
self.assertTrue(commented_rewrite_rule in conf_text)
11501153
mock_get_utility().add_message.assert_called_once_with(mock.ANY,
1154+
11511155
mock.ANY)
1156+
@mock.patch("certbot_apache.configurator.zope.component.getUtility")
1157+
def test_make_vhost_ssl_with_existing_rewrite_conds(self, mock_get_utility):
1158+
self.config.parser.modules.add("rewrite_module")
1159+
1160+
http_vhost = self.vh_truth[0]
1161+
1162+
self.config.parser.add_dir(
1163+
http_vhost.path, "RewriteEngine", "on")
1164+
1165+
# Add a chunk that should not be commented out.
1166+
self.config.parser.add_dir(http_vhost.path,
1167+
"RewriteCond", ["%{DOCUMENT_ROOT}/%{REQUEST_FILENAME}", "!-f"])
1168+
self.config.parser.add_dir(
1169+
http_vhost.path, "RewriteRule",
1170+
["^(.*)$", "b://u%{REQUEST_URI}", "[P,QSA,L]"])
1171+
1172+
# Add a chunk that should be commented out.
1173+
self.config.parser.add_dir(http_vhost.path,
1174+
"RewriteCond", ["%{HTTPS}", "!=on"])
1175+
self.config.parser.add_dir(http_vhost.path,
1176+
"RewriteCond", ["%{HTTPS}", "!^$"])
1177+
self.config.parser.add_dir(
1178+
http_vhost.path, "RewriteRule",
1179+
["^",
1180+
"https://%{SERVER_NAME}%{REQUEST_URI}",
1181+
"[L,QSA,R=permanent]"])
1182+
1183+
self.config.save()
1184+
1185+
ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0])
1186+
1187+
conf_line_set = set(open(ssl_vhost.filep).read().splitlines())
1188+
1189+
not_commented_cond1 = ("RewriteCond "
1190+
"%{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f")
1191+
not_commented_rewrite_rule = ("RewriteRule "
1192+
"^(.*)$ b://u%{REQUEST_URI} [P,QSA,L]")
1193+
1194+
commented_cond1 = "# RewriteCond %{HTTPS} !=on"
1195+
commented_cond2 = "# RewriteCond %{HTTPS} !^$"
1196+
commented_rewrite_rule = ("# RewriteRule ^ "
1197+
"https://%{SERVER_NAME}%{REQUEST_URI} "
1198+
"[L,QSA,R=permanent]")
1199+
1200+
self.assertTrue(not_commented_cond1 in conf_line_set)
1201+
self.assertTrue(not_commented_rewrite_rule in conf_line_set)
1202+
1203+
self.assertTrue(commented_cond1 in conf_line_set)
1204+
self.assertTrue(commented_cond2 in conf_line_set)
1205+
self.assertTrue(commented_rewrite_rule in conf_line_set)
1206+
mock_get_utility().add_message.assert_called_once_with(mock.ANY,
1207+
mock.ANY)
1208+
11521209

11531210
def get_achalls(self):
11541211
"""Return testing achallenges."""

0 commit comments

Comments
 (0)