IdSSLOpenSSL.pas 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 10337: IdSSLOpenSSL.pas
  11. {
  12. { Rev 1.3 2004-05-18 21:33:10 Mattias
  13. { Fixed unload bug
  14. }
  15. {
  16. { Rev 1.2 2004-05-07 16:33:46 Mattias
  17. { Minor fix properly releasing locking structure
  18. }
  19. {
  20. { Rev 1.1 2004-05-07 10:10:44 Mattias
  21. { Implemented OpenSSL locking callbacks for thread safity
  22. }
  23. {
  24. { Rev 1.0 2002.11.12 10:52:32 PM czhower
  25. }
  26. unit IdSSLOpenSSL;
  27. {
  28. Author: Gregor Ibic ([email protected])
  29. Copyright: (c) Gregor Ibic, Intelicom d.o.o and Indy Working Group.
  30. }
  31. interface
  32. uses
  33. Classes,
  34. IdException,
  35. IdStackConsts,
  36. IdSocketHandle,
  37. IdSSLOpenSSLHeaders,
  38. IdComponent,
  39. IdIOHandler,
  40. IdGlobal,
  41. IdTCPServer,
  42. IdThread,
  43. IdTCPConnection,
  44. IdIntercept, SysUtils,
  45. IdIOHandlerSocket,
  46. IdServerIOHandler,
  47. IdSocks;
  48. type
  49. TIdX509 = class;
  50. TIdSSLVersion = (sslvSSLv2, sslvSSLv23, sslvSSLv3, sslvTLSv1);
  51. TIdSSLMode = (sslmUnassigned, sslmClient, sslmServer, sslmBoth);
  52. TIdSSLVerifyMode = (sslvrfPeer, sslvrfFailIfNoPeerCert, sslvrfClientOnce);
  53. TIdSSLVerifyModeSet = set of TIdSSLVerifyMode;
  54. TIdSSLCtxMode = (sslCtxClient, sslCtxServer);
  55. TIdSSLAction = (sslRead, sslWrite);
  56. TULong = packed record
  57. case Byte of
  58. 0: (B1,B2,B3,B4: Byte);
  59. 1: (W1,W2: Word);
  60. 2: (L1: Longint);
  61. 3: (C1: Cardinal);
  62. end;
  63. TEVP_MD = record
  64. Length: Integer;
  65. MD: Array[0..OPENSSL_EVP_MAX_MD_SIZE-1] of Char;
  66. end;
  67. TByteArray = record
  68. Length: Integer;
  69. Data: PChar;
  70. End;
  71. TIdSSLIOHandlerSocket = class;
  72. TIdSSLCipher = class;
  73. TCallbackEvent = procedure(Msg: String) of object;
  74. TPasswordEvent = procedure(var Password: String) of object;
  75. TVerifyPeerEvent = function(Certificate: TIdX509): Boolean of object;
  76. TIOHandlerNotify = procedure(ASender: TIdSSLIOHandlerSocket) of object;
  77. TIdSSLOptions = class(TPersistent)
  78. protected
  79. fsRootCertFile, fsCertFile, fsKeyFile: TFileName;
  80. fMethod: TIdSSLVersion;
  81. fMode: TIdSSLMode;
  82. fVerifyDepth: Integer;
  83. fVerifyMode: TIdSSLVerifyModeSet;
  84. //fVerifyFile,
  85. fVerifyDirs, fCipherList: String;
  86. procedure AssignTo(ASource: TPersistent); override;
  87. published
  88. property RootCertFile: TFileName read fsRootCertFile write fsRootCertFile;
  89. property CertFile: TFileName read fsCertFile write fsCertFile;
  90. property KeyFile: TFileName read fsKeyFile write fsKeyFile;
  91. property Method: TIdSSLVersion read fMethod write fMethod;
  92. property Mode: TIdSSLMode read fMode write fMode;
  93. property VerifyMode: TIdSSLVerifyModeSet read fVerifyMode write fVerifyMode;
  94. property VerifyDepth: Integer read fVerifyDepth write fVerifyDepth;
  95. // property VerifyFile: String read fVerifyFile write fVerifyFile;
  96. property VerifyDirs: String read fVerifyDirs write fVerifyDirs;
  97. property CipherList: String read fCipherList write fCipherList;
  98. public
  99. // procedure Assign(ASource: TPersistent); override;
  100. end;
  101. TIdSSLContext = class(TObject)
  102. protected
  103. fMethod: TIdSSLVersion;
  104. fMode: TIdSSLMode;
  105. fsRootCertFile, fsCertFile, fsKeyFile: String;
  106. fVerifyDepth: Integer;
  107. fVerifyMode: TIdSSLVerifyModeSet;
  108. // fVerifyFile: String;
  109. fVerifyDirs: String;
  110. fCipherList: String;
  111. fContext: PSSL_CTX;
  112. fStatusInfoOn: Boolean;
  113. // fPasswordRoutineOn: Boolean;
  114. fVerifyOn: Boolean;
  115. fSessionId: Integer;
  116. fCtxMode: TIdSSLCtxMode;
  117. procedure DestroyContext;
  118. function SetSSLMethod: PSSL_METHOD;
  119. procedure SetVerifyMode(Mode: TIdSSLVerifyModeSet; CheckRoutine: Boolean);
  120. function GetVerifyMode: TIdSSLVerifyModeSet;
  121. procedure InitContext(CtxMode: TIdSSLCtxMode);
  122. public
  123. Parent: TObject;
  124. constructor Create;
  125. destructor Destroy; override;
  126. function LoadRootCert: Boolean;
  127. function LoadCert: Boolean;
  128. function LoadKey: Boolean;
  129. property StatusInfoOn: Boolean read fStatusInfoOn write fStatusInfoOn;
  130. // property PasswordRoutineOn: Boolean read fPasswordRoutineOn write fPasswordRoutineOn;
  131. property VerifyOn: Boolean read fVerifyOn write fVerifyOn;
  132. published
  133. property Method: TIdSSLVersion read fMethod write fMethod;
  134. property Mode: TIdSSLMode read fMode write fMode;
  135. property RootCertFile: String read fsRootCertFile write fsRootCertFile;
  136. property CertFile: String read fsCertFile write fsCertFile;
  137. property KeyFile: String read fsKeyFile write fsKeyFile;
  138. // property VerifyMode: TIdSSLVerifyModeSet read GetVerifyMode write SetVerifyMode;
  139. property VerifyMode: TIdSSLVerifyModeSet read fVerifyMode write fVerifyMode;
  140. property VerifyDepth: Integer read fVerifyDepth write fVerifyDepth;
  141. end;
  142. TIdSSLSocket = class(TObject)
  143. private
  144. fPeerCert: TIdX509;
  145. //fCipherList: String;
  146. fSSLCipher: TIdSSLCipher;
  147. fParent: TObject;
  148. fSSLContext: TIdSSLContext;
  149. function GetPeerCert: TIdX509;
  150. function GetSSLError(retCode: Integer): Integer;
  151. function GetSSLCipher: TIdSSLCipher;
  152. public
  153. fSSL: PSSL;
  154. //
  155. constructor Create(Parent: TObject);
  156. procedure Accept(const pHandle: TIdStackSocketHandle; fSSLContext: TIdSSLContext);
  157. procedure Connect(const pHandle: TIdStackSocketHandle; fSSLContext: TIdSSLContext);
  158. function Send(var ABuf; ALen: integer): integer;
  159. function Recv(var ABuf; ALen: integer): integer;
  160. destructor Destroy; override;
  161. function GetSessionID: TByteArray;
  162. function GetSessionIDAsString:String;
  163. procedure SetCipherList(CipherList: String);
  164. //
  165. property PeerCert: TIdX509 read GetPeerCert;
  166. property Cipher: TIdSSLCipher read GetSSLCipher;
  167. end;
  168. TIdSSLIOHandlerSocket = class(TIdIOHandlerSocket)
  169. private
  170. fSSLContext: TIdSSLContext;
  171. fxSSLOptions: TIdSSLOptions;
  172. fSSLSocket: TIdSSLSocket;
  173. fIsPeer: Boolean;
  174. //fPeerCert: TIdX509;
  175. fOnStatusInfo: TCallbackEvent;
  176. fOnGetPassword: TPasswordEvent;
  177. fOnVerifyPeer: TVerifyPeerEvent;
  178. fSSLLayerClosed: Boolean;
  179. fOnBeforeConnect: TIOHandlerNotify;
  180. // function GetPeerCert: TIdX509;
  181. //procedure CreateSSLContext(axMode: TIdSSLMode);
  182. fPassThrough: Boolean;
  183. //
  184. procedure SetPassThrough(const Value: Boolean);
  185. procedure Init;
  186. protected
  187. procedure DoBeforeConnect(ASender: TIdSSLIOHandlerSocket); virtual;
  188. procedure DoStatusInfo(Msg: String); virtual;
  189. procedure DoGetPassword(var Password: String); virtual;
  190. function DoVerifyPeer(Certificate: TIdX509): Boolean; virtual;
  191. function RecvEnc(var ABuf; ALen: integer): integer; virtual;
  192. function SendEnc(var ABuf; ALen: integer): integer; virtual;
  193. procedure OpenEncodedConnection; virtual;
  194. public
  195. constructor Create(AOwner: TComponent); override;
  196. destructor Destroy; override;
  197. procedure AfterAccept; override;
  198. procedure ConnectClient(const AHost: string; const APort: Integer; const ABoundIP: string;
  199. const ABoundPort: Integer; const ABoundPortMin: Integer; const ABoundPortMax: Integer;
  200. const ATimeout: Integer = IdTimeoutDefault); override;
  201. procedure Close; override;
  202. procedure Open; override;
  203. function Recv(var ABuf; ALen: integer): integer; override;
  204. function Send(var ABuf; ALen: integer): integer; override;
  205. property SSLSocket: TIdSSLSocket read fSSLSocket write fSSLSocket;
  206. property PassThrough: Boolean read fPassThrough write SetPassThrough;
  207. property OnBeforeConnect: TIOHandlerNotify read fOnBeforeConnect write fOnBeforeConnect;
  208. published
  209. property SSLOptions: TIdSSLOptions read fxSSLOptions write fxSSLOptions;
  210. property OnStatusInfo: TCallbackEvent read fOnStatusInfo write fOnStatusInfo;
  211. property OnGetPassword: TPasswordEvent read fOnGetPassword write fOnGetPassword;
  212. property OnVerifyPeer: TVerifyPeerEvent read fOnVerifyPeer write fOnVerifyPeer;
  213. end;
  214. TIdServerIOHandlerSSL = class(TIdServerIOHandler)
  215. private
  216. fSSLContext: TIdSSLContext;
  217. fxSSLOptions: TIdSSLOptions;
  218. // fPeerCert: TIdX509;
  219. // function GetPeerCert: TIdX509;
  220. fIsInitialized: Boolean;
  221. fOnStatusInfo: TCallbackEvent;
  222. fOnGetPassword: TPasswordEvent;
  223. fOnVerifyPeer: TVerifyPeerEvent;
  224. //procedure CreateSSLContext(axMode: TIdSSLMode);
  225. //procedure CreateSSLContext;
  226. protected
  227. procedure DoStatusInfo(Msg: String); virtual;
  228. procedure DoGetPassword(var Password: String); virtual;
  229. function DoVerifyPeer(Certificate: TIdX509): Boolean; virtual;
  230. public
  231. procedure Init; override;
  232. function Accept(ASocket: TIdStackSocketHandle; AThread: TIdThread = nil): TIdIOHandler; override;
  233. constructor Create(AOwner: TComponent); override;
  234. destructor Destroy; override;
  235. published
  236. property SSLOptions: TIdSSLOptions read fxSSLOptions write fxSSLOptions;
  237. property OnStatusInfo: TCallbackEvent read fOnStatusInfo write fOnStatusInfo;
  238. property OnGetPassword: TPasswordEvent read fOnGetPassword write fOnGetPassword;
  239. property OnVerifyPeer: TVerifyPeerEvent read fOnVerifyPeer write fOnVerifyPeer;
  240. end;
  241. TIdX509Name = class(TObject)
  242. private
  243. fX509Name: PX509_NAME;
  244. function CertInOneLine: String;
  245. function GetHash: TULong;
  246. function GetHashAsString: String;
  247. public
  248. constructor Create(aX509Name: PX509_NAME);
  249. //
  250. property Hash: TULong read GetHash;
  251. property HashAsString: string read GetHashAsString;
  252. property OneLine: string read CertInOneLine;
  253. end;
  254. TIdX509 = class(TObject)
  255. protected
  256. FX509 : PX509;
  257. FSubject : TIdX509Name;
  258. FIssuer : TIdX509Name;
  259. function RSubject:TIdX509Name;
  260. function RIssuer:TIdX509Name;
  261. function RnotBefore:TDateTime;
  262. function RnotAfter:TDateTime;
  263. function RFingerprint:TEVP_MD;
  264. function RFingerprintAsString:String;
  265. public
  266. Constructor Create(aX509: PX509); virtual;
  267. Destructor Destroy; override;
  268. //
  269. property Fingerprint: TEVP_MD read RFingerprint;
  270. property FingerprintAsString: String read RFingerprintAsString;
  271. property Subject: TIdX509Name read RSubject;
  272. property Issuer: TIdX509Name read RIssuer;
  273. property notBefore: TDateTime read RnotBefore;
  274. property notAfter: TDateTime read RnotAfter;
  275. end;
  276. TIdSSLCipher = class(TObject)
  277. private
  278. FSSLSocket: TIdSSLSocket;
  279. function GetDescription: String;
  280. function GetName: String;
  281. function GetBits: Integer;
  282. function GetVersion: String;
  283. public
  284. constructor Create(AOwner: TIdSSLSocket);
  285. destructor Destroy; override;
  286. published
  287. property Description: String read GetDescription;
  288. property Name: String read GetName;
  289. property Bits: Integer read GetBits;
  290. property Version: String read GetVersion;
  291. end;
  292. type
  293. EIdOpenSSLError = class(EIdException);
  294. EIdOpenSSLLoadError = class(EIdOpenSSLError);
  295. EIdOSSLCouldNotLoadSSLLibrary = class(EIdOpenSSLLoadError);
  296. EIdOSSLModeNotSet = class(EIdOpenSSLError);
  297. EIdOSSLGetMethodError = class(EIdOpenSSLError);
  298. EIdOSSLCreatingContextError = class(EIdOpenSSLError);
  299. EIdOSSLLoadingRootCertError = class(EIdOpenSSLLoadError);
  300. EIdOSSLLoadingCertError = class(EIdOpenSSLLoadError);
  301. EIdOSSLLoadingKeyError = class(EIdOpenSSLLoadError);
  302. EIdOSSLSettingCipherError = class(EIdOpenSSLError);
  303. EIdOSSLDataBindingError = class(EIdOpenSSLError);
  304. EIdOSSLAcceptError = class(EIdOpenSSLError);
  305. EIdOSSLConnectError = class(EIdOpenSSLError);
  306. function LogicalAnd(A, B: Integer): Boolean;
  307. procedure InfoCallback(sslSocket: PSSL; where: Integer; ret: Integer); cdecl;
  308. function PasswordCallback(buf:PChar; size:Integer; rwflag:Integer; userdata: Pointer):Integer; cdecl;
  309. function VerifyCallback(Ok: Integer; ctx: PX509_STORE_CTX):Integer; cdecl;
  310. implementation
  311. uses
  312. IdResourceStrings, SyncObjs;
  313. var
  314. DLLLoadCount: Integer = 0;
  315. LockInfoCB: TCriticalSection;
  316. LockPassCB: TCriticalSection;
  317. LockVerifyCB: TCriticalSection;
  318. CallbackLockList: TThreadList;
  319. //////////////////////////////////////////////////////////////
  320. // SSL SUPPORT FUNCTIONS
  321. //////////////////////////////////////////////////////////////
  322. //////////////////////////////////////////////////////////////
  323. // SSL CALLBACK ROUTINES
  324. //////////////////////////////////////////////////////////////
  325. function PasswordCallback(buf:PChar; size:Integer; rwflag:Integer; userdata: Pointer):Integer; cdecl;
  326. var
  327. Password: String;
  328. IdSSLContext: TIdSSLContext;
  329. begin
  330. LockPassCB.Enter;
  331. try
  332. Password := ''; {Do not Localize}
  333. IdSSLContext := TIdSSLContext(userdata);
  334. if (IdSSLContext.Parent is TIdSSLIOHandlerSocket) then begin
  335. TIdSSLIOHandlerSocket(IdSSLContext.Parent).DoGetPassword(Password);
  336. end;
  337. if (IdSSLContext.Parent is TIdServerIOHandlerSSL) then begin
  338. TIdServerIOHandlerSSL(IdSSLContext.Parent).DoGetPassword(Password);
  339. end;
  340. size := Length(Password);
  341. StrLCopy(buf, PChar(Password + #0), size + 1);
  342. Result := size;
  343. finally
  344. LockPassCB.Leave;
  345. end;
  346. end;
  347. procedure InfoCallback(sslSocket: PSSL; where: Integer; ret: Integer); cdecl;
  348. var
  349. IdSSLSocket: TIdSSLSocket;
  350. StatusStr : String;
  351. begin
  352. LockInfoCB.Enter;
  353. try
  354. IdSSLSocket := TIdSSLSocket(IdSslGetAppData(sslSocket));
  355. StatusStr := Format(RSOSSLStatusString, [StrPas(IdSslStateStringLong(sslSocket))]);
  356. if (IdSSLSocket.fParent is TIdSSLIOHandlerSocket) then begin
  357. TIdSSLIOHandlerSocket(IdSSLSocket.fParent).DoStatusInfo(StatusStr);
  358. end;
  359. if (IdSSLSocket.fParent is TIdServerIOHandlerSSL) then begin
  360. TIdServerIOHandlerSSL(IdSSLSocket.fParent).DoStatusInfo(StatusStr);
  361. end;
  362. finally
  363. LockInfoCB.Leave;
  364. end;
  365. end;
  366. {function RSACallback(sslSocket: PSSL; e: Integer; KeyLength: Integer):PRSA; cdecl;
  367. const
  368. RSA: PRSA = nil;
  369. var
  370. SSLSocket: TSSLWSocket;
  371. IdSSLSocket: TIdSSLSocket;
  372. begin
  373. IdSSLSocket := TIdSSLSocket(IdSslGetAppData(sslSocket));
  374. if Assigned(IdSSLSocket) then begin
  375. IdSSLSocket.TriggerSSLRSACallback(KeyLength);
  376. end;
  377. if not Assigned(RSA) then begin
  378. RSA := f_RSA_generate_key(KeyLength, RSA_F4, @RSAProgressCallback, ssl);
  379. end;
  380. Result := RSA;
  381. end;}
  382. function AddMins (const DT: TDateTime; const Mins: Extended): TDateTime;
  383. begin
  384. Result := DT + Mins / (60 * 24)
  385. end;
  386. function AddHrs (const DT: TDateTime; const Hrs: Extended): TDateTime;
  387. begin
  388. Result := DT + Hrs / 24.0
  389. end;
  390. {function GetLocalTZBias: LongInt;
  391. var
  392. TZ : TTimeZoneInformation;
  393. begin
  394. case GetTimeZoneInformation (TZ) of
  395. TIME_ZONE_ID_STANDARD: Result := TZ.Bias + TZ.StandardBias;
  396. TIME_ZONE_ID_DAYLIGHT: Result := TZ.Bias + TZ.DaylightBias;
  397. else
  398. Result := TZ.Bias;
  399. end;
  400. end;}
  401. function GetLocalTime (const DT: TDateTime): TDateTime;
  402. begin
  403. Result := DT - TimeZoneBias{ / (24 * 60)};
  404. end;
  405. procedure SslLockingCallback(mode, n : integer; Afile : PChar; line : integer) cdecl;
  406. var
  407. Lock : TCriticalSection;
  408. begin
  409. with CallbackLockList.LockList do
  410. try
  411. Lock := TCriticalSection(Items[n]);
  412. finally
  413. CallbackLockList.UnlockList;
  414. end;
  415. if (mode and OPENSSL_CRYPTO_LOCK) > 0 then
  416. Lock.Acquire
  417. else
  418. Lock.Release;
  419. end;
  420. procedure PrepareOpenSSLLocking;
  421. var
  422. i, cnt : integer;
  423. begin
  424. with CallbackLockList.LockList do
  425. try
  426. cnt := IdSslCryptoNumLocks;
  427. for i := 0 to cnt-1 do
  428. Add(TCriticalSection.Create);
  429. finally
  430. CallbackLockList.UnlockList;
  431. end;
  432. end;
  433. function _GetThreadID : integer cdecl;
  434. begin
  435. Result := GetCurrentThreadHandle;
  436. end;
  437. function LoadOpenSLLibrary: Boolean;
  438. begin
  439. if not IdSSLOpenSSLHeaders.Load then begin
  440. Result := False;
  441. Exit;
  442. end;
  443. InitializeRandom;
  444. // IdSslRandScreen;
  445. IdSslLoadErrorStrings;
  446. // Successful loading if true
  447. result := IdSslAddSslAlgorithms > 0;
  448. // Create locking structures, we need them for callback routines
  449. // they are probably not thread safe
  450. LockInfoCB := TCriticalSection.Create;
  451. LockPassCB := TCriticalSection.Create;
  452. LockVerifyCB := TCriticalSection.Create;
  453. // Handle internal OpenSSL locking
  454. CallbackLockList := TThreadList.Create;
  455. IdSslSetLockingCallback(SslLockingCallback);
  456. PrepareOpenSSLLocking;
  457. IdSslSetIdCallback(_GetThreadID);
  458. end;
  459. procedure UnLoadOpenSLLibrary;
  460. var
  461. i : integer;
  462. begin
  463. FreeAndNil(LockInfoCB);
  464. FreeAndNil(LockPassCB);
  465. FreeAndNil(LockVerifyCB);
  466. if Assigned(CallbackLockList) then
  467. begin
  468. with CallbackLockList.LockList do
  469. try
  470. for i := 0 to Count-1 do
  471. TObject(Items[i]).Free;
  472. Clear;
  473. finally
  474. CallbackLockList.UnlockList;
  475. end;
  476. FreeAndNil(CallbackLockList);
  477. end;
  478. IdSSLOpenSSLHeaders.Unload;
  479. end;
  480. function UTCTime2DateTime(UCTTime: PASN1_UTCTIME):TDateTime;
  481. var
  482. year : Word;
  483. month : Word;
  484. day : Word;
  485. hour : Word;
  486. min : Word;
  487. sec : Word;
  488. tz_h : Integer;
  489. tz_m : Integer;
  490. begin
  491. Result := 0;
  492. if IdSslUCTTimeDecode(UCTTime, year, month, day, hour, min, sec, tz_h, tz_m) > 0 Then Begin
  493. Result := EncodeDate(year, month, day) + EncodeTime(hour, min, sec, 0);
  494. AddMins(Result, tz_m);
  495. AddHrs(Result, tz_h);
  496. Result := GetLocalTime(Result);
  497. end;
  498. end;
  499. function TranslateInternalVerifyToSLL(Mode: TIdSSLVerifyModeSet): Integer;
  500. begin
  501. Result := OPENSSL_SSL_VERIFY_NONE;
  502. if sslvrfPeer in Mode then Result := Result or OPENSSL_SSL_VERIFY_PEER;
  503. if sslvrfFailIfNoPeerCert in Mode then Result:= Result or OPENSSL_SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
  504. if sslvrfClientOnce in Mode then Result:= Result or OPENSSL_SSL_VERIFY_CLIENT_ONCE;
  505. end;
  506. {function TranslateSLLVerifyToInternal(Mode: Integer): TIdSSLVerifyModeSet;
  507. begin
  508. Result := [];
  509. if LogicalAnd(Mode, OPENSSL_SSL_VERIFY_PEER) then Result := Result + [sslvrfPeer];
  510. if LogicalAnd(Mode, OPENSSL_SSL_VERIFY_FAIL_IF_NO_PEER_CERT) then Result := Result + [sslvrfFailIfNoPeerCert];
  511. if LogicalAnd(Mode, OPENSSL_SSL_VERIFY_CLIENT_ONCE) then Result := Result + [sslvrfClientOnce];
  512. end;}
  513. function LogicalAnd(A, B: Integer): Boolean;
  514. begin
  515. Result := (A and B) = B;
  516. end;
  517. function VerifyCallback(Ok: Integer; ctx: PX509_STORE_CTX): Integer; cdecl;
  518. var
  519. hcert: PX509;
  520. Certificate: TIdX509;
  521. hSSL: PSSL;
  522. IdSSLSocket: TIdSSLSocket;
  523. // str: String;
  524. VerifiedOK: Boolean;
  525. Depth: Integer;
  526. // Error: Integer;
  527. begin
  528. LockVerifyCB.Enter;
  529. try
  530. VerifiedOK := True;
  531. try
  532. hcert := IdSslX509StoreCtxGetCurrentCert(ctx);
  533. hSSL := IdSslX509StoreCtxGetAppData(ctx);
  534. Certificate := TIdX509.Create(hcert);
  535. if hSSL <> nil then begin
  536. IdSSLSocket := TIdSSLSocket(IdSslGetAppData(hSSL));
  537. end
  538. else begin
  539. Result := Ok;
  540. exit;
  541. end;
  542. //Error :=
  543. IdSslX509StoreCtxGetError(ctx);
  544. Depth := IdSslX509StoreCtxGetErrorDepth(ctx);
  545. // str := Format('Certificate: %s', [Certificate.Subject.OneLine]); {Do not Localize}
  546. // str := IdSSLSocket.GetSessionIDAsString;
  547. // ShowMessage(str);
  548. if (IdSSLSocket.fParent is TIdSSLIOHandlerSocket) then begin
  549. VerifiedOK := TIdSSLIOHandlerSocket(IdSSLSocket.fParent).DoVerifyPeer(Certificate);
  550. end;
  551. if (IdSSLSocket.fParent is TIdServerIOHandlerSSL) then begin
  552. VerifiedOK := TIdServerIOHandlerSSL(IdSSLSocket.fParent).DoVerifyPeer(Certificate);
  553. end;
  554. if not ((Ok>0) and (IdSSLSocket.fSSLContext.VerifyDepth>=Depth)) then begin
  555. Ok := 0;
  556. {if Error = OPENSSL_X509_V_OK then begin
  557. Error := OPENSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG;
  558. end;}
  559. end;
  560. FreeAndNil(Certificate);
  561. except
  562. end;
  563. if VerifiedOK and (Ok > 0) then begin
  564. Result := 1;
  565. end
  566. else begin
  567. Result := 0;
  568. end;
  569. // Result := Ok; // testing
  570. finally
  571. LockVerifyCB.Leave;
  572. end;
  573. end;
  574. //////////////////////////////////////////////////////
  575. // TIdSSLOptions
  576. ///////////////////////////////////////////////////////
  577. procedure TIdSSLOptions.AssignTo(ASource: TPersistent);
  578. begin
  579. if ASource is TIdSSLOptions then
  580. with TIdSSLOptions(ASource) do begin
  581. RootCertFile := Self.RootCertFile;
  582. CertFile := Self.CertFile;
  583. KeyFile := Self.KeyFile;
  584. Method := Self.Method;
  585. Mode := Self.Mode;
  586. VerifyMode := Self.VerifyMode;
  587. VerifyDepth := Self.VerifyDepth;
  588. VerifyDirs := Self.VerifyDirs;
  589. CipherList := Self.CipherList;
  590. end
  591. else
  592. inherited AssignTo(ASource);
  593. end;
  594. ///////////////////////////////////////////////////////
  595. // TIdServerIOHandlerSSL
  596. ///////////////////////////////////////////////////////
  597. { TIdServerIOHandlerSSL }
  598. constructor TIdServerIOHandlerSSL.Create(AOwner: TComponent);
  599. begin
  600. inherited Create(AOwner);
  601. fIsInitialized := False;
  602. fxSSLOptions := TIdSSLOptions.Create;
  603. end;
  604. destructor TIdServerIOHandlerSSL.Destroy;
  605. begin
  606. if fSSLContext <> nil then begin
  607. FreeAndNil(fSSLContext);
  608. end;
  609. FreeAndNil(fxSSLOptions);
  610. inherited Destroy;
  611. end;
  612. procedure TIdServerIOHandlerSSL.Init;
  613. begin
  614. // CreateSSLContext(SSLOptions.fMode);
  615. // CreateSSLContext;
  616. fSSLContext := TIdSSLContext.Create;
  617. with fSSLContext do begin
  618. Parent := self;
  619. RootCertFile := SSLOptions.RootCertFile;
  620. CertFile := SSLOptions.CertFile;
  621. KeyFile := SSLOptions.KeyFile;
  622. fVerifyDepth := SSLOptions.fVerifyDepth;
  623. fVerifyMode := SSLOptions.fVerifyMode;
  624. // fVerifyFile := SSLOptions.fVerifyFile;
  625. fVerifyDirs := SSLOptions.fVerifyDirs;
  626. fCipherList := SSLOptions.fCipherList;
  627. if Assigned(fOnVerifyPeer) then begin
  628. VerifyOn := True;
  629. end
  630. else begin
  631. VerifyOn := False;
  632. end;
  633. if Assigned(fOnStatusInfo) then begin
  634. StatusInfoOn := True;
  635. end
  636. else begin
  637. StatusInfoOn := False;
  638. end;
  639. {if Assigned(fOnGetPassword) then begin
  640. PasswordRoutineOn := True;
  641. end
  642. else begin
  643. PasswordRoutineOn := False;
  644. end;}
  645. fMethod := SSLOptions.Method;
  646. fMode := SSLOptions.Mode;
  647. fSSLContext.InitContext(sslCtxServer);
  648. end;
  649. fIsInitialized := True;
  650. end;
  651. function TIdServerIOHandlerSSL.Accept(ASocket: TIdStackSocketHandle; AThread: TIdThread = nil): TIdIOHandler;
  652. var
  653. tmpIdCIOpenSSL: TIdSSLIOHandlerSocket;
  654. begin
  655. if not fIsInitialized then begin
  656. Init;
  657. end;
  658. tmpIdCIOpenSSL := TIdSSLIOHandlerSocket.Create(nil); // Was self
  659. tmpIdCIOpenSSL.fIsPeer := True;
  660. tmpIdCIOpenSSL.Open;
  661. if tmpIdCIOpenSSL.Binding.Accept(ASocket) then begin
  662. tmpIdCIOpenSSL.fxSSLOptions.Assign(fxSSLOptions);
  663. tmpIdCIOpenSSL.fSSLSocket := TIdSSLSocket.Create(self);
  664. tmpIdCIOpenSSL.fSSLContext := fSSLContext;
  665. result := tmpIdCIOpenSSL;
  666. end
  667. else begin
  668. result := nil;
  669. FreeAndNil(tmpIdCIOpenSSL);
  670. end;
  671. end;
  672. procedure TIdServerIOHandlerSSL.DoStatusInfo(Msg: String);
  673. begin
  674. if Assigned(fOnStatusInfo) then
  675. fOnStatusInfo(Msg);
  676. end;
  677. procedure TIdServerIOHandlerSSL.DoGetPassword(var Password: String);
  678. begin
  679. if Assigned(fOnGetPassword) then
  680. fOnGetPassword(Password);
  681. end;
  682. function TIdServerIOHandlerSSL.DoVerifyPeer(Certificate: TIdX509): Boolean;
  683. begin
  684. Result := True;
  685. if Assigned(fOnVerifyPeer) then
  686. Result := fOnVerifyPeer(Certificate);
  687. end;
  688. ///////////////////////////////////////////////////////
  689. // TIdSSLIOHandlerSocket
  690. ///////////////////////////////////////////////////////
  691. { TIdSSLIOHandlerSocket }
  692. constructor TIdSSLIOHandlerSocket.Create(AOwner: TComponent);
  693. begin
  694. inherited Create(AOwner);
  695. fIsPeer := False;
  696. fxSSLOptions := TIdSSLOptions.Create;
  697. fSSLLayerClosed := True;
  698. end;
  699. destructor TIdSSLIOHandlerSocket.Destroy;
  700. begin
  701. FreeAndNil(fxSSLOptions); //Added
  702. FreeAndNil(fSSLSocket);
  703. // FreeAndNil(fSSLContext);
  704. if not fIsPeer then begin
  705. FreeAndNil(fSSLContext);
  706. end;
  707. inherited Destroy;
  708. end;
  709. procedure TIdSSLIOHandlerSocket.ConnectClient(const AHost: string; const APort: Integer; const ABoundIP: string;
  710. const ABoundPort: Integer; const ABoundPortMin: Integer; const ABoundPortMax: Integer;
  711. const ATimeout: Integer = IdTimeoutDefault);
  712. begin
  713. inherited ConnectClient(AHost, APort, ABoundIP, ABoundPort, ABoundPortMin, ABoundPortMax, ATimeout);
  714. DoBeforeConnect(self);
  715. // CreateSSLContext(sslmClient);
  716. // CreateSSLContext(SSLOptions.fMode);
  717. try
  718. Init;
  719. except
  720. on EIdOSSLCouldNotLoadSSLLibrary do begin
  721. if not PassThrough then raise;
  722. end;
  723. end;
  724. if not PassThrough then begin
  725. OpenEncodedConnection;
  726. end;
  727. end;
  728. procedure TIdSSLIOHandlerSocket.Close;
  729. begin
  730. FreeAndNil(fSSLSocket);
  731. if not fIsPeer then begin
  732. FreeAndNil(fSSLContext);
  733. end;
  734. inherited Close;
  735. end;
  736. procedure TIdSSLIOHandlerSocket.Open;
  737. begin
  738. inherited Open;
  739. end;
  740. function TIdSSLIOHandlerSocket.Recv(var ABuf; ALen: integer): integer;
  741. begin
  742. if fPassThrough then begin
  743. result := inherited Recv(ABuf, ALen);
  744. end
  745. else begin
  746. result := RecvEnc(ABuf, ALen);
  747. end;
  748. end;
  749. function TIdSSLIOHandlerSocket.Send(var ABuf; ALen: integer): integer;
  750. begin
  751. if fPassThrough then begin
  752. result := inherited Send(ABuf, ALen);
  753. end
  754. else begin
  755. result := SendEnc(ABuf, ALen);
  756. end;
  757. end;
  758. procedure TIdSSLIOHandlerSocket.SetPassThrough(const Value: Boolean);
  759. begin
  760. if not Value then begin
  761. if Connected then begin
  762. if Assigned(fSSLContext) then begin
  763. OpenEncodedConnection;
  764. end
  765. else begin
  766. raise EIdOSSLCouldNotLoadSSLLibrary.Create(RSOSSLCouldNotLoadSSLLibrary);
  767. end;
  768. end;
  769. end;
  770. fPassThrough := Value;
  771. end;
  772. function TIdSSLIOHandlerSocket.RecvEnc(var ABuf; ALen: integer): integer;
  773. begin
  774. Result := fSSLSocket.Recv(ABuf, ALen);
  775. end;
  776. function TIdSSLIOHandlerSocket.SendEnc(var ABuf; ALen: integer): integer;
  777. begin
  778. Result := fSSLSocket.Send(ABuf, ALen);
  779. end;
  780. procedure TIdSSLIOHandlerSocket.AfterAccept;
  781. begin
  782. try
  783. inherited AfterAccept;
  784. fSSLSocket.Accept(Binding.Handle, fSSLContext);
  785. except
  786. Close;
  787. raise;
  788. end;
  789. end;
  790. procedure TIdSSLIOHandlerSocket.Init;
  791. begin
  792. fSSLContext := TIdSSLContext.Create;
  793. with fSSLContext do begin
  794. Parent := self;
  795. RootCertFile := SSLOptions.RootCertFile;
  796. CertFile := SSLOptions.CertFile;
  797. KeyFile := SSLOptions.KeyFile;
  798. fVerifyDepth := SSLOptions.fVerifyDepth;
  799. fVerifyMode := SSLOptions.fVerifyMode;
  800. // fVerifyFile := SSLOptions.fVerifyFile;
  801. fVerifyDirs := SSLOptions.fVerifyDirs;
  802. fCipherList := SSLOptions.fCipherList;
  803. if Assigned(fOnVerifyPeer) then begin
  804. VerifyOn := True;
  805. end
  806. else begin
  807. VerifyOn := False;
  808. end;
  809. if Assigned(fOnStatusInfo) then begin
  810. StatusInfoOn := True;
  811. end
  812. else begin
  813. StatusInfoOn := False;
  814. end;
  815. {if Assigned(fOnGetPassword) then begin
  816. PasswordRoutineOn := True;
  817. end
  818. else begin
  819. PasswordRoutineOn := False;
  820. end;}
  821. fMethod := SSLOptions.Method;
  822. fMode := SSLOptions.Mode;
  823. fSSLContext.InitContext(sslCtxClient);
  824. end;
  825. {fSSLContext := TIdSSLContext.Create;
  826. with fSSLContext do begin
  827. Parent := self;
  828. RootCertFile := SSLOptions.RootCertFile;
  829. CertFile := SSLOptions.CertFile;
  830. KeyFile := SSLOptions.KeyFile;
  831. if Assigned(fOnStatusInfo) then begin
  832. StatusInfoOn := True;
  833. end
  834. else begin
  835. StatusInfoOn := False;
  836. end;
  837. if Assigned(fOnVerifyPeer) then begin
  838. VerifyOn := True;
  839. end
  840. else begin
  841. VerifyOn := False;
  842. end;
  843. // Must set mode after above props are set
  844. Method := SSLOptions.Method;
  845. Mode := axMode;
  846. end;}
  847. end;
  848. //}
  849. {function TIdSSLIOHandlerSocket.GetPeerCert: TIdX509;
  850. begin
  851. if fSSLContext <> nil then begin
  852. Result := fSSLSocket.PeerCert;
  853. end
  854. else begin
  855. Result := nil;
  856. end;
  857. end;}
  858. procedure TIdSSLIOHandlerSocket.DoStatusInfo(Msg: String);
  859. begin
  860. if Assigned(fOnStatusInfo) then
  861. fOnStatusInfo(Msg);
  862. end;
  863. procedure TIdSSLIOHandlerSocket.DoGetPassword(var Password: String);
  864. begin
  865. if Assigned(fOnGetPassword) then
  866. fOnGetPassword(Password);
  867. end;
  868. function TIdSSLIOHandlerSocket.DoVerifyPeer(Certificate: TIdX509): Boolean;
  869. begin
  870. Result := True;
  871. if Assigned(fOnVerifyPeer) then
  872. Result := fOnVerifyPeer(Certificate);
  873. end;
  874. procedure TIdSSLIOHandlerSocket.OpenEncodedConnection;
  875. begin
  876. if not Assigned(fSSLSocket) then
  877. begin
  878. fSSLSocket := TIdSSLSocket.Create(self);
  879. fSSLSocket.fSSLContext := fSSLContext;
  880. fSSLSocket.Connect(Binding.Handle, fSSLContext);
  881. end;
  882. end;
  883. procedure TIdSSLIOHandlerSocket.DoBeforeConnect(ASender: TIdSSLIOHandlerSocket);
  884. begin
  885. if Assigned(OnBeforeConnect) then begin
  886. OnBeforeConnect(Self);
  887. end;
  888. end;
  889. { TIdSSLContext }
  890. constructor TIdSSLContext.Create;
  891. begin
  892. inherited Create;
  893. if DLLLoadCount <= 0 then begin
  894. if not IdSSLOpenSSL.LoadOpenSLLibrary then begin
  895. raise EIdOSSLCouldNotLoadSSLLibrary.Create(RSOSSLCouldNotLoadSSLLibrary);
  896. end;
  897. end;
  898. Inc(DLLLoadCount);
  899. fVerifyMode := [];
  900. fMode := sslmUnassigned;
  901. fSessionId := 1;
  902. end;
  903. destructor TIdSSLContext.Destroy;
  904. begin
  905. DestroyContext;
  906. inherited Destroy;
  907. end;
  908. procedure TIdSSLContext.DestroyContext;
  909. begin
  910. if fContext <> nil then begin
  911. IdSslCtxFree(fContext);
  912. fContext := nil;
  913. end;
  914. end;
  915. procedure TIdSSLContext.InitContext(CtxMode: TIdSSLCtxMode);
  916. var
  917. SSLMethod: PSSL_METHOD;
  918. error: Integer;
  919. pCipherList, pRootCertFile: PChar;
  920. // pCAname: PSTACK_X509_NAME;
  921. begin
  922. // Destroy the context first
  923. DestroyContext;
  924. if fMode = sslmUnassigned then begin
  925. if CtxMode = sslCtxServer then begin
  926. fMode := sslmServer;
  927. end
  928. else begin
  929. fMode := sslmClient;
  930. end
  931. end;
  932. // get SSL method function (SSL2, SSL23, SSL3, TLS)
  933. SSLMethod := SetSSLMethod;
  934. // create new SSL context
  935. fContext := IdSslCtxNew(SSLMethod);
  936. if fContext = nil then begin
  937. raise EIdOSSLCreatingContextError.Create(RSSSLCreatingContextError);
  938. end;
  939. // assign a password lookup routine
  940. // if PasswordRoutineOn then begin
  941. IdSslCtxSetDefaultPasswdCb(fContext, @PasswordCallback);
  942. IdSslCtxSetDefaultPasswdCbUserdata(fContext, self);
  943. // end;
  944. IdSSLCtxSetDefaultVerifyPaths(fContext);
  945. // load key and certificate files
  946. if RootCertFile <> '' then begin {Do not Localize}
  947. if not LoadRootCert then begin
  948. raise EIdOSSLLoadingRootCertError.Create(RSSSLLoadingRootCertError);
  949. end;
  950. end;
  951. if CertFile <> '' then begin {Do not Localize}
  952. if not LoadCert then begin
  953. raise EIdOSSLLoadingCertError.Create(RSSSLLoadingCertError);
  954. end;
  955. end;
  956. if KeyFile <> '' then begin {Do not Localize}
  957. if not LoadKey then begin
  958. raise EIdOSSLLoadingKeyError.Create(RSSSLLoadingKeyError);
  959. end;
  960. end;
  961. if StatusInfoOn then begin
  962. IdSslCtxSetInfoCallback(fContext, PFunction(@InfoCallback));
  963. end;
  964. // f_SSL_CTX_set_tmp_rsa_callback(hSSLContext, @RSACallback);
  965. if fCipherList <> '' then begin {Do not Localize}
  966. pCipherList := StrNew(PChar(fCipherList));
  967. error := IdSslCtxSetCipherList(fContext, pCipherList);
  968. StrDispose(pCipherList);
  969. end
  970. else begin
  971. error := IdSslCtxSetCipherList(fContext, OPENSSL_SSL_DEFAULT_CIPHER_LIST);
  972. end;
  973. if error <= 0 then begin
  974. raise EIdOSSLSettingCipherError.Create(RSSSLSettingCipherError);
  975. end;
  976. if fVerifyMode <> [] then begin
  977. SetVerifyMode(fVerifyMode, VerifyOn);
  978. end;
  979. if CtxMode = sslCtxServer then begin
  980. IdSSLCtxSetSessionIdContext(fContext, PChar(@fSessionId), SizeOf(fSessionId));
  981. end;
  982. // CA list
  983. if RootCertFile <> '' then begin {Do not Localize}
  984. pRootCertFile := StrNew(PChar(RootCertFile));
  985. IdSSLCtxSetClientCAList(fContext, IdSSLLoadClientCAFile(pRootCertFile));
  986. StrDispose(pRootCertFile);
  987. end
  988. end;
  989. procedure TIdSSLContext.SetVerifyMode(Mode: TIdSSLVerifyModeSet; CheckRoutine: Boolean);
  990. begin
  991. if fContext<>nil then begin
  992. // IdSSLCtxSetDefaultVerifyPaths(fContext);
  993. if CheckRoutine then begin
  994. IdSslCtxSetVerify(fContext, TranslateInternalVerifyToSLL(Mode), PFunction(@VerifyCallback));
  995. end
  996. else begin
  997. IdSslCtxSetVerify(fContext, TranslateInternalVerifyToSLL(Mode), nil);
  998. end;
  999. IdSslCtxSetVerifyDepth(fContext, fVerifyDepth);
  1000. end;
  1001. end;
  1002. function TIdSSLContext.GetVerifyMode: TIdSSLVerifyModeSet;
  1003. begin
  1004. Result := fVerifyMode;
  1005. end;
  1006. {
  1007. function TIdSSLContext.LoadVerifyLocations(FileName: String; Dirs: String): Boolean;
  1008. var
  1009. pFileName, pDirs : PChar;
  1010. begin
  1011. Result := False;
  1012. pFileName := nil;
  1013. pDirs := nil;
  1014. if FileName <> '' then begin
  1015. pFileName := StrNew(PChar(FileName));
  1016. end;
  1017. if Dirs <> '' then begin
  1018. pDirs := StrNew(PChar(Dirs));
  1019. end;
  1020. If (pDirs<>nil) or (pFileName<>nil) Then begin
  1021. If IdSslCtxLoadVerifyLocations(fContext, pFileName, pDirs)<=0 Then Begin
  1022. raise EIdOSSLCouldNotLoadSSLLibrary.Create(RSOSSLCouldNotLoadSSLLibrary);
  1023. exit;
  1024. End;
  1025. end;
  1026. StrDispose(pFileName);
  1027. StrDispose(pDirs);
  1028. Result:=True;
  1029. End;
  1030. }
  1031. function TIdSSLContext.SetSSLMethod: PSSL_METHOD;
  1032. begin
  1033. if fMode = sslmUnassigned then begin
  1034. raise EIdOSSLModeNotSet.create(RSOSSLModeNotSet);
  1035. end;
  1036. case fMethod of
  1037. sslvSSLv2:
  1038. case fMode of
  1039. sslmServer : Result := IdSslMethodServerV2;
  1040. sslmClient : Result := IdSslMethodClientV2;
  1041. sslmBoth : Result := IdSslMethodV2;
  1042. else
  1043. Result := IdSslMethodV2;
  1044. end;
  1045. sslvSSLv23:
  1046. case fMode of
  1047. sslmServer : Result := IdSslMethodServerV23;
  1048. sslmClient : Result := IdSslMethodClientV23;
  1049. sslmBoth : Result := IdSslMethodV23;
  1050. else
  1051. Result := IdSslMethodV23;
  1052. end;
  1053. sslvSSLv3:
  1054. case fMode of
  1055. sslmServer : Result := IdSslMethodServerV3;
  1056. sslmClient : Result := IdSslMethodClientV3;
  1057. sslmBoth : Result := IdSslMethodV3;
  1058. else
  1059. Result := IdSslMethodV3;
  1060. end;
  1061. sslvTLSv1:
  1062. case fMode of
  1063. sslmServer : Result := IdSslMethodServerTLSV1;
  1064. sslmClient : Result := IdSslMethodClientTLSV1;
  1065. sslmBoth : Result := IdSslMethodTLSV1;
  1066. else
  1067. Result := IdSslMethodTLSV1;
  1068. end;
  1069. else
  1070. raise EIdOSSLGetMethodError.Create(RSSSLGetMethodError);
  1071. end;
  1072. end;
  1073. function TIdSSLContext.LoadRootCert: Boolean;
  1074. var
  1075. pStr: PChar;
  1076. error: Integer;
  1077. // pDirs : PChar;
  1078. begin
  1079. pStr := StrNew(PChar(RootCertFile));
  1080. { if fVerifyDirs <> '' then begin
  1081. pDirs := StrNew(PChar(fVerifyDirs));
  1082. error := IdSslCtxLoadVerifyLocations(
  1083. fContext,
  1084. pStr,
  1085. pDirs);
  1086. StrDispose(pDirs);
  1087. end
  1088. else begin
  1089. }
  1090. error := IdSslCtxLoadVerifyLocations(
  1091. fContext,
  1092. pStr,
  1093. nil);
  1094. { end;}
  1095. if error <= 0 then begin
  1096. Result := False
  1097. end else begin
  1098. Result := True;
  1099. end;
  1100. StrDispose(pStr);
  1101. end;
  1102. function TIdSSLContext.LoadCert: Boolean;
  1103. var
  1104. pStr: PChar;
  1105. error: Integer;
  1106. begin
  1107. pStr := StrNew(PChar(CertFile));
  1108. error := IdSslCtxUseCertificateFile(
  1109. fContext,
  1110. pStr,
  1111. OPENSSL_SSL_FILETYPE_PEM);
  1112. if error <= 0 then
  1113. Result := False
  1114. else
  1115. Result := True;
  1116. StrDispose(pStr);
  1117. end;
  1118. function TIdSSLContext.LoadKey: Boolean;
  1119. var
  1120. pStr: PChar;
  1121. error: Integer;
  1122. begin
  1123. Result := True;
  1124. pStr := StrNew(PChar(fsKeyFile));
  1125. error := IdSslCtxUsePrivateKeyFile(
  1126. fContext,
  1127. pStr,
  1128. OPENSSL_SSL_FILETYPE_PEM);
  1129. if error <= 0 then begin
  1130. Result := False;
  1131. end else begin
  1132. error := IdSslCtxCheckPrivateKeyFile(fContext);
  1133. if error <= 0 then begin
  1134. Result := False;
  1135. end;
  1136. end;
  1137. StrDispose(pStr);
  1138. end;
  1139. //////////////////////////////////////////////////////////////
  1140. { TIdSSLSocket }
  1141. constructor TIdSSLSocket.Create(Parent: TObject);
  1142. begin
  1143. inherited Create;
  1144. fParent := Parent;
  1145. fSSLContext := nil;
  1146. end;
  1147. destructor TIdSSLSocket.Destroy;
  1148. begin
  1149. if fSSL <> nil then begin
  1150. //IdSslSetShutdown(fSSL, OPENSSL_SSL_SENT_SHUTDOWN);
  1151. IdSslShutdown(fSSL);
  1152. IdSslFree(fSSL);
  1153. fSSL := nil;
  1154. end;
  1155. if fSSLCipher <> nil then begin
  1156. FreeAndNil(fSSLCipher);
  1157. end;
  1158. inherited Destroy;
  1159. end;
  1160. function TIdSSLSocket.GetSSLError(retCode: Integer): Integer;
  1161. begin
  1162. // COMMENT!!!
  1163. // I found out that SSL layer should not interpret errors, cause they will pop up
  1164. // on the socket layer. Only thing that the SSL layer should consider is key
  1165. // or protocol renegotiation. This is done by loop in read and write
  1166. Result := IdSslGetError(fSSL, retCode);
  1167. case Result of
  1168. OPENSSL_SSL_ERROR_NONE:
  1169. Result := OPENSSL_SSL_ERROR_NONE;
  1170. OPENSSL_SSL_ERROR_WANT_WRITE:
  1171. Result := OPENSSL_SSL_ERROR_WANT_WRITE;
  1172. OPENSSL_SSL_ERROR_WANT_READ:
  1173. Result := OPENSSL_SSL_ERROR_WANT_READ;
  1174. OPENSSL_SSL_ERROR_ZERO_RETURN:
  1175. Result := OPENSSL_SSL_ERROR_ZERO_RETURN;
  1176. //Result := OPENSSL_SSL_ERROR_NONE;
  1177. {
  1178. // ssl layer has been disconnected, it is not necessary that also
  1179. // socked has been closed
  1180. case Mode of
  1181. sslemClient: begin
  1182. case Action of
  1183. sslWrite: begin
  1184. if retCode = 0 then begin
  1185. Result := 0;
  1186. end
  1187. else begin
  1188. raise EIdException.Create(RSOSSLConnectionDropped);
  1189. end;
  1190. end;
  1191. end;
  1192. end;}
  1193. //raise EIdException.Create(RSOSSLConnectionDropped);
  1194. // X509_LOOKUP event is not really an error, just an event
  1195. // OPENSSL_SSL_ERROR_WANT_X509_LOOKUP:
  1196. // raise EIdException.Create(RSOSSLCertificateLookup);
  1197. OPENSSL_SSL_ERROR_SYSCALL:
  1198. Result := OPENSSL_SSL_ERROR_SYSCALL;
  1199. // Result := OPENSSL_SSL_ERROR_NONE;
  1200. {//raise EIdException.Create(RSOSSLInternal);
  1201. if (retCode <> 0) or (DataLen <> 0) then begin
  1202. raise EIdException.Create(RSOSSLConnectionDropped);
  1203. end
  1204. else begin
  1205. Result := 0;
  1206. end;}
  1207. OPENSSL_SSL_ERROR_SSL:
  1208. // raise EIdException.Create(RSOSSLInternal);
  1209. Result := OPENSSL_SSL_ERROR_SSL;
  1210. // Result := OPENSSL_SSL_ERROR_NONE;
  1211. end;
  1212. end;
  1213. procedure TIdSSLSocket.Accept(const pHandle: TIdStackSocketHandle; fSSLContext: TIdSSLContext);
  1214. var
  1215. err: Integer;
  1216. StatusStr: String;
  1217. begin
  1218. fSSL := IdSslNew(fSSLContext.fContext);
  1219. if fSSL = nil then exit;
  1220. if IdSslSetAppData(fSSL, self) <= 0 then begin
  1221. raise EIdOSSLDataBindingError.Create(RSSSLDataBindingError);
  1222. exit;
  1223. end;
  1224. self.fSSLContext := fSSLContext;
  1225. IdSslSetFd(fSSL, pHandle);
  1226. err := IdSslAccept(fSSL);
  1227. if err <= 0 then begin
  1228. // err := GetSSLError(err);
  1229. {if err <= -1 then
  1230. raise EIdOSSLAcceptError.Create(RSSSLAcceptError)
  1231. else}
  1232. raise EIdOSSLAcceptError.Create(RSSSLAcceptError);
  1233. end;
  1234. StatusStr := 'Cipher: name = ' + Cipher.Name + '; ' + {Do not Localize}
  1235. 'description = ' + Cipher.Description + '; ' + {Do not Localize}
  1236. 'bits = ' + IntToStr(Cipher.Bits) + '; ' + {Do not Localize}
  1237. 'version = ' + Cipher.Version + '; '; {Do not Localize}
  1238. if (fParent is TIdServerIOHandlerSSL) then begin
  1239. (fParent as TIdServerIOHandlerSSL).DoStatusInfo(StatusStr);
  1240. end;
  1241. end;
  1242. procedure TIdSSLSocket.Connect(const pHandle: TIdStackSocketHandle; fSSLContext: TIdSSLContext);
  1243. var
  1244. error: Integer;
  1245. StatusStr: String;
  1246. begin
  1247. fSSL := IdSslNew(fSSLContext.fContext);
  1248. if fSSL = nil then exit;
  1249. if IdSslSetAppData(fSSL, self) <= 0 then begin
  1250. raise EIdOSSLDataBindingError.Create(RSSSLDataBindingError);
  1251. exit;
  1252. end;
  1253. IdSslSetFd(fSSL, pHandle);
  1254. error := IdSslConnect(fSSL);
  1255. if error <= 0 then begin
  1256. // error2 := IdSslGetError(fSSL, error);
  1257. raise EIdOSSLConnectError.Create(RSSSLConnectError);
  1258. end;
  1259. StatusStr := 'Cipher: name = ' + Cipher.Name + '; ' + {Do not Localize}
  1260. 'description = ' + Cipher.Description + '; ' + {Do not Localize}
  1261. 'bits = ' + IntToStr(Cipher.Bits) + '; ' + {Do not Localize}
  1262. 'version = ' + Cipher.Version + '; '; {Do not Localize}
  1263. if (fParent is TIdSSLIOHandlerSocket) then begin
  1264. (fParent as TIdSSLIOHandlerSocket).DoStatusInfo(StatusStr);
  1265. end;
  1266. end;
  1267. function TIdSSLSocket.Recv(var ABuf; ALen: integer): integer;
  1268. var
  1269. err: Integer;
  1270. begin
  1271. Result := IdSslRead(fSSL, @ABuf, ALen);
  1272. err := GetSSLError(Result);
  1273. if (err = OPENSSL_SSL_ERROR_WANT_READ) or (err = OPENSSL_SSL_ERROR_WANT_WRITE) then begin
  1274. Result := IdSslRead(fSSL, @ABuf, ALen);
  1275. end;
  1276. end;
  1277. function TIdSSLSocket.Send(var ABuf; ALen: integer): integer;
  1278. var
  1279. err: Integer;
  1280. begin
  1281. Result := IdSslWrite(fSSL, @ABuf, ALen);
  1282. err := GetSSLError(Result);
  1283. if (err = OPENSSL_SSL_ERROR_WANT_READ) or (err = OPENSSL_SSL_ERROR_WANT_WRITE) then begin
  1284. Result := IdSslWrite(fSSL, @ABuf, ALen);
  1285. end;
  1286. end;
  1287. function TIdSSLSocket.GetPeerCert: TIdX509;
  1288. var
  1289. X509: PX509;
  1290. begin
  1291. if fPeerCert = nil then begin
  1292. X509 := IdSslGetPeerCertificate(fSSL);
  1293. if X509 <> nil then begin
  1294. fPeerCert := TIdX509.Create(X509);
  1295. end;
  1296. end;
  1297. Result := fPeerCert;
  1298. end;
  1299. function TIdSSLSocket.GetSSLCipher: TIdSSLCipher;
  1300. begin
  1301. if (fSSLCipher = nil) and (fSSL<>nil) then begin
  1302. fSSLCipher := TIdSSLCipher.Create(self);
  1303. end;
  1304. Result := fSSLCipher;
  1305. end;
  1306. function TIdSSLSocket.GetSessionID: TByteArray;
  1307. var
  1308. pSession: PSSL_SESSION;
  1309. tmpArray: TByteArray;
  1310. begin
  1311. Result.Length := 0;
  1312. FillChar(tmpArray, SizeOf(TByteArray), 0);
  1313. if fSSL<>nil then begin
  1314. pSession := IdSslGetSession(fSSL);
  1315. if pSession <> nil then begin
  1316. IdSslSessionGetId(pSession, @tmpArray.Data, @tmpArray.Length);
  1317. Result := tmpArray;
  1318. end;
  1319. end;
  1320. end;
  1321. function TIdSSLSocket.GetSessionIDAsString:String;
  1322. var
  1323. Data: TByteArray;
  1324. i: Integer;
  1325. begin
  1326. Result := ''; {Do not Localize}
  1327. Data := GetSessionID;
  1328. for i := 0 to Data.Length-1 do begin
  1329. Result := Result+Format('%.2x', [Byte(Data.Data[I])]);{do not localize}
  1330. end;
  1331. end;
  1332. procedure TIdSSLSocket.SetCipherList(CipherList: String);
  1333. //var
  1334. // tmpPStr: PChar;
  1335. begin
  1336. {
  1337. fCipherList := CipherList;
  1338. fCipherList_Ch:=True;
  1339. aCipherList:=aCipherList+#0;
  1340. If hSSL<>nil Then f_SSL_set_cipher_list(hSSL, @aCipherList[1]);
  1341. }
  1342. end;
  1343. ///////////////////////////////////////////////////////////////
  1344. // X509 Certificate
  1345. ///////////////////////////////////////////////////////////////
  1346. { TIdX509Name }
  1347. function TIdX509Name.CertInOneLine: String;
  1348. var
  1349. OneLine: Array[0..2048] of Char;
  1350. begin
  1351. if FX509Name = nil then begin
  1352. Result := ''; {Do not Localize}
  1353. end
  1354. else begin
  1355. Result := StrPas(IdSslX509NameOneline(FX509Name, PChar(@OneLine), sizeof(OneLine)));
  1356. end;
  1357. end;
  1358. function TIdX509Name.GetHash: TULong;
  1359. begin
  1360. if FX509Name = nil then begin
  1361. FillChar(Result, SizeOf(Result), 0)
  1362. end
  1363. else begin
  1364. Result.C1 := IdSslX509NameHash(FX509Name);
  1365. end;
  1366. end;
  1367. function TIdX509Name.GetHashAsString: String;
  1368. begin
  1369. Result := Format('%.8x', [Hash.L1]); {do not localize}
  1370. end;
  1371. constructor TIdX509Name.Create(aX509Name: PX509_NAME);
  1372. begin
  1373. Inherited Create;
  1374. FX509Name := aX509Name;
  1375. end;
  1376. ///////////////////////////////////////////////////////////////
  1377. // X509 Certificate
  1378. ///////////////////////////////////////////////////////////////
  1379. { TIdX509 }
  1380. constructor TIdX509.Create(aX509: PX509);
  1381. begin
  1382. inherited Create;
  1383. FX509 := aX509;
  1384. FSubject := nil;
  1385. FIssuer := nil;
  1386. end;
  1387. destructor TIdX509.Destroy;
  1388. begin
  1389. if Assigned(FSubject) then FSubject.Destroy;
  1390. if Assigned(FIssuer) then FIssuer.Destroy;
  1391. inherited Destroy;
  1392. end;
  1393. function TIdX509.RSubject: TIdX509Name;
  1394. var
  1395. x509_name: PX509_NAME;
  1396. Begin
  1397. if not Assigned(FSubject) then begin
  1398. if FX509<>nil then
  1399. x509_name := IdSslX509GetSubjectName(FX509)
  1400. else
  1401. x509_name := nil;
  1402. FSubject := TIdX509Name.Create(x509_name);
  1403. end;
  1404. Result := FSubject;
  1405. end;
  1406. function TIdX509.RIssuer: TIdX509Name;
  1407. var
  1408. x509_name: PX509_NAME;
  1409. begin
  1410. if not Assigned(FIssuer) then begin
  1411. if FX509<>nil then
  1412. x509_name := IdSslX509GetIssuerName(FX509)
  1413. else
  1414. x509_name := nil;
  1415. FIssuer := TIdX509Name.Create(x509_name);
  1416. End;
  1417. Result := FIssuer;
  1418. end;
  1419. function TIdX509.RFingerprint: TEVP_MD;
  1420. begin
  1421. IdSslX509Digest(FX509, IdSslEvpMd5, PChar(@Result.MD), @Result.Length);
  1422. end;
  1423. function TIdX509.RFingerprintAsString: String;
  1424. var
  1425. I: Integer;
  1426. EVP_MD: TEVP_MD;
  1427. begin
  1428. Result := '';
  1429. EVP_MD := Fingerprint;
  1430. for I := 0 to EVP_MD.Length - 1 do begin
  1431. if I <> 0 then Result := Result + ':'; {Do not Localize}
  1432. Result := Result + Format('%.2x', [Byte(EVP_MD.MD[I])]); {do not localize}
  1433. end;
  1434. end;
  1435. function TIdX509.RnotBefore:TDateTime;
  1436. begin
  1437. if FX509=nil then
  1438. Result := 0
  1439. else
  1440. Result := UTCTime2DateTime(IdSslX509GetNotBefore(FX509));
  1441. end;
  1442. function TIdX509.RnotAfter:TDateTime;
  1443. begin
  1444. if FX509=nil then
  1445. Result := 0
  1446. else
  1447. Result := UTCTime2DateTime(IdSslX509GetNotAfter(FX509));
  1448. end;
  1449. ///////////////////////////////////////////////////////////////
  1450. // TIdSSLCipher
  1451. ///////////////////////////////////////////////////////////////
  1452. constructor TIdSSLCipher.Create(AOwner: TIdSSLSocket);
  1453. begin
  1454. inherited Create;
  1455. FSSLSocket := AOwner;
  1456. end;
  1457. destructor TIdSSLCipher.Destroy;
  1458. begin
  1459. inherited Destroy;
  1460. end;
  1461. function TIdSSLCipher.GetDescription;
  1462. var
  1463. Buf: Array[0..1024] of Char;
  1464. begin
  1465. Result := StrPas(IdSSLCipherDescription(IdSSLGetCurrentCipher(FSSLSocket.fSSL), @Buf[0], SizeOf(Buf)-1));
  1466. end;
  1467. function TIdSSLCipher.GetName:String;
  1468. begin
  1469. Result := StrPas(IdSSLCipherGetName(IdSSLGetCurrentCipher(FSSLSocket.fSSL)));
  1470. end;
  1471. function TIdSSLCipher.GetBits:Integer;
  1472. begin
  1473. IdSSLCipherGetBits(IdSSLGetCurrentCipher(FSSLSocket.fSSL), @Result);
  1474. end;
  1475. function TIdSSLCipher.GetVersion:String;
  1476. begin
  1477. Result := StrPas(IdSSLCipherGetVersion(IdSSLGetCurrentCipher(FSSLSocket.fSSL)));
  1478. end;
  1479. initialization
  1480. // Let's load the library {Do not Localize}
  1481. //if DLLLoadCount <= 0 then begin
  1482. {
  1483. if not LoadOpenSLLibrary then begin
  1484. raise EIdException.Create(RSOSSLCouldNotLoadSSLLibrary);
  1485. end;
  1486. }
  1487. //end;
  1488. //Inc(DLLLoadCount);
  1489. finalization
  1490. // if DLLLoadCount = 0 then begin
  1491. UnLoadOpenSLLibrary;
  1492. // end;
  1493. end.