Use sequence-actions.
This commit is contained in:
parent
f57b68603a
commit
f59bec0145
|
@ -147,20 +147,18 @@
|
||||||
(transition state (kill))]
|
(transition state (kill))]
|
||||||
[(tcp-channel _ _ (? bytes? remote-identification))
|
[(tcp-channel _ _ (? bytes? remote-identification))
|
||||||
(check-remote-identification! remote-identification)
|
(check-remote-identification! remote-identification)
|
||||||
;; First, set the incoming mode to bytes. Then
|
(sequence-actions state
|
||||||
;; initialise the reader, switching to packet-reading
|
;; First, set the incoming mode to bytes.
|
||||||
;; mode. Finally, spawn the remaining processes and
|
(at-meta-level (send-tcp-mode remote-addr local-addr 'bytes))
|
||||||
;; issue the initial credit to the reader.
|
;; Then initialise the reader, switching to packet-reading mode.
|
||||||
(extend-transition
|
(lambda (ignored-state) (ssh-reader local-addr remote-addr))
|
||||||
(prefix-transition (ssh-reader local-addr remote-addr)
|
;; Finally, spawn the remaining processes and issue the initial credit to the reader.
|
||||||
(at-meta-level (send-tcp-mode remote-addr local-addr 'bytes)))
|
|
||||||
(spawn (ssh-writer local-addr remote-addr)
|
(spawn (ssh-writer local-addr remote-addr)
|
||||||
#:monitor? #t
|
#:monitor? #t
|
||||||
#:debug-name 'ssh-writer)
|
#:debug-name 'ssh-writer)
|
||||||
;; Wait for a cycle to let the reader and writer get
|
;; (Wait for a cycle to let the reader and writer get
|
||||||
;; started, then tell the reader we are ready for a
|
;; started, then tell the reader we are ready for a single
|
||||||
;; single packet and spawn the session manager.
|
;; packet and spawn the session manager.)
|
||||||
|
|
||||||
;; TODO: try using presence instead of the yield.
|
;; TODO: try using presence instead of the yield.
|
||||||
(yield #:state state
|
(yield #:state state
|
||||||
(transition state
|
(transition state
|
||||||
|
|
148
ssh-session.rkt
148
ssh-session.rkt
|
@ -119,22 +119,20 @@
|
||||||
(hash-remove d packet-type-number)))
|
(hash-remove d packet-type-number)))
|
||||||
(cddr key-value-pairs))))))
|
(cddr key-value-pairs))))))
|
||||||
|
|
||||||
;; Transition [ Byte Maybe<PacketHandler> ]* -> ConnectionState
|
;; ConnectionState [ Byte Maybe<PacketHandler> ]* -> ConnectionState
|
||||||
;; Installs (or removes) PacketHandlers in the given connection state;
|
;; Installs (or removes) PacketHandlers in the given connection state;
|
||||||
;; see extend-packet-dispatcher.
|
;; see extend-packet-dispatcher.
|
||||||
(define (set-handlers t . key-value-pairs)
|
(define (set-handlers conn . key-value-pairs)
|
||||||
(extend-transition* t
|
(struct-copy connection conn
|
||||||
(lambda (conn)
|
[dispatch-table (apply extend-packet-dispatcher
|
||||||
(struct-copy connection conn
|
(connection-dispatch-table conn)
|
||||||
[dispatch-table (apply extend-packet-dispatcher
|
key-value-pairs)]))
|
||||||
(connection-dispatch-table conn)
|
|
||||||
key-value-pairs)]))))
|
|
||||||
|
|
||||||
;; Transition Byte PacketHandler -> ConnectionState
|
;; Transition Byte PacketHandler -> ConnectionState
|
||||||
;; Installs a PacketHandler that removes the installed dispatch entry
|
;; Installs a PacketHandler that removes the installed dispatch entry
|
||||||
;; and then delegates to its argument.
|
;; and then delegates to its argument.
|
||||||
(define (oneshot-handler t packet-type-number packet-handler)
|
(define (oneshot-handler conn packet-type-number packet-handler)
|
||||||
(set-handlers t
|
(set-handlers conn
|
||||||
packet-type-number
|
packet-type-number
|
||||||
(lambda (packet message conn)
|
(lambda (packet message conn)
|
||||||
(packet-handler packet
|
(packet-handler packet
|
||||||
|
@ -273,11 +271,12 @@
|
||||||
(define h-signature (host-key-signature host-key-private
|
(define h-signature (host-key-signature host-key-private
|
||||||
host-key-alg
|
host-key-alg
|
||||||
exchange-hash))
|
exchange-hash))
|
||||||
(prefix-transition (finish shared-secret exchange-hash hash-alg conn)
|
(sequence-actions conn
|
||||||
(send-message (outbound-packet
|
(send-message (outbound-packet
|
||||||
(ssh-msg-kexdh-reply (bit-string->bytes host-key-bytes)
|
(ssh-msg-kexdh-reply (bit-string->bytes host-key-bytes)
|
||||||
public-key-as-integer
|
public-key-as-integer
|
||||||
(bit-string->bytes h-signature)))))))]
|
(bit-string->bytes h-signature))))
|
||||||
|
(lambda (conn) (finish shared-secret exchange-hash hash-alg conn)))))]
|
||||||
[else (disconnect-with-error SSH_DISCONNECT_KEY_EXCHANGE_FAILED
|
[else (disconnect-with-error SSH_DISCONNECT_KEY_EXCHANGE_FAILED
|
||||||
"Bad key-exchange algorithm ~v" kex-alg)]))
|
"Bad key-exchange algorithm ~v" kex-alg)]))
|
||||||
|
|
||||||
|
@ -293,7 +292,9 @@
|
||||||
dh:oakley-group-2)) ;; yes, SSH's group1 == Oakley/RFC2409 group 2
|
dh:oakley-group-2)) ;; yes, SSH's group1 == Oakley/RFC2409 group 2
|
||||||
(define-values (private-key public-key) (generate-key group))
|
(define-values (private-key public-key) (generate-key group))
|
||||||
(define public-key-as-integer (bit-string->integer public-key #t #f))
|
(define public-key-as-integer (bit-string->integer public-key #t #f))
|
||||||
(prefix-transition
|
(sequence-actions conn
|
||||||
|
(send-message (outbound-packet (ssh-msg-kexdh-init public-key-as-integer)))
|
||||||
|
(lambda (conn)
|
||||||
(oneshot-handler conn
|
(oneshot-handler conn
|
||||||
SSH_MSG_KEXDH_REPLY
|
SSH_MSG_KEXDH_REPLY
|
||||||
(lambda (packet message conn)
|
(lambda (packet message conn)
|
||||||
|
@ -315,8 +316,7 @@
|
||||||
host-key-alg
|
host-key-alg
|
||||||
exchange-hash
|
exchange-hash
|
||||||
(ssh-msg-kexdh-reply-h-signature message))
|
(ssh-msg-kexdh-reply-h-signature message))
|
||||||
(finish shared-secret exchange-hash hash-alg conn)))
|
(finish shared-secret exchange-hash hash-alg conn)))))]
|
||||||
(send-message (outbound-packet (ssh-msg-kexdh-init public-key-as-integer))))]
|
|
||||||
[else (disconnect-with-error SSH_DISCONNECT_KEY_EXCHANGE_FAILED
|
[else (disconnect-with-error SSH_DISCONNECT_KEY_EXCHANGE_FAILED
|
||||||
"Bad key-exchange algorithm ~v" kex-alg)]))
|
"Bad key-exchange algorithm ~v" kex-alg)]))
|
||||||
|
|
||||||
|
@ -437,7 +437,7 @@
|
||||||
(let ((t (if should-discard-first-kex-packet
|
(let ((t (if should-discard-first-kex-packet
|
||||||
(struct-copy connection (continue-after-discard conn) [discard-next-packet? #t])
|
(struct-copy connection (continue-after-discard conn) [discard-next-packet? #t])
|
||||||
(continue-after-discard conn))))
|
(continue-after-discard conn))))
|
||||||
(prefix-transition* t
|
(sequence-actions t
|
||||||
(lambda (conn)
|
(lambda (conn)
|
||||||
(if (rekey-wait? (connection-rekey-state conn))
|
(if (rekey-wait? (connection-rekey-state conn))
|
||||||
(transition (struct-copy connection conn [rekey-state (rekey-local local-algs)])
|
(transition (struct-copy connection conn [rekey-state (rekey-local local-algs)])
|
||||||
|
@ -455,10 +455,11 @@
|
||||||
(if (connection-authentication-state conn)
|
(if (connection-authentication-state conn)
|
||||||
(disconnect-with-error SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
|
(disconnect-with-error SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
|
||||||
"Repeated authentication is not permitted")
|
"Repeated authentication is not permitted")
|
||||||
(prefix-transition (oneshot-handler conn
|
(sequence-actions conn
|
||||||
SSH_MSG_USERAUTH_REQUEST
|
(send-message (outbound-packet (ssh-msg-service-accept service)))
|
||||||
handle-msg-userauth-request)
|
(lambda (conn) (oneshot-handler conn
|
||||||
(send-message (outbound-packet (ssh-msg-service-accept service)))))]
|
SSH_MSG_USERAUTH_REQUEST
|
||||||
|
handle-msg-userauth-request))))]
|
||||||
[else
|
[else
|
||||||
(disconnect-with-error SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
|
(disconnect-with-error SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
|
||||||
"Service ~v not supported"
|
"Service ~v not supported"
|
||||||
|
@ -475,15 +476,16 @@
|
||||||
[(and (positive? (bytes-length user-name))
|
[(and (positive? (bytes-length user-name))
|
||||||
(equal? service-name #"ssh-connection"))
|
(equal? service-name #"ssh-connection"))
|
||||||
;; TODO: Actually implement client authentication
|
;; TODO: Actually implement client authentication
|
||||||
(prefix-transition
|
(sequence-actions conn
|
||||||
|
(send-message (outbound-packet (ssh-msg-userauth-success)))
|
||||||
|
(lambda (conn)
|
||||||
(start-connection-service
|
(start-connection-service
|
||||||
(set-handlers (struct-copy connection conn
|
(set-handlers (struct-copy connection conn
|
||||||
[authentication-state (authenticated user-name service-name)])
|
[authentication-state (authenticated user-name service-name)])
|
||||||
SSH_MSG_USERAUTH_REQUEST
|
SSH_MSG_USERAUTH_REQUEST
|
||||||
(lambda (packet message conn)
|
(lambda (packet message conn)
|
||||||
;; RFC4252 section 5.1 page 6
|
;; RFC4252 section 5.1 page 6
|
||||||
conn)))
|
conn)))))]
|
||||||
(send-message (outbound-packet (ssh-msg-userauth-success))))]
|
|
||||||
[else
|
[else
|
||||||
(transition conn
|
(transition conn
|
||||||
(send-message (outbound-packet (ssh-msg-userauth-failure '(none) #f))))]))
|
(send-message (outbound-packet (ssh-msg-userauth-failure '(none) #f))))]))
|
||||||
|
@ -660,7 +662,7 @@
|
||||||
(channel-stream-name (wild) (channel-name #t (wild) (wild))))
|
(channel-stream-name (wild) (channel-name #t (wild) (wild))))
|
||||||
(define arbitrary-locally-originated-traffic
|
(define arbitrary-locally-originated-traffic
|
||||||
(channel-message arbitrary-locally-originated-stream (wild)))
|
(channel-message arbitrary-locally-originated-stream (wild)))
|
||||||
(extend-transition
|
(sequence-actions
|
||||||
(set-handlers conn
|
(set-handlers conn
|
||||||
;; TODO: SSH_MSG_GLOBAL_REQUEST handle-msg-global-request
|
;; TODO: SSH_MSG_GLOBAL_REQUEST handle-msg-global-request
|
||||||
SSH_MSG_CHANNEL_OPEN handle-msg-channel-open
|
SSH_MSG_CHANNEL_OPEN handle-msg-channel-open
|
||||||
|
@ -764,9 +766,10 @@
|
||||||
(define ch (get-channel conn local-ref))
|
(define ch (get-channel conn local-ref))
|
||||||
(define description (bit-string->bytes description*))
|
(define description (bit-string->bytes description*))
|
||||||
(define inbound-stream (channel-stream-name #t (ssh-channel-name ch)))
|
(define inbound-stream (channel-stream-name #t (ssh-channel-name ch)))
|
||||||
(prefix-transition (maybe-close-channel (ssh-channel-name ch) conn 'remote)
|
(sequence-actions conn
|
||||||
(send-message (channel-message inbound-stream
|
(send-message (channel-message inbound-stream
|
||||||
(channel-stream-open-failure reason description)))))
|
(channel-stream-open-failure reason description)))
|
||||||
|
(lambda (conn) (maybe-close-channel (ssh-channel-name ch) conn 'remote))))
|
||||||
|
|
||||||
(define (handle-msg-channel-window-adjust packet message conn)
|
(define (handle-msg-channel-window-adjust packet message conn)
|
||||||
(match-define (ssh-msg-channel-window-adjust local-ref count) message)
|
(match-define (ssh-msg-channel-window-adjust local-ref count) message)
|
||||||
|
@ -824,11 +827,9 @@
|
||||||
(else (disconnect-with-error SSH_DISCONNECT_PROTOCOL_ERROR
|
(else (disconnect-with-error SSH_DISCONNECT_PROTOCOL_ERROR
|
||||||
"Not authenticated"))))
|
"Not authenticated"))))
|
||||||
|
|
||||||
(define (bump-total t amount)
|
(define ((bump-total amount) conn)
|
||||||
(extend-transition* t
|
(struct-copy connection conn
|
||||||
(lambda (conn)
|
[total-transferred (+ (connection-total-transferred conn) amount)]))
|
||||||
(struct-copy connection conn
|
|
||||||
[total-transferred (+ (connection-total-transferred conn) amount)]))))
|
|
||||||
|
|
||||||
;; (K V A -> A) A Hash<K,V> -> A
|
;; (K V A -> A) A Hash<K,V> -> A
|
||||||
(define (hash-fold fn seed hash)
|
(define (hash-fold fn seed hash)
|
||||||
|
@ -836,15 +837,13 @@
|
||||||
(seed seed (fn (hash-iterate-key hash pos) (hash-iterate-value hash pos) seed)))
|
(seed seed (fn (hash-iterate-key hash pos) (hash-iterate-value hash pos) seed)))
|
||||||
((not pos) seed)))
|
((not pos) seed)))
|
||||||
|
|
||||||
(define (rekey-wrap t)
|
(define (maybe-rekey conn)
|
||||||
(extend-transition* t
|
(define rekey (connection-rekey-state conn))
|
||||||
(lambda (conn)
|
(if (time-to-rekey? rekey conn)
|
||||||
(define rekey (connection-rekey-state conn))
|
(let ((algs ((local-algorithm-list))))
|
||||||
(if (time-to-rekey? rekey conn)
|
(transition (struct-copy connection conn [rekey-state (rekey-local algs)])
|
||||||
(let ((algs ((local-algorithm-list))))
|
(send-message (outbound-packet algs))))
|
||||||
(transition (struct-copy connection conn [rekey-state (rekey-local algs)])
|
conn))
|
||||||
(send-message (outbound-packet algs))))
|
|
||||||
conn))))
|
|
||||||
|
|
||||||
;; PacketDispatcher. Handles the core transport message types.
|
;; PacketDispatcher. Handles the core transport message types.
|
||||||
(define base-packet-dispatcher
|
(define base-packet-dispatcher
|
||||||
|
@ -858,38 +857,45 @@
|
||||||
peer-identification-string
|
peer-identification-string
|
||||||
application-boot
|
application-boot
|
||||||
session-role)
|
session-role)
|
||||||
(lambda (self-pid)
|
(boot-specification
|
||||||
(transition (connection #f
|
(lambda (self-pid)
|
||||||
base-packet-dispatcher
|
(transition (connection #f
|
||||||
0
|
base-packet-dispatcher
|
||||||
(rekey-in-seconds-or-bytes -1 -1 0)
|
0
|
||||||
#f
|
(rekey-in-seconds-or-bytes -1 -1 0)
|
||||||
'()
|
#f
|
||||||
(case session-role ((client) #f) ((server) #t))
|
'()
|
||||||
local-identification-string
|
(case session-role ((client) #f) ((server) #t))
|
||||||
peer-identification-string
|
local-identification-string
|
||||||
#f)
|
peer-identification-string
|
||||||
|
#f)
|
||||||
|
|
||||||
(spawn (nested-vm 'ssh-application-vm application-boot)
|
(spawn (nested-vm 'ssh-application-vm application-boot)
|
||||||
#:monitor? #t
|
#:monitor? #t
|
||||||
#:debug-name 'ssh-application-vm)
|
#:debug-name 'ssh-application-vm)
|
||||||
|
|
||||||
(role 'rekey-waiter (topic-subscriber (timer-expired 'rekey-timer (wild)))
|
(role 'rekey-waiter (topic-subscriber (timer-expired 'rekey-timer (wild)))
|
||||||
#:state conn
|
#:state conn
|
||||||
[(timer-expired 'rekey-timer now)
|
[(timer-expired 'rekey-timer now)
|
||||||
(rekey-wrap conn)])
|
(sequence-actions conn
|
||||||
|
maybe-rekey)])
|
||||||
|
|
||||||
(role 'credit-listener (topic-subscriber (outbound-byte-credit (wild)))
|
(role 'credit-listener (topic-subscriber (outbound-byte-credit (wild)))
|
||||||
#:state conn
|
#:state conn
|
||||||
[(outbound-byte-credit amount)
|
[(outbound-byte-credit amount)
|
||||||
(rekey-wrap (bump-total conn amount))])
|
(sequence-actions conn
|
||||||
|
(bump-total amount)
|
||||||
|
maybe-rekey)])
|
||||||
|
|
||||||
(role 'packet-listener (topic-subscriber (inbound-packet (wild) (wild) (wild) (wild)))
|
(role 'packet-listener (topic-subscriber (inbound-packet (wild) (wild) (wild) (wild)))
|
||||||
#:state conn
|
#:state conn
|
||||||
[(inbound-packet sequence-number payload message transfer-size)
|
[(inbound-packet sequence-number payload message transfer-size)
|
||||||
(let* ((t (if (connection-discard-next-packet? conn)
|
(sequence-actions conn
|
||||||
(struct-copy connection conn [discard-next-packet? #f])
|
(lambda (conn)
|
||||||
(dispatch-packet sequence-number payload message conn)))
|
(if (connection-discard-next-packet? conn)
|
||||||
(t (bump-total t transfer-size))
|
(struct-copy connection conn [discard-next-packet? #f])
|
||||||
(t (extend-transition t (send-message (inbound-credit 1)))))
|
(dispatch-packet sequence-number payload message conn)))
|
||||||
(rekey-wrap t))]))))
|
(bump-total transfer-size)
|
||||||
|
(send-message (inbound-credit 1))
|
||||||
|
maybe-rekey)])))
|
||||||
|
connection?))
|
||||||
|
|
Loading…
Reference in New Issue