feat(sync): http:// limite au reseau local, Basic des la 1re requete
APK : le clair est permis par Android et trie dans TSyncClient.RefusalReason (IsLocalHost : RFC 1918, 127.x, .local, .lan, nom sans point) - chacun pointe vers son propre WebDAV sans IP connue a la compilation ; vers Internet, HTTPS. PC : Authorization Basic envoye d'emblee, plus de 401 anonyme ni de PUT du coffre envoye deux fois. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -56,6 +56,11 @@ type
|
||||
Error: string; // message brut, pour le journal
|
||||
end;
|
||||
|
||||
/// Vrai pour une adresse du reseau local (RFC 1918, boucle, .local, .lan,
|
||||
/// nom sans point) : le seul endroit ou le HTTP en clair est accepte.
|
||||
function IsLocalHost(const AHost: string): Boolean;
|
||||
|
||||
type
|
||||
TSyncClient = class
|
||||
private
|
||||
FBaseUrl: string;
|
||||
@@ -64,6 +69,7 @@ type
|
||||
/// Attente de la POIGNEE DE MAIN, distincte de celle de la reponse.
|
||||
FConnectMs: Integer;
|
||||
FPrivacyChecked: Boolean;
|
||||
function PublicRepoWarning: string;
|
||||
public
|
||||
constructor Create(const ABaseUrl, AToken: string);
|
||||
|
||||
@@ -82,11 +88,12 @@ type
|
||||
/// l'ecriture (412 = un autre appareil a publie entre-temps).
|
||||
function IsWebDav: Boolean;
|
||||
|
||||
/// Refus LOCAL, avant tout envoi : http:// hors reseau local, puis depot public.
|
||||
/// UN DEPOT PUBLIC EST REFUSE (Gitea comme GitHub) : chaque synchro est un
|
||||
/// commit, et l'historique garde tous les instantanes, attaquables hors
|
||||
/// ligne par quiconque peut les lire. Message a afficher, ou '' si le depot
|
||||
/// est prive ou si on n'a pas pu le savoir. Verifie une fois par instance.
|
||||
function PublicRepoWarning: string;
|
||||
function RefusalReason: string;
|
||||
|
||||
/// POURQUOI UN 404 OU UN 401, en clair pour l'utilisateur. Gitea repond 404
|
||||
/// aussi bien pour un fichier absent que pour un depot ou un proprietaire
|
||||
@@ -113,7 +120,7 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.JSON, System.NetEncoding;
|
||||
System.JSON, System.NetEncoding, System.StrUtils;
|
||||
|
||||
function TSyncClient.IsGitea: Boolean;
|
||||
begin
|
||||
@@ -207,6 +214,49 @@ begin
|
||||
if LP > 0 then Result := Copy(AContentsUrl, 1, LP - 1) else Result := '';
|
||||
end;
|
||||
|
||||
/// HTTP EN CLAIR : RESEAU LOCAL SEULEMENT. Android le permet partout
|
||||
/// (network_security_config) pour que chacun pointe vers SON serveur WebDAV,
|
||||
/// a une adresse qu'on ne connait pas a la compilation ; le tri se fait donc
|
||||
/// ici. Vers Internet, le jeton ne part qu'en HTTPS.
|
||||
/// ponytail: un Wi-Fi etranger qui reutilise la meme plage recevrait le jeton
|
||||
/// en clair - le coffre, lui, reste chiffre. HTTPS chez soi supprime le risque.
|
||||
function IsLocalHost(const AHost: string): Boolean;
|
||||
var
|
||||
LParts: TArray<string>;
|
||||
A, B: Integer;
|
||||
begin
|
||||
var LHost := AHost.ToLower;
|
||||
if (LHost = 'localhost') or LHost.EndsWith('.local') or LHost.EndsWith('.lan') or
|
||||
(LHost.IndexOf('.') < 0) and (LHost <> '') then
|
||||
Exit(True);
|
||||
LParts := LHost.Split(['.']);
|
||||
if (Length(LParts) <> 4) or not TryStrToInt(LParts[0], A) or
|
||||
not TryStrToInt(LParts[1], B) then
|
||||
Exit(False);
|
||||
for var LPart in LParts do
|
||||
if not TryStrToInt(LPart, A) then Exit(False);
|
||||
A := StrToInt(LParts[0]);
|
||||
Result := (A = 10) or (A = 127) or ((A = 192) and (B = 168)) or
|
||||
((A = 172) and (B >= 16) and (B <= 31));
|
||||
end;
|
||||
|
||||
function TSyncClient.RefusalReason: string;
|
||||
var
|
||||
LHost: string;
|
||||
begin
|
||||
if StartsText('http://', FBaseUrl) then
|
||||
begin
|
||||
try
|
||||
LHost := TURI.Create(FBaseUrl).Host;
|
||||
except
|
||||
LHost := '';
|
||||
end;
|
||||
if not IsLocalHost(LHost) then
|
||||
Exit('http:// is only allowed on the local network (192.168.x.x, 10.x.x.x, .local, .lan) - use https:// for ' + LHost);
|
||||
end;
|
||||
Result := PublicRepoWarning;
|
||||
end;
|
||||
|
||||
function TSyncClient.PublicRepoWarning: string;
|
||||
var
|
||||
LHttp: THTTPClient;
|
||||
@@ -389,7 +439,7 @@ begin
|
||||
Result.Error := 'Ecriture disponible seulement vers Gitea, GitHub ou WebDAV (jeton utilisateur:mot-de-passe)';
|
||||
Exit;
|
||||
end;
|
||||
Result.Error := PublicRepoWarning;
|
||||
Result.Error := RefusalReason;
|
||||
if Result.Error <> '' then
|
||||
begin
|
||||
Result.Status := ssRefused; // HttpCode 0 : refus local, pas du serveur
|
||||
@@ -522,7 +572,7 @@ begin
|
||||
Result.Error := 'URL ou jeton non configure';
|
||||
Exit;
|
||||
end;
|
||||
Result.Error := PublicRepoWarning;
|
||||
Result.Error := RefusalReason;
|
||||
if Result.Error <> '' then
|
||||
begin
|
||||
Result.Status := ssRefused; // HttpCode 0 : refus local, pas du serveur
|
||||
|
||||
Reference in New Issue
Block a user