Skip to content

Commit e89f4b7

Browse files
committed
FEAT: added possibility to start TLS connection reusing existing TCP port
1 parent abc58b7 commit e89f4b7

File tree

1 file changed

+107
-69
lines changed

1 file changed

+107
-69
lines changed

src/mezz/prot-tls.reb

+107-69
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ REBOL [
1212
See: http://www.apache.org/licenses/LICENSE-2.0
1313
}
1414
Author: ["Richard 'Cyphre' Smolak" "Oldes" "Brian Dickens (Hostilefork)"]
15-
Version: 0.9.0
16-
Date: 16-Feb-2022
15+
Version: 0.9.1
16+
Date: 6-May-2022
1717
history: [
1818
0.6.1 "Cyphre" "Initial implementation used in old R3-alpha"
1919
0.7.0 "Oldes" {
@@ -34,6 +34,7 @@ REBOL [
3434
0.7.4 "Oldes" "Pass data to parent handler even when ALERT message is not decoded"
3535
0.8.0 "Oldes" "Using new `crypt` port introduced in Rebol 3.8.0"
3636
0.9.0 "Oldes" "Added (limited) support for a `server` role"
37+
0.9.1 "Oldes" "Improved initialization to be able reuse already opened TCP port"
3738
]
3839
todo: {
3940
* cached sessions
@@ -359,7 +360,7 @@ _log-debug: func[msg][
359360
if block? msg [msg: reform msg]
360361
print rejoin [" ^[[33m[TLS] ^[[0;32m" msg "^[[0m"]
361362
]
362-
_log-----: does [print "----------------------------------------------------------------"]
363+
_log-----: does [print-horizontal-line]
363364

364365
log-error: log-info: log-more: log-debug: log-----: none
365366

@@ -439,8 +440,8 @@ suported-cipher-suites: decode-cipher-suites suported-cipher-suites-binary: rejo
439440
#{C027} ;TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
440441
#{C014} ;TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
441442
#{C013} ;TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
442-
#{C00A} ;TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
443-
#{C009} ;TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
443+
;@@ #{C00A} ;TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ; some issue!
444+
;@@ #{C009} ;TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA ; some issue!
444445
;#{006A} ;TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
445446
#{006B} ;TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
446447
#{0067} ;TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
@@ -565,8 +566,7 @@ change-state: function [
565566
][
566567
ctx/state-prev: ctx/state
567568
if ctx/state <> new-state [
568-
;log-info "_________________________________________________________"
569-
log-info ["New state:^[[33m" new-state "^[[22mfrom:" ctx/state]
569+
log-more ["New state:^[[33m" new-state "^[[22mfrom:" ctx/state]
570570
ctx/state: new-state
571571
]
572572
]
@@ -978,7 +978,8 @@ application-data: func [
978978
ctx [object!]
979979
message [binary! string!]
980980
][
981-
log-more "application-data"
981+
log-debug "application-data"
982+
log-more ["W[" ctx/seq-write "] application data:" length? message "bytes"]
982983
;prin "unencrypted: " ?? message
983984
message: encrypt-data ctx to binary! message
984985
;prin "encrypted: " ?? message
@@ -1307,7 +1308,7 @@ do-commands: func [
13071308
]
13081309
;ctx/out/buffer: head ctx/out/buffer
13091310
;?? ctx/out/buffer
1310-
log-info ["Writing bytes:" length? ctx/out/buffer]
1311+
log-debug ["Writing bytes:" length? ctx/out/buffer]
13111312
ctx/out/buffer: head ctx/out/buffer
13121313
write ctx/tcp-port ctx/out/buffer
13131314

@@ -1332,7 +1333,7 @@ do-commands: func [
13321333
;--- TLS scheme -------------------------------;
13331334
;----------------------------------------------;
13341335

1335-
TLS-init: func [
1336+
TLS-init-context: func [
13361337
"Resets existing TLS context"
13371338
ctx [object!]
13381339
][
@@ -1342,6 +1343,38 @@ TLS-init: func [
13421343
clear ctx/server-certs
13431344
]
13441345

1346+
TLS-init-connection: function [ctx [object!]][
1347+
error: try [
1348+
TLS-port: ctx/TLS-port
1349+
do-commands ctx [client-hello]
1350+
log-debug ["CONNECT^[[22m: client-hello done; protocol:^[[1m" ctx/protocol]
1351+
if ctx/protocol = 'HANDSHAKE [
1352+
do-commands ctx [
1353+
client-key-exchange
1354+
change-cipher-spec
1355+
finished
1356+
]
1357+
]
1358+
if open? TLS-port [
1359+
;send-event 'connect TLS-port
1360+
return false
1361+
]
1362+
cause-TLS-error *Alert/Close_notify
1363+
]
1364+
print error
1365+
log-error error
1366+
if ctx [
1367+
if error? ctx/state [
1368+
; upper protocol was already closed and reports the error in its state
1369+
; it's safe to throw the error now
1370+
do ctx/state
1371+
]
1372+
; in case that the upper protocol is not yet closed, store error and report it
1373+
ctx/error: error
1374+
]
1375+
send-event 'error TLS-port
1376+
false
1377+
]
13451378

13461379
TLS-read-data: function [
13471380
ctx [object!]
@@ -1351,7 +1384,7 @@ TLS-read-data: function [
13511384
;@@ but we need just parts of it, before it is decrypted! Unfortunatelly the current
13521385
;@@ bincode does not allow shrinking of the buffer :-/ NEEDS REWRITE!!!
13531386

1354-
log-more ["read-data:^[[1m" length? tcp-data "^[[22mbytes previous rest:" length? ctx/rest]
1387+
log-debug ["read-data:^[[1m" length? tcp-data "^[[22mbytes previous rest:" length? ctx/rest]
13551388
inp: ctx/in
13561389

13571390
binary/write inp ctx/rest ;- possible leftover from previous packet
@@ -1383,7 +1416,7 @@ TLS-read-data: function [
13831416

13841417
if available < len [
13851418
;probe inp/buffer
1386-
log-info ["Incomplete fragment:^[[22m available^[[1m" available "^[[22mof^[[1m" len "^[[22mbytes"]
1419+
log-debug ["Incomplete fragment:^[[22m available^[[1m" available "^[[22mof^[[1m" len "^[[22mbytes"]
13871420
;?? inp/buffer
13881421
binary/read inp [AT :start] ;resets position
13891422
log-debug ["Data starts: " copy/part inp/buffer 10]
@@ -1401,7 +1434,7 @@ TLS-read-data: function [
14011434
end: start + len + 5 ; header size is 5 bytes
14021435

14031436
;log-debug "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
1404-
log-info ["^[[22mR[" ctx/seq-read "] Protocol^[[1m" protocol "^[[22m" server-version "bytes:^[[1m" len "^[[22mfrom^[[1m" start "^[[22mto^[[1m" end]
1437+
log-more ["^[[22mR[" ctx/seq-read "] Protocol^[[1m" protocol "^[[22mbytes:^[[1m" len "^[[22mfrom^[[1m" start "^[[22mto^[[1m" end]
14051438

14061439
ctx/protocol: protocol
14071440

@@ -1494,11 +1527,8 @@ TLS-read-data: function [
14941527
]
14951528

14961529
unless ctx/reading? [
1497-
;? ctx
1498-
;print "^/================================================================"
1499-
log-more ["Reading finished!"]
1500-
log-----
1501-
1530+
log-debug ["Reading finished!"]
1531+
;log-----
15021532
return true
15031533
]
15041534
]
@@ -1867,9 +1897,15 @@ send-event: function[
18671897
event [word!]
18681898
target [port!]
18691899
][
1870-
log-debug ["Send-event:^[[1m" event]
1871-
;if 'error = event [ ? target ? target/extra ]
1872-
insert system/ports/system make event! [ type: event port: target ]
1900+
log-debug ["Send-event:^[[1m" pad event 8 "^[[m->" target/spec/ref]
1901+
either all [
1902+
port? target/parent
1903+
function? :target/parent/awake
1904+
][ ;; If there is parent scheme, send the event to its awake function
1905+
target/parent/awake make event! [ type: event port: target ]
1906+
][ ;; If not, insert the event into the system port's que
1907+
insert system/ports/system make event! [ type: event port: target ]
1908+
]
18731909
]
18741910

18751911

@@ -1966,7 +2002,7 @@ TLS-server-awake: func [event /local port info serv] [
19662002

19672003

19682004
TLS-client-awake: function [event [event!]][
1969-
log-more ["AWAKE Client:^[[1m" event/type]
2005+
log-debug ["AWAKE Client:^[[1m" event/type]
19702006
TCP-port: event/port
19712007
;? TCP-port
19722008
ctx: TCP-port/extra
@@ -1986,39 +2022,12 @@ TLS-client-awake: function [event [event!]][
19862022
switch/default event/type [
19872023
lookup [
19882024
open TCP-port
1989-
TLS-init ctx
2025+
TLS-init-context ctx
19902026
return false
19912027
]
19922028
connect [
1993-
error: try [
1994-
do-commands ctx [client-hello]
1995-
if none? ctx [return true] ;- probably closed meanwhile
1996-
log-info ["CONNECT^[[22m: client-hello done; protocol:^[[1m" ctx/protocol]
1997-
if ctx/protocol = 'HANDSHAKE [
1998-
do-commands ctx [
1999-
client-key-exchange
2000-
change-cipher-spec
2001-
finished
2002-
]
2003-
]
2004-
if open? TLS-port [
2005-
send-event 'connect TLS-port
2006-
return false
2007-
]
2008-
cause-TLS-error *Alert/Close_notify
2009-
]
2010-
;?? error
2011-
if ctx [
2012-
if error? ctx/state [
2013-
; upper protocol was already closed and reports the error in its state
2014-
; it's safe to throw the error now
2015-
do ctx/state
2016-
]
2017-
; in case that the upper protocol is not yet closed, store error and report it
2018-
ctx/error: error
2019-
]
2020-
send-event 'error TLS-port
2021-
return true
2029+
if none? ctx [return true] ;- probably closed meanwhile
2030+
return TLS-init-connection ctx
20222031
]
20232032
wrote [
20242033
switch ctx/protocol [
@@ -2035,7 +2044,7 @@ TLS-client-awake: function [event [event!]][
20352044
]
20362045
read [
20372046
error: try [
2038-
log-info ["READ TCP" length? TCP-port/data "bytes proto-state:" ctx/protocol]
2047+
log-debug ["READ TCP" length? TCP-port/data "bytes proto-state:" ctx/protocol]
20392048
;@@ This part deserves a serious review!
20402049
complete?: TLS-read-data ctx TCP-port/data
20412050
;? port
@@ -2049,14 +2058,14 @@ TLS-client-awake: function [event [event!]][
20492058
binary/init ctx/in none ; resets input buffer
20502059
;?? ctx/protocol
20512060
either 'APPLICATION = ctx/protocol [
2052-
;print "------------------"
20532061
;- report that we have data to higher layer
2054-
;probe to-string TLS-port/data
2055-
send-event 'read TLS-port
2062+
either ctx/state-prev = 'FINISHED [
2063+
send-event 'connect TLS-port
2064+
][ send-event 'read TLS-port ]
2065+
;print-horizontal-line
20562066
][ read TCP-port ]
20572067
return true
20582068
]
2059-
;print error
20602069
; on error:
20612070
if ctx [ ctx/error: error ]
20622071
send-event 'error TLS-port
@@ -2088,16 +2097,33 @@ do-TLS-open: func [
20882097
port [port!]
20892098
/local spec conn config certs bin der key
20902099
][
2091-
log-more "OPEN"
2100+
log-debug "OPEN"
20922101
if port/state [return port]
20932102
spec: port/spec
2094-
conn: make port! [
2095-
scheme: 'tcp
2096-
host: spec/host
2097-
port: spec/port
2098-
ref: rejoin [tcp:// any [host ""] ":" port]
2103+
2104+
either port? conn: select spec 'conn [
2105+
;- reusing already prepared TCP connection
2106+
spec/host: conn/spec/host
2107+
spec/port: conn/spec/port
2108+
if block? spec/ref [
2109+
spec/ref: rejoin [tls:// any [spec/host ""] ":" spec/port]
2110+
]
2111+
][
2112+
;- opening new low level TCP connection
2113+
conn: make port! [
2114+
scheme: 'tcp
2115+
host: spec/host
2116+
port: spec/port
2117+
ref: rejoin [tcp:// any [host ""] ":" port]
2118+
]
2119+
if port/parent [
2120+
conn/state: port/parent/state
2121+
]
2122+
conn/parent: port
20992123
]
2124+
21002125
either spec/host [
2126+
;- CLIENT connection ---------------------------
21012127
port/extra: conn/extra: make TLS-context [
21022128
tcp-port: conn
21032129
tls-port: port
@@ -2106,6 +2132,7 @@ do-TLS-open: func [
21062132
port/data: conn/extra/port-data
21072133
conn/awake: :TLS-client-awake
21082134
][
2135+
;- SERVER connection ---------------------------
21092136
spec/ref: rejoin [tls://: spec/port]
21102137
port/spec/title: "TLS Server"
21112138
conn/spec/title: "TLS Server (internal)"
@@ -2116,7 +2143,7 @@ do-TLS-open: func [
21162143
elliptic-curves: decode-supported-groups :supported-elliptic-curves
21172144
version: *Protocol-version/TLS1.2
21182145
]
2119-
? spec
2146+
;? spec
21202147
if config: select spec 'config [
21212148
certs: any [select config 'certificates []]
21222149
unless block? certs [certs: to block! certs]
@@ -2151,30 +2178,41 @@ do-TLS-open: func [
21512178
conn/parent: port
21522179
conn/awake: :TLS-server-awake
21532180
]
2154-
open conn
2181+
either open? conn [
2182+
TLS-init-context conn/extra
2183+
TLS-init-connection conn/extra
2184+
][
2185+
open conn
2186+
]
21552187
port
21562188
]
2157-
do-TLS-close: func [port [port!] /local ctx][
2158-
log-more "CLOSE"
2189+
do-TLS-close: func [port [port!] /local ctx parent][
2190+
log-debug "CLOSE"
21592191
unless ctx: port/extra [return port]
2192+
parent: port/parent
21602193
log-debug "Closing port/extra/tcp-port"
21612194
close ctx/tcp-port
21622195
if port? ctx/encrypt-port [ close ctx/encrypt-port ]
21632196
if port? ctx/decrypt-port [ close ctx/decrypt-port ]
21642197
ctx/encrypt-port: none
21652198
ctx/decrypt-port: none
21662199
ctx/tcp-port/awake: none
2200+
ctx/tcp-port: none
2201+
ctx/tls-port: none
21672202
port/extra: none
21682203
log-more "Port closed"
2204+
if parent [
2205+
insert system/ports/system make event! [type: 'close port: parent]
2206+
]
21692207
port
21702208
]
21712209
do-TLS-read: func [port [port!]][
2172-
log-more "READ"
2210+
log-debug "READ"
21732211
read port/extra/tcp-port
21742212
port
21752213
]
21762214
do-TLS-write: func[port [port!] value [any-type!]][
2177-
log-more "WRITE"
2215+
log-debug "WRITE"
21782216
if port/extra/protocol = 'APPLICATION [
21792217
do-commands/no-wait port/extra compose [
21802218
application (value)

0 commit comments

Comments
 (0)