ssl_openssl.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. {==============================================================================|
  2. | Project : Ararat Synapse | 001.001.000 |
  3. |==============================================================================|
  4. | Content: SSL support by OpenSSL |
  5. |==============================================================================|
  6. | Copyright (c)1999-2008, 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-2008. |
  37. | All Rights Reserved. |
  38. |==============================================================================|
  39. | Contributor(s): |
  40. |==============================================================================|
  41. | History: see HISTORY.HTM from distribution package |
  42. | (Found at URL: http://www.ararat.cz/synapse/) |
  43. |==============================================================================}
  44. //requires OpenSSL libraries!
  45. {:@abstract(SSL plugin for OpenSSL)
  46. You need OpenSSL libraries version 0.9.7. It can work with 0.9.6 too, but
  47. application mysteriously crashing when you are using freePascal on Linux.
  48. Use Kylix on Linux is OK! If you have version 0.9.7 on Linux, then I not see
  49. any problems with FreePascal.
  50. OpenSSL libraries are loaded dynamicly - you not need OpenSSl librares even you
  51. compile your application with this unit. SSL just not working when you not have
  52. OpenSSL libraries.
  53. This plugin have limited support for .NET too! Because is not possible to use
  54. callbacks with CDECL calling convention under .NET, is not supported
  55. key/certificate passwords and multithread locking. :-(
  56. For handling keys and certificates you can use this properties:
  57. @link(TCustomSSL.CertificateFile) for PEM or ASN1 DER (cer) format. @br
  58. @link(TCustomSSL.Certificate) for ASN1 DER format only. @br
  59. @link(TCustomSSL.PrivateKeyFile) for PEM or ASN1 DER (key) format. @br
  60. @link(TCustomSSL.PrivateKey) for ASN1 DER format only. @br
  61. @link(TCustomSSL.CertCAFile) for PEM CA certificate bundle. @br
  62. @link(TCustomSSL.PFXFile) for PFX format. @br
  63. @link(TCustomSSL.PFX) for PFX format from binary string. @br
  64. This plugin is capable to create Ad-Hoc certificates. When you start SSL/TLS
  65. server without explicitly assigned key and certificate, then this plugin create
  66. Ad-Hoc key and certificate for each incomming connection by self. It slowdown
  67. accepting of new connections!
  68. }
  69. {$IFDEF FPC}
  70. {$MODE DELPHI}
  71. {$ENDIF}
  72. {$H+}
  73. unit ssl_openssl;
  74. interface
  75. uses
  76. SysUtils, Classes,
  77. blcksock, synsock, synautil,
  78. {$IFDEF CIL}
  79. System.Text,
  80. {$ENDIF}
  81. ssl_openssl_lib;
  82. type
  83. {:@abstract(class implementing OpenSSL SSL plugin.)
  84. Instance of this class will be created for each @link(TTCPBlockSocket).
  85. You not need to create instance of this class, all is done by Synapse itself!}
  86. TSSLOpenSSL = class(TCustomSSL)
  87. protected
  88. FSsl: PSSL;
  89. Fctx: PSSL_CTX;
  90. function SSLCheck: Boolean;
  91. function SetSslKeys: boolean;
  92. function Init(server:Boolean): Boolean;
  93. function DeInit: Boolean;
  94. function Prepare(server:Boolean): Boolean;
  95. function LoadPFX(pfxdata: ansistring): Boolean;
  96. function CreateSelfSignedCert(Host: string): Boolean; override;
  97. public
  98. {:See @inherited}
  99. constructor Create(const Value: TTCPBlockSocket); override;
  100. destructor Destroy; override;
  101. {:See @inherited}
  102. function LibVersion: String; override;
  103. {:See @inherited}
  104. function LibName: String; override;
  105. {:See @inherited and @link(ssl_cryptlib) for more details.}
  106. function Connect: boolean; override;
  107. {:See @inherited and @link(ssl_cryptlib) for more details.}
  108. function Accept: boolean; override;
  109. {:See @inherited}
  110. function Shutdown: boolean; override;
  111. {:See @inherited}
  112. function BiShutdown: boolean; override;
  113. {:See @inherited}
  114. function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override;
  115. {:See @inherited}
  116. function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
  117. {:See @inherited}
  118. function WaitingData: Integer; override;
  119. {:See @inherited}
  120. function GetSSLVersion: string; override;
  121. {:See @inherited}
  122. function GetPeerSubject: string; override;
  123. {:See @inherited}
  124. function GetPeerIssuer: string; override;
  125. {:See @inherited}
  126. function GetPeerName: string; override;
  127. {:See @inherited}
  128. function GetPeerFingerprint: string; override;
  129. {:See @inherited}
  130. function GetCertInfo: string; override;
  131. {:See @inherited}
  132. function GetCipherName: string; override;
  133. {:See @inherited}
  134. function GetCipherBits: integer; override;
  135. {:See @inherited}
  136. function GetCipherAlgBits: integer; override;
  137. {:See @inherited}
  138. function GetVerifyCert: integer; override;
  139. end;
  140. implementation
  141. {==============================================================================}
  142. {$IFNDEF CIL}
  143. function PasswordCallback(buf:PAnsiChar; size:Integer; rwflag:Integer; userdata: Pointer):Integer; cdecl;
  144. var
  145. Password: AnsiString;
  146. begin
  147. Password := '';
  148. if TCustomSSL(userdata) is TCustomSSL then
  149. Password := TCustomSSL(userdata).KeyPassword;
  150. if Length(Password) > (Size - 1) then
  151. SetLength(Password, Size - 1);
  152. Result := Length(Password);
  153. StrLCopy(buf, PAnsiChar(Password + #0), Result + 1);
  154. end;
  155. {$ENDIF}
  156. {==============================================================================}
  157. constructor TSSLOpenSSL.Create(const Value: TTCPBlockSocket);
  158. begin
  159. inherited Create(Value);
  160. FCiphers := 'DEFAULT';
  161. FSsl := nil;
  162. Fctx := nil;
  163. end;
  164. destructor TSSLOpenSSL.Destroy;
  165. begin
  166. DeInit;
  167. inherited Destroy;
  168. end;
  169. function TSSLOpenSSL.LibVersion: String;
  170. begin
  171. Result := SSLeayversion(0);
  172. end;
  173. function TSSLOpenSSL.LibName: String;
  174. begin
  175. Result := 'ssl_openssl';
  176. end;
  177. function TSSLOpenSSL.SSLCheck: Boolean;
  178. var
  179. {$IFDEF CIL}
  180. sb: StringBuilder;
  181. {$ENDIF}
  182. s : AnsiString;
  183. begin
  184. Result := true;
  185. FLastErrorDesc := '';
  186. FLastError := ErrGetError;
  187. ErrClearError;
  188. if FLastError <> 0 then
  189. begin
  190. Result := False;
  191. {$IFDEF CIL}
  192. sb := StringBuilder.Create(256);
  193. ErrErrorString(FLastError, sb, 256);
  194. FLastErrorDesc := Trim(sb.ToString);
  195. {$ELSE}
  196. s := StringOfChar(#0, 256);
  197. ErrErrorString(FLastError, s, Length(s));
  198. FLastErrorDesc := s;
  199. {$ENDIF}
  200. end;
  201. end;
  202. function TSSLOpenSSL.CreateSelfSignedCert(Host: string): Boolean;
  203. var
  204. pk: EVP_PKEY;
  205. x: PX509;
  206. rsa: PRSA;
  207. t: PASN1_UTCTIME;
  208. name: PX509_NAME;
  209. b: PBIO;
  210. xn, y: integer;
  211. s: AnsiString;
  212. {$IFDEF CIL}
  213. sb: StringBuilder;
  214. {$ENDIF}
  215. begin
  216. Result := True;
  217. pk := EvpPkeynew;
  218. x := X509New;
  219. try
  220. rsa := RsaGenerateKey(1024, $10001, nil, nil);
  221. EvpPkeyAssign(pk, EVP_PKEY_RSA, rsa);
  222. X509SetVersion(x, 2);
  223. Asn1IntegerSet(X509getSerialNumber(x), 0);
  224. t := Asn1UtctimeNew;
  225. try
  226. X509GmtimeAdj(t, -60 * 60 *24);
  227. X509SetNotBefore(x, t);
  228. X509GmtimeAdj(t, 60 * 60 * 60 *24);
  229. X509SetNotAfter(x, t);
  230. finally
  231. Asn1UtctimeFree(t);
  232. end;
  233. X509SetPubkey(x, pk);
  234. Name := X509GetSubjectName(x);
  235. X509NameAddEntryByTxt(Name, 'C', $1001, 'CZ', -1, -1, 0);
  236. X509NameAddEntryByTxt(Name, 'CN', $1001, host, -1, -1, 0);
  237. x509SetIssuerName(x, Name);
  238. x509Sign(x, pk, EvpGetDigestByName('SHA1'));
  239. b := BioNew(BioSMem);
  240. try
  241. i2dX509Bio(b, x);
  242. xn := bioctrlpending(b);
  243. {$IFDEF CIL}
  244. sb := StringBuilder.Create(xn);
  245. y := bioread(b, sb, xn);
  246. if y > 0 then
  247. begin
  248. sb.Length := y;
  249. s := sb.ToString;
  250. end;
  251. {$ELSE}
  252. setlength(s, xn);
  253. y := bioread(b, s, xn);
  254. if y > 0 then
  255. setlength(s, y);
  256. {$ENDIF}
  257. finally
  258. BioFreeAll(b);
  259. end;
  260. FCertificate := s;
  261. b := BioNew(BioSMem);
  262. try
  263. i2dPrivatekeyBio(b, pk);
  264. xn := bioctrlpending(b);
  265. {$IFDEF CIL}
  266. sb := StringBuilder.Create(xn);
  267. y := bioread(b, sb, xn);
  268. if y > 0 then
  269. begin
  270. sb.Length := y;
  271. s := sb.ToString;
  272. end;
  273. {$ELSE}
  274. setlength(s, xn);
  275. y := bioread(b, s, xn);
  276. if y > 0 then
  277. setlength(s, y);
  278. {$ENDIF}
  279. finally
  280. BioFreeAll(b);
  281. end;
  282. FPrivatekey := s;
  283. finally
  284. X509free(x);
  285. EvpPkeyFree(pk);
  286. end;
  287. end;
  288. function TSSLOpenSSL.LoadPFX(pfxdata: Ansistring): Boolean;
  289. var
  290. cert, pkey, ca: SslPtr;
  291. b: PBIO;
  292. p12: SslPtr;
  293. begin
  294. Result := False;
  295. b := BioNew(BioSMem);
  296. try
  297. BioWrite(b, pfxdata, Length(PfxData));
  298. p12 := d2iPKCS12bio(b, nil);
  299. if not Assigned(p12) then
  300. Exit;
  301. try
  302. cert := nil;
  303. pkey := nil;
  304. ca := nil;
  305. if PKCS12parse(p12, FKeyPassword, pkey, cert, ca) > 0 then
  306. if SSLCTXusecertificate(Fctx, cert) > 0 then
  307. if SSLCTXusePrivateKey(Fctx, pkey) > 0 then
  308. Result := True;
  309. finally
  310. PKCS12free(p12);
  311. end;
  312. finally
  313. BioFreeAll(b);
  314. end;
  315. end;
  316. function TSSLOpenSSL.SetSslKeys: boolean;
  317. var
  318. st: TFileStream;
  319. s: string;
  320. begin
  321. Result := False;
  322. if not assigned(FCtx) then
  323. Exit;
  324. try
  325. if FCertificateFile <> '' then
  326. if SslCtxUseCertificateChainFile(FCtx, FCertificateFile) <> 1 then
  327. if SslCtxUseCertificateFile(FCtx, FCertificateFile, SSL_FILETYPE_PEM) <> 1 then
  328. if SslCtxUseCertificateFile(FCtx, FCertificateFile, SSL_FILETYPE_ASN1) <> 1 then
  329. Exit;
  330. if FCertificate <> '' then
  331. if SslCtxUseCertificateASN1(FCtx, length(FCertificate), FCertificate) <> 1 then
  332. Exit;
  333. SSLCheck;
  334. if FPrivateKeyFile <> '' then
  335. if SslCtxUsePrivateKeyFile(FCtx, FPrivateKeyFile, SSL_FILETYPE_PEM) <> 1 then
  336. if SslCtxUsePrivateKeyFile(FCtx, FPrivateKeyFile, SSL_FILETYPE_ASN1) <> 1 then
  337. Exit;
  338. if FPrivateKey <> '' then
  339. if SslCtxUsePrivateKeyASN1(EVP_PKEY_RSA, FCtx, FPrivateKey, length(FPrivateKey)) <> 1 then
  340. Exit;
  341. SSLCheck;
  342. if FCertCAFile <> '' then
  343. if SslCtxLoadVerifyLocations(FCtx, FCertCAFile, '') <> 1 then
  344. Exit;
  345. if FPFXfile <> '' then
  346. begin
  347. try
  348. st := TFileStream.Create(FPFXfile, fmOpenRead or fmShareDenyNone);
  349. try
  350. s := ReadStrFromStream(st, st.Size);
  351. finally
  352. st.Free;
  353. end;
  354. if not LoadPFX(s) then
  355. Exit;
  356. except
  357. on Exception do
  358. Exit;
  359. end;
  360. end;
  361. if FPFX <> '' then
  362. if not LoadPFX(FPfx) then
  363. Exit;
  364. SSLCheck;
  365. Result := True;
  366. finally
  367. SSLCheck;
  368. end;
  369. end;
  370. function TSSLOpenSSL.Init(server:Boolean): Boolean;
  371. var
  372. s: AnsiString;
  373. begin
  374. Result := False;
  375. FLastErrorDesc := '';
  376. FLastError := 0;
  377. Fctx := nil;
  378. case FSSLType of
  379. LT_SSLv2:
  380. Fctx := SslCtxNew(SslMethodV2);
  381. LT_SSLv3:
  382. Fctx := SslCtxNew(SslMethodV3);
  383. LT_TLSv1:
  384. Fctx := SslCtxNew(SslMethodTLSV1);
  385. LT_all:
  386. Fctx := SslCtxNew(SslMethodV23);
  387. else
  388. Exit;
  389. end;
  390. if Fctx = nil then
  391. begin
  392. SSLCheck;
  393. Exit;
  394. end
  395. else
  396. begin
  397. s := FCiphers;
  398. SslCtxSetCipherList(Fctx, s);
  399. if FVerifyCert then
  400. SslCtxSetVerify(FCtx, SSL_VERIFY_PEER, nil)
  401. else
  402. SslCtxSetVerify(FCtx, SSL_VERIFY_NONE, nil);
  403. {$IFNDEF CIL}
  404. SslCtxSetDefaultPasswdCb(FCtx, @PasswordCallback);
  405. SslCtxSetDefaultPasswdCbUserdata(FCtx, self);
  406. {$ENDIF}
  407. if server and (FCertificateFile = '') and (FCertificate = '')
  408. and (FPFXfile = '') and (FPFX = '') then
  409. begin
  410. CreateSelfSignedcert(FSocket.ResolveIPToName(FSocket.GetRemoteSinIP));
  411. end;
  412. if not SetSSLKeys then
  413. Exit
  414. else
  415. begin
  416. Fssl := nil;
  417. Fssl := SslNew(Fctx);
  418. if Fssl = nil then
  419. begin
  420. SSLCheck;
  421. exit;
  422. end;
  423. end;
  424. end;
  425. Result := true;
  426. end;
  427. function TSSLOpenSSL.DeInit: Boolean;
  428. begin
  429. Result := True;
  430. if assigned (Fssl) then
  431. sslfree(Fssl);
  432. Fssl := nil;
  433. if assigned (Fctx) then
  434. begin
  435. SslCtxFree(Fctx);
  436. Fctx := nil;
  437. ErrRemoveState(0);
  438. end;
  439. FSSLEnabled := False;
  440. end;
  441. function TSSLOpenSSL.Prepare(server:Boolean): Boolean;
  442. begin
  443. Result := false;
  444. DeInit;
  445. if Init(server) then
  446. Result := true
  447. else
  448. DeInit;
  449. end;
  450. function TSSLOpenSSL.Connect: boolean;
  451. var
  452. x: integer;
  453. begin
  454. Result := False;
  455. if FSocket.Socket = INVALID_SOCKET then
  456. Exit;
  457. if Prepare(False) then
  458. begin
  459. {$IFDEF CIL}
  460. if sslsetfd(FSsl, FSocket.Socket.Handle.ToInt32) < 1 then
  461. {$ELSE}
  462. if sslsetfd(FSsl, FSocket.Socket) < 1 then
  463. {$ENDIF}
  464. begin
  465. SSLCheck;
  466. Exit;
  467. end;
  468. x := sslconnect(FSsl);
  469. if x < 1 then
  470. begin
  471. SSLcheck;
  472. Exit;
  473. end;
  474. if FverifyCert then
  475. if GetVerifyCert <> 0 then
  476. Exit;
  477. FSSLEnabled := True;
  478. Result := True;
  479. end;
  480. end;
  481. function TSSLOpenSSL.Accept: boolean;
  482. var
  483. x: integer;
  484. begin
  485. Result := False;
  486. if FSocket.Socket = INVALID_SOCKET then
  487. Exit;
  488. if Prepare(True) then
  489. begin
  490. {$IFDEF CIL}
  491. if sslsetfd(FSsl, FSocket.Socket.Handle.ToInt32) < 1 then
  492. {$ELSE}
  493. if sslsetfd(FSsl, FSocket.Socket) < 1 then
  494. {$ENDIF}
  495. begin
  496. SSLCheck;
  497. Exit;
  498. end;
  499. x := sslAccept(FSsl);
  500. if x < 1 then
  501. begin
  502. SSLcheck;
  503. Exit;
  504. end;
  505. FSSLEnabled := True;
  506. Result := True;
  507. end;
  508. end;
  509. function TSSLOpenSSL.Shutdown: boolean;
  510. begin
  511. if assigned(FSsl) then
  512. sslshutdown(FSsl);
  513. DeInit;
  514. Result := True;
  515. end;
  516. function TSSLOpenSSL.BiShutdown: boolean;
  517. var
  518. x: integer;
  519. begin
  520. if assigned(FSsl) then
  521. begin
  522. x := sslshutdown(FSsl);
  523. if x = 0 then
  524. begin
  525. Synsock.Shutdown(FSocket.Socket, 1);
  526. sslshutdown(FSsl);
  527. end;
  528. end;
  529. DeInit;
  530. Result := True;
  531. end;
  532. function TSSLOpenSSL.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
  533. var
  534. err: integer;
  535. {$IFDEF CIL}
  536. s: ansistring;
  537. {$ENDIF}
  538. begin
  539. FLastError := 0;
  540. FLastErrorDesc := '';
  541. repeat
  542. {$IFDEF CIL}
  543. s := StringOf(Buffer);
  544. Result := SslWrite(FSsl, s, Len);
  545. {$ELSE}
  546. Result := SslWrite(FSsl, Buffer , Len);
  547. {$ENDIF}
  548. err := SslGetError(FSsl, Result);
  549. until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  550. if err = SSL_ERROR_ZERO_RETURN then
  551. Result := 0
  552. else
  553. if (err <> 0) then
  554. FLastError := err;
  555. end;
  556. function TSSLOpenSSL.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
  557. var
  558. err: integer;
  559. {$IFDEF CIL}
  560. sb: stringbuilder;
  561. s: ansistring;
  562. {$ENDIF}
  563. begin
  564. FLastError := 0;
  565. FLastErrorDesc := '';
  566. repeat
  567. {$IFDEF CIL}
  568. sb := StringBuilder.Create(Len);
  569. Result := SslRead(FSsl, sb, Len);
  570. if Result > 0 then
  571. begin
  572. sb.Length := Result;
  573. s := sb.ToString;
  574. System.Array.Copy(BytesOf(s), Buffer, length(s));
  575. end;
  576. {$ELSE}
  577. Result := SslRead(FSsl, Buffer , Len);
  578. {$ENDIF}
  579. err := SslGetError(FSsl, Result);
  580. until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  581. if err = SSL_ERROR_ZERO_RETURN then
  582. Result := 0
  583. else
  584. if (err <> 0) then
  585. FLastError := err;
  586. end;
  587. function TSSLOpenSSL.WaitingData: Integer;
  588. begin
  589. Result := sslpending(Fssl);
  590. end;
  591. function TSSLOpenSSL.GetSSLVersion: string;
  592. begin
  593. if not assigned(FSsl) then
  594. Result := ''
  595. else
  596. Result := SSlGetVersion(FSsl);
  597. end;
  598. function TSSLOpenSSL.GetPeerSubject: string;
  599. var
  600. cert: PX509;
  601. s: ansistring;
  602. {$IFDEF CIL}
  603. sb: StringBuilder;
  604. {$ENDIF}
  605. begin
  606. if not assigned(FSsl) then
  607. begin
  608. Result := '';
  609. Exit;
  610. end;
  611. cert := SSLGetPeerCertificate(Fssl);
  612. if not assigned(cert) then
  613. begin
  614. Result := '';
  615. Exit;
  616. end;
  617. {$IFDEF CIL}
  618. sb := StringBuilder.Create(4096);
  619. Result := X509NameOneline(X509GetSubjectName(cert), sb, 4096);
  620. {$ELSE}
  621. setlength(s, 4096);
  622. Result := X509NameOneline(X509GetSubjectName(cert), s, Length(s));
  623. {$ENDIF}
  624. X509Free(cert);
  625. end;
  626. function TSSLOpenSSL.GetPeerName: string;
  627. var
  628. s: ansistring;
  629. begin
  630. s := GetPeerSubject;
  631. s := SeparateRight(s, '/CN=');
  632. Result := Trim(SeparateLeft(s, '/'));
  633. end;
  634. function TSSLOpenSSL.GetPeerIssuer: string;
  635. var
  636. cert: PX509;
  637. s: ansistring;
  638. {$IFDEF CIL}
  639. sb: StringBuilder;
  640. {$ENDIF}
  641. begin
  642. if not assigned(FSsl) then
  643. begin
  644. Result := '';
  645. Exit;
  646. end;
  647. cert := SSLGetPeerCertificate(Fssl);
  648. if not assigned(cert) then
  649. begin
  650. Result := '';
  651. Exit;
  652. end;
  653. {$IFDEF CIL}
  654. sb := StringBuilder.Create(4096);
  655. Result := X509NameOneline(X509GetIssuerName(cert), sb, 4096);
  656. {$ELSE}
  657. setlength(s, 4096);
  658. Result := X509NameOneline(X509GetIssuerName(cert), s, Length(s));
  659. {$ENDIF}
  660. X509Free(cert);
  661. end;
  662. function TSSLOpenSSL.GetPeerFingerprint: string;
  663. var
  664. cert: PX509;
  665. x: integer;
  666. {$IFDEF CIL}
  667. sb: StringBuilder;
  668. {$ENDIF}
  669. begin
  670. if not assigned(FSsl) then
  671. begin
  672. Result := '';
  673. Exit;
  674. end;
  675. cert := SSLGetPeerCertificate(Fssl);
  676. if not assigned(cert) then
  677. begin
  678. Result := '';
  679. Exit;
  680. end;
  681. {$IFDEF CIL}
  682. sb := StringBuilder.Create(EVP_MAX_MD_SIZE);
  683. X509Digest(cert, EvpGetDigestByName('MD5'), sb, x);
  684. sb.Length := x;
  685. Result := sb.ToString;
  686. {$ELSE}
  687. setlength(Result, EVP_MAX_MD_SIZE);
  688. X509Digest(cert, EvpGetDigestByName('MD5'), Result, x);
  689. SetLength(Result, x);
  690. {$ENDIF}
  691. X509Free(cert);
  692. end;
  693. function TSSLOpenSSL.GetCertInfo: string;
  694. var
  695. cert: PX509;
  696. x, y: integer;
  697. b: PBIO;
  698. s: AnsiString;
  699. {$IFDEF CIL}
  700. sb: stringbuilder;
  701. {$ENDIF}
  702. begin
  703. if not assigned(FSsl) then
  704. begin
  705. Result := '';
  706. Exit;
  707. end;
  708. cert := SSLGetPeerCertificate(Fssl);
  709. if not assigned(cert) then
  710. begin
  711. Result := '';
  712. Exit;
  713. end;
  714. b := BioNew(BioSMem);
  715. try
  716. X509Print(b, cert);
  717. x := bioctrlpending(b);
  718. {$IFDEF CIL}
  719. sb := StringBuilder.Create(x);
  720. y := bioread(b, sb, x);
  721. if y > 0 then
  722. begin
  723. sb.Length := y;
  724. s := sb.ToString;
  725. end;
  726. {$ELSE}
  727. setlength(s,x);
  728. y := bioread(b,s,x);
  729. if y > 0 then
  730. setlength(s, y);
  731. {$ENDIF}
  732. Result := ReplaceString(s, LF, CRLF);
  733. finally
  734. BioFreeAll(b);
  735. end;
  736. end;
  737. function TSSLOpenSSL.GetCipherName: string;
  738. begin
  739. if not assigned(FSsl) then
  740. Result := ''
  741. else
  742. Result := SslCipherGetName(SslGetCurrentCipher(FSsl));
  743. end;
  744. function TSSLOpenSSL.GetCipherBits: integer;
  745. var
  746. x: integer;
  747. begin
  748. if not assigned(FSsl) then
  749. Result := 0
  750. else
  751. Result := SSLCipherGetBits(SslGetCurrentCipher(FSsl), x);
  752. end;
  753. function TSSLOpenSSL.GetCipherAlgBits: integer;
  754. begin
  755. if not assigned(FSsl) then
  756. Result := 0
  757. else
  758. SSLCipherGetBits(SslGetCurrentCipher(FSsl), Result);
  759. end;
  760. function TSSLOpenSSL.GetVerifyCert: integer;
  761. begin
  762. if not assigned(FSsl) then
  763. Result := 1
  764. else
  765. Result := SslGetVerifyResult(FSsl);
  766. end;
  767. {==============================================================================}
  768. initialization
  769. if InitSSLInterface then
  770. SSLImplementation := TSSLOpenSSL;
  771. end.