@@ -12,8 +12,8 @@ REBOL [
12
12
See: http://www.apache.org/licenses/LICENSE-2.0
13
13
}
14
14
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
17
17
history: [
18
18
0.6.1 "Cyphre" "Initial implementation used in old R3-alpha"
19
19
0.7.0 "Oldes" {
@@ -34,6 +34,7 @@ REBOL [
34
34
0.7.4 "Oldes" "Pass data to parent handler even when ALERT message is not decoded"
35
35
0.8.0 "Oldes" "Using new `crypt` port introduced in Rebol 3.8.0"
36
36
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"
37
38
]
38
39
todo: {
39
40
* cached sessions
@@ -359,7 +360,7 @@ _log-debug: func[msg][
359
360
if block? msg [msg: reform msg]
360
361
print rejoin [" ^[ [33m[TLS] ^[ [0;32m" msg "^[ [0m" ]
361
362
]
362
- _log----- : does [print "----------------------------------------------------------------" ]
363
+ _log----- : does [print-horizontal-line ]
363
364
364
365
log-error: log-info: log-more: log-debug: log-----: none
365
366
@@ -439,8 +440,8 @@ suported-cipher-suites: decode-cipher-suites suported-cipher-suites-binary: rejo
439
440
#{ C027 } ;TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
440
441
#{ C014 } ;TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
441
442
#{ 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!
444
445
;#{006A} ;TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
445
446
#{ 006B } ;TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
446
447
#{ 0067 } ;TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
@@ -565,8 +566,7 @@ change-state: function [
565
566
] [
566
567
ctx/state-prev: ctx/state
567
568
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 ]
570
570
ctx/state: new-state
571
571
]
572
572
]
@@ -978,7 +978,8 @@ application-data: func [
978
978
ctx [object! ]
979
979
message [binary! string! ]
980
980
] [
981
- log-more "application-data"
981
+ log-debug "application-data"
982
+ log-more ["W[" ctx/seq-write "] application data:" length? message "bytes" ]
982
983
;prin "unencrypted: " ?? message
983
984
message: encrypt-data ctx to binary! message
984
985
;prin "encrypted: " ?? message
@@ -1307,7 +1308,7 @@ do-commands: func [
1307
1308
]
1308
1309
;ctx/out/buffer: head ctx/out/buffer
1309
1310
;?? ctx/out/buffer
1310
- log-info ["Writing bytes:" length? ctx/out/buffer ]
1311
+ log-debug ["Writing bytes:" length? ctx/out/buffer ]
1311
1312
ctx/out/buffer: head ctx/out/buffer
1312
1313
write ctx/tcp-port ctx/out/buffer
1313
1314
@@ -1332,7 +1333,7 @@ do-commands: func [
1332
1333
;--- TLS scheme -------------------------------;
1333
1334
;----------------------------------------------;
1334
1335
1335
- TLS-init : func [
1336
+ TLS-init-context : func [
1336
1337
"Resets existing TLS context"
1337
1338
ctx [object! ]
1338
1339
] [
@@ -1342,6 +1343,38 @@ TLS-init: func [
1342
1343
clear ctx/server-certs
1343
1344
]
1344
1345
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
+ ]
1345
1378
1346
1379
TLS-read-data : function [
1347
1380
ctx [object! ]
@@ -1351,7 +1384,7 @@ TLS-read-data: function [
1351
1384
;@@ but we need just parts of it, before it is decrypted! Unfortunatelly the current
1352
1385
;@@ bincode does not allow shrinking of the buffer :-/ NEEDS REWRITE!!!
1353
1386
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 ]
1355
1388
inp: ctx/in
1356
1389
1357
1390
binary/write inp ctx/rest ;- possible leftover from previous packet
@@ -1383,7 +1416,7 @@ TLS-read-data: function [
1383
1416
1384
1417
if available < len [
1385
1418
;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" ]
1387
1420
;?? inp/buffer
1388
1421
binary/read inp [AT :start ] ;resets position
1389
1422
log-debug ["Data starts: " copy/part inp/buffer 10 ]
@@ -1401,7 +1434,7 @@ TLS-read-data: function [
1401
1434
end: start + len + 5 ; header size is 5 bytes
1402
1435
1403
1436
;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]
1405
1438
1406
1439
ctx/protocol: protocol
1407
1440
@@ -1494,11 +1527,8 @@ TLS-read-data: function [
1494
1527
]
1495
1528
1496
1529
unless ctx/reading? [
1497
- ;? ctx
1498
- ;print "^/================================================================"
1499
- log-more ["Reading finished!" ]
1500
- log-----
1501
-
1530
+ log-debug ["Reading finished!" ]
1531
+ ;log-----
1502
1532
return true
1503
1533
]
1504
1534
]
@@ -1867,9 +1897,15 @@ send-event: function[
1867
1897
event [word! ]
1868
1898
target [port! ]
1869
1899
] [
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
+ ]
1873
1909
]
1874
1910
1875
1911
@@ -1966,7 +2002,7 @@ TLS-server-awake: func [event /local port info serv] [
1966
2002
1967
2003
1968
2004
TLS-client-awake : function [ event [event! ]] [
1969
- log-more ["AWAKE Client:^[ [1m" event/type ]
2005
+ log-debug ["AWAKE Client:^[ [1m" event/type ]
1970
2006
TCP-port: event/port
1971
2007
;? TCP-port
1972
2008
ctx: TCP-port/extra
@@ -1986,39 +2022,12 @@ TLS-client-awake: function [event [event!]][
1986
2022
switch /default event/type [
1987
2023
lookup [
1988
2024
open TCP-port
1989
- TLS-init ctx
2025
+ TLS-init-context ctx
1990
2026
return false
1991
2027
]
1992
2028
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
2022
2031
]
2023
2032
wrote [
2024
2033
switch ctx/protocol [
@@ -2035,7 +2044,7 @@ TLS-client-awake: function [event [event!]][
2035
2044
]
2036
2045
read [
2037
2046
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 ]
2039
2048
;@@ This part deserves a serious review!
2040
2049
complete?: TLS-read-data ctx TCP-port/data
2041
2050
;? port
@@ -2049,14 +2058,14 @@ TLS-client-awake: function [event [event!]][
2049
2058
binary/init ctx/in none ; resets input buffer
2050
2059
;?? ctx/protocol
2051
2060
either 'APPLICATION = ctx/protocol [
2052
- ;print "------------------"
2053
2061
;- 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
2056
2066
][ read TCP-port ]
2057
2067
return true
2058
2068
]
2059
- ;print error
2060
2069
; on error:
2061
2070
if ctx [ ctx/error: error ]
2062
2071
send-event 'error TLS-port
@@ -2088,16 +2097,33 @@ do-TLS-open: func [
2088
2097
port [port! ]
2089
2098
/local spec conn config certs bin der key
2090
2099
] [
2091
- log-more "OPEN"
2100
+ log-debug "OPEN"
2092
2101
if port/state [return port]
2093
2102
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
2099
2123
]
2124
+
2100
2125
either spec/host [
2126
+ ;- CLIENT connection ---------------------------
2101
2127
port/extra: conn/extra: make TLS-context [
2102
2128
tcp-port: conn
2103
2129
tls-port: port
@@ -2106,6 +2132,7 @@ do-TLS-open: func [
2106
2132
port/data: conn/extra/port-data
2107
2133
conn/awake: :TLS-client-awake
2108
2134
][
2135
+ ;- SERVER connection ---------------------------
2109
2136
spec/ref: rejoin [tls://: spec/port ]
2110
2137
port/spec/title: "TLS Server"
2111
2138
conn/spec/title: "TLS Server (internal)"
@@ -2116,7 +2143,7 @@ do-TLS-open: func [
2116
2143
elliptic-curves: decode-supported-groups :supported-elliptic-curves
2117
2144
version: *Protocol-version/TLS1.2
2118
2145
]
2119
- ? spec
2146
+ ; ? spec
2120
2147
if config: select spec 'config [
2121
2148
certs: any [select config 'certificates []]
2122
2149
unless block? certs [certs: to block! certs]
@@ -2151,30 +2178,41 @@ do-TLS-open: func [
2151
2178
conn/parent: port
2152
2179
conn/awake: :TLS-server-awake
2153
2180
]
2154
- open conn
2181
+ either open? conn [
2182
+ TLS-init-context conn/extra
2183
+ TLS-init-connection conn/extra
2184
+ ][
2185
+ open conn
2186
+ ]
2155
2187
port
2156
2188
]
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"
2159
2191
unless ctx: port/extra [return port]
2192
+ parent: port/parent
2160
2193
log-debug "Closing port/extra/tcp-port"
2161
2194
close ctx/tcp-port
2162
2195
if port? ctx/encrypt-port [ close ctx/encrypt-port ]
2163
2196
if port? ctx/decrypt-port [ close ctx/decrypt-port ]
2164
2197
ctx/encrypt-port: none
2165
2198
ctx/decrypt-port: none
2166
2199
ctx/tcp-port/awake: none
2200
+ ctx/tcp-port: none
2201
+ ctx/tls-port: none
2167
2202
port/extra: none
2168
2203
log-more "Port closed"
2204
+ if parent [
2205
+ insert system/ports/system make event! [type: 'close port: parent]
2206
+ ]
2169
2207
port
2170
2208
]
2171
2209
do-TLS-read : func [ port [port! ]] [
2172
- log-more "READ"
2210
+ log-debug "READ"
2173
2211
read port/extra/tcp-port
2174
2212
port
2175
2213
]
2176
2214
do-TLS-write : func [ port [port! ] value [any-type! ]] [
2177
- log-more "WRITE"
2215
+ log-debug "WRITE"
2178
2216
if port/extra/protocol = 'APPLICATION [
2179
2217
do-commands/no-wait port/extra compose [
2180
2218
application (value)
0 commit comments