web-dev-qa-db-fra.com

Apache 2.4 <Directory> avec regexp - l'opérateur d'alternance est-il rompu, ou suis-je confus?

J'ai plusieurs répertoires racine de document, /opt/lampp/htdocs/proj1, /opt/lampp/proj2, etc., qui ont la protection AuthType Basic par mot de passe. Je veux que leurs arborescences de sous-répertoires uploads ne nécessitent pas de mot de passe. Sauf que l'arborescence de sous-répertoires private de uploads ne devrait permettre aucun accès. Selon http://httpd.Apache.org/docs/current/mod/core.html#directory :

Les expressions régulières ne sont pas considérées avant que toutes les sections normales aient été appliquées. Ensuite, toutes les expressions régulières sont testées dans l'ordre dans lequel elles sont apparues dans le fichier de configuration.

J'ai donc utilisé ces directives:

#==========================================================
# regexp enables access to images without login (needed for wp_sideload_image)
<Directory ~ "/opt/lampp/htdocs/[^/]*/public/(uploads|wp/wp-content/uploads)">
    Require all granted
</Directory>

#==========================================================
# regexp protects private uploads unconditionally
# regexps processed in source order, so MUST BE AFTER ENABLING IMAGES
<Directory ~ "/opt/lampp/htdocs/[^/]*/public/uploads/private">
    Require all denied
</Directory>

Ce que j’ai trouvé, c’est que la directive Require all denied n’était pas efficace; il était possible d’accéder à tout ce qui se trouvait en-dessous des téléchargements sans mot de passe, y compris les éléments ci-dessous privés. Juste pour le plaisir, j'ai essayé de supprimer l'expression d'alternance en faisant le premier bloc:

<Directory ~ "/opt/lampp/htdocs/[^/]*/public/uploads">
    Require all granted
</Directory>

Et à ma grande surprise (et ravissement), les choses ont fonctionné comme je le voulais. Je peux donc obtenir l'effet de l'expression régulière d'origine en ajoutant un autre <Directory>:

<Directory ~ "/opt/lampp/htdocs/[^/]*/public/wp/wp-content/uploads">
    Require all granted
</Directory>

Bien que cela fonctionne, je pourrais aussi bien utiliser des blocs <Directory> normaux avec un caractère générique '*' pour le niveau inférieur à htdocs. J'ai pensé qu'il serait plus concis d'utiliser le formulaire regexp. Je veux toujours utiliser regexp pour la section privée, car j'ai besoin que cela soit traité après les directives qui accordent l'accès.

Quelqu'un peut-il expliquer pourquoi le code d'origine ne fonctionne pas? Les documents Apache disent qu'ils utilisent PCRE, et l'expression utilisant l'alternance fonctionne bien avec egrep. De plus, je ne vois pas en quoi cette expression pourrait affecter les Require all denied suivants, car il s’agit de regexps, qui sont supposés être traités dans l’ordre source. Donc, la directive refusée devrait remplacer quoi qu'il en soit, ne devrait-elle pas? C'est ce qui se produit lorsque je remplace l'alternance par deux directives regexp distinctes. Qu'est-ce que je rate?

EDIT: Au moment où j’ai posté ceci, j’avais évidemment un moment de réflexion en pensant que la règle non-regexp de "shortest path first" signifiait que je devais utiliser une expression rationnelle pour s’assurer que le "Require all denied" serait traité assez tard. Mais clairement, bien qu'il puisse y avoir des chemins plus longs sous "uploads" que ceux situés sous "uploads/private", dans ce cas, il n'y aurait pas de correspondance sur "uploads/private", ces chemins ne devraient donc pas être interdits de toute façon. . Ainsi, je crois que la "meilleure" solution pour ma situation actuelle consiste simplement à éliminer complètement l'utilisation de "regexp" et à utiliser trois directives normales "<Directory>" avec des caractères génériques similaires à ceux affichés avec les expressions rationnelles ci-dessus, mais en remplaçant les "[^/]*" regexp avec le caractère générique Shell "*". Cela fonctionne très bien et les microsecondes sont probablement plus rapides :-)

Cependant, j'aimerais toujours savoir pourquoi mon code d'origine n'a pas fonctionné. Il me semble toujours que le traitement par Apache de la directive contenant l'opérateur "|" regexp était incorrect.

3
sootsnoot

Cette question m'a fait mélanger pas mal de choses. Celui-ci fonctionne comme prévu en fonction de ce que j'ai testé, avec l'opérateur |, tirant parti de la possibilité offerte par Apache 2.4 d'utiliser le signe $ comme fin de ligne:

<DirectoryMatch "/opt/lampp/htdocs/[^/]*/public/(uploads(/[^/]*)?|(wp/wp-content/uploads(/[^/]*)?))$">
    Require all granted
</DirectoryMatch>
<DirectoryMatch "/opt/lampp/htdocs/[^/]*/public/uploads/private">
    Require all denied
</DirectoryMatch>

Je pensais comprendre en partie pourquoi ce comportement, mais en fait je ne le comprenais pas. Je suppose que c'est quelque chose que je demanderai à la liste de diffusion Apache.

1
Zimmi

Ma seule suggestion serait d'ajouter d'autres parenthèses à l'expression régulière:

<Directory ~ "/opt/lampp/htdocs/[^/]*/public/(uploads|(wp/wp-content/uploads))">

L'ordre des opérations avec | et / pourrait faire partie du problème.

0
Stephen Ostermiller