-
-
Save achechulin/fb785cf87040175707e666aa58377ef5 to your computer and use it in GitHub Desktop.
TLS support for THttpServer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- a/httpServerRaw.dpr | |
+++ b/httpServerRaw.dpr | |
@@ -103 +103 @@ begin | |
- fHttpServer := THttpAsyncServer.Create( | |
+ fHttpServer := THttpServer.Create( |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- a/mormot.net.sock.pas | |
+++ b/mormot.net.sock.pas | |
@@ -3255,3 +3255 @@ begin | |
- aTLS and | |
- not doBind and | |
- ({%H-}PtrInt(aSock) <= 0) then | |
+ (PtrInt(aSock) > 0) then |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- a/mormot.net.sock.windows.inc | |
+++ b/mormot.net.sock.windows.inc | |
@@ -11 +11,3 @@ uses | |
- Windows; | |
+ Windows, | |
+ // ASC_REQ_*, TSChannel_Cred, CertFindCertificateInStore, etc | |
+ mormot.lib.sspi; | |
@@ -1045,0 +1048,5 @@ type | |
+ TCryptDataBlob = record | |
+ cbData: Cardinal; | |
+ pbData: Pointer; | |
+ end; | |
+ | |
@@ -1092,0 +1100,3 @@ var | |
+ function PFXImportCertStore(pPFX: Pointer; szPassword: PWideChar; | |
+ dwFlags: Cardinal): HCERTSTORE; stdcall; external 'crypt32.dll'; | |
+ | |
@@ -1136 +1146,9 @@ const | |
- | |
+ // ASC_REQ_* const values differs from ISC_REQ_* | |
+ ASC_REQ_REPLAY_DETECT = $00000004; | |
+ ASC_REQ_SEQUENCE_DETECT = $00000008; | |
+ ASC_REQ_EXTENDED_ERROR = $00008000; | |
+ ASC_REQ_STREAM = $00010000; | |
+ ASC_REQ_FLAGS = | |
+ ASC_REQ_SEQUENCE_DETECT or ASC_REQ_REPLAY_DETECT or | |
+ ASC_REQ_CONFIDENTIALITY or ASC_REQ_EXTENDED_ERROR or | |
+ ASC_REQ_ALLOCATE_MEMORY or ASC_REQ_STREAM; | |
@@ -1294,0 +1313,5 @@ end; | |
+// Shared context | |
+var | |
+ gCertStore: HCERTSTORE; | |
+ gCert: PCCERT_CONTEXT; | |
+ | |
@@ -1298,2 +1321,3 @@ var | |
- buf: THandshakeBuf; | |
- res, f: cardinal; | |
+ certblob: RawByteString; | |
+ blob: TCryptDataBlob; | |
+ cred: TSChannel_Cred; | |
@@ -1304,0 +1329,25 @@ begin | |
+ // Create shared TLS context. Not thread safe. | |
+ // Should be created before server start, i.e. in NewServerTlsContext | |
+ if gCert = nil then | |
+ begin | |
+ certblob := StringFromFile('mycert.pfx'); | |
+ blob.cbData := Length(certblob); | |
+ blob.pbData := Pointer(certblob); | |
+ // We can load certificate from WIndows certificate store | |
+ // or from file. I use Let's Encrypt sertificate, converted to PFX: | |
+ // openssl pkcs12 -inkey privkey.pem -in cert.pem -export -out mycert.pfx | |
+ // Unfortunately, CertOpenStore(CERT_STORE_PROV_PKCS12) does not work. | |
+ // May be private key not loaded? But PFXImportCertStore works fine. | |
+ // Or use current user certificate store: | |
+ // gCertStore := CertOpenSystemStoreW(nil, 'MY'); | |
+ gCertStore := PFXImportCertStore(@blob, nil, {PKCS12_INCLUDE_EXTENDED_PROPERTIES}$10); | |
+ // Find first certificate in store | |
+ gCert := CertFindCertificateInStore(gCertStore, 0, 0, {CERT_FIND_ANY}0, nil, nil); | |
+ if not Assigned(gCert) then | |
+ raise ESChannel.Create('Certificate not available'); | |
+ // After shutdown call CertFreeCertificateContext and CertCloseStore | |
+ end; | |
+ FillCharFast(cred, SizeOf(cred), 0); | |
+ cred.dwVersion := {SCHANNEL_CRED_VERSION}4; | |
+ cred.cCreds := 1; | |
+ cred.paCred := @gCert; | |
@@ -1307,2 +1356,2 @@ begin | |
- CheckSEC_E_OK(AcquireCredentialsHandle(nil, UNISP_NAME, SECPKG_CRED_OUTBOUND, | |
- nil, nil, nil, nil, @fCred, nil)); | |
+ CheckSEC_E_OK(AcquireCredentialsHandle(nil, UNISP_NAME, SECPKG_CRED_INBOUND, | |
+ nil, @cred, nil, nil, @fCred, nil)); | |
@@ -1311,16 +1360 @@ begin | |
- fFlags := ISC_REQ_FLAGS; | |
- if Context.IgnoreCertificateErrors then | |
- // prevent SEC_E_UNTRUSTED_ROOT result in HandshakeLoop | |
- fFlags := fFlags or ISC_REQ_MANUAL_CRED_VALIDATION; | |
- // initiate a ClientHello TLS message and a new fCtxt | |
- HandshakeBufInit(buf); | |
- res := InitializeSecurityContext(@fCred, nil, pointer(ServerAddress), | |
- fFlags, 0, 0, nil, 0, @fCtxt, @buf.output, @f, nil); | |
- if res <> SEC_I_CONTINUE_NEEDED then | |
- ESChannelRaiseLastError(res); | |
- if (buf.buf[2].cbBuffer = 0) or | |
- (buf.buf[2].pvBuffer = nil) then | |
- raise ESChannel.CreateFmt('Void Hello answer to %s', [ServerAddress]); | |
- CheckSocket(mormot.net.sock.Send( | |
- fSocket.Socket, buf.buf[2].pvBuffer, buf.buf[2].cbBuffer, 0)); | |
- CheckSEC_E_OK(FreeContextBuffer(buf.buf[2].pvBuffer)); | |
+ fFlags := ASC_REQ_FLAGS; | |
@@ -1343,0 +1378 @@ procedure TSChannelClient.HandshakeLoop; | |
+ e: LARGE_INTEGER; | |
@@ -1344,0 +1380 @@ procedure TSChannelClient.HandshakeLoop; | |
+ LInCtxPtr: PSecHandle; | |
@@ -1350,2 +1386,6 @@ procedure TSChannelClient.HandshakeLoop; | |
- result := InitializeSecurityContext(@fCred, @fCtxt, pointer(fServerAddress), | |
- fFlags, 0, 0, @buf.input, 0, nil, @buf.output, @f, nil); | |
+ if (fCtxt.dwLower = nil) and (fCtxt.dwUpper = nil) then | |
+ LInCtxPtr := nil | |
+ else | |
+ LInCtxPtr := @fCtxt; | |
+ result := AcceptSecurityContext(@fCred, LInCtxPtr, @buf.input, | |
+ fFlags, 0, @fCtxt, @buf.output, f, e); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment