feat(licence): deuxieme couche, l'API refuse sans licence valable
L'ecran d'activation ne consultait qu'un branchement : le rapiecer ouvrait tout, l'API ne demandant rien. Chaque route de PM.Router passe maintenant par PM.LicenceGate.ApiLicenceOk avant son handler. Aucune fonction de decision partagee avec PM.Licence — sinon un seul rapiecage ouvrirait les deux couches. La verification est refaite de bout en bout, appels CNG redeclares compris ; seules la cle publique et le nom de la pref sont partages, parce que ce sont des donnees. Branchee dans DispatchRequest : les fichiers de l'ecran d'activation passent par TryServeEmbedded, non garde, sinon l'ecran ne se chargerait plus. Un oui est retenu pour le processus, un non jamais. Le risque etait qu'elle refuse un client licencie. Auto-test sur un vecteur lie a une empreinte fixe, sens accepte en premier ; et accord verifie en conditions reelles sur ce poste : IsLicensed = TRUE, ApiLicenceOk = TRUE. Documente aussi le piege du jour, sans lien avec ce code : des .dcu TMS x64 deposes a cote des sources cassaient le build Win32, et la sortie redirigee vers E: faute de place sur Z:. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -459,6 +459,43 @@ en dix minutes serait le mauvais echange. Le but est de tenir le mobile attache
|
||||
a un poste paye, pas de resister a une attaque — l'APK ne peut pas resister, et
|
||||
faire semblant couterait plus que de l'admettre.
|
||||
|
||||
### Deuxieme couche : l'API refuse sans licence (`PM.LicenceGate`)
|
||||
|
||||
La premiere couche (l'ecran d'activation) ne consultait qu'un branchement,
|
||||
`IsLicensed` ; le rapiecer ouvrait tout, l'API ne demandant rien. **Chaque route
|
||||
de `PM.Router` passe maintenant par `ApiLicenceOk` avant son handler** — sauter
|
||||
l'ecran ne donne plus acces aux donnees.
|
||||
|
||||
- **Aucune fonction de decision partagee avec `PM.Licence`.** Si les deux
|
||||
couches appelaient `IsLicensed`, un seul rapiecage les ouvrirait toutes les
|
||||
deux. `PM.LicenceGate` refait sa propre verification de bout en bout —
|
||||
decodage, SHA-256, appels CNG **redeclares sous d'autres noms**, lecture du
|
||||
champ `m` — et ne prend a `PM.Licence` que des **donnees** : la cle publique
|
||||
(`LicencePublicKey`) et le nom de la pref (`LicencePrefKey`).
|
||||
- **Branchee dans `DispatchRequest`, pas avant.** Seules les routes de l'API
|
||||
atteignent ce point ; les fichiers de l'ecran d'activation passent par
|
||||
`TryServeEmbedded`, non garde — sinon l'ecran qui permet de s'activer ne se
|
||||
chargerait plus. **404**, pas 403, comme le reste du verrouillage.
|
||||
- Un **oui** est retenu pour le processus (le test est sur le chemin de chaque
|
||||
requete) ; un **non** jamais, pour qu'une activation faite juste avant soit
|
||||
vue a la requete suivante.
|
||||
- **Le prix de l'independance : deux implementations qui doivent dire la meme
|
||||
chose.** Une divergence ferait passer l'ecran puis tomber chaque requete en
|
||||
404 — refuser quelqu'un qui a paye. `SelfTestLicenceGate` eprouve la 2e couche
|
||||
seule sur un vecteur lie a une empreinte fixe (`0123456789abcdef`, paire
|
||||
jetable dont la privee n'a jamais ete ecrite), **en commencant par le sens qui
|
||||
accepte**. L'**accord** entre couches ne se teste pas en vecteur — la 1re
|
||||
compare a l'empreinte reelle du poste — et se prouve en conditions reelles :
|
||||
au 2026-09-16, sur ce poste avec la vraie licence, `IsLicensed` = TRUE et
|
||||
`ApiLicenceOk` = TRUE.
|
||||
- **Ce que ca n'arrete pas** : quelqu'un qui trouve et rapiece les deux. Une
|
||||
heure devient deux ; la nature d'un schema hors ligne ne change pas. Les
|
||||
protections du commerce (VMProtect, Themida) iraient plus loin mais
|
||||
declenchent des **faux positifs antivirus** — ruineux pour un gestionnaire de
|
||||
mots de passe. Les outils libres ne s'appliquent pas : OLLVM exige un
|
||||
compilateur LLVM (dcc32 Win32 n'en est pas un), Alcatraz est x64 seulement,
|
||||
UPX se defait par `upx -d`.
|
||||
|
||||
**ORDRE OBLIGATOIRE.** Tant que `LicencePublicKeyBlob` est a zero, aucune
|
||||
licence n'est valide et l'ecran d'activation est **infranchissable** — l'exe
|
||||
construit ne s'ouvre plus. Poser la cle publique AVANT de deployer :
|
||||
@@ -1375,6 +1412,25 @@ le vide ET vide `FPendingURL` → écran noir permanent sur cold-start lent.
|
||||
fix port-fixe est possible (`port=N` dans `config.txt`) mais on perd
|
||||
l'aléatoire qui complique le scan externe.
|
||||
- **Modifier les `Enable*` props TMS en `OnInitialized`**, pas FormCreate.
|
||||
- **`F2048 Bad unit format … FMX.TMSFNC*.dcu … Found x64`** : le dossier des
|
||||
sources `… mssoftware
|
||||
egistered\TMS FNC Core\` est dans le chemin de
|
||||
recherche, et une compilation y depose ses `.dcu` **a cote des `.pas`**. Une
|
||||
compilation **Win64** (le 2026-09-07 a 11 h 45) en a reecrit 33 en x64, et le
|
||||
build Win32 buttait dessus — **sans aucun rapport avec le code du projet** :
|
||||
l'arbre propre echouait a l'identique. Correctif : les deplacer
|
||||
(sauvegarde dans `… mssoftware\_backup-x64-dcu-2026-09-07`) ; le build Win32
|
||||
retombe sur `Delphi12\Win32\Release\`. Le symptome reviendra a chaque
|
||||
alternance Win32/Win64 sur ce poste.
|
||||
- **Z: est quasi plein (0,3 Go au 2026-09-16).** Le build est redirige vers
|
||||
`E:\password manager\` **par surcharge MSBuild**, pas dans le `.dproj` — un
|
||||
chemin propre a une machine n'a pas sa place dans un fichier versionne :
|
||||
```
|
||||
msbuild PMServer.dproj /p:Config=Release /p:Platform=Win32
|
||||
"/p:DCC_ExeOutput=E:\password manager" "/p:DCC_DcuOutput=E:\password manager\dcu"
|
||||
```
|
||||
**F9 dans l'IDE sort toujours sur Z:.** Et l'exe de `E:\password manager\`
|
||||
cree **son propre `vault.db`** a cote de lui, sans `config.txt` : ce n'est pas
|
||||
le coffre de `delphi-backend\` ni celui de `E: pmanager\`.
|
||||
|
||||
## Conventions code (héritage sessions précédentes)
|
||||
|
||||
Reference in New Issue
Block a user