Browse Source

* Allow range of SSH versions, some IIS servers react strangely to svAny

git-svn-id: trunk@34064 -
michael 9 years ago
parent
commit
81953d7856
1 changed files with 82 additions and 8 deletions
  1. 82 8
      packages/fcl-web/src/base/fpwebclient.pp

+ 82 - 8
packages/fcl-web/src/base/fpwebclient.pp

@@ -21,13 +21,21 @@ uses
   Classes, SysUtils;
   Classes, SysUtils;
 
 
 Type
 Type
+
   { TRequestResponse }
   { TRequestResponse }
+  
+  // Some IIS servers react badly to svAny. So we set up a system where you can set a min/max SSL version.
+  
+  TSSLVersion = (svNone,svAny,svSSLv2,svSSLv3,svTLSv1,svTLSv11,svTLSv12,svTLSv13);
+  TSSLVersions = Set of TSSLVersion;
+  TSSLVersionArray = Array of TSSLVersion;
 
 
   TRequestResponse = Class(TObject)
   TRequestResponse = Class(TObject)
   private
   private
     FHeaders : TStrings;
     FHeaders : TStrings;
     FStream : TStream;
     FStream : TStream;
     FOwnsStream : Boolean;
     FOwnsStream : Boolean;
+    FSSLVersion : TSSLVersion;
   Protected
   Protected
     function GetHeaders: TStrings;virtual;
     function GetHeaders: TStrings;virtual;
     function GetStream: TStream;virtual;
     function GetStream: TStream;virtual;
@@ -39,6 +47,8 @@ Type
     Property Headers : TStrings Read GetHeaders;
     Property Headers : TStrings Read GetHeaders;
     // Request content or response content
     // Request content or response content
     Property Content: TStream Read GetStream;
     Property Content: TStream Read GetStream;
+    // SSLVersion : Which version to use
+    Property SSLVersion : TSSLVersion Read FSSLVersion Write FSSLVersion;
   end;
   end;
 
 
   { TWebClientRequest }
   { TWebClientRequest }
@@ -95,9 +105,6 @@ Type
 
 
   { TAbstractWebClient }
   { TAbstractWebClient }
 
 
-  TSSLVersion = (svAny,svSSLv2,svSSLv3,svTLSv1,svTLSv11,svTLSv12,svTLSv13);
-  TSSLVersions = Set of TSSLVersion;
-  TSSLVersionArray = Array of TSSLVersion;
 
 
   TAbstractWebClient = Class(TComponent)
   TAbstractWebClient = Class(TComponent)
   private
   private
@@ -105,14 +112,19 @@ Type
     FSigner: TAbstractRequestSigner;
     FSigner: TAbstractRequestSigner;
     FLogFile : String;
     FLogFile : String;
     FLogStream : TStream;
     FLogStream : TStream;
-    FTrySSLVersion: TSSLVersion;
+    FMinSSLVersion: TSSLVersion;
+    FMaxSSLVersion: TSSLVersion;
     Procedure LogRequest(AMethod, AURL: String; ARequest: TWebClientRequest);
     Procedure LogRequest(AMethod, AURL: String; ARequest: TWebClientRequest);
     Procedure LogResponse(AResponse: TWebClientResponse);
     Procedure LogResponse(AResponse: TWebClientResponse);
     procedure SetLogFile(AValue: String);
     procedure SetLogFile(AValue: String);
+    procedure SetSSLVersion(AValue : TSSLVersion);
+    Function GetSSLVersion : TSSLVersion;
   protected
   protected
+    // Determine min/max version to try
+    procedure GetVersionLimits(out PMin, PMax: TSSLVersion);
     // Write a string to the log file
     // Write a string to the log file
     procedure StringToStream(str: string);
     procedure StringToStream(str: string);
-    // Must execute the requested method using request/response. Must take ResponseCOntent stream into account
+    // Must execute the requested method using request/response. Must take ResponseContent stream into account
     Function DoHTTPMethod(Const AMethod,AURL : String; ARequest : TWebClientRequest) : TWebClientResponse; virtual; abstract;
     Function DoHTTPMethod(Const AMethod,AURL : String; ARequest : TWebClientRequest) : TWebClientResponse; virtual; abstract;
     // Must create a request.
     // Must create a request.
     Function DoCreateRequest : TWebClientRequest; virtual; abstract;
     Function DoCreateRequest : TWebClientRequest; virtual; abstract;
@@ -130,7 +142,12 @@ Type
     Property RequestSigner : TAbstractRequestSigner Read FSigner Write FSigner;
     Property RequestSigner : TAbstractRequestSigner Read FSigner Write FSigner;
     Property ResponseExaminer : TAbstractResponseExaminer Read FExaminer Write FExaminer;
     Property ResponseExaminer : TAbstractResponseExaminer Read FExaminer Write FExaminer;
     Property LogFile : String Read FLogFile Write SetLogFile;
     Property LogFile : String Read FLogFile Write SetLogFile;
