I'm using OpenSSL 1.0.2o with Indy 10.6.2 in Delphi 2010.
This is what I have done so far:
procedure TServerForm.FormCreate(Sender: TObject);
var
LEcdh: PEC_KEY;
FSslCtx: PSSL_CTX;
SSL: PSSL;
FSSLContext: TIdSSLContext;
begin
//mServer.Active := True;
FSingle:=TCriticalSection.Create;
appdir := ExtractFilePath(ParamStr(0));
IdServerIOHandlerSSLOpenSSL1.SSLOptions.RootCertFile := appdir + 'EccCA.pem';
IdServerIOHandlerSSLOpenSSL1.SSLOptions.KeyFile := appdir + 'EccSite.key';
IdServerIOHandlerSSLOpenSSL1.SSLOptions.CertFile := appdir + 'EccSite.pem';
IdServerIOHandlerSSLOpenSSL1.SSLOptions.DHParamsFile := appdir + 'dhparam.pem';
IdServerIOHandlerSSLOpenSSL1.SSLOptions.Method := sslvTLSv1_2;
IdServerIOHandlerSSLOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1_2];
IdServerIOHandlerSSLOpenSSL1.SSLOptions.CipherList :=
//'ECDHE-ECDSA-AES128-GCM-SHA256:' +
'ECDHE-RSA-AES128-GCM-SHA256:' +
//'ECDHE-RSA-AES256-GCM-SHA384:' +
//'ECDHE-ECDSA-AES256-GCM-SHA384:' +
//'DHE-RSA-AES128-GCM-SHA256:' +
//'ECDHE-RSA-AES128-SHA256:' +
//'DHE-RSA-AES128-SHA256:' +
//'ECDHE-RSA-AES256-SHA384:' +
//'DHE-RSA-AES256-SHA384:' +
//'ECDHE-RSA-AES256-SHA256:' +
//'DHE-RSA-AES256-SHA256:' +
'HIGH:' +
'!aNULL:' +
'!eNULL:' +
'!EXPORT:' +
'!DES:' +
'!RC4:' +
'!MD5:' +
'!PSK:' +
'!SRP:' +
'!CAMELLIA';
MServer.IndyServer.IOHandler := IdServerIOHandlerSSLOpenSSL1;
mServer.Active := True;
//FSSLContext := TIdSSLContext(IdServerIOHandlerSSLOpenSSL1.SSLContext);
end;
This does not work.
Does anyone have good suggestions?
First off, make sure that you update your version of Indy to the latest SVN snapshot. After the previous discussion I had with Roberto Frances on the Embarcadero forums, I added SSL_CTRL_SET_ECDH_AUTO and SSL_CTX_set_ecdh_auto() to Indy's IdSSLOpenSSLHeaders unit.
So, the only piece missing from the code in that other discussion is the definition of TMyIdSSLContext, which I assume is simply this:
type
TMyIdSSLContext = class(TIdSSLContext)
end;
Since the TIdSSLContext.fContext member is declared as protected, the unit that declares TMyIdSSLContext gains access to TIdSSLContext's protected members. Thus, your code can then look like this:
type
TMyIdSSLContext = class(TIdSSLContext)
end;
procedure TServerForm.FormCreate(Sender: TObject);
var
FSSLContext: TMyIdSSLContext;
begin
FSingle := TCriticalSection.Create;
appdir := ExtractFilePath(ParamStr(0));
IdServerIOHandlerSSLOpenSSL1.SSLOptions.RootCertFile := appdir + 'EccCA.pem';
IdServerIOHandlerSSLOpenSSL1.SSLOptions.KeyFile := appdir + 'EccSite.key';
IdServerIOHandlerSSLOpenSSL1.SSLOptions.CertFile := appdir + 'EccSite.pem';
IdServerIOHandlerSSLOpenSSL1.SSLOptions.DHParamsFile := appdir + 'dhparam.pem';
IdServerIOHandlerSSLOpenSSL1.SSLOptions.Method := sslvTLSv1_2;
IdServerIOHandlerSSLOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1_2];
IdServerIOHandlerSSLOpenSSL1.SSLOptions.CipherList :=
//'ECDHE-ECDSA-AES128-GCM-SHA256:' +
'ECDHE-RSA-AES128-GCM-SHA256:' +
//'ECDHE-RSA-AES256-GCM-SHA384:' +
//'ECDHE-ECDSA-AES256-GCM-SHA384:' +
//'DHE-RSA-AES128-GCM-SHA256:' +
//'ECDHE-RSA-AES128-SHA256:' +
//'DHE-RSA-AES128-SHA256:' +
//'ECDHE-RSA-AES256-SHA384:' +
//'DHE-RSA-AES256-SHA384:' +
//'ECDHE-RSA-AES256-SHA256:' +
//'DHE-RSA-AES256-SHA256:' +
'HIGH:' +
'!aNULL:' +
'!eNULL:' +
'!EXPORT:' +
'!DES:' +
'!RC4:' +
'!MD5:' +
'!PSK:' +
'!SRP:' +
'!CAMELLIA';
MServer.IndyServer.IOHandler := IdServerIOHandlerSSLOpenSSL1;
mServer.Active := True;
FSSLContext := TMyIdSSLContext(IdServerIOHandlerSSLOpenSSL1.SSLContext);
SSL_CTX_set_ecdh_auto(FSSLContext.fContext, 1);
end;
Related
I have a Web Service running on Windows Server 2012R2 with sTunnel.
When using Postman I have to turn of SSL verification for it to work or I get a: no connection error.
Some of my client using our Delphi Windows application get the Error HTTP 1.1 500 and the message Reject due to policy restriction.
The following shows in the sTunnel log: SSL routines: ssl3_read_bytes: sslv3 alert certificate unknow
I have the latest open SSl dll in the System32 folder.
I don't know if I can turn something on/off in Delphi or in sTunnel.
Here is the code for sending the SMS and the send the result to my webserver.
procedure SendSMS.Execute;
var
JsonToSend: TStringStream;
url, SMSText, Rtext, AppId, Json: String;
IdHTTP1: TIdHTTP;
IdSSLIOHandlerSocketOpenSSL2: TIdSSLIOHandlerSocketOpenSSL;
jsonRecived: TJSONObject;
begin
AppId := 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx';
mySMSSent := False;
if (Length(DataM1.ComTbl.FieldByName('SMSToken').AsString) > 10) and (Length(SMSMessageText) > 3) then
begin
SMSText := StringReplace(SMSMessageText,#$A,'\n',[rfReplaceAll, rfIgnoreCase]);
SMSText := StringReplace(SMSText,#$D,'',[rfReplaceAll, rfIgnoreCase]);
Try
IdSSLIOHandlerSocketOpenSSL2 := TIdSSLIOHandlerSocketOpenSSL.Create;
IdHTTP1 := TIdHTTP.Create;
IdHTTP1.Request.UserAgent := 'Mozilla/3.0 (compatible; Indy Library)';
IdHTTP1.Request.ContentType := 'application/json';
IdHTTP1.Request.BasicAuthentication := true;
IdHTTP1.Request.Username := SMSPass;
IdHTTP1.Request.Password := SMSToken;
IdSSLIOHandlerSocketOpenSSL2.SSLOptions.Method := sslvTLSv1_2;
IdHTTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL2;
IdHTTP1.HandleRedirects := False;
if Length(SMSMedia) > 5 then
Json := '{"from": "+1' + SMSPhone + '","to": "+1' + ToPhone + '","text": "' + SMSText + '","applicationId": "' + AppId + '","media": "' + SMSMedia + '","tag": "' + NameID + '"}'
else
Json := '{"from": "+1' + SMSPhone + '","to": "+1' + ToPhone + '","text": "' + SMSText + '","applicationId": "' + AppId + '","tag": "' + NameID + '"}';
url:='https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx?';
JsonToSend := TStringStream.Create(Json);
try
Rtext:=IdHTTP1.Post(url, JsonToSend);
except
on E:Exception do
begin
SMSText := E.Classname + ': ' + E.Message;
mySMSSent := True;
end;
end;
if Pos('owner',Rtext) > 0 then // Send to web service //
begin
jsonRecived := TJSONObject.create(rtext);
if jsonRecived <> nil then
begin
Json := '{"id": "';
Json := Json + jsonRecived.optString('id') + '","from": "+1';
Json := Json + SMSPhone + '","time": "';
Json := Json + jsonRecived.optString('time') + '","direction": "';
Json := Json + jsonRecived.optString('direction') + '","text": "';
Json := Json + SMSText + '","to": "+1' + ToPhone + '"}';
Try
if Assigned(JsonToSend) then
FreeAndNil(JsonToSend);
JsonToSend := TStringStream.Create(Json);
url:='https://mywebservice';
IdHTTP1.Post(url, JsonToSend);
Except
End;
end;
end;
Finally
IdHTTP1.Disconnect;
IdSSLIOHandlerSocketOpenSSL2.Free;
IdHTTP1.Free;
JsonToSend.Free;
End;
end;
end;
I have a TRichMemo object which I create and populate with text at runtime.
I have a timer that triggers a function each 10 seconds. The function looks something like this:
procedure TServerSideForm.NewLineTimerTimer(Sender: TObject);
var
timeForward: TDateTime;
timerText: wideString;
startRange, endRange: longInt;
begin
timeForward := Time;
timeForward := IncSecond(timeForward, ServerSideForm.NewLineTimer.Interval div 1000);
//...
timerText := TimeToStr(Time) + ' - ' + TimeToStr(timeForward);
startRange := Length(WindowMemo.Text);
WindowMemo.Text := WindowMemo.Text + sLineBreak + sLineBreak + timerText + sLineBreak + sLineBreak;
endRange := Length(WindowMemo.Text) - 1;
WindowMemo.SetRangeColor(startRange, endRange, clGreen);
//...
end;
Everything works perfectly, text in the desired range becomes green.
But as soon as I add some new text to my TRichMemo, everything resets back to black text.
Why is this happening? Is there a way to prevent this reset from happening?
P.S Same situation happens, when I use the SetRangeParams function.
Use Append method instead of accessing a type String value Text as it keeps only the literals not the format.
Change
WindowMemo.Text := WindowMemo.Text + sLineBreak + sLineBreak + timerText + sLineBreak + sLineBreak;
with
WindowMemo.Append(sLineBreak + sLineBreak + timerText + sLineBreak + sLineBreak);
METHOD 2
Should you decide to add text withot line breaks you can replace the mentioned line with
uses RichMemoUtils;
...
InsertColorStyledText(WindowMemo,timerText,Random($FFFFFF),[],Length(WindowMemo.Text) -1);
I have two files - one contains a number of short strings (that I call Items) and the other contains the IDs for these short strings. I also have a number of other files, each of which contains a very long string that is broken up into thousands of smaller strings by means of line breaks. I need to find the number of times each short string ("Item") occurs in each of the large string files, as well as the starting and ending position for each hit.
My first task is to remove the line breaks in the large files so that the hits do not straddle across two or more smaller strings, and then find the number of occurrences and start and end positions of each short string in the large strings, and report these results using the ID numbers for each short string.
I am getting a EInOutError (Access Denied) error apparently at the ReWrite(ResultFile) line (in the bottom half of the second procedure in the code below). Not sure why. I can see the file created for the results of the first long string, but it is blank. Here is the code; pretty simple and straightforward, actually. Thanks.
procedure TForm1.OpenStrCmdBtnClick(Sender: TObject);
begin
if OpenDialog1.execute then OpenStrEditBx.Text := OpenDialog1.FileName
else ShowMessage('Cannot open file!');
end;
procedure TForm1.FindItemfCmdBtnClick(Sender: TObject);
var
I, LenItem, NumTimes, offset: integer;
Extension, FileName, Dir, Str, Item, ID: string;
TempList, IDList, ItemList: TStringList;
searchResult: TSearchRec;
ResultFile: TextFile;
begin
IDList := TStringList.Create;
ItemList := TStringList.Create;
IDList.LoadFromFile('D:\...\IDs.txt');
ItemList.LoadFromFile('D:\...\Items.txt');
try
Dir := ExtractFilePath(OpenStrEditBx.Text);
//concatenate each line in each str sequence to get full string
if FindFirst(Dir + '*.txt', faAnyFile, searchResult) = 0 then
repeat
Extension := ExtractFileExt(OpenStrEditBx.Text);
FileName := StringReplace(searchResult.Name, Extension, '', [rFReplaceAll, rFIgnoreCase]);//remove file extension to get only file name
TempList := TStringList.Create;
TempList.LoadFromFile(Dir + searchResult.Name);
Str := '';
for I := 1 to TempList.Count-1 do // I <> 0 to ignore ID in first line
begin
Str := Str + TempList[I];
ProgressBar1.Position := (ProgressBar1.Position + 10) mod ProgressBar1.Max;
end;
TempList.Free;
//Find number and location of occurrences of each Item
for I := 0 to ItemList.Count-1 do
begin
Item := ItemList[I];
LenItem := Length(Item);
ID := IDList[I];
NumTimes := 0;
Offset := PosEx(Item, Str, 1);
AssignFile(ResultFile, 'D:\...\' + FileName + '.txt');
ReWrite(ResultFile);
while Offset <> 0 do
begin
inc(NumTimes);
if NumTimes > 0 then
WriteLn(ResultFile, 'The ' + IntToStr(NumTimes) + 'th occurrence of ' + 'ID# ' + ID + ' is from Position# ' + IntToStr(Offset) + ' to Position# ' + IntToStr(Offset + LenItem- 1) + ' in ' + FileName);
Offset := PosEx(Item, Str, Offset + LenItem);
end;
WriteLn(ResultFile, 'ID# ' + ID + ' occurs ' + IntToStr(NumTimes) + ' number of times in ' + FileName);
end;
CloseFile(ResultFile);
ShowMessage(FileName + ' done!');
until FindNext(searchResult) <> 0;
FindClose(searchResult);
finally
IDList.Free;
ItemList.Free;
end;
end;
I have developed a TSP to talk to a CTI server. In the most part it works, but when setting the caller/called ID parties, in
function TSPI_lineGetCallInfo(
hdCall : HDRVCALL;
lpCallInfo : LPLINECALLINFO
) : LONG;
I am finding the offsets are all corrects but the size fields are NOT. At the end of the function I output (to debugger) the size and offsets of each field and they are what I expect them to be. But when I inspect the values using a TAPI program the sizes are different, (but the offsets are EXACTLY the same as per the debug statements) in fact the size field 5 regardless of what is actually there, whereas the debug statements at the end of the code below shows the correct values...
Any help greatly appreciated.
lpCallInfo^.dwCallerIDOffset := 0;
lpCallInfo^.dwCallerIDSize := 0;
lpCallInfo^.dwCalledIDOffset := 0;
lpCallInfo^.dwCalledIDSize := 0;
lpCallInfo^.dwConnectedIDOffset := 0;
lpCallInfo^.dwConnectedIDSize := 0;
extnid := thiscall.CallItem.ExtnId;
phoneno := thiscall.CallItem.DialNum;
extnid_size := (Length(extnid) + 1) * sizeof(WCHAR);
phoneno_size := (Length(phoneno) + 1) * sizeof(WCHAR);
extnidw := StringToWideStringEx(extnid, CP_ACP);
phonenow := StringToWideStringEx(phoneno, CP_ACP);
if lpCallInfo^.dwOrigin = LINECALLORIGIN_INTERNAL then
begin
{me}
lpCallInfo^.dwCallerIDOffset := sizeof(TLINECALLINFO);
lpCallInfo^.dwCallerIDSize := extnid_size;
Move(ExtnIdw[1], ptr^, extnid_size * 2);
ptr := Pointer(integer(ptr) + lpCallInfo^.dwCallerIDSize);
{other party}
if phoneno <> '' then
begin
lpCallInfo^.dwCalledIDOffset :=
sizeof(TLINECALLINFO) + lpCallInfo^.dwCallerIDSize;
lpCallInfo^.dwCalledIDSize := phoneno_size;
Move(phonenow[1], ptr^, phoneno_size * 2);
end;
end
else
begin
if thiscall.CallItem.CallType = 1 then
begin {incoming call}
{agent is the called party}
lpCallInfo^.dwCalledIDOffset := sizeof(TLINECALLINFO);
lpCallInfo^.dwCalledIDSize := extnid_size;
Move(ExtnIdw[1], ptr^, extnid_size);
ptr := Pointer(integer(ptr) + lpCallInfo^.dwCalledIDSize);
{other party is the caller}
if phoneno <> '' then
begin
lpCallInfo^.dwCallerIDOffset :=
sizeof(TLINECALLINFO) + lpCallInfo^.dwCalledIDSize;
lpCallInfo^.dwCallerIDSize := phoneno_size;
Move(phonenow[1], ptr^, phoneno_size);
ptr := Pointer(integer(ptr) + lpCallInfo^.dwCallerIDSize);
end;
end
else
begin
{agnet is the caller}
lpCallInfo^.dwCallerIDOffset := sizeof(TLINECALLINFO);
lpCallInfo^.dwCallerIDSize := extnid_size;
Move(ExtnIdw[1], ptr^, extnid_size);
ptr := Pointer(integer(ptr) + lpCallInfo^.dwCallerIDSize);
{dialed number is the called party}
if phoneno <> '' then
begin
lpCallInfo^.dwCalledIDOffset :=
sizeof(TLINECALLINFO) + lpCallInfo^.dwCallerIDSize;
lpCallInfo^.dwCalledIDSize := phoneno_size;
Move(phonenow[1], ptr^, phoneno_size);
ptr := Pointer(integer(ptr) + lpCallInfo^.dwCalledIDSize);
end;
end;
if (thiscall.CallItem.CallState = cs_Connected) and
(phoneno <> '') then
begin
lpCallInfo^.dwConnectedIDOffset := sizeof(TLINECALLINFO) +
lpCallInfo^.dwCallerIDSize + lpCallInfo^.dwCalledIDSize;
lpCallInfo^.dwConnectedIDSize := phoneno_size;
Move(phonenow[1], ptr^, phoneno_size);
ptr := Pointer(integer(ptr) + lpCallInfo^.dwConnectedIDSize);
end;
end;
end;
DEBUG('TSPI_lineGetCallInfo::dwCallerIDOffset=' + intToStr(lpCallInfo^.dwCallerIDOffset));
DEBUG('TSPI_lineGetCallInfo::dwCallerIDSize=' + intToStr(lpCallInfo^.dwCallerIDSize));
DEBUG('TSPI_lineGetCallInfo::dwCalledIDOffset=' + intToStr(lpCallInfo^.dwCalledIDOffset));
DEBUG('TSPI_lineGetCallInfo::dwCalledIDSize=' + intToStr(lpCallInfo^.dwCalledIDSize));
DEBUG('TSPI_lineGetCallInfo::dwConnectedIDOffset=' + intToStr(lpCallInfo^.dwConnectedIDOffset));
DEBUG('TSPI_lineGetCallInfo::dwConnectedIDSize=' + intToStr(lpCallInfo^.dwConnectedIDSize));
These are strange results. Your code seems to check out. It may be a longshot but the result could be caused by too few memory reserved for the lpCallInfo structure. What tapi program do you use? Most programs just reserve a large surplus beforehand. However, another commonly used approach is to 'ask' the TSP the exact amount needed by first calling TSPI_lineGetCallInfo and then reserving the exact amount after you set the dwNeededSize and returning LINEERR_STRUCTURETOOSMALL. You don't seem to check the dwTotalSize or set the dwNeededSize and dwUsedSize fields (which is dangerous).
Please look at the : LINEERR constants
and let me know if it solves the issue. If it doesn't, I would be curious to see the structure log from the Tapi Browser, but let's hope it works. Good luck!
I can't understand what's going on here. Can you give me a hand? This is the problematic code:
While not EOF(Archi) do begin
index:= index + 1;
Read(Archi, Alumno[index]);
Promes[index] := (Alumno[index].nota1 + Alumno[index].nota2) / 2;
if Promes[index] >= 6 then begin
alguPromo := true;
PromosIndex := PromosIndex + 1;
Promos[PromosIndex]:= Alumno[index];
end;
else begin
if Promes[index] > 4 then cantiRecu:= cantiRecu + 1;
else begin
LibresIndex += 1;
Libres[LibresIndex] := Alumno[index];
end;
end;
end;
The compiler marks error in the line 10 of this code (else begin). The error is:
Fatal: Syntax error, ; expected but ELSE found.
If someone wants to tray compile here is the entire code: http://pastebin.com/dRg1Lguu
Note that in Pascal the semicolon is a separator, not a terminator. Sometimes this doesn't matter, but in some cases it does, particularly before an else. Your code should be:
while not EOF(Archi) do
begin
index:= index + 1;
Read(Archi, Alumno[index]);
Promes[index] := (Alumno[index].nota1 + Alumno[index].nota2) / 2;
if Promes[index] >= 6 then
begin
alguPromo := true;
PromosIndex := PromosIndex + 1;
Promos[PromosIndex] := Alumno[index]
end
else
begin
if Promes[index] > 4 then
cantiRecu:= cantiRecu + 1
else
begin
LibresIndex := LibresIndex + 1;
Libres[LibresIndex] := Alumno[index]
end
end
end
Note that I have re-formatted the code into a more conventional style which helps to make the program logic more easily understood and which also makes it more obvious where the semicolons are needed and where they are not.
Looks like problem in += operator