- il faut avoir le champ backup_cles en base (donc avoir fait la migration de base)
- il faut etre sur le login d'un webmestre (donc sur son login *apres* migration de la base) => faut il invalider la session du webmestre qui upgrade pour le forcer a se reconnecter ?
Le but est d'eviter de generer une cle et de commencer a chiffrer les password des utilisateurs alors qu'aucun webmestre n'a encore de backup, ce qui reviendrait a perdre les pass de tous ces utilisateurs si on perd le fichier cles.php
- la clé secret_du_site est partagée entre le disque et la base de données. Il faut les 2 pour le calculer (la clé secret_du_site, et la meta secret_du_site).
- Si on demande à chiffrer avec autre chose qu’une clé de longueur adaptée (ie: générée par Chiffrement::keygen()), tel qu’un mot de passe, alors on passe dans sodium_crypto_pwhash(),
qui est la fonction adaptée à ce cas, mais le coût est très élevé dans ce cas (temps / mémoire, même au minimum possible)
- On s’arrange donc pour que le secret_du_site obtenu soit effectivement de la taille adaptée à la clé de chiffrement.
On chiffre le jeton en base, mais on permet 2 choses
- Pouvoir retrouver le jeton actuellement utilisé sur un auteur (déchiffrage possible) (Rastapopoulos)
- On limite le nombre de déchiffrages à effectuer en ayant une partie publique du jeton en bdd, qui
sert à filtrer les auteurs dont on veut vérifier les jetons (a priori 1 seul auteur à vérifier)
Introduction d’une fonction auteur_lire_jeton($id_auteur, $autoInit = false), qui lit un jeton
sans écraser le précédent utilisé (ce que fait auteur_attribuer_jeton())
Notons que ces histoires de jeton mériteraient quelques améliorations
- permettre l’expiration des jetons
- permettre plusieurs jetons pour un même auteur directement
- Utiliser sodium_pad et sodium_unpad sur le message à chiffrer
- Hacher un password en sha256 dans le chiffrement s’il sert comme clé.
C’est un compromis suffisant.
- il faut creer une cle des auth si besoin
- on utilise la fonction auth_spip_modifier_pass() pour changer le pass du webmestre que l'on cree
- si on a perdu le fichier config/cle.php on demande a ce que l'installation se fasse par un webmestre qui a un backup des cles, avec son mot de passe actuel - et on restaure les cles a l'installation
On rappelle que la securite des actions ne doit jamais reposer sur ces hash mais sur un appel a autoriser() pour verifier que l'auteur a bien le droit de faire l'action
Upgrade de base pour ajouter un champ `backup_cles` sur spip_auteurs qui
permet aux webmestres de conserver une copie des cles
Le secret_du_site est fourni via SpipCles et plus via spip_meta, il est
supprime de la base (on le reinit au passage, mais c'est pas tres grave)
On ajoute une fonction auth_spip_initialiser_secret() en charge de ça qui fait toutes les verif, et on ajoute des logs circonstancies pour aider les webmestres perdus au cas ou
Inutile de sauver les cles, c'est fait automatiquement si une nouvelle cle est generee
les différentes fonctionnalités. C’est mieux structuré.
- Chiffrement gère chiffrer() / dechiffrer() / keygen() (génération d’une nouvelle clé)
en s’appuyant sur Sodium, toujours présent dans PHP depuis PHP 7.2.
On utilise une chifferement symétrique (comme avec openssl précédement),
mais le code est simplifié car libsodium gère l’authentification du message et son salage.
- Password gère verifier() et hacher() en utilisant password_hash donc,
mais en retirant l’option 'salt' qui n’est plus utilisé par PHP > 8,
et effectivement il vaut mieux ne pas le renseigner (PHP gère un salt tournant
tout seul comme un grand). On s’en sert pour régénerer notre password haché en bdd.
- Cles est un conteneur de clés (tableau nom => clé)
- SpipClés gère les clés SPIP et utilisant Cles. Des fonctions backup() et restore() permettent de lire un backup chiffré
J’ai mis l’attribut `#[\SensitiveParameter]` sur différents paramètres en passant,
il devrait être actif à partir de PHP 8.2 pour dire de ne pas afficher la valeur
dans les affichages de backtrace() par exemple, afin de ne pas divulguer
malencontreusement certaines infos en debug.
Également (Cerdic)
- Sodium exige une cle de chiffrement exactement de la bonne longueur : adapter la cle fournir si besoin (cas du chiffrement du backup des cles avec le pass du user)
- La regeneration des cles ne peut se faire que cle par cle : si on a perdu le fichier des cles, c'est OK de regenerer un secret_du_site a la volee pour pouvoir afficher un formulaire de login par exemple, mais on ne doit surtout pas regenerer un secret_des_auth qui invaliderait tous les mots de passe
- Permettre d'avoir plusieurs instances de SpipCles avec des fichiers de cle differents. Peut etre utile pout les tests unitaires, ou pour faire de l'auth multi-sites (on cherche l'auteur dans plusieurs bases SPIP, chacune associee a un fichier de cle different)
- plus de hashage+sel cote client, car les algos js sont penibles a gerer et https est maintenant un standard de securite
- cote serveur on utilise les fonction modernes de PHP pour la gestion des mots de passe (sel, poivre, hashage et verification)
Encore une fois directement inspire du plugin chiffrer de g0uz https://git.spip.net/spip-contrib-extensions/chiffrer
La classe Spip\Core\Chiffrer se charge de la gestion des cles secrètes (initialiser, lire, ecrire, sauvegarder, restaurer, chiffrer, dechiffrer et verifier le mot de passe d'un auteur)
Directement insipiré du plugin Chiffrer de g0uZ https://git.spip.net/spip-contrib-extensions/chiffrer
Cela indique une icone alternative à utiliser si jamais on ne retrouve pas
l'image.
De même `http_style_background()` peut recevoir un dernier argument
`$alternative`.
On se sert de ces alternatives dans `icone_base()` et dans `debut_cadre()`.
`icone_horizontale`).
Icone par @erational
Fix spip-contrib-extensions/champs_extras_interface#5
(cherry picked from commit 6a4c7bf849)
On utilise `include list` et `exclude list` en anglais,
et `liste d’inclusion` et `liste d’exclusion` en français.
(cherry picked from commit f65708e67f)
Capturer aussi les \ParseError dans ce cas.
Attention, la variable $res est globale est utilisée ensuite par l’appeleur.
(cherry picked from commit c13d2e4f05)
pour charger un fichier de langue et vérifier qu’il est correct.
On loge une erreur sinon.
Par ailleurs on permet qu’ils retournent directement un array plutôt que
de peupler une globale.
(cherry picked from commit 676d51d329)
[Salvatore] [source:ecrire/lang/ spip] Export depuis https://trad.spip.net de la langue en
[Salvatore] [source:ecrire/lang/ spip] Mise a jour du bilan depuis https://trad.spip.net
(cherry picked from commit e4ccf39e22)
1) le contexte compile est un array vide
2) recuperer_fond ne retourne pas 'entete' sur une erreur d’absence de squelette.
(cherry picked from commit d076de147c)
Or avec PHP 8, utiliser `@ini_set` est insuffisant car maintenant, une
fonction désactivée génère une Fatal Error (et plus un Warning) si on tente de l’utiliser
et `@` n’attraple plus les erreurs fatales.
(cherry picked from commit 58999d2590)
fonction n'est pas trouvée, alors même que le fichier a été trouvé : il
faut indiquer dans ce cas que la fonction n'est pas trouvée, pas que le
fichier n'est pas trouvé !
On en profite pour remplacer `<b>` en `<code>`.
(cherry picked from commit 2f7bdd868d)
Retour sur ce9510b0f0 donc.
On considère les identifiants (d’autorisation) comme pouvant être
- non utiles pour certaines autorisations (null)
- un identifiant d’objet éditorial (int)
- un identifiant textuel (string)
(cherry picked from commit 354102a0fa)
- mieux decouper les chaines y compris dans le cas des simples quote echappes par sqlite
- echapper le % dans la chaine pour eviter la confusion de sprintf
- remplacer les chaines 1 par 1 via substr_replace() en commencant par la fin
- ne pas appeler sprintf() quand le tableau de remplacement est vide
+ la fonction securiser_acces() est renommee en securiser_acces_low_sec() et definie dans inc/acces. On garde une filtre_securiser_acces_dist() dans inc/filtres pour la compat des vieux squelettes
+ utiliser generer_url_api_low_sec() dans la fonction bouton_spip_rss()
+ la fonction param_low_sec() est depreciee
Fonctionnement de l'API transmettre :
* si le lowsec est bon, pas la peine de passer par autoriser() qui est appele si pas de cle valide et si on a une session
(mais un auteur identifie peut donc utiliser l'api avec un lowsec invalide, si autoriser() lui permet l'action, ce qui permet facilement de changer les args sans recalculer la cle)
* toujours chercher dans prive/ si le fond est pas disponible par defaut
* faire une erreur si le fond n'est pas dispo
* un log si le resultat est vide
ce qui ne pose pas de problème au validateur interne à SPIP,
mais en pose à d’autres validateurs (notamment DomDocument de PHP).
Effectivement on a
- soit `<!ENTITY name SYSTEM "URI">`
- soit `<!ENTITY name PUBLIC "public_ID" "URI">`
Mais il n’y a pas de public_ID sur SYSTEM.
modification de la valeur de retour par défaut de index_pile() lorsque
le champ n’était pas trouvé dans une boucle et pris du coup dans de contexte.
Plutôt que d’analyser le code retourné, on force une valeur par défaut qui
nous convient… Ça simplifie.
des nouvelles fonctions d’URL, car il y a des appels avec "" ou "new" ou null, qui ne peuvent être
transformés en int par PHP de la sorte. On enlève le type, et on applique intval dessus dans la foulée.
Lorsqu’on charge un élément nouveau, l’argument attendu est $id = 'new', mais le plugin Formidable
envoie $id = 0. Ce qui entre dans en monde parallèle où on essaie de récupérer une ligne SQL inexistante.
peut avoir le premier paramètre `null` (si pas d’action), et du coup
appeler decoder_urls avec ce qui provoque une notice plus loin.
On corrige directement dans form_action.
Notons par ailleurs que `#ENV{action}` est la valeur par défaut de `#ACTION_FORMULAIRE`
et donc que `#ACTION_FORMULARE{#ENV{action}}` peut être simplifié en `#ACTION_FORMULARE` tout court
tel que dans `[(#REM|generer_url_ecrire_entite_edit{#ENV{objet_source}} ...`
PHP ne sait pas caster automatiquement cette chaine (qui n’est pas un nombre) en int.
On applique donc intval pour appeler les nouvelles api typées.
De plus, pour un module d'url qui voudrait etre compatible avec les anciennes versions de SPIP et cette nouvelle convention, il suffra de proposer une fonction urls_xxxx_dist() non typee qui fait le routage vers les 2 fonctions generer_url_objet() et decoder_url() du module
- remplace l'usage peu evident de generer_objet_url('', '', '', '', true) pour recuperer la fonction de decodage
- permet l'implementation d'une fonction d'url propre pour les pages SPIP, soit dans un module d'url propre soit dans une fonction custom utilisateur (fix#962)
- permet d'eviter un point d'entree unique dans les fonctions d'url propre, ce qui permettra de decoder des urls numerique et de mieux typer les arguments (ouvre la porte pour traiter #4981)
Au passage, les fonction d'urls d'objet de type urls_generer_url_document() sont maintenant attentues sous la forme urls_generer_document_url() par coherence avec les autres nommages, mais l'ancien nommage continue a etre supporter pour la transition du code - pas de rupture de compat donc
* generer_info_entite => generer_objet_info qui delegue maintenant a des fonctions generer_objet_TRUC() ou generer_TYPE_TRUC()
* generer_lien_entite => generer_objet_lien
* generer_introduction_entite => generer_objet_introduction
Les anciens nommage sont mappes pour compatibilite
en évitant le filtrage appliqué dans `critere_parinverse()` quand il est utilisé dans une boucle DATA et en ajoutant les caractères :_-. à la liste autorisée par `select_orderby()`
fix#4910
voire POST => 307 sur url2 => POST sur url2 => 302 sur url3 => GET sur url3 le tout sans perdre les headers d'origine
en consequence on refabrique les donnes formattes a chaque redirection si besoin a partir des options headers+datas dont la derniere est eventuellement videe en cours de route
comme dans `[(#CHEMIN{absent}|image_reduire{24}|inserer_attribut{..., ...})]`
Dans le cas de null, ou d’une chaine vide, on sait qu’on n’aura pas de balise,
et donc rien à insérer.
(Eric)
Comme annoncé à la sortie de SPIP 3.2 en 2017, il faut adapter vers `Cookies.get`
ou `Cookies.set` si vous ne l’aviez toujours pas fait depuis.
```
$.cookie(key) devient Cookies.get(key)
$.cookie(key, value) devient Cookies.set(key, value)
$.cookie(key, value, options) devient Cookies.set(key, value, options)
```
sinon des choses tel que `[title="(#ENV{_compositions/#ENV{composition}/description}|attribut_html)"]`
créent une fatale, car il était accepté de transmettre `null`.
raler_fichier() est appelé, terminer de charger les constantes de SPIP avant
de charger minipres(), sinon une fatale est levée car certaines constantes
manquent.
Le comportement de `sql_quote(null)` est potentiellement problématique.
Il se comporte comme auparavant, c’est à dire tel que `sql_quote('')`.
Il serait plus logique de retourner le vrai terme `NULL` pour Mysql ;
c’est d’ailleurs ce qui est fait lorsqu’on indique le type de champ
tel que `sql_quote(null, 'int')`.
Par contre, si le type explicite `not null` tel que dans `sql_quote(null, 'int NOT NULL')`,
alors ça retourne "''" car l’on sait que NULL ne peut être présent dans la colonne.
Cependant, toute opération de comparaison avec `NULL` en mysql retourne `NULL`
(cf: https://dev.mysql.com/doc/refman/8.0/en/working-with-null.html).
Donc si une personne voulait effecivement comparer avec null, il faut utiliser `IS NULL` ou `IS NOT NULL`
ce que ne sera pas fait avec `'texte = ' . sql_quote(null, 'string')`.
Seuls certains (comme typo()) sont ignorés car ils semblent avoir des spécificités ($connect = null).
De même, typage de quelques $serveur, mais il faudrait généraliser.
- texte_script et texte_backend qui pouvaient obtenir null en entrée.
- Typages sur inserer_attribut, vider_attribut, attribut_html, texte_backend, texte_script.
Sur les éléments :
- filtre sinon() : strlen qui doit être appliqué uniquement sur un string.
- parametre_url() sans affectation : rawurlencode et strlen s’appliquent
uniquement sur un string (pas sur null).
- les traductions peuvent retourner `null` si la clé demandée n’existe
nul part. Ne pas tenter d’appliquer strlen ou autre dessus.
+ mini reformatage dans _T().
- _image_tag_changer_taille() : éviter d’appeler preg_replace sur null
- protege_champ() si la valeur null est passée. + Refactoring de la fonction.
- image_filtrer()
- critère pagination.
- _q(), sur addslashes avec valeur null.
- Éviter de créer un 'connect' qui vaut null, alors qu’il doit être une chaine.
- sur la propriété Boucle->limit
- echapper_faux_tags()
- urls_decoder_url()
- spip_mysql_cite()
- modifier_class() + refactoring
- spip_connect_sql() lorsque le serveur sql est injoignable.
- _image_valeurs_trans()
- formulaires_editer_liens_charger_dist (À revoir ! )
- extraire_balise, si null est transmis…
- formulaires_editer_objet_charger lorsque id_parent vaut null
- le login : ne pas appliquer trim sur null.
- sur appel d’autorisation : s’assurer d’avoir un int `$id`.
- S’assurer de passer un int à tester_statut_inscription.
- ratio_passe_partout()
- filtre in_any() avec valeurs null.
- sur les balises TOTAL_BOUCLE, GRAND_TOTAL, COMPTEUR_BOUCLE, lorsqu’utilisées
sur les parties alternatives de boucles lorsque les tables sont inexistantes
(ex: boucles de compaptage sur une (SIGNATURES?) avec le plugin pétitions absent.
- Sur autoriser() dont le type est null
- sur balise `#VAL`, lorsqu’utilisée vide comme `#VAL|filtre`
+ typage sur interprete_argument_balise.
Il suffit d'y poser un fichier inhib_purger_repertoire.txt
(ex: css référencées dans un CDN, images referencees par un moteur de recherche...)
+ toujours retourner un entier
1 year ago
338 changed files with 4795 additions and 4570 deletions