ssl_openssl.pas 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. {==============================================================================|
  2. | Project : Ararat Synapse | 001.004.000 |
  3. |==============================================================================|
  4. | Content: SSL support by OpenSSL |
  5. |==============================================================================|
  6. | Copyright (c)1999-2017, Lukas Gebauer |
  7. | All rights reserved. |
  8. | |
  9. | Redistribution and use in source and binary forms, with or without |
  10. | modification, are permitted provided that the following conditions are met: |
  11. | |
  12. | Redistributions of source code must retain the above copyright notice, this |
  13. | list of conditions and the following disclaimer. |
  14. | |
  15. | Redistributions in binary form must reproduce the above copyright notice, |
  16. | this list of conditions and the following disclaimer in the documentation |
  17. | and/or other materials provided with the distribution. |
  18. | |
  19. | Neither the name of Lukas Gebauer nor the names of its contributors may |
  20. | be used to endorse or promote products derived from this software without |
  21. | specific prior written permission. |
  22. | |
  23. | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
  24. | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
  25. | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
  26. | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
  27. | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
  28. | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
  29. | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
  30. | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
  31. | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
  32. | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
  33. | DAMAGE. |
  34. |==============================================================================|
  35. | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
  36. | Portions created by Lukas Gebauer are Copyright (c)2005-2017. |
  37. | Portions created by Petr Fejfar are Copyright (c)2011-2012. |
  38. | Portions created by Pepak are Copyright (c)2018. |
  39. | All Rights Reserved. |
  40. |==============================================================================|
  41. | Contributor(s): |
  42. |==============================================================================|
  43. | History: see HISTORY.HTM from distribution package |
  44. | (Found at URL: http://www.ararat.cz/synapse/) |
  45. |==============================================================================}
  46. //requires OpenSSL libraries!
  47. {:@abstract(SSL plugin for OpenSSL)
  48. Compatibility with OpenSSL versions:
  49. 0.9.6 should work, known mysterious crashing on FreePascal and Linux platform.
  50. 0.9.7 - 1.0.0 working fine.
  51. 1.1.0 should work, under testing.
  52. OpenSSL libraries are loaded dynamicly - you not need OpenSSL librares even you
  53. compile your application with this unit. SSL just not working when you not have
  54. OpenSSL libraries.
  55. This plugin have limited support for .NET too! Because is not possible to use
  56. callbacks with CDECL calling convention under .NET, is not supported
  57. key/certificate passwords and multithread locking. :-(
  58. For handling keys and certificates you can use this properties:
  59. @link(TCustomSSL.CertificateFile) for PEM or ASN1 DER (cer) format. @br
  60. @link(TCustomSSL.Certificate) for ASN1 DER format only. @br
  61. @link(TCustomSSL.PrivateKeyFile) for PEM or ASN1 DER (key) format. @br
  62. @link(TCustomSSL.PrivateKey) for ASN1 DER format only. @br
  63. @link(TCustomSSL.CertCAFile) for PEM CA certificate bundle. @br
  64. @link(TCustomSSL.PFXFile) for PFX format. @br
  65. @link(TCustomSSL.PFX) for PFX format from binary string. @br
  66. This plugin is capable to create Ad-Hoc certificates. When you start SSL/TLS
  67. server without explicitly assigned key and certificate, then this plugin create
  68. Ad-Hoc key and certificate for each incomming connection by self. It slowdown
  69. accepting of new connections!
  70. }
  71. {$IFDEF FPC}
  72. {$MODE DELPHI}
  73. {$ENDIF}
  74. {$H+}
  75. {$IFDEF UNICODE}
  76. {$WARN IMPLICIT_STRING_CAST OFF}
  77. {$WARN IMPLICIT_STRING_CAST_LOSS OFF}
  78. {$ENDIF}
  79. unit ssl_openssl{$IFDEF SUPPORTS_DEPRECATED} deprecated{$IFDEF SUPPORTS_DEPRECATED_DETAILS} 'Use ssl_openssl3 with OpenSSL 3.0 instead'{$ENDIF}{$ENDIF};
  80. interface
  81. uses
  82. SysUtils, Classes,
  83. blcksock, synsock, synautil,
  84. synabyte,
  85. {$IFDEF CIL}
  86. System.Text,
  87. {$ENDIF}
  88. ssl_openssl_lib;
  89. type
  90. {:@abstract(class implementing OpenSSL SSL plugin.)
  91. Instance of this class will be created for each @link(TTCPBlockSocket).
  92. You not need to create instance of this class, all is done by Synapse itself!}
  93. TSSLOpenSSL = class(TCustomSSL)
  94. private
  95. FServer: boolean;
  96. protected
  97. FSsl: PSSL;
  98. Fctx: PSSL_CTX;
  99. function NeedSigningCertificate: boolean; virtual;
  100. function SSLCheck: Boolean;
  101. function SetSslKeys: boolean; virtual;
  102. function Init: Boolean;
  103. function DeInit: Boolean;
  104. function Prepare: Boolean;
  105. function LoadPFX(pfxdata: TSynaBytes): Boolean;
  106. function CreateSelfSignedCert(Host: string): Boolean; override;
  107. property Server: boolean read FServer;
  108. public
  109. {:See @inherited}
  110. constructor Create(const Value: TTCPBlockSocket); override;
  111. destructor Destroy; override;
  112. {:See @inherited}
  113. function LibVersion: String; override;
  114. {:See @inherited}
  115. function LibName: String; override;
  116. {:See @inherited and @link(ssl_cryptlib) for more details.}
  117. function Connect: boolean; override;
  118. {:See @inherited and @link(ssl_cryptlib) for more details.}
  119. function Accept: boolean; override;
  120. {:See @inherited}
  121. function Shutdown: boolean; override;
  122. {:See @inherited}
  123. function BiShutdown: boolean; override;
  124. {:See @inherited}
  125. function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override;
  126. {:See @inherited}
  127. function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
  128. {:See @inherited}
  129. function WaitingData: Integer; override;
  130. {:See @inherited}
  131. function GetSSLVersion: string; override;
  132. {:See @inherited}
  133. function GetPeerSubject: string; override;
  134. {:See @inherited}
  135. function GetPeerSerialNo: integer; override; {pf}
  136. {:See @inherited}
  137. function GetPeerIssuer: string; override;
  138. {:See @inherited}
  139. function GetPeerName: string; override;
  140. {:See @inherited}
  141. function GetPeerNameHash: cardinal; override; {pf}
  142. {:See @inherited}
  143. function GetPeerFingerprint: string; override;
  144. function GetPeerFingerprintDigest(const ADigest: string): string; override;
  145. {:See @inherited}
  146. function GetCertInfo: string; override;
  147. {:See @inherited}
  148. function GetCipherName: string; override;
  149. {:See @inherited}
  150. function GetCipherBits: integer; override;
  151. {:See @inherited}
  152. function GetCipherAlgBits: integer; override;
  153. {:See @inherited}
  154. function GetVerifyCert: integer; override;
  155. end;
  156. implementation
  157. {==============================================================================}
  158. {$IFNDEF CIL}
  159. function PasswordCallback(Buf:PByte; size:Integer; rwflag:Integer; userdata: Pointer):Integer; cdecl;
  160. var
  161. Password: TSynabytes;
  162. begin
  163. Password := '';
  164. if TCustomSSL(userdata) is TCustomSSL then
  165. Password := TCustomSSL(userdata).KeyPassword;
  166. if Length(Password) > (Size - 1) then
  167. {$IFDEF UNICODE}
  168. Password.Length := Size - 1;
  169. {$ELSE}
  170. SetLength(Password, Size - 1);
  171. {$ENDIF}
  172. Result := Length(Password);
  173. Password := Password + #0;
  174. {$IFDEF UNICODE}
  175. Move(Password.Data^, buf^, result+1);
  176. {$ELSE}
  177. Move(PAnsiChar(AnsiString(Password))^, buf^, result+1);
  178. {$ENDIF}
  179. end;
  180. {$ENDIF}
  181. {==============================================================================}
  182. constructor TSSLOpenSSL.Create(const Value: TTCPBlockSocket);
  183. begin
  184. inherited Create(Value);
  185. FCiphers := 'DEFAULT';
  186. FSsl := nil;
  187. Fctx := nil;
  188. end;
  189. destructor TSSLOpenSSL.Destroy;
  190. begin
  191. DeInit;
  192. inherited Destroy;
  193. end;
  194. function TSSLOpenSSL.LibVersion: String;
  195. begin
  196. Result := SSLeayversion(0);
  197. end;
  198. function TSSLOpenSSL.LibName: String;
  199. begin
  200. Result := 'ssl_openssl';
  201. end;
  202. function TSSLOpenSSL.SSLCheck: Boolean;
  203. var
  204. {$IFDEF CIL}
  205. sb: StringBuilder;
  206. {$ELSE}
  207. se: integer;
  208. {$ENDIF}
  209. s : TSynabytes;
  210. begin
  211. Result := true;
  212. FLastErrorDesc := '';
  213. FLastError := ErrGetError;
  214. ErrClearError;
  215. if FLastError <> 0 then
  216. begin
  217. Result := False;
  218. {$IFDEF CIL}
  219. sb := StringBuilder.Create(256);
  220. ErrErrorString(FLastError, sb, 256);
  221. FLastErrorDesc := Trim(sb.ToString);
  222. {$ELSE}
  223. //{$IFDEF WIN???}
  224. if FLastError = SSL_ERROR_SYSCALL then
  225. begin
  226. se := WSAGetLastError();
  227. FLastErrorDesc := '#sslErr:' + SysUtils.IntToStr(FLastError)
  228. + ' #sysErr:' + SysUtils.IntToStr(se)
  229. + ' ' + string(TBlockSocket.GetErrorDesc(se)) // cast
  230. end;
  231. //{$ELSE}
  232. //{$ENDIF}
  233. if FLastErrorDesc = '' then
  234. begin
  235. s := StringOfChar(AnsiChar(#0), 256);
  236. ErrErrorString(FLastError, s, Length(s));
  237. FLastErrorDesc := '#sslErr:' + SysUtils.IntToStr(FLastError)
  238. + ' ' + string(s); // cast
  239. end
  240. {$ENDIF}
  241. end;
  242. end;
  243. function TSSLOpenSSL.CreateSelfSignedCert(Host: string): Boolean;
  244. var
  245. pk: EVP_PKEY;
  246. x: PX509;
  247. rsa: PRSA;
  248. t: PASN1_UTCTIME;
  249. name: PX509_NAME;
  250. b: PBIO;
  251. xn, y: integer;
  252. s: TBytes;
  253. {$IFDEF CIL}
  254. sb: StringBuilder;
  255. {$ENDIF}
  256. begin
  257. Result := True;
  258. pk := EvpPkeynew;
  259. x := X509New;
  260. try
  261. rsa := RsaGenerateKey(2048, $10001, nil, nil);
  262. EvpPkeyAssign(pk, EVP_PKEY_RSA, rsa);
  263. X509SetVersion(x, 2);
  264. Asn1IntegerSet(X509getSerialNumber(x), 0);
  265. t := Asn1UtctimeNew;
  266. try
  267. X509GmtimeAdj(t, -60 * 60 *24);
  268. X509SetNotBefore(x, t);
  269. X509GmtimeAdj(t, 60 * 60 * 60 *24);
  270. X509SetNotAfter(x, t);
  271. finally
  272. Asn1UtctimeFree(t);
  273. end;
  274. X509SetPubkey(x, pk);
  275. Name := X509GetSubjectName(x);
  276. X509NameAddEntryByTxt(Name, 'C', $1001, 'CZ', -1, -1, 0);
  277. X509NameAddEntryByTxt(Name, 'CN', $1001, host, -1, -1, 0);
  278. x509SetIssuerName(x, Name);
  279. x509Sign(x, pk, EvpGetDigestByName('SHA1'));
  280. b := BioNew(BioSMem);
  281. try
  282. i2dX509Bio(b, x);
  283. xn := bioctrlpending(b);
  284. {$IFDEF CIL}
  285. sb := StringBuilder.Create(xn);
  286. y := bioread(b, sb, xn);
  287. if y > 0 then
  288. begin
  289. sb.Length := y;
  290. s := sb.ToString;
  291. end;
  292. {$ELSE}
  293. setlength(s, xn);
  294. y := bioread(b, @s[0], xn);
  295. if y > 0 then
  296. setlength(s, y);
  297. {$ENDIF}
  298. finally
  299. BioFreeAll(b);
  300. end;
  301. FCertificate := StringOf(s);
  302. b := BioNew(BioSMem);
  303. try
  304. i2dPrivatekeyBio(b, pk);
  305. xn := bioctrlpending(b);
  306. {$IFDEF CIL}
  307. sb := StringBuilder.Create(xn);
  308. y := bioread(b, sb, xn);
  309. if y > 0 then
  310. begin
  311. sb.Length := y;
  312. s := sb.ToString;
  313. end;
  314. {$ELSE}
  315. setlength(s, xn);
  316. y := bioread(b, @s[0], xn);
  317. if y > 0 then
  318. setlength(s, y);
  319. {$ENDIF}
  320. finally
  321. BioFreeAll(b);
  322. end;
  323. FPrivatekey := StringOf(s);
  324. finally
  325. X509free(x);
  326. EvpPkeyFree(pk);
  327. end;
  328. end;
  329. function TSSLOpenSSL.LoadPFX(pfxdata: TSynaBytes): Boolean;
  330. var
  331. cert, pkey, ca: SslPtr;
  332. b: PBIO;
  333. p12: SslPtr;
  334. buf: PByte;
  335. len: cardinal;
  336. begin
  337. Result := False;
  338. b := BioNew(BioSMem);
  339. try
  340. {$IFDEF UNICODE}
  341. buf := pfxdata.Data;
  342. len := pfxdata.Length;
  343. {$ELSE}
  344. buf := PByte(pfxData);
  345. len := length(pfxData);
  346. {$ENDIF}
  347. BioWrite(b, buf, len);
  348. p12 := d2iPKCS12bio(b, nil);
  349. if not Assigned(p12) then
  350. Exit;
  351. try
  352. cert := nil;
  353. pkey := nil;
  354. ca := nil;
  355. try {pf}
  356. if PKCS12parse(p12, FKeyPassword, pkey, cert, ca) > 0 then
  357. if SSLCTXusecertificate(Fctx, cert) > 0 then
  358. if SSLCTXusePrivateKey(Fctx, pkey) > 0 then
  359. Result := True;
  360. {pf}
  361. finally
  362. EvpPkeyFree(pkey);
  363. X509free(cert);
  364. SkX509PopFree(ca,_X509Free); // for ca=nil a new STACK was allocated...
  365. end;
  366. {/pf}
  367. finally
  368. PKCS12free(p12);
  369. end;
  370. finally
  371. BioFreeAll(b);
  372. end;
  373. end;
  374. function TSSLOpenSSL.SetSslKeys: boolean;
  375. var
  376. st: TFileStream;
  377. s: string;
  378. begin
  379. Result := False;
  380. if not assigned(FCtx) then
  381. Exit;
  382. try
  383. if FCertificateFile <> '' then
  384. if SslCtxUseCertificateChainFile(FCtx, FCertificateFile) <> 1 then
  385. if SslCtxUseCertificateFile(FCtx, FCertificateFile, SSL_FILETYPE_PEM) <> 1 then
  386. if SslCtxUseCertificateFile(FCtx, FCertificateFile, SSL_FILETYPE_ASN1) <> 1 then
  387. Exit;
  388. if FCertificate <> '' then
  389. if SslCtxUseCertificateASN1(FCtx, length(FCertificate), FCertificate) <> 1 then
  390. Exit;
  391. SSLCheck;
  392. if FPrivateKeyFile <> '' then
  393. if SslCtxUsePrivateKeyFile(FCtx, FPrivateKeyFile, SSL_FILETYPE_PEM) <> 1 then
  394. if SslCtxUsePrivateKeyFile(FCtx, FPrivateKeyFile, SSL_FILETYPE_ASN1) <> 1 then
  395. Exit;
  396. if FPrivateKey <> '' then
  397. if SslCtxUsePrivateKeyASN1(EVP_PKEY_RSA, FCtx, FPrivateKey, length(FPrivateKey)) <> 1 then
  398. Exit;
  399. SSLCheck;
  400. if FCertCAFile <> '' then
  401. if SslCtxLoadVerifyLocations(FCtx, FCertCAFile, '') <> 1 then
  402. Exit;
  403. if FPFXfile <> '' then
  404. begin
  405. try
  406. st := TFileStream.Create(FPFXfile, fmOpenRead or fmShareDenyNone);
  407. try
  408. s := ReadStrFromStream(st, st.Size);
  409. finally
  410. st.Free;
  411. end;
  412. if not LoadPFX(s) then
  413. Exit;
  414. except
  415. on Exception do
  416. Exit;
  417. end;
  418. end;
  419. if FPFX <> '' then
  420. if not LoadPFX(FPfx) then
  421. Exit;
  422. SSLCheck;
  423. Result := True;
  424. finally
  425. SSLCheck;
  426. end;
  427. end;
  428. function TSSLOpenSSL.NeedSigningCertificate: boolean;
  429. begin
  430. Result := (FCertificateFile = '') and (FCertificate = '') and (FPFXfile = '') and (FPFX = '');
  431. end;
  432. function TSSLOpenSSL.Init: Boolean;
  433. var
  434. s: TSynabytes;
  435. buf: PByte;
  436. begin
  437. Result := False;
  438. FLastErrorDesc := '';
  439. FLastError := 0;
  440. Fctx := nil;
  441. case FSSLType of
  442. LT_SSLv2:
  443. Fctx := SslCtxNew(SslMethodV2);
  444. LT_SSLv3:
  445. Fctx := SslCtxNew(SslMethodV3);
  446. LT_TLSv1:
  447. Fctx := SslCtxNew(SslMethodTLSV1);
  448. LT_TLSv1_1:
  449. Fctx := SslCtxNew(SslMethodTLSV11);
  450. LT_TLSv1_2:
  451. Fctx := SslCtxNew(SslMethodTLSV12);
  452. LT_all:
  453. begin
  454. //try new call for OpenSSL 1.1.0 first
  455. Fctx := SslCtxNew(SslMethodTLS);
  456. if Fctx=nil then
  457. //callback to previous versions
  458. Fctx := SslCtxNew(SslMethodV23);
  459. end;
  460. else
  461. Exit;
  462. end;
  463. if Fctx = nil then
  464. begin
  465. SSLCheck;
  466. Exit;
  467. end
  468. else
  469. begin
  470. s := FCiphers;
  471. {$IFDEF UNICODE}
  472. buf := s.Data;
  473. {$ELSE}
  474. buf := PByte(s);
  475. {$ENDIF}
  476. SslCtxSetCipherList(Fctx, buf);
  477. if FVerifyCert then
  478. SslCtxSetVerify(FCtx, SSL_VERIFY_PEER, nil)
  479. else
  480. SslCtxSetVerify(FCtx, SSL_VERIFY_NONE, nil);
  481. {$IFNDEF CIL}
  482. SslCtxSetDefaultPasswdCb(FCtx, @PasswordCallback);
  483. SslCtxSetDefaultPasswdCbUserdata(FCtx, self);
  484. {$ENDIF}
  485. if server and NeedSigningCertificate then
  486. begin
  487. CreateSelfSignedcert(FSocket.ResolveIPToName(FSocket.GetRemoteSinIP));
  488. end;
  489. if not SetSSLKeys then
  490. Exit
  491. else
  492. begin
  493. Fssl := nil;
  494. Fssl := SslNew(Fctx);
  495. if Fssl = nil then
  496. begin
  497. SSLCheck;
  498. exit;
  499. end;
  500. end;
  501. end;
  502. Result := true;
  503. end;
  504. function TSSLOpenSSL.DeInit: Boolean;
  505. begin
  506. Result := True;
  507. if assigned (Fssl) then
  508. sslfree(Fssl);
  509. Fssl := nil;
  510. if assigned (Fctx) then
  511. begin
  512. SslCtxFree(Fctx);
  513. Fctx := nil;
  514. ErrRemoveState(0);
  515. end;
  516. FSSLEnabled := False;
  517. end;
  518. function TSSLOpenSSL.Prepare: Boolean;
  519. begin
  520. Result := false;
  521. DeInit;
  522. if Init then
  523. Result := true
  524. else
  525. DeInit;
  526. end;
  527. function TSSLOpenSSL.Connect: boolean;
  528. var
  529. x: integer;
  530. b: boolean;
  531. err: integer;
  532. s: TSynabytes;
  533. buf: PByte;
  534. begin
  535. Result := False;
  536. if FSocket.Socket = INVALID_SOCKET then
  537. Exit;
  538. FServer := False;
  539. if Prepare then
  540. begin
  541. {$IFDEF CIL}
  542. if sslsetfd(FSsl, FSocket.Socket.Handle.ToInt32) < 1 then
  543. {$ELSE}
  544. if sslsetfd(FSsl, FSocket.Socket) < 1 then
  545. {$ENDIF}
  546. begin
  547. SSLCheck;
  548. Exit;
  549. end;
  550. if SNIHost<>'' then
  551. begin
  552. s := sniHost;
  553. {$IFDEF UNICODE}
  554. buf := s.Data;
  555. {$ELSE}
  556. buf := PByte(s);
  557. {$ENDIF}
  558. SSLCtrl(Fssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, buf);
  559. end;
  560. if FSocket.ConnectionTimeout <= 0 then //do blocking call of SSL_Connect
  561. begin
  562. x := sslconnect(FSsl);
  563. if x < 1 then
  564. begin
  565. SSLcheck;
  566. Exit;
  567. end;
  568. end
  569. else //do non-blocking call of SSL_Connect
  570. begin
  571. b := Fsocket.NonBlockMode;
  572. Fsocket.NonBlockMode := true;
  573. repeat
  574. x := sslconnect(FSsl);
  575. err := SslGetError(FSsl, x);
  576. if err = SSL_ERROR_WANT_READ then
  577. if not FSocket.CanRead(FSocket.ConnectionTimeout) then
  578. break;
  579. if err = SSL_ERROR_WANT_WRITE then
  580. if not FSocket.CanWrite(FSocket.ConnectionTimeout) then
  581. break;
  582. until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  583. Fsocket.NonBlockMode := b;
  584. if err <> SSL_ERROR_NONE then
  585. begin
  586. SSLcheck;
  587. Exit;
  588. end;
  589. end;
  590. if FverifyCert then
  591. if (GetVerifyCert <> 0) or (not DoVerifyCert) then
  592. Exit;
  593. FSSLEnabled := True;
  594. Result := True;
  595. end;
  596. end;
  597. function TSSLOpenSSL.Accept: boolean;
  598. var
  599. x: integer;
  600. begin
  601. Result := False;
  602. if FSocket.Socket = INVALID_SOCKET then
  603. Exit;
  604. FServer := True;
  605. if Prepare then
  606. begin
  607. {$IFDEF CIL}
  608. if sslsetfd(FSsl, FSocket.Socket.Handle.ToInt32) < 1 then
  609. {$ELSE}
  610. if sslsetfd(FSsl, FSocket.Socket) < 1 then
  611. {$ENDIF}
  612. begin
  613. SSLCheck;
  614. Exit;
  615. end;
  616. x := sslAccept(FSsl);
  617. if x < 1 then
  618. begin
  619. SSLcheck;
  620. Exit;
  621. end;
  622. FSSLEnabled := True;
  623. Result := True;
  624. end;
  625. end;
  626. function TSSLOpenSSL.Shutdown: boolean;
  627. begin
  628. if assigned(FSsl) then
  629. sslshutdown(FSsl);
  630. DeInit;
  631. Result := True;
  632. end;
  633. function TSSLOpenSSL.BiShutdown: boolean;
  634. var
  635. x: integer;
  636. begin
  637. if assigned(FSsl) then
  638. begin
  639. x := sslshutdown(FSsl);
  640. if x = 0 then
  641. begin
  642. Synsock.Shutdown(FSocket.Socket, 1);
  643. sslshutdown(FSsl);
  644. end;
  645. end;
  646. DeInit;
  647. Result := True;
  648. end;
  649. function TSSLOpenSSL.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
  650. var
  651. err: integer;
  652. {$IFDEF CIL}
  653. s: ansistring;
  654. {$ENDIF}
  655. begin
  656. FLastError := 0;
  657. FLastErrorDesc := '';
  658. repeat
  659. {$IFDEF CIL}
  660. s := StringOf(Buffer);
  661. Result := SslWrite(FSsl, s, Len);
  662. {$ELSE}
  663. Result := SslWrite(FSsl, Buffer , Len);
  664. {$ENDIF}
  665. err := SslGetError(FSsl, Result);
  666. until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  667. if err = SSL_ERROR_ZERO_RETURN then
  668. Result := 0
  669. else
  670. if (err <> 0) then
  671. FLastError := err;
  672. end;
  673. function TSSLOpenSSL.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
  674. var
  675. err: integer;
  676. {$IFDEF CIL}
  677. sb: stringbuilder;
  678. s: ansistring;
  679. {$ENDIF}
  680. begin
  681. FLastError := 0;
  682. FLastErrorDesc := '';
  683. repeat
  684. {$IFDEF CIL}
  685. sb := StringBuilder.Create(Len);
  686. Result := SslRead(FSsl, sb, Len);
  687. if Result > 0 then
  688. begin
  689. sb.Length := Result;
  690. s := sb.ToString;
  691. System.Array.Copy(BytesOf(s), Buffer, length(s));
  692. end;
  693. {$ELSE}
  694. Result := SslRead(FSsl, Buffer , Len);
  695. {$ENDIF}
  696. err := SslGetError(FSsl, Result);
  697. until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  698. if err = SSL_ERROR_ZERO_RETURN then
  699. Result := 0
  700. {pf}// Verze 1.1.0 byla s else tak jak to ted mam,
  701. // ve verzi 1.1.1 bylo ELSE zruseno, ale pak je SSL_ERROR_ZERO_RETURN
  702. // propagovano jako Chyba.
  703. {pf} else {/pf} if (err <> 0) then
  704. FLastError := err;
  705. end;
  706. function TSSLOpenSSL.WaitingData: Integer;
  707. begin
  708. Result := sslpending(Fssl);
  709. end;
  710. function TSSLOpenSSL.GetSSLVersion: string;
  711. begin
  712. if not assigned(FSsl) then
  713. Result := ''
  714. else
  715. Result := SSlGetVersion(FSsl);
  716. end;
  717. function TSSLOpenSSL.GetPeerSubject: string;
  718. var
  719. cert: PX509;
  720. s: TBytes;
  721. {$IFDEF CIL}
  722. sb: StringBuilder;
  723. {$ENDIF}
  724. begin
  725. if not assigned(FSsl) then
  726. begin
  727. Result := '';
  728. Exit;
  729. end;
  730. cert := SSLGetPeerCertificate(Fssl);
  731. if not assigned(cert) then
  732. begin
  733. Result := '';
  734. Exit;
  735. end;
  736. {$IFDEF CIL}
  737. sb := StringBuilder.Create(4096);
  738. Result := X509NameOneline(X509GetSubjectName(cert), sb, 4096);
  739. {$ELSE}
  740. setlength(s, 4096);
  741. Result := X509NameOneline(X509GetSubjectName(cert), @s[0], Length(s));
  742. {$ENDIF}
  743. X509Free(cert);
  744. end;
  745. function TSSLOpenSSL.GetPeerSerialNo: integer; {pf}
  746. var
  747. cert: PX509;
  748. SN: PASN1_INTEGER;
  749. begin
  750. if not assigned(FSsl) then
  751. begin
  752. Result := -1;
  753. Exit;
  754. end;
  755. cert := SSLGetPeerCertificate(Fssl);
  756. try
  757. if not assigned(cert) then
  758. begin
  759. Result := -1;
  760. Exit;
  761. end;
  762. SN := X509GetSerialNumber(cert);
  763. Result := Asn1IntegerGet(SN);
  764. finally
  765. X509Free(cert);
  766. end;
  767. end;
  768. function TSSLOpenSSL.GetPeerName: string;
  769. var
  770. s: string;
  771. begin
  772. s := GetPeerSubject;
  773. s := SeparateRight(s, '/CN=');
  774. Result := Trim(SeparateLeft(s, '/'));
  775. end;
  776. function TSSLOpenSSL.GetPeerNameHash: cardinal; {pf}
  777. var
  778. cert: PX509;
  779. begin
  780. if not assigned(FSsl) then
  781. begin
  782. Result := 0;
  783. Exit;
  784. end;
  785. cert := SSLGetPeerCertificate(Fssl);
  786. try
  787. if not assigned(cert) then
  788. begin
  789. Result := 0;
  790. Exit;
  791. end;
  792. Result := X509NameHash(X509GetSubjectName(cert));
  793. finally
  794. X509Free(cert);
  795. end;
  796. end;
  797. function TSSLOpenSSL.GetPeerIssuer: string;
  798. var
  799. cert: PX509;
  800. s: TBytes;
  801. {$IFDEF CIL}
  802. sb: StringBuilder;
  803. {$ENDIF}
  804. begin
  805. if not assigned(FSsl) then
  806. begin
  807. Result := '';
  808. Exit;
  809. end;
  810. cert := SSLGetPeerCertificate(Fssl);
  811. if not assigned(cert) then
  812. begin
  813. Result := '';
  814. Exit;
  815. end;
  816. {$IFDEF CIL}
  817. sb := StringBuilder.Create(4096);
  818. Result := X509NameOneline(X509GetIssuerName(cert), sb, 4096);
  819. {$ELSE}
  820. setlength(s, 4096);
  821. Result := X509NameOneline(X509GetIssuerName(cert), @s[0], Length(s));
  822. {$ENDIF}
  823. X509Free(cert);
  824. end;
  825. function TSSLOpenSSL.GetPeerFingerprint: string;
  826. var
  827. cert: PX509;
  828. x: integer;
  829. {$IFDEF CIL}
  830. sb: StringBuilder;
  831. {$ENDIF}
  832. begin
  833. if not assigned(FSsl) then
  834. begin
  835. Result := '';
  836. Exit;
  837. end;
  838. cert := SSLGetPeerCertificate(Fssl);
  839. if not assigned(cert) then
  840. begin
  841. Result := '';
  842. Exit;
  843. end;
  844. {$IFDEF CIL}
  845. sb := StringBuilder.Create(EVP_MAX_MD_SIZE);
  846. X509Digest(cert, EvpGetDigestByName('MD5'), sb, x);
  847. sb.Length := x;
  848. Result := sb.ToString;
  849. {$ELSE}
  850. setlength(Result, EVP_MAX_MD_SIZE);
  851. X509Digest(cert, EvpGetDigestByName('MD5'), Result, x);
  852. SetLength(Result, x);
  853. {$ENDIF}
  854. X509Free(cert);
  855. end;
  856. function TSSLOpenSSL.GetPeerFingerprintDigest(const ADigest: string): string;
  857. var
  858. cert: PX509;
  859. x: integer;
  860. begin
  861. if not assigned(FSsl) then
  862. begin
  863. Result := '';
  864. Exit;
  865. end;
  866. cert := SSLGetPeerCertificate(Fssl);
  867. if not assigned(cert) then
  868. begin
  869. Result := '';
  870. Exit;
  871. end;
  872. setlength(Result, 128);
  873. X509Digest(cert, EvpGetDigestByName(ADigest), Result, x);
  874. SetLength(Result, x);
  875. X509Free(cert);
  876. end;
  877. function TSSLOpenSSL.GetCertInfo: string;
  878. var
  879. cert: PX509;
  880. x, y: integer;
  881. b: PBIO;
  882. s: TBytes;
  883. {$IFDEF CIL}
  884. sb: stringbuilder;
  885. {$ENDIF}
  886. begin
  887. if not assigned(FSsl) then
  888. begin
  889. Result := '';
  890. Exit;
  891. end;
  892. cert := SSLGetPeerCertificate(Fssl);
  893. if not assigned(cert) then
  894. begin
  895. Result := '';
  896. Exit;
  897. end;
  898. try {pf}
  899. b := BioNew(BioSMem);
  900. try
  901. X509Print(b, cert);
  902. x := bioctrlpending(b);
  903. {$IFDEF CIL}
  904. sb := StringBuilder.Create(x);
  905. y := bioread(b, sb, x);
  906. if y > 0 then
  907. begin
  908. sb.Length := y;
  909. s := sb.ToString;
  910. end;
  911. {$ELSE}
  912. setlength(s,x);
  913. y := bioread(b,@s[0],x);
  914. if y > 0 then
  915. setlength(s, y);
  916. {$ENDIF}
  917. Result := ReplaceString(StringOf(s), LF, CRLF);
  918. finally
  919. BioFreeAll(b);
  920. end;
  921. {pf}
  922. finally
  923. X509Free(cert);
  924. end;
  925. {/pf}
  926. end;
  927. function TSSLOpenSSL.GetCipherName: string;
  928. begin
  929. if not assigned(FSsl) then
  930. Result := ''
  931. else
  932. Result := SslCipherGetName(SslGetCurrentCipher(FSsl));
  933. end;
  934. function TSSLOpenSSL.GetCipherBits: integer;
  935. var
  936. x: integer;
  937. begin
  938. if not assigned(FSsl) then
  939. Result := 0
  940. else
  941. Result := SSLCipherGetBits(SslGetCurrentCipher(FSsl), x);
  942. end;
  943. function TSSLOpenSSL.GetCipherAlgBits: integer;
  944. begin
  945. if not assigned(FSsl) then
  946. Result := 0
  947. else
  948. SSLCipherGetBits(SslGetCurrentCipher(FSsl), Result);
  949. end;
  950. function TSSLOpenSSL.GetVerifyCert: integer;
  951. begin
  952. if not assigned(FSsl) then
  953. Result := 1
  954. else
  955. Result := SslGetVerifyResult(FSsl);
  956. end;
  957. {==============================================================================}
  958. initialization
  959. if InitSSLInterface then
  960. SSLImplementation := TSSLOpenSSL;
  961. end.