-    property SSLVersion : TSSLVersion Read FTrySSLVersion Write FTrySSLVersion;
+    // This will set MinSSLversion and MaxSSLversion
+    property SSLVersion : TSSLVersion Read GetSSLVersion Write SetSSLVersion;
+    // Minimum Version to try. If spNone is set, all should be tried in succession from high to MinSSLVersion.
+    Property MinSSLVersion : TSSLVersion Read FMinSSLVersion Write FMinSSLVersion default svAny;
+    // Maximum Version to try. If spNone is set, all should be tried in succession from MaxSSLVersion to low.
+    Property MaxSSLVersion : TSSLVersion Read FMaxSSLVersion Write FMaxSSLVersion default svAny;
   end;
   end;
   TAbstractWebClientClass = Class of TAbstractWebClient;
   TAbstractWebClientClass = Class of TAbstractWebClient;
 
 
@@ -211,6 +228,18 @@ end;
 
 
 { TAbstractWebClient }
 { TAbstractWebClient }
 
 
+procedure TAbstractWebClient.SetSSLVersion(AValue : TSSLVersion);
+
+begin
+  MinSSLVersion:=AValue;
+  MaxSSLVersion:=AValue;
+end;
+
+Function TAbstractWebClient.GetSSLVersion : TSSLVersion;
+
+begin
+  Result:=MinSSLVersion;
+end;
 
 
 procedure TAbstractWebClient.SetLogFile(AValue: String);
 procedure TAbstractWebClient.SetLogFile(AValue: String);
 begin
 begin
@@ -220,7 +249,10 @@ begin
   FLogFile:=AValue;
   FLogFile:=AValue;
   if (FLogFile<>'') then
   if (FLogFile<>'') then
     if FileExists(FLogFile) then
     if FileExists(FLogFile) then
-      FLogStream:=TFileStream.Create(FLogFile,fmOpenWrite or fmShareDenyWrite)
+      begin
+      FLogStream:=TFileStream.Create(FLogFile,fmOpenWrite or fmShareDenyWrite);
+      FLogStream.Seek(0,soFromEnd);
+      end
     else
     else
       FLogStream:=TFileStream.Create(FLogFile,fmCreate or fmShareDenyWrite);
       FLogStream:=TFileStream.Create(FLogFile,fmCreate or fmShareDenyWrite);
 end;
 end;
@@ -277,19 +309,61 @@ begin
   StringToStream('');
   StringToStream('');
 end;
 end;
 
 
+procedure TAbstractWebClient.GetVersionLimits(out PMin, PMax: TSSLVersion);
+
+begin
+  if MinSSLVersion=svNone then
+    PMin:=Succ(Low(TSSLVersion))
+  else
+    PMin:=MinSSLVersion;
+  if MaxSSLVersion=svNone then
+    PMax:=High(TSSLVersion)
+  else
+    PMax:=MaxSSLVersion;
+  if PMax<PMin then
+    PMax:=PMin;
+end;
+
 function TAbstractWebClient.ExecuteRequest(const AMethod, AURL: String;
 function TAbstractWebClient.ExecuteRequest(const AMethod, AURL: String;
   ARequest: TWebClientRequest): TWebClientResponse;
   ARequest: TWebClientRequest): TWebClientResponse;
+  
+Var
+  P,PMax,PMin : TSSLVersion;
+  S: String;
+
 begin
 begin
   if Assigned(FLogStream) then
   if Assigned(FLogStream) then
     LogRequest(AMethod,AURL,ARequest);
     LogRequest(AMethod,AURL,ARequest);
   Result:=DoHTTPMethod(AMethod,AURL,ARequest);
   Result:=DoHTTPMethod(AMethod,AURL,ARequest);
+  GetVersionLimits(PMin,PMax);
+  if PMin<>PMax then
+    StringToStream('Trying multiple protocols.');
+  P:=PMax;
+  While (Not Assigned(Result)) and (P>=PMin) do
+    begin
+    Str(P,S);
+    StringToStream('Trying protocol: '+S);
+    Result:=Nil;
+    ARequest.SSLVersion:=P;
+    if Assigned(FLogStream) then
+      LogRequest(AMethod,AURL,ARequest);
+    try
+      Result:=DoHTTPMethod(AMethod,AURL,ARequest);
+    except
+      if (P=PMin) then
+        Raise;
+    end;
+    P:=Pred(P);
+    end;
   if Assigned(Result) then
   if Assigned(Result) then
     begin
     begin
     if Assigned(FLogStream) then
     if Assigned(FLogStream) then
       LogResponse(Result);
       LogResponse(Result);
     If Assigned(FExaminer) then
     If Assigned(FExaminer) then
       FExaminer.ExamineResponse(Result);
       FExaminer.ExamineResponse(Result);
-    end;
+    end
+  else
+    StringToStream('Request generated no response');
 end;
 end;
 
 
 function TAbstractWebClient.ExecuteSignedRequest(const AMethod, AURL: String;
 function TAbstractWebClient.ExecuteSignedRequest(const AMethod, AURL: String;