ssl_openssl.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. {==============================================================================|
  2. | Project : Ararat Synapse | 001.004.001 |
  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;
  80. interface
  81. uses
  82. SysUtils, Classes,
  83. blcksock, synsock, synautil,
  84. {$IFDEF CIL}
  85. System.Text,
  86. {$ENDIF}
  87. {$IFDEF DELPHI23_UP}
  88. AnsiStrings,
  89. {$ENDIF}
  90. ssl_openssl_lib;
  91. type
  92. {:@abstract(class implementing OpenSSL SSL plugin.)
  93. Instance of this class will be created for each @link(TTCPBlockSocket).
  94. You not need to create instance of this class, all is done by Synapse itself!}
  95. TSSLOpenSSL = class(TCustomSSL)
  96. private
  97. FServer: boolean;
  98. protected
  99. FSsl: PSSL;
  100. Fctx: PSSL_CTX;
  101. function NeedSigningCertificate: boolean; virtual;
  102. function SSLCheck: Boolean;
  103. function SetSslKeys: boolean; virtual;
  104. function Init: Boolean;
  105. function DeInit: Boolean;
  106. function Prepare: Boolean;
  107. function LoadPFX(pfxdata: ansistring): Boolean;
  108. function CreateSelfSignedCert(Host: string): Boolean; override;
  109. property Server: boolean read FServer;
  110. public
  111. {:See @inherited}
  112. constructor Create(const Value: TTCPBlockSocket); override;
  113. destructor Destroy; override;
  114. {:See @inherited}
  115. function LibVersion: String; override;
  116. {:See @inherited}
  117. function LibName: String; override;
  118. {:See @inherited and @link(ssl_cryptlib) for more details.}
  119. function Connect: boolean; override;
  120. {:See @inherited and @link(ssl_cryptlib) for more details.}
  121. function Accept: boolean; override;
  122. {:See @inherited}
  123. function Shutdown: boolean; override;
  124. {:See @inherited}
  125. function BiShutdown: boolean; override;
  126. {:See @inherited}
  127. function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override;
  128. {:See @inherited}
  129. function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
  130. {:See @inherited}
  131. function WaitingData: Integer; override;
  132. {:See @inherited}
  133. function GetSSLVersion: string; override;
  134. {:See @inherited}
  135. function GetPeerSubject: string; override;
  136. {:See @inherited}
  137. function GetPeerSerialNo: integer; override; {pf}
  138. {:See @inherited}
  139. function GetPeerIssuer: string; override;
  140. {:See @inherited}
  141. function GetPeerName: string; override;
  142. {:See @inherited}
  143. function GetPeerNameHash: cardinal; override; {pf}
  144. {:See @inherited}
  145. function GetPeerFingerprint: ansistring; override;
  146. {:See @inherited}
  147. function GetCertInfo: string; override;
  148. {:See @inherited}
  149. function GetCipherName: string; override;
  150. {:See @inherited}
  151. function GetCipherBits: integer; override;
  152. {:See @inherited}
  153. function GetCipherAlgBits: integer; override;
  154. {:See @inherited}
  155. function GetVerifyCert: integer; override;
  156. end;
  157. implementation
  158. {==============================================================================}
  159. {$IFNDEF CIL}
  160. function PasswordCallback(buf:PAnsiChar; size:Integer; rwflag:Integer; userdata: Pointer):Integer; cdecl;
  161. var
  162. Password: AnsiString;
  163. begin
  164. Password := '';
  165. if TCustomSSL(userdata) is TCustomSSL then
  166. Password := TCustomSSL(userdata).KeyPassword;
  167. if Length(Password) > (Size - 1) then
  168. SetLength(Password, Size - 1);
  169. Result := Length(Password);
  170. {$IFDEF DELPHI23_UP}AnsiStrings.{$ENDIF}StrLCopy(buf, PAnsiChar(Password + #0), Result + 1);
  171. end;
  172. {$ENDIF}
  173. {==============================================================================}
  174. constructor TSSLOpenSSL.Create(const Value: TTCPBlockSocket);
  175. begin
  176. inherited Create(Value);
  177. FCiphers := 'DEFAULT';
  178. FSsl := nil;
  179. Fctx := nil;
  180. end;
  181. destructor TSSLOpenSSL.Destroy;
  182. begin
  183. DeInit;
  184. inherited Destroy;
  185. end;
  186. function TSSLOpenSSL.LibVersion: String;
  187. begin
  188. Result := SSLeayversion(0);
  189. end;
  190. function TSSLOpenSSL.LibName: String;
  191. begin
  192. Result := 'ssl_openssl';
  193. end;
  194. function TSSLOpenSSL.SSLCheck: Boolean;
  195. var
  196. {$IFDEF CIL}
  197. sb: StringBuilder;
  198. {$ENDIF}
  199. s : AnsiString;
  200. begin
  201. Result := true;
  202. FLastErrorDesc := '';
  203. FLastError := ErrGetError;
  204. ErrClearError;
  205. if FLastError <> 0 then
  206. begin
  207. Result := False;
  208. {$IFDEF CIL}
  209. sb := StringBuilder.Create(256);
  210. ErrErrorString(FLastError, sb, 256);
  211. FLastErrorDesc := Trim(sb.ToString);
  212. {$ELSE}
  213. s := StringOfChar(#0, 256);
  214. ErrErrorString(FLastError, s, Length(s));
  215. FLastErrorDesc := s;
  216. {$ENDIF}
  217. end;
  218. end;
  219. function TSSLOpenSSL.CreateSelfSignedCert(Host: string): Boolean;
  220. var
  221. pk: EVP_PKEY;
  222. x: PX509;
  223. rsa: PRSA;
  224. t: PASN1_UTCTIME;
  225. name: PX509_NAME;
  226. b: PBIO;
  227. xn, y: integer;
  228. s: AnsiString;
  229. {$IFDEF CIL}
  230. sb: StringBuilder;
  231. {$ENDIF}
  232. begin
  233. Result := True;
  234. pk := EvpPkeynew;
  235. x := X509New;
  236. try
  237. rsa := RsaGenerateKey(2048, $10001, nil, nil);
  238. EvpPkeyAssign(pk, EVP_PKEY_RSA, rsa);
  239. X509SetVersion(x, 2);
  240. Asn1IntegerSet(X509getSerialNumber(x), 0);
  241. t := Asn1UtctimeNew;
  242. try
  243. X509GmtimeAdj(t, -60 * 60 *24);
  244. X509SetNotBefore(x, t);
  245. X509GmtimeAdj(t, 60 * 60 * 60 *24);
  246. X509SetNotAfter(x, t);
  247. finally
  248. Asn1UtctimeFree(t);
  249. end;
  250. X509SetPubkey(x, pk);
  251. Name := X509GetSubjectName(x);
  252. X509NameAddEntryByTxt(Name, 'C', $1001, 'CZ', -1, -1, 0);
  253. X509NameAddEntryByTxt(Name, 'CN', $1001, host, -1, -1, 0);
  254. x509SetIssuerName(x, Name);
  255. x509Sign(x, pk, EvpGetDigestByName('SHA1'));
  256. b := BioNew(BioSMem);
  257. try
  258. i2dX509Bio(b, x);
  259. xn := bioctrlpending(b);
  260. {$IFDEF CIL}
  261. sb := StringBuilder.Create(xn);
  262. y := bioread(b, sb, xn);
  263. if y > 0 then
  264. begin
  265. sb.Length := y;
  266. s := sb.ToString;
  267. end;
  268. {$ELSE}
  269. setlength(s, xn);
  270. y := bioread(b, s, xn);
  271. if y > 0 then
  272. setlength(s, y);
  273. {$ENDIF}
  274. finally
  275. BioFreeAll(b);
  276. end;
  277. FCertificate := s;
  278. b := BioNew(BioSMem);
  279. try
  280. i2dPrivatekeyBio(b, pk);
  281. xn := bioctrlpending(b);
  282. {$IFDEF CIL}
  283. sb := StringBuilder.Create(xn);
  284. y := bioread(b, sb, xn);
  285. if y > 0 then
  286. begin
  287. sb.Length := y;
  288. s := sb.ToString;
  289. end;
  290. {$ELSE}
  291. setlength(s, xn);
  292. y := bioread(b, s, xn);
  293. if y > 0 then
  294. setlength(s, y);
  295. {$ENDIF}
  296. finally
  297. BioFreeAll(b);
  298. end;
  299. FPrivatekey := s;
  300. finally
  301. X509free(x);
  302. EvpPkeyFree(pk);
  303. end;
  304. end;
  305. function TSSLOpenSSL.LoadPFX(pfxdata: Ansistring): Boolean;
  306. var
  307. cert, pkey, ca: SslPtr;
  308. b: PBIO;
  309. p12: SslPtr;
  310. begin
  311. Result := False;
  312. b := BioNew(BioSMem);
  313. try
  314. BioWrite(b, pfxdata, Length(PfxData));
  315. p12 := d2iPKCS12bio(b, nil);
  316. if not Assigned(p12) then
  317. Exit;
  318. try
  319. cert := nil;
  320. pkey := nil;
  321. ca := nil;
  322. try {pf}
  323. if PKCS12parse(p12, FKeyPassword, pkey, cert, ca) > 0 then
  324. if SSLCTXusecertificate(Fctx, cert) > 0 then
  325. if SSLCTXusePrivateKey(Fctx, pkey) > 0 then
  326. Result := True;
  327. {pf}
  328. finally
  329. EvpPkeyFree(pkey);
  330. X509free(cert);
  331. SkX509PopFree(ca,_X509Free); // for ca=nil a new STACK was allocated...
  332. end;
  333. {/pf}
  334. finally
  335. PKCS12free(p12);
  336. end;
  337. finally
  338. BioFreeAll(b);
  339. end;
  340. end;
  341. function TSSLOpenSSL.SetSslKeys: boolean;
  342. var
  343. st: TFileStream;
  344. s: string;
  345. begin
  346. Result := False;
  347. if not assigned(FCtx) then
  348. Exit;
  349. try
  350. if FCertificateFile <> '' then
  351. if SslCtxUseCertificateChainFile(FCtx, FCertificateFile) <> 1 then
  352. if SslCtxUseCertificateFile(FCtx, FCertificateFile, SSL_FILETYPE_PEM) <> 1 then
  353. if SslCtxUseCertificateFile(FCtx, FCertificateFile, SSL_FILETYPE_ASN1) <> 1 then
  354. Exit;
  355. if FCertificate <> '' then
  356. if SslCtxUseCertificateASN1(FCtx, length(FCertificate), FCertificate) <> 1 then
  357. Exit;
  358. SSLCheck;
  359. if FPrivateKeyFile <> '' then
  360. if SslCtxUsePrivateKeyFile(FCtx, FPrivateKeyFile, SSL_FILETYPE_PEM) <> 1 then
  361. if SslCtxUsePrivateKeyFile(FCtx, FPrivateKeyFile, SSL_FILETYPE_ASN1) <> 1 then
  362. Exit;
  363. if FPrivateKey <> '' then
  364. if SslCtxUsePrivateKeyASN1(EVP_PKEY_RSA, FCtx, FPrivateKey, length(FPrivateKey)) <> 1 then
  365. Exit;
  366. SSLCheck;
  367. if FCertCAFile <> '' then
  368. if SslCtxLoadVerifyLocations(FCtx, FCertCAFile, '') <> 1 then
  369. Exit;
  370. if FPFXfile <> '' then
  371. begin
  372. try
  373. st := TFileStream.Create(FPFXfile, fmOpenRead or fmShareDenyNone);
  374. try
  375. s := ReadStrFromStream(st, st.Size);
  376. finally
  377. st.Free;
  378. end;
  379. if not LoadPFX(s) then
  380. Exit;
  381. except
  382. on Exception do
  383. Exit;
  384. end;
  385. end;
  386. if FPFX <> '' then
  387. if not LoadPFX(FPfx) then
  388. Exit;
  389. SSLCheck;
  390. Result := True;
  391. finally
  392. SSLCheck;
  393. end;
  394. end;
  395. function TSSLOpenSSL.NeedSigningCertificate: boolean;
  396. begin
  397. Result := (FCertificateFile = '') and (FCertificate = '') and (FPFXfile = '') and (FPFX = '');
  398. end;
  399. function TSSLOpenSSL.Init: Boolean;
  400. var
  401. s: AnsiString;
  402. begin
  403. Result := False;
  404. FLastErrorDesc := '';
  405. FLastError := 0;
  406. Fctx := nil;
  407. case FSSLType of
  408. LT_SSLv2:
  409. Fctx := SslCtxNew(SslMethodV2);
  410. LT_SSLv3:
  411. Fctx := SslCtxNew(SslMethodV3);
  412. LT_TLSv1:
  413. Fctx := SslCtxNew(SslMethodTLSV1);
  414. LT_TLSv1_1:
  415. Fctx := SslCtxNew(SslMethodTLSV11);
  416. LT_TLSv1_2:
  417. Fctx := SslCtxNew(SslMethodTLSV12);
  418. LT_all:
  419. begin
  420. //try new call for OpenSSL 1.1.0 first
  421. Fctx := SslCtxNew(SslMethodTLS);
  422. if Fctx=nil then
  423. //callback to previous versions
  424. Fctx := SslCtxNew(SslMethodV23);
  425. end;
  426. else
  427. Exit;
  428. end;
  429. if Fctx = nil then
  430. begin
  431. SSLCheck;
  432. Exit;
  433. end
  434. else
  435. begin
  436. s := FCiphers;
  437. SslCtxSetCipherList(Fctx, s);
  438. if FVerifyCert then
  439. SslCtxSetVerify(FCtx, SSL_VERIFY_PEER, nil)
  440. else
  441. SslCtxSetVerify(FCtx, SSL_VERIFY_NONE, nil);
  442. {$IFNDEF CIL}
  443. SslCtxSetDefaultPasswdCb(FCtx, @PasswordCallback);
  444. SslCtxSetDefaultPasswdCbUserdata(FCtx, self);
  445. {$ENDIF}
  446. if server and NeedSigningCertificate then
  447. begin
  448. CreateSelfSignedcert(FSocket.ResolveIPToName(FSocket.GetRemoteSinIP));
  449. end;
  450. if not SetSSLKeys then
  451. Exit
  452. else
  453. begin
  454. Fssl := nil;
  455. Fssl := SslNew(Fctx);
  456. if Fssl = nil then
  457. begin
  458. SSLCheck;
  459. exit;
  460. end;
  461. end;
  462. end;
  463. Result := true;
  464. end;
  465. function TSSLOpenSSL.DeInit: Boolean;
  466. begin
  467. Result := True;
  468. if Assigned(FSessionNew) then
  469. begin
  470. SslSessionFree(FSessionNew);
  471. FSessionNew := nil;
  472. end;
  473. if assigned (Fssl) then
  474. sslfree(Fssl);
  475. Fssl := nil;
  476. if assigned (Fctx) then
  477. begin
  478. SslCtxFree(Fctx);
  479. Fctx := nil;
  480. ErrRemoveState(0);
  481. end;
  482. FSSLEnabled := False;
  483. end;
  484. function TSSLOpenSSL.Prepare: Boolean;
  485. begin
  486. Result := false;
  487. DeInit;
  488. if Init then
  489. Result := true
  490. else
  491. DeInit;
  492. end;
  493. function TSSLOpenSSL.Connect: boolean;
  494. var
  495. x: integer;
  496. b: boolean;
  497. err: integer;
  498. begin
  499. Result := False;
  500. if FSocket.Socket = INVALID_SOCKET then
  501. Exit;
  502. FServer := False;
  503. if Prepare then
  504. begin
  505. {$IFDEF CIL}
  506. if sslsetfd(FSsl, FSocket.Socket.Handle.ToInt32) < 1 then
  507. {$ELSE}
  508. if sslsetfd(FSsl, FSocket.Socket) < 1 then
  509. {$ENDIF}
  510. begin
  511. SSLCheck;
  512. Exit;
  513. end;
  514. // Reuse session
  515. if Assigned(FSessionOld) then begin
  516. SslSetSession(Fssl, FSessionOld);
  517. end;
  518. if SNIHost<>'' then
  519. begin
  520. SSLCtrl(Fssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, PAnsiChar(AnsiString(SNIHost)));
  521. SslSet1Host(Fssl, PAnsiChar(AnsiString(SNIHost)));
  522. end;
  523. if FSocket.ConnectionTimeout <= 0 then //do blocking call of SSL_Connect
  524. begin
  525. x := sslconnect(FSsl);
  526. if x < 1 then
  527. begin
  528. SSLcheck;
  529. Exit;
  530. end;
  531. end
  532. else //do non-blocking call of SSL_Connect
  533. begin
  534. b := Fsocket.NonBlockMode;
  535. Fsocket.NonBlockMode := true;
  536. repeat
  537. x := sslconnect(FSsl);
  538. err := SslGetError(FSsl, x);
  539. if err = SSL_ERROR_WANT_READ then
  540. if not FSocket.CanRead(FSocket.ConnectionTimeout) then
  541. break;
  542. if err = SSL_ERROR_WANT_WRITE then
  543. if not FSocket.CanWrite(FSocket.ConnectionTimeout) then
  544. break;
  545. until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  546. Fsocket.NonBlockMode := b;
  547. if err <> SSL_ERROR_NONE then
  548. begin
  549. SSLcheck;
  550. Exit;
  551. end;
  552. end;
  553. if FverifyCert then
  554. if (GetVerifyCert <> 0) or (not DoVerifyCert) then
  555. Exit;
  556. FSSLEnabled := True;
  557. Result := True;
  558. end;
  559. if Result and (FSessionOld = nil) then begin
  560. FSessionNew := SslGet1Session(Fssl);
  561. end;
  562. end;
  563. function TSSLOpenSSL.Accept: boolean;
  564. var
  565. x: integer;
  566. begin
  567. Result := False;
  568. if FSocket.Socket = INVALID_SOCKET then
  569. Exit;
  570. FServer := True;
  571. if Prepare then
  572. begin
  573. {$IFDEF CIL}
  574. if sslsetfd(FSsl, FSocket.Socket.Handle.ToInt32) < 1 then
  575. {$ELSE}
  576. if sslsetfd(FSsl, FSocket.Socket) < 1 then
  577. {$ENDIF}
  578. begin
  579. SSLCheck;
  580. Exit;
  581. end;
  582. x := sslAccept(FSsl);
  583. if x < 1 then
  584. begin
  585. SSLcheck;
  586. Exit;
  587. end;
  588. FSSLEnabled := True;
  589. Result := True;
  590. end;
  591. end;
  592. function TSSLOpenSSL.Shutdown: boolean;
  593. begin
  594. if assigned(FSsl) then
  595. sslshutdown(FSsl);
  596. DeInit;
  597. Result := True;
  598. end;
  599. function TSSLOpenSSL.BiShutdown: boolean;
  600. var
  601. x: integer;
  602. begin
  603. if assigned(FSsl) then
  604. begin
  605. x := sslshutdown(FSsl);
  606. if x = 0 then
  607. begin
  608. Synsock.Shutdown(FSocket.Socket, 1);
  609. sslshutdown(FSsl);
  610. end;
  611. end;
  612. DeInit;
  613. Result := True;
  614. end;
  615. function TSSLOpenSSL.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
  616. var
  617. err: integer;
  618. {$IFDEF CIL}
  619. s: ansistring;
  620. {$ENDIF}
  621. begin
  622. FLastError := 0;
  623. FLastErrorDesc := '';
  624. repeat
  625. {$IFDEF CIL}
  626. s := StringOf(Buffer);
  627. Result := SslWrite(FSsl, s, Len);
  628. {$ELSE}
  629. Result := SslWrite(FSsl, Buffer , Len);
  630. {$ENDIF}
  631. err := SslGetError(FSsl, Result);
  632. until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  633. if err = SSL_ERROR_ZERO_RETURN then
  634. Result := 0
  635. else
  636. if (err <> 0) then
  637. FLastError := err;
  638. end;
  639. function TSSLOpenSSL.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
  640. var
  641. err: integer;
  642. {$IFDEF CIL}
  643. sb: stringbuilder;
  644. s: ansistring;
  645. {$ENDIF}
  646. begin
  647. FLastError := 0;
  648. FLastErrorDesc := '';
  649. repeat
  650. {$IFDEF CIL}
  651. sb := StringBuilder.Create(Len);
  652. Result := SslRead(FSsl, sb, Len);
  653. if Result > 0 then
  654. begin
  655. sb.Length := Result;
  656. s := sb.ToString;
  657. System.Array.Copy(BytesOf(s), Buffer, length(s));
  658. end;
  659. {$ELSE}
  660. Result := SslRead(FSsl, Buffer , Len);
  661. {$ENDIF}
  662. err := SslGetError(FSsl, Result);
  663. until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  664. if err = SSL_ERROR_ZERO_RETURN then
  665. Result := 0
  666. {pf}// Verze 1.1.0 byla s else tak jak to ted mam,
  667. // ve verzi 1.1.1 bylo ELSE zruseno, ale pak je SSL_ERROR_ZERO_RETURN
  668. // propagovano jako Chyba.
  669. {pf} else {/pf} if (err <> 0) then
  670. FLastError := err;
  671. end;
  672. function TSSLOpenSSL.WaitingData: Integer;
  673. begin
  674. Result := sslpending(Fssl);
  675. end;
  676. function TSSLOpenSSL.GetSSLVersion: string;
  677. begin
  678. if not assigned(FSsl) then
  679. Result := ''
  680. else
  681. Result := SSlGetVersion(FSsl);
  682. end;
  683. function TSSLOpenSSL.GetPeerSubject: string;
  684. var
  685. cert: PX509;
  686. s: ansistring;
  687. {$IFDEF CIL}
  688. sb: StringBuilder;
  689. {$ENDIF}
  690. begin
  691. if not assigned(FSsl) then
  692. begin
  693. Result := '';
  694. Exit;
  695. end;
  696. cert := SSLGetPeerCertificate(Fssl);
  697. if not assigned(cert) then
  698. begin
  699. Result := '';
  700. Exit;
  701. end;
  702. {$IFDEF CIL}
  703. sb := StringBuilder.Create(4096);
  704. Result := X509NameOneline(X509GetSubjectName(cert), sb, 4096);
  705. {$ELSE}
  706. setlength(s, 4096);
  707. Result := X509NameOneline(X509GetSubjectName(cert), s, Length(s));
  708. {$ENDIF}
  709. X509Free(cert);
  710. end;
  711. function TSSLOpenSSL.GetPeerSerialNo: integer; {pf}
  712. var
  713. cert: PX509;
  714. SN: PASN1_INTEGER;
  715. begin
  716. if not assigned(FSsl) then
  717. begin
  718. Result := -1;
  719. Exit;
  720. end;
  721. cert := SSLGetPeerCertificate(Fssl);
  722. try
  723. if not assigned(cert) then
  724. begin
  725. Result := -1;
  726. Exit;
  727. end;
  728. SN := X509GetSerialNumber(cert);
  729. Result := Asn1IntegerGet(SN);
  730. finally
  731. X509Free(cert);
  732. end;
  733. end;
  734. function TSSLOpenSSL.GetPeerName: string;
  735. var
  736. s: ansistring;
  737. begin
  738. s := GetPeerSubject;
  739. s := SeparateRight(s, '/CN=');
  740. Result := Trim(SeparateLeft(s, '/'));
  741. end;
  742. function TSSLOpenSSL.GetPeerNameHash: cardinal; {pf}
  743. var
  744. cert: PX509;
  745. begin
  746. if not assigned(FSsl) then
  747. begin
  748. Result := 0;
  749. Exit;
  750. end;
  751. cert := SSLGetPeerCertificate(Fssl);
  752. try
  753. if not assigned(cert) then
  754. begin
  755. Result := 0;
  756. Exit;
  757. end;
  758. Result := X509NameHash(X509GetSubjectName(cert));
  759. finally
  760. X509Free(cert);
  761. end;
  762. end;
  763. function TSSLOpenSSL.GetPeerIssuer: string;
  764. var
  765. cert: PX509;
  766. s: ansistring;
  767. {$IFDEF CIL}
  768. sb: StringBuilder;
  769. {$ENDIF}
  770. begin
  771. if not assigned(FSsl) then
  772. begin
  773. Result := '';
  774. Exit;
  775. end;
  776. cert := SSLGetPeerCertificate(Fssl);
  777. if not assigned(cert) then
  778. begin
  779. Result := '';
  780. Exit;
  781. end;
  782. {$IFDEF CIL}
  783. sb := StringBuilder.Create(4096);
  784. Result := X509NameOneline(X509GetIssuerName(cert), sb, 4096);
  785. {$ELSE}
  786. setlength(s, 4096);
  787. Result := X509NameOneline(X509GetIssuerName(cert), s, Length(s));
  788. {$ENDIF}
  789. X509Free(cert);
  790. end;
  791. function TSSLOpenSSL.GetPeerFingerprint: ansistring;
  792. var
  793. cert: PX509;
  794. x: integer;
  795. {$IFDEF CIL}
  796. sb: StringBuilder;
  797. {$ENDIF}
  798. begin
  799. if not assigned(FSsl) then
  800. begin
  801. Result := '';
  802. Exit;
  803. end;
  804. cert := SSLGetPeerCertificate(Fssl);
  805. if not assigned(cert) then
  806. begin
  807. Result := '';
  808. Exit;
  809. end;
  810. {$IFDEF CIL}
  811. sb := StringBuilder.Create(EVP_MAX_MD_SIZE);
  812. X509Digest(cert, EvpGetDigestByName('MD5'), sb, x);
  813. sb.Length := x;
  814. Result := sb.ToString;
  815. {$ELSE}
  816. setlength(Result, EVP_MAX_MD_SIZE);
  817. X509Digest(cert, EvpGetDigestByName('MD5'), Result, x);
  818. SetLength(Result, x);
  819. {$ENDIF}
  820. X509Free(cert);
  821. end;
  822. function TSSLOpenSSL.GetCertInfo: string;
  823. var
  824. cert: PX509;
  825. x, y: integer;
  826. b: PBIO;
  827. s: AnsiString;
  828. {$IFDEF CIL}
  829. sb: stringbuilder;
  830. {$ENDIF}
  831. begin
  832. if not assigned(FSsl) then
  833. begin
  834. Result := '';
  835. Exit;
  836. end;
  837. cert := SSLGetPeerCertificate(Fssl);
  838. if not assigned(cert) then
  839. begin
  840. Result := '';
  841. Exit;
  842. end;
  843. try {pf}
  844. b := BioNew(BioSMem);
  845. try
  846. X509Print(b, cert);
  847. x := bioctrlpending(b);
  848. {$IFDEF CIL}
  849. sb := StringBuilder.Create(x);
  850. y := bioread(b, sb, x);
  851. if y > 0 then
  852. begin
  853. sb.Length := y;
  854. s := sb.ToString;
  855. end;
  856. {$ELSE}
  857. setlength(s,x);
  858. y := bioread(b,s,x);
  859. if y > 0 then
  860. setlength(s, y);
  861. {$ENDIF}
  862. Result := ReplaceString(s, LF, CRLF);
  863. finally
  864. BioFreeAll(b);
  865. end;
  866. {pf}
  867. finally
  868. X509Free(cert);
  869. end;
  870. {/pf}
  871. end;
  872. function TSSLOpenSSL.GetCipherName: string;
  873. begin
  874. if not assigned(FSsl) then
  875. Result := ''
  876. else
  877. Result := SslCipherGetName(SslGetCurrentCipher(FSsl));
  878. end;
  879. function TSSLOpenSSL.GetCipherBits: integer;
  880. var
  881. x: integer;
  882. begin
  883. if not assigned(FSsl) then
  884. Result := 0
  885. else
  886. Result := SSLCipherGetBits(SslGetCurrentCipher(FSsl), x);
  887. end;
  888. function TSSLOpenSSL.GetCipherAlgBits: integer;
  889. begin
  890. if not assigned(FSsl) then
  891. Result := 0
  892. else
  893. SSLCipherGetBits(SslGetCurrentCipher(FSsl), Result);
  894. end;
  895. function TSSLOpenSSL.GetVerifyCert: integer;
  896. begin
  897. if not assigned(FSsl) then
  898. Result := 1
  899. else
  900. Result := SslGetVerifyResult(FSsl);
  901. end;
  902. {==============================================================================}
  903. initialization
  904. if InitSSLInterface then
  905. SSLImplementation := TSSLOpenSSL;
  906. end.