forked from syndicate-lang/marketplace-ssh-2014
Push through to channel layer
This commit is contained in:
parent
5479511afa
commit
4e1d525904
|
@ -25,7 +25,7 @@
|
||||||
(spawn-tcp-driver ds)
|
(spawn-tcp-driver ds)
|
||||||
(spawn #:name 'ssh-tcp-listener
|
(spawn #:name 'ssh-tcp-listener
|
||||||
(at ds
|
(at ds
|
||||||
(during/spawn (Connection $conn (TcpInbound "0.0.0.0" 29418))
|
(during/spawn (Connection $conn (TcpLocal "0.0.0.0" 29418))
|
||||||
#:name (list 'ssh conn)
|
#:name (list 'ssh conn)
|
||||||
(session ds conn))))))
|
(session ds conn))))))
|
||||||
|
|
||||||
|
@ -43,66 +43,69 @@
|
||||||
peer-identification-string)))
|
peer-identification-string)))
|
||||||
|
|
||||||
(define (session ground-ds conn)
|
(define (session ground-ds conn)
|
||||||
(define root-facet this-facet)
|
|
||||||
|
|
||||||
(define update-input-handler
|
|
||||||
(accept-connection conn
|
|
||||||
#:initial-credit #f
|
|
||||||
#:on-data (lambda (input mode) (error 'session "Unexpected input"))))
|
|
||||||
|
|
||||||
(define local-identification #"SSH-2.0-RacketSSH_0.0")
|
(define local-identification #"SSH-2.0-RacketSSH_0.0")
|
||||||
(send-line conn local-identification)
|
|
||||||
|
|
||||||
(send-lines-credit conn 1 (LineMode-crlf))
|
(define id-line-reader-facet
|
||||||
(update-input-handler
|
(react
|
||||||
#:on-data (lambda (remote-identification _mode)
|
(on-start (send-line conn local-identification)
|
||||||
(check-remote-identification! remote-identification)
|
(send-lines-credit conn 1 (LineMode-crlf)))
|
||||||
|
(accept-connection conn
|
||||||
|
#:initial-credit #f
|
||||||
|
#:on-eof (lambda () (stop-current-facet))
|
||||||
|
#:on-data (lambda (remote-identification _mode)
|
||||||
|
(check-remote-identification! remote-identification)
|
||||||
|
(send! session-vm-factory remote-identification)))))
|
||||||
|
|
||||||
(define session-vm
|
(define transfer-control
|
||||||
(actor-group [(on-stop
|
(object #:name 'transfer-control
|
||||||
(stop-facet root-facet)
|
[#:message 'transfer-control (stop-facet id-line-reader-facet)]))
|
||||||
(log-info "Session VM for ~a closed" conn))]
|
|
||||||
(define conn-ds (dataspace #:name (gensym 'conn-ds)))
|
|
||||||
|
|
||||||
(spawn/link #:name 'reader
|
(define session-vm-factory
|
||||||
(ssh-reader conn-ds conn update-input-handler))
|
(object
|
||||||
(spawn/link #:name 'writer
|
#:name 'session-vm-factory
|
||||||
(ssh-writer conn-ds conn))
|
[#:message remote-identification
|
||||||
|
(on-stop (log-info "Session VM for ~a closed" conn))
|
||||||
|
(actor-group
|
||||||
|
#:link? #t
|
||||||
|
(define conn-ds (dataspace #:name (gensym 'conn-ds)))
|
||||||
|
|
||||||
;; Wait for the reader and writer get started, then tell the reader
|
(spawn #:name 'reader (ssh-reader conn-ds conn transfer-control))
|
||||||
;; we are ready for a single packet and spawn the session manager.
|
(spawn #:name 'writer (ssh-writer conn-ds conn))
|
||||||
(react
|
|
||||||
(at conn-ds
|
|
||||||
(stop-when (asserted (Observe (:pattern (inbound-credit ,_)) _))
|
|
||||||
(send! conn-ds (inbound-credit 1))
|
|
||||||
|
|
||||||
(spawn/link
|
;; Wait for the reader and writer get started, then tell the reader
|
||||||
#:name 'session
|
;; we are ready for a single packet and spawn the session manager.
|
||||||
(ssh-session conn-ds
|
(react
|
||||||
ground-ds
|
(at conn-ds
|
||||||
local-identification
|
(stop-when (asserted (Observe (:pattern (inbound-credit ,_)) _))
|
||||||
remote-identification
|
(send! conn-ds (inbound-credit 1))
|
||||||
(lambda (user-name)
|
|
||||||
(error 'repl-boot "Would start session with ~a" user-name))
|
|
||||||
'server)))))
|
|
||||||
|
|
||||||
(at conn-ds
|
(spawn
|
||||||
;; (during $m
|
#:name 'session
|
||||||
;; (on-start (log-info "++ ~v" m))
|
(ssh-session conn-ds
|
||||||
;; (on-stop (log-info "-- ~v" m)))
|
ground-ds
|
||||||
(when (message $m)
|
local-identification
|
||||||
(log-info ">> ~v" m)))
|
remote-identification
|
||||||
|
(lambda (user-name)
|
||||||
|
(error 'repl-boot "Would start session with ~a" user-name))
|
||||||
|
'server)))))
|
||||||
|
|
||||||
(at conn-ds
|
;; (at conn-ds
|
||||||
(when (asserted (protocol-error $reason-code $message _ $originated-at-peer?))
|
;; ;; (during $m
|
||||||
(when (not originated-at-peer?)
|
;; ;; (on-start (log-info "++ ~v" m))
|
||||||
(send! conn-ds
|
;; ;; (on-stop (log-info "-- ~v" m)))
|
||||||
(outbound-packet (ssh-msg-disconnect reason-code
|
;; (when (message $m)
|
||||||
(string->bytes/utf-8 message)
|
;; (log-info ">> ~v" m)))
|
||||||
#""))))
|
|
||||||
(actor-system-shutdown! session-vm)))))
|
|
||||||
|
|
||||||
(void))))
|
(at conn-ds
|
||||||
|
(when (asserted (protocol-error $reason-code $message _ $originated-at-peer?))
|
||||||
|
(when (not originated-at-peer?)
|
||||||
|
(send! conn-ds
|
||||||
|
(outbound-packet (ssh-msg-disconnect reason-code
|
||||||
|
(string->bytes/utf-8 message)
|
||||||
|
#""))))
|
||||||
|
(sync! conn-ds (stop-actor-system)))))]))
|
||||||
|
|
||||||
|
(void))
|
||||||
|
|
||||||
;;---------------------------------------------------------------------------
|
;;---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -58,9 +58,6 @@
|
||||||
(case host-key-alg
|
(case host-key-alg
|
||||||
[(ssh-ed25519)
|
[(ssh-ed25519)
|
||||||
(define signature (pk-sign private-key exchange-hash))
|
(define signature (pk-sign private-key exchange-hash))
|
||||||
(log-info "signature length ~a value ~v verifies"
|
|
||||||
(bytes-length signature)
|
|
||||||
signature)
|
|
||||||
(bit-string (#"ssh-ed25519" :: (t:string))
|
(bit-string (#"ssh-ed25519" :: (t:string))
|
||||||
(signature :: (t:string)))]))
|
(signature :: (t:string)))]))
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,36 @@
|
||||||
(struct task (seq packet-type packet message) #:prefab)
|
(struct task (seq packet-type packet message) #:prefab)
|
||||||
(struct task-complete (seq) #:prefab)
|
(struct task-complete (seq) #:prefab)
|
||||||
|
|
||||||
|
(define-event-expander with-incoming-task
|
||||||
|
(syntax-rules ()
|
||||||
|
[(_ (seq-id type-byte packet-pattern message-pattern) body ...)
|
||||||
|
(with-incoming-task* when (seq-id type-byte packet-pattern message-pattern) body ...)]))
|
||||||
|
|
||||||
|
(define-syntax-rule
|
||||||
|
(with-incoming-task/react conn-ds (seq-id type-byte packet-pattern message-pattern) body ...)
|
||||||
|
(react
|
||||||
|
(at conn-ds
|
||||||
|
(with-incoming-task* stop-when (seq-id type-byte packet-pattern message-pattern)
|
||||||
|
body ...))))
|
||||||
|
|
||||||
|
(define-event-expander with-incoming-task*
|
||||||
|
(syntax-rules ()
|
||||||
|
[(_ when-stx (seq-id type-byte packet-pattern message-pattern) body ...)
|
||||||
|
(when-stx (message (task ($ seq-id _) type-byte packet-pattern message-pattern))
|
||||||
|
body ...
|
||||||
|
(send! this-target (task-complete seq-id)))]))
|
||||||
|
|
||||||
|
(define-syntax-rule (with-assertion-presence ds assertion
|
||||||
|
#:on-present [body-present ...]
|
||||||
|
#:on-absent [body-absent ...])
|
||||||
|
(let ((assertion-present #f))
|
||||||
|
(at ds (when (asserted assertion)
|
||||||
|
(set! assertion-present #t)
|
||||||
|
body-present ...))
|
||||||
|
(sync! ds (when (not assertion-present)
|
||||||
|
(void)
|
||||||
|
body-absent ...))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Key Exchange
|
;; Key Exchange
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -120,29 +150,24 @@
|
||||||
(define private-key (generate-private-key group))
|
(define private-key (generate-private-key group))
|
||||||
(match-define (list 'dh 'public p g public-key-as-integer)
|
(match-define (list 'dh 'public p g public-key-as-integer)
|
||||||
(pk-key->datum private-key 'rkt-public))
|
(pk-key->datum private-key 'rkt-public))
|
||||||
(react
|
(with-incoming-task/react conn-ds (seq SSH_MSG_KEXDH_INIT _ (ssh-msg-kexdh-init $e))
|
||||||
(at conn-ds
|
(define peer-key (datum->pk-key (list 'dh 'public p g e) 'rkt-public))
|
||||||
(when (message (task $seq SSH_MSG_KEXDH_INIT _ (ssh-msg-kexdh-init $e)))
|
(define shared-secret (pk-derive-secret private-key peer-key))
|
||||||
(define peer-key (datum->pk-key (list 'dh 'public p g e) 'rkt-public))
|
(define hash-alg sha256)
|
||||||
(define shared-secret (pk-derive-secret private-key peer-key))
|
(define-values (host-key-private host-key-public) (host-key-algorithm->keys host-key-alg))
|
||||||
(define hash-alg sha256)
|
(define host-key-bytes (pieces->ssh-host-key (public-key->pieces host-key-public)))
|
||||||
(define-values (host-key-private host-key-public)
|
(define exchange-hash (dh-exchange-hash hash-alg
|
||||||
(host-key-algorithm->keys host-key-alg))
|
hash-info
|
||||||
(define host-key-bytes (pieces->ssh-host-key (public-key->pieces host-key-public)))
|
host-key-bytes
|
||||||
(define exchange-hash (dh-exchange-hash hash-alg
|
e
|
||||||
hash-info
|
public-key-as-integer
|
||||||
host-key-bytes
|
(bit-string->integer shared-secret #t #f)))
|
||||||
e
|
(define h-signature (host-key-signature host-key-private host-key-alg exchange-hash))
|
||||||
public-key-as-integer
|
(send! conn-ds (outbound-packet
|
||||||
(bit-string->integer shared-secret #t #f)))
|
(ssh-msg-kexdh-reply (bit-string->bytes host-key-bytes)
|
||||||
(define h-signature (host-key-signature host-key-private host-key-alg exchange-hash))
|
public-key-as-integer
|
||||||
(log-info "h-signature ~v public-key-as-integer ~v" h-signature public-key-as-integer)
|
(bit-string->bytes h-signature))))
|
||||||
(send! conn-ds (outbound-packet
|
(finish shared-secret exchange-hash hash-alg))]
|
||||||
(ssh-msg-kexdh-reply (bit-string->bytes host-key-bytes)
|
|
||||||
public-key-as-integer
|
|
||||||
(bit-string->bytes h-signature))))
|
|
||||||
(send! conn-ds (task-complete seq))
|
|
||||||
(finish shared-secret exchange-hash hash-alg))))]
|
|
||||||
[_ (disconnect-with-error conn-ds SSH_DISCONNECT_KEY_EXCHANGE_FAILED
|
[_ (disconnect-with-error conn-ds SSH_DISCONNECT_KEY_EXCHANGE_FAILED
|
||||||
"Bad key-exchange algorithm ~v" kex-alg)]))
|
"Bad key-exchange algorithm ~v" kex-alg)]))
|
||||||
|
|
||||||
|
@ -156,23 +181,20 @@
|
||||||
(match-define (list 'dh 'public p g public-key-as-integer)
|
(match-define (list 'dh 'public p g public-key-as-integer)
|
||||||
(pk-key->datum private-key 'rkt-public))
|
(pk-key->datum private-key 'rkt-public))
|
||||||
(send! conn-ds (outbound-packet (ssh-msg-kexdh-init public-key-as-integer)))
|
(send! conn-ds (outbound-packet (ssh-msg-kexdh-init public-key-as-integer)))
|
||||||
(react
|
(with-incoming-task/react conn-ds (seq SSH_MSG_KEXDH_REPLY _
|
||||||
(at conn-ds
|
(ssh-msg-kexdh-reply $host-key-bytes $f $h-signature))
|
||||||
(when (message (task $seq SSH_MSG_KEXDH_REPLY _
|
(define peer-key (datum->pk-key (list 'dh 'public p g f) 'rkt-public))
|
||||||
(ssh-msg-kexdh-reply $host-key-bytes $f $h-signature)))
|
(define shared-secret (pk-derive-secret private-key peer-key))
|
||||||
(define peer-key (datum->pk-key (list 'dh 'public p g f) 'rkt-public))
|
(define hash-alg sha256)
|
||||||
(define shared-secret (pk-derive-secret private-key peer-key))
|
(define host-public-key (pieces->public-key (ssh-host-key->pieces host-key-bytes)))
|
||||||
(define hash-alg sha256)
|
(define exchange-hash (dh-exchange-hash hash-alg
|
||||||
(define host-public-key (pieces->public-key (ssh-host-key->pieces host-key-bytes)))
|
hash-info
|
||||||
(define exchange-hash (dh-exchange-hash hash-alg
|
host-key-bytes
|
||||||
hash-info
|
public-key-as-integer
|
||||||
host-key-bytes
|
f
|
||||||
public-key-as-integer
|
(bit-string->integer shared-secret #t #f)))
|
||||||
f
|
(verify-host-key-signature! host-public-key host-key-alg exchange-hash h-signature)
|
||||||
(bit-string->integer shared-secret #t #f)))
|
(finish shared-secret exchange-hash hash-alg))]
|
||||||
(verify-host-key-signature! host-public-key host-key-alg exchange-hash h-signature)
|
|
||||||
(send! conn-ds (task-complete seq))
|
|
||||||
(finish shared-secret exchange-hash hash-alg))))]
|
|
||||||
[_ (disconnect-with-error conn-ds SSH_DISCONNECT_KEY_EXCHANGE_FAILED
|
[_ (disconnect-with-error conn-ds SSH_DISCONNECT_KEY_EXCHANGE_FAILED
|
||||||
"Bad key-exchange algorithm ~v" kex-alg)]))
|
"Bad key-exchange algorithm ~v" kex-alg)]))
|
||||||
|
|
||||||
|
@ -266,78 +288,65 @@
|
||||||
(extend (bytes-append key (hash-alg (bit-string->bytes
|
(extend (bytes-append key (hash-alg (bit-string->bytes
|
||||||
(bit-string (k-h-prefix :: binary)
|
(bit-string (k-h-prefix :: binary)
|
||||||
(key :: binary))))))))))
|
(key :: binary))))))))))
|
||||||
(react
|
(with-incoming-task/react conn-ds (seq SSH_MSG_NEWKEYS _ (ssh-msg-newkeys))
|
||||||
(at conn-ds
|
;; First, send our SSH_MSG_NEWKEYS, incrementing the
|
||||||
(when (message (task $seq SSH_MSG_NEWKEYS _ (ssh-msg-newkeys)))
|
;; various counters, and then apply the new algorithms.
|
||||||
;; First, send our SSH_MSG_NEWKEYS, incrementing the
|
;; Also arm our rekey timer.
|
||||||
;; various counters, and then apply the new algorithms.
|
(rekey-state (rekey-in-seconds-or-bytes (rekey-interval)
|
||||||
;; Also arm our rekey timer.
|
(rekey-volume)
|
||||||
(rekey-state (rekey-in-seconds-or-bytes (rekey-interval)
|
(total-transferred)))
|
||||||
(rekey-volume)
|
(send! conn-ds 'enable-service-request-handler)
|
||||||
(total-transferred)))
|
(send! conn-ds (outbound-packet (ssh-msg-newkeys)))
|
||||||
(send! conn-ds 'enable-service-request!)
|
(send! conn-ds (new-keys is-server?
|
||||||
(send! conn-ds (outbound-packet (ssh-msg-newkeys)))
|
(embedded derive-key)
|
||||||
(send! conn-ds (new-keys is-server?
|
c2s-enc s2c-enc
|
||||||
(embedded derive-key)
|
c2s-mac s2c-mac
|
||||||
c2s-enc s2c-enc
|
c2s-zip s2c-zip))
|
||||||
c2s-mac s2c-mac
|
(send! ground-ds (SetTimer 'rekey-timer
|
||||||
c2s-zip s2c-zip))
|
(* (rekey-wait-deadline (rekey-state)) 1000)
|
||||||
(send! ground-ds (SetTimer 'rekey-timer
|
(TimerKind-absolute)))))))
|
||||||
(* (rekey-wait-deadline (rekey-state)) 1000)
|
|
||||||
(TimerKind-absolute)))
|
|
||||||
(send! conn-ds (task-complete seq))))))))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Service request manager
|
;; Service request manager and user authentication
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; (define (handle-msg-service-request packet message conn)
|
(define (service-request-handler conn-ds)
|
||||||
;; (define service (bit-string->bytes (ssh-msg-service-request-service-name message)))
|
(define-field authentication-state #f)
|
||||||
;; (match service
|
|
||||||
;; [#"ssh-userauth"
|
|
||||||
;; (if (connection-authentication-state conn)
|
|
||||||
;; (disconnect-with-error SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
|
|
||||||
;; "Repeated authentication is not permitted")
|
|
||||||
;; (sequence-actions (transition conn)
|
|
||||||
;; (send-message (outbound-packet (ssh-msg-service-accept service)))
|
|
||||||
;; (lambda (conn) (transition
|
|
||||||
;; (oneshot-handler conn
|
|
||||||
;; SSH_MSG_USERAUTH_REQUEST
|
|
||||||
;; handle-msg-userauth-request)))))]
|
|
||||||
;; [else
|
|
||||||
;; (disconnect-with-error SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
|
|
||||||
;; "Service ~v not supported"
|
|
||||||
;; service)]))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
(at conn-ds
|
||||||
;; User authentication
|
(assert #:when (authentication-state) (authentication-state))
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
;; (define (handle-msg-userauth-request packet message conn)
|
(with-incoming-task (seq SSH_MSG_SERVICE_REQUEST _ (ssh-msg-service-request $service))
|
||||||
;; (define user-name (bit-string->bytes (ssh-msg-userauth-request-user-name message)))
|
(match service
|
||||||
;; (define service-name (bit-string->bytes (ssh-msg-userauth-request-service-name message)))
|
[#"ssh-userauth"
|
||||||
;; (cond
|
(cond
|
||||||
;; [(and (positive? (bytes-length user-name))
|
[(authentication-state)
|
||||||
;; (equal? service-name #"ssh-connection"))
|
(disconnect-with-error SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
|
||||||
;; ;; TODO: Actually implement client authentication
|
"Repeated authentication is not permitted")]
|
||||||
;; (sequence-actions (transition conn)
|
[else
|
||||||
;; (send-message (outbound-packet (ssh-msg-userauth-success)))
|
(send! conn-ds (outbound-packet (ssh-msg-service-accept service)))
|
||||||
;; (lambda (conn)
|
(with-incoming-task/react conn-ds
|
||||||
;; (start-connection-service
|
(seq SSH_MSG_USERAUTH_REQUEST _
|
||||||
;; (set-handlers (struct-copy connection conn
|
(ssh-msg-userauth-request $user-name $service-name _ _))
|
||||||
;; [authentication-state (authenticated user-name service-name)])
|
(cond
|
||||||
;; SSH_MSG_USERAUTH_REQUEST
|
[(and (positive? (bytes-length user-name))
|
||||||
;; (lambda (packet message conn)
|
(equal? service-name #"ssh-connection"))
|
||||||
;; ;; RFC4252 section 5.1 page 6
|
;; TODO: Actually implement client authentication
|
||||||
;; conn))))
|
(send! conn-ds (outbound-packet (ssh-msg-userauth-success)))
|
||||||
;; (lambda (conn)
|
(authentication-state (authenticated user-name service-name))
|
||||||
;; (transition conn
|
(react
|
||||||
;; ;; TODO: canary for NESTED VM!: #:exit-signal? #t
|
(at conn-ds
|
||||||
;; (spawn-vm #:debug-name 'ssh-application-vm
|
(with-incoming-task (seq SSH_MSG_USERAUTH_REQUEST _ _)
|
||||||
;; ((connection-application-boot conn) user-name)))))]
|
;; RFC4252 section 5.1 page 6
|
||||||
;; [else
|
)))
|
||||||
;; (transition conn
|
(let ((a (authentication-state)))
|
||||||
;; (send-message (outbound-packet (ssh-msg-userauth-failure '(none) #f))))]))
|
(spawn #:name 'connection-service (start-connection-service conn-ds a)))]
|
||||||
|
[else
|
||||||
|
(send! conn-ds (outbound-packet (ssh-msg-userauth-failure '(none) #f)))]))])]
|
||||||
|
[_
|
||||||
|
(disconnect-with-error SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
|
||||||
|
"Service ~v not supported"
|
||||||
|
service)]))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Channel management
|
;; Channel management
|
||||||
|
@ -518,65 +527,78 @@
|
||||||
;; '())))
|
;; '())))
|
||||||
;; (transition conn)))
|
;; (transition conn)))
|
||||||
|
|
||||||
;; (define (start-connection-service conn)
|
(define (start-connection-service conn-ds authentication)
|
||||||
;; (sequence-actions
|
(match-define (authenticated user-name _service-name) authentication)
|
||||||
;; (transition
|
|
||||||
;; (set-handlers conn
|
|
||||||
;; ;; TODO: SSH_MSG_GLOBAL_REQUEST handle-msg-global-request
|
|
||||||
;; SSH_MSG_CHANNEL_OPEN handle-msg-channel-open
|
|
||||||
;; SSH_MSG_CHANNEL_OPEN_CONFIRMATION handle-msg-channel-open-confirmation
|
|
||||||
;; SSH_MSG_CHANNEL_OPEN_FAILURE handle-msg-channel-open-failure
|
|
||||||
;; SSH_MSG_CHANNEL_WINDOW_ADJUST handle-msg-channel-window-adjust
|
|
||||||
;; SSH_MSG_CHANNEL_DATA handle-msg-channel-data
|
|
||||||
;; SSH_MSG_CHANNEL_EXTENDED_DATA handle-msg-channel-extended-data
|
|
||||||
;; SSH_MSG_CHANNEL_EOF handle-msg-channel-eof
|
|
||||||
;; SSH_MSG_CHANNEL_CLOSE handle-msg-channel-close
|
|
||||||
;; SSH_MSG_CHANNEL_REQUEST handle-msg-channel-request
|
|
||||||
;; SSH_MSG_CHANNEL_SUCCESS handle-msg-channel-success
|
|
||||||
;; SSH_MSG_CHANNEL_FAILURE handle-msg-channel-failure))
|
|
||||||
;; ;; Start responding to channel interest coming from the
|
|
||||||
;; ;; application. We are responding to channels appearing from the
|
|
||||||
;; ;; remote peer by virtue of our installation of the handler for
|
|
||||||
;; ;; SSH_MSG_CHANNEL_OPEN above.
|
|
||||||
;; (observe-subscribers (channel-message (channel-stream-name ? (channel-name #t ? ?)) ?)
|
|
||||||
;; (match-state conn
|
|
||||||
;; (match-conversation (channel-message (channel-stream-name #t cname) _)
|
|
||||||
;; (on-presence (respond-to-opened-outbound-channel conn cname)))))
|
|
||||||
;; (observe-publishers (channel-message (channel-stream-name ? (channel-name #t ? ?)) ?)
|
|
||||||
;; (match-state conn
|
|
||||||
;; (match-conversation (channel-message (channel-stream-name #f cname) _)
|
|
||||||
;; (on-presence (respond-to-opened-outbound-channel conn cname)))))))
|
|
||||||
|
|
||||||
;; (define (handle-msg-channel-open packet message conn)
|
(handle-msg-channel-open conn-ds)
|
||||||
;; (match-define (ssh-msg-channel-open channel-type*
|
|
||||||
;; remote-ref
|
|
||||||
;; initial-window-size
|
|
||||||
;; maximum-packet-size
|
|
||||||
;; extra-request-data*)
|
|
||||||
;; message)
|
|
||||||
|
|
||||||
;; (when (memf (lambda (c) (equal? (ssh-channel-remote-ref c) remote-ref))
|
;; (set-handlers conn
|
||||||
;; (connection-channels conn))
|
;; ;; TODO: SSH_MSG_GLOBAL_REQUEST handle-msg-global-request
|
||||||
;; (disconnect-with-error SSH_DISCONNECT_PROTOCOL_ERROR
|
;; SSH_MSG_CHANNEL_OPEN handle-msg-channel-open
|
||||||
;; "Attempt to open already-open channel ~v"
|
;; SSH_MSG_CHANNEL_OPEN_CONFIRMATION handle-msg-channel-open-confirmation
|
||||||
;; remote-ref))
|
;; SSH_MSG_CHANNEL_OPEN_FAILURE handle-msg-channel-open-failure
|
||||||
|
;; SSH_MSG_CHANNEL_WINDOW_ADJUST handle-msg-channel-window-adjust
|
||||||
|
;; SSH_MSG_CHANNEL_DATA handle-msg-channel-data
|
||||||
|
;; SSH_MSG_CHANNEL_EXTENDED_DATA handle-msg-channel-extended-data
|
||||||
|
;; SSH_MSG_CHANNEL_EOF handle-msg-channel-eof
|
||||||
|
;; SSH_MSG_CHANNEL_CLOSE handle-msg-channel-close
|
||||||
|
;; SSH_MSG_CHANNEL_REQUEST handle-msg-channel-request
|
||||||
|
;; SSH_MSG_CHANNEL_SUCCESS handle-msg-channel-success
|
||||||
|
;; SSH_MSG_CHANNEL_FAILURE handle-msg-channel-failure))
|
||||||
|
|
||||||
;; (define channel-type (bit-string->bytes channel-type*))
|
;; (at conn-ds
|
||||||
;; (define extra-request-data (bit-string->bytes extra-request-data*))
|
;; (during ...))
|
||||||
;; (define cname (channel-name #f channel-type remote-ref))
|
;; ;; Start responding to channel interest coming from the
|
||||||
|
;; ;; application. We are responding to channels appearing from the
|
||||||
|
;; ;; remote peer by virtue of our installation of the handler for
|
||||||
|
;; ;; SSH_MSG_CHANNEL_OPEN above.
|
||||||
|
;; (observe-subscribers (channel-message (channel-stream-name ? (channel-name #t ? ?)) ?)
|
||||||
|
;; (match-state conn
|
||||||
|
;; (match-conversation (channel-message (channel-stream-name #t cname) _)
|
||||||
|
;; (on-presence (respond-to-opened-outbound-channel conn cname)))))
|
||||||
|
;; (observe-publishers (channel-message (channel-stream-name ? (channel-name #t ? ?)) ?)
|
||||||
|
;; (match-state conn
|
||||||
|
;; (match-conversation (channel-message (channel-stream-name #f cname) _)
|
||||||
|
;; (on-presence (respond-to-opened-outbound-channel conn cname)))))
|
||||||
|
(void)
|
||||||
|
)
|
||||||
|
|
||||||
;; (transition (update-channel cname
|
(define (handle-msg-channel-open conn-ds)
|
||||||
;; (lambda (e) (struct-copy ssh-channel e [remote-ref remote-ref]))
|
(void)
|
||||||
;; conn)
|
;; (at conn-ds
|
||||||
;; (channel-endpoints cname
|
;; (with-incoming-task (seq SSH_MSG_CHANNEL_OPEN _ (ssh-msg-channel-open $channel-type
|
||||||
;; (lambda (inbound-stream outbound-stream)
|
;; $remote-ref
|
||||||
;; (list (send-feedback
|
;; $initial-window-size
|
||||||
;; (channel-message outbound-stream
|
;; $maximum-packet-size
|
||||||
;; (channel-stream-config maximum-packet-size
|
;; $extra-request-data))
|
||||||
;; extra-request-data)))
|
;; (react
|
||||||
;; (send-feedback
|
;; (at conn-ds
|
||||||
;; (channel-message outbound-stream
|
;; (when (asserted (Observe (:pattern (
|
||||||
;; (channel-stream-credit initial-window-size))))))))
|
;; (sync! conn-ds
|
||||||
|
;; (
|
||||||
|
;; (when (memf (lambda (c) (equal? (ssh-channel-remote-ref c) remote-ref))
|
||||||
|
;; (connection-channels conn))
|
||||||
|
;; (disconnect-with-error SSH_DISCONNECT_PROTOCOL_ERROR
|
||||||
|
;; "Attempt to open already-open channel ~v"
|
||||||
|
;; remote-ref))
|
||||||
|
|
||||||
|
;; (define channel-type (bit-string->bytes channel-type*))
|
||||||
|
;; (define extra-request-data (bit-string->bytes extra-request-data*))
|
||||||
|
;; (define cname (channel-name #f channel-type remote-ref))
|
||||||
|
|
||||||
|
;; (transition (update-channel cname
|
||||||
|
;; (lambda (e) (struct-copy ssh-channel e [remote-ref remote-ref]))
|
||||||
|
;; conn)
|
||||||
|
;; (channel-endpoints cname
|
||||||
|
;; (lambda (inbound-stream outbound-stream)
|
||||||
|
;; (list (send-feedback
|
||||||
|
;; (channel-message outbound-stream
|
||||||
|
;; (channel-stream-config maximum-packet-size
|
||||||
|
;; extra-request-data)))
|
||||||
|
;; (send-feedback
|
||||||
|
;; (channel-message outbound-stream
|
||||||
|
;; (channel-stream-credit initial-window-size))))))))
|
||||||
|
)
|
||||||
|
|
||||||
;; (define (handle-msg-channel-open-confirmation packet message conn)
|
;; (define (handle-msg-channel-open-confirmation packet message conn)
|
||||||
;; (match-define (ssh-msg-channel-open-confirmation local-ref
|
;; (match-define (ssh-msg-channel-open-confirmation local-ref
|
||||||
|
@ -674,59 +696,48 @@
|
||||||
(define-field total-transferred 0)
|
(define-field total-transferred 0)
|
||||||
(define-field discard-next-packet? #f)
|
(define-field discard-next-packet? #f)
|
||||||
|
|
||||||
(define authentication-state #f)
|
|
||||||
(define channels '())
|
(define channels '())
|
||||||
(define is-server? (case session-role ((client) #f) ((server) #t)))
|
|
||||||
|
|
||||||
(at conn-ds
|
(at conn-ds
|
||||||
(when (message (task $seq SSH_MSG_DISCONNECT _
|
(with-incoming-task (seq SSH_MSG_DISCONNECT _
|
||||||
(ssh-msg-disconnect $reason-code $description $language-tag)))
|
(ssh-msg-disconnect $reason-code $description $language-tag))
|
||||||
(disconnect-with-error* conn-ds #t
|
(disconnect-with-error* conn-ds #t
|
||||||
'()
|
'()
|
||||||
reason-code
|
reason-code
|
||||||
"Received SSH_MSG_DISCONNECT with reason code ~a and message ~s"
|
"Received SSH_MSG_DISCONNECT with reason code ~a and message ~s"
|
||||||
reason-code
|
reason-code
|
||||||
(bytes->string/utf-8 (bit-string->bytes description)))
|
(bytes->string/utf-8 (bit-string->bytes description))))
|
||||||
(send! conn-ds (task-complete seq)))
|
|
||||||
|
|
||||||
(when (message (task $seq SSH_MSG_IGNORE _ (ssh-msg-ignore _)))
|
(with-incoming-task (seq SSH_MSG_IGNORE _ (ssh-msg-ignore _)))
|
||||||
(send! conn-ds (task-complete seq)))
|
|
||||||
|
|
||||||
(when (message (task $seq SSH_MSG_UNIMPLEMENTED _ (ssh-msg-unimplemented $peer-seq)))
|
(with-incoming-task (seq SSH_MSG_UNIMPLEMENTED _ (ssh-msg-unimplemented $peer-seq))
|
||||||
(disconnect-with-error/local-info
|
(disconnect-with-error/local-info
|
||||||
conn-ds
|
conn-ds
|
||||||
`((offending-sequence-number ,peer-seq))
|
`((offending-sequence-number ,peer-seq))
|
||||||
SSH_DISCONNECT_PROTOCOL_ERROR
|
SSH_DISCONNECT_PROTOCOL_ERROR
|
||||||
"Disconnecting because of received SSH_MSG_UNIMPLEMENTED.")
|
"Disconnecting because of received SSH_MSG_UNIMPLEMENTED."))
|
||||||
(send! conn-ds (task-complete seq)))
|
|
||||||
|
|
||||||
(when (message (task $seq SSH_MSG_DEBUG _ ($ message (ssh-msg-debug _ _ _))))
|
(with-incoming-task (seq SSH_MSG_DEBUG _ ($ message (ssh-msg-debug _ _ _)))
|
||||||
(log-info (format "Received SSHv2 SSH_MSG_DEBUG packet ~v" message))
|
(log-info (format "Received SSHv2 SSH_MSG_DEBUG packet ~v" message)))
|
||||||
(send! conn-ds (task-complete seq)))
|
|
||||||
|
|
||||||
(when (message (task $seq SSH_MSG_KEXINIT $packet
|
(with-incoming-task (seq SSH_MSG_KEXINIT $packet
|
||||||
($ message (ssh-msg-kexinit _ _ _ _ _ _ _ _ _ _ _ _ _))))
|
($ message (ssh-msg-kexinit _ _ _ _ _ _ _ _ _ _ _ _ _)))
|
||||||
(do-kexinit conn-ds
|
(do-kexinit conn-ds
|
||||||
ground-ds
|
ground-ds
|
||||||
#:packet packet
|
#:packet packet
|
||||||
#:message message
|
#:message message
|
||||||
#:rekey-state rekey-state
|
#:rekey-state rekey-state
|
||||||
#:is-server? is-server?
|
#:is-server? (case session-role ((client) #f) ((server) #t))
|
||||||
#:local-id local-identification-string
|
#:local-id local-identification-string
|
||||||
#:remote-id peer-identification-string
|
#:remote-id peer-identification-string
|
||||||
#:session-id session-id
|
#:session-id session-id
|
||||||
#:total-transferred total-transferred
|
#:total-transferred total-transferred
|
||||||
#:discard-next-packet? discard-next-packet?)
|
#:discard-next-packet? discard-next-packet?)))
|
||||||
(send! conn-ds (task-complete seq)))
|
|
||||||
|
|
||||||
(when (message 'enable-service-request!)
|
(react
|
||||||
(log-info "Saw enable-service-request!")
|
(at conn-ds
|
||||||
;; TODO::
|
(stop-when (message 'enable-service-request-handler)
|
||||||
;; (set-handlers
|
(spawn #:name 'service-request-handler (service-request-handler conn-ds)))))
|
||||||
;; (struct-copy connection conn [rekey-state new-rekey-state])
|
|
||||||
;; SSH_MSG_SERVICE_REQUEST handle-msg-service-request)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
(define (maybe-rekey)
|
(define (maybe-rekey)
|
||||||
(match (rekey-state)
|
(match (rekey-state)
|
||||||
|
@ -768,14 +779,11 @@
|
||||||
(react
|
(react
|
||||||
(on-start
|
(on-start
|
||||||
(send! conn-ds (task sequence-number packet-type-number payload message)))
|
(send! conn-ds (task sequence-number packet-type-number payload message)))
|
||||||
(let ((handler-present #f))
|
(with-assertion-presence conn-ds
|
||||||
(at conn-ds
|
(Observe (:pattern (task ,_ packet-type-number ,_ ,_)) _)
|
||||||
(when (asserted (Observe (:pattern (task ,_ packet-type-number ,_ ,_)) _))
|
#:on-present []
|
||||||
(set! handler-present #t)))
|
#:on-absent [(send! conn-ds (outbound-packet (ssh-msg-unimplemented sequence-number)))
|
||||||
(sync! conn-ds
|
(send! conn-ds (task-complete sequence-number))])
|
||||||
(when (not handler-present)
|
|
||||||
(send! conn-ds (outbound-packet (ssh-msg-unimplemented sequence-number)))
|
|
||||||
(send! conn-ds (task-complete sequence-number)))))
|
|
||||||
(at conn-ds (stop-when (message (task-complete sequence-number))))
|
(at conn-ds (stop-when (message (task-complete sequence-number))))
|
||||||
(on-stop (send! conn-ds (inbound-credit 1)))))))
|
(on-stop (send! conn-ds (inbound-credit 1)))))))
|
||||||
(total-transferred (+ (total-transferred) transfer-size))
|
(total-transferred (+ (total-transferred) transfer-size))
|
||||||
|
|
|
@ -258,7 +258,14 @@
|
||||||
;; Encrypted Packet Input
|
;; Encrypted Packet Input
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(define (ssh-reader conn-ds conn update-input-handler)
|
(define (ssh-reader conn-ds conn transfer-control)
|
||||||
|
(define input-handler #f)
|
||||||
|
(define (update-input-handler #:on-data proc) (set! input-handler proc))
|
||||||
|
(assert-control conn
|
||||||
|
#:on-eof (lambda () (stop-current-facet))
|
||||||
|
#:on-data (lambda (data mode) (input-handler data mode)))
|
||||||
|
(send! transfer-control 'transfer-control)
|
||||||
|
|
||||||
(define packet-size-limit (default-packet-limit))
|
(define packet-size-limit (default-packet-limit))
|
||||||
(define sequence-number 0)
|
(define sequence-number 0)
|
||||||
(define remaining-credit 0)
|
(define remaining-credit 0)
|
||||||
|
@ -274,7 +281,7 @@
|
||||||
|
|
||||||
(define (issue-credit)
|
(define (issue-credit)
|
||||||
(when (positive? remaining-credit)
|
(when (positive? remaining-credit)
|
||||||
(send-bytes-credit conn (block-size))))
|
(send-packet-credit conn (block-size))))
|
||||||
|
|
||||||
(define (handle-packet-header encrypted-packet _mode)
|
(define (handle-packet-header encrypted-packet _mode)
|
||||||
(define first-block (decrypt-chunk encrypted-packet))
|
(define first-block (decrypt-chunk encrypted-packet))
|
||||||
|
@ -284,11 +291,11 @@
|
||||||
(define remaining-to-read (- packet-length amount-of-packet-in-first-block))
|
(define remaining-to-read (- packet-length amount-of-packet-in-first-block))
|
||||||
(if (positive? remaining-to-read)
|
(if (positive? remaining-to-read)
|
||||||
(begin
|
(begin
|
||||||
(send-bytes-credit conn remaining-to-read)
|
(send-packet-credit conn remaining-to-read)
|
||||||
(update-input-handler
|
(update-input-handler
|
||||||
#:on-data (lambda (encrypted-packet _mode)
|
#:on-data (lambda (encrypted-packet _mode)
|
||||||
(check-hmac (bytes-append first-block (decrypt-chunk encrypted-packet))
|
(define subsequent-chunk (decrypt-chunk encrypted-packet))
|
||||||
packet-length))))
|
(check-hmac (bytes-append first-block subsequent-chunk) packet-length))))
|
||||||
(check-hmac first-block packet-length)))
|
(check-hmac first-block packet-length)))
|
||||||
|
|
||||||
(define (check-hmac packet packet-length)
|
(define (check-hmac packet packet-length)
|
||||||
|
@ -298,7 +305,7 @@
|
||||||
(define mac-byte-count (bytes-length computed-hmac-bytes))
|
(define mac-byte-count (bytes-length computed-hmac-bytes))
|
||||||
(if (positive? mac-byte-count)
|
(if (positive? mac-byte-count)
|
||||||
(begin
|
(begin
|
||||||
(send-bytes-credit conn mac-byte-count)
|
(send-packet-credit conn mac-byte-count)
|
||||||
(update-input-handler
|
(update-input-handler
|
||||||
#:on-data (lambda (received-hmac-bytes _mode)
|
#:on-data (lambda (received-hmac-bytes _mode)
|
||||||
(if (equal? computed-hmac-bytes received-hmac-bytes)
|
(if (equal? computed-hmac-bytes received-hmac-bytes)
|
||||||
|
@ -322,9 +329,7 @@
|
||||||
(set! remaining-credit (- remaining-credit 1))
|
(set! remaining-credit (- remaining-credit 1))
|
||||||
(issue-credit))
|
(issue-credit))
|
||||||
|
|
||||||
(update-input-handler
|
(update-input-handler #:on-data handle-packet-header)
|
||||||
#:on-eof (lambda () (stop-current-facet))
|
|
||||||
#:on-data handle-packet-header)
|
|
||||||
|
|
||||||
(at conn-ds
|
(at conn-ds
|
||||||
(when (message (inbound-credit $amount))
|
(when (message (inbound-credit $amount))
|
||||||
|
@ -338,8 +343,6 @@
|
||||||
;; Encrypted Packet Output
|
;; Encrypted Packet Output
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; (struct ssh-writer-state (config sequence-number) #:prefab)
|
|
||||||
|
|
||||||
(define (ssh-writer conn-ds conn)
|
(define (ssh-writer conn-ds conn)
|
||||||
(define config initial-crypto-configuration)
|
(define config initial-crypto-configuration)
|
||||||
(define sequence-number 0)
|
(define sequence-number 0)
|
||||||
|
|
Loading…
Reference in New Issue