diff --git a/.travis.yml b/.travis.yml index c6dcc83c7e..6fbfc591e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,45 +2,53 @@ jobs: include: - os: linux language: nix - nix: 2.1.3 - env: STACK_YAML=pkg/hs/stack.yaml + nix: 2.3.6 before_install: - git lfs pull - - sh/travis-install-stack - install: - nix-env -iA cachix -f https://cachix.org/api/v1/install - - stack --no-terminal --install-ghc build urbit-king --only-dependencies - script: - cachix use urbit2 - ./sh/cachix - make build - make release - - sh/release-king-linux64-dynamic - sh/ci-tests + - os: linux + language: generic + env: STACK_YAML=pkg/hs/stack.yaml + cache: + directories: + - $HOME/.ghc + - $HOME/.cabal + - $HOME/.stack + - $TRAVIS_BUILD_DIR/.stack-work + before_install: + - sh/travis-install-stack + install: + - stack --no-terminal --install-ghc build urbit-king --only-dependencies + script: + - stack test + - sh/release-king-linux64-dynamic + - os: osx language: generic sudo: required env: STACK_YAML=pkg/hs/stack.yaml - + cache: + directories: + - $HOME/.ghc + - $HOME/.cabal + - $HOME/.stack + - $TRAVIS_BUILD_DIR/.stack-work before_install: - sh/travis-install-stack - install: - stack --no-terminal --install-ghc build urbit-king --only-dependencies - script: + - stack test - sh/release-king-darwin-dynamic -cache: - directories: - - $HOME/.ghc - - $HOME/.cabal - - $HOME/.stack - - $TRAVIS_BUILD_DIR/.stack-work - deploy: - skip_cleanup: true provider: gcs diff --git a/bin/solid.pill b/bin/solid.pill index 30d0e94e1d..f125db3892 100644 --- a/bin/solid.pill +++ b/bin/solid.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd9ee3401fd2a29fc49ef84aa51754be5929f2cddbb7e378ffac4641695e886c -size 13838435 +oid sha256:657e130a063598dc9e4800039f6dde1e7e4b7a3c56e57561a46a4f06641da48e +size 17337052 diff --git a/nix/ops/test/builder.sh b/nix/ops/test/builder.sh index 875be32b3b..4a852ab3f5 100644 --- a/nix/ops/test/builder.sh +++ b/nix/ops/test/builder.sh @@ -38,8 +38,9 @@ herb ./ship -p test -d ':- %renders /' herb ./ship -d '~& %finish-test-renders ~' # Run the test generator -herb ./ship -d '+test, =seed `@uvI`(shaz %reproducible)' | - tee test-generator-output +herb ./ship -d '+test, =seed `@uvI`(shaz %reproducible)' > test-generator-output + +cat test-generator-output || true herb ./ship -p hood -d '+hood/mass' diff --git a/pkg/arvo/app/chat-hook.hoon b/pkg/arvo/app/chat-hook.hoon index c582ea5505..c4c98266ef 100644 --- a/pkg/arvo/app/chat-hook.hoon +++ b/pkg/arvo/app/chat-hook.hoon @@ -381,6 +381,7 @@ :* [%give %kick ~[[%mailbox path.act]] ~] [%give %fact [/synced]~ %chat-hook-update !>([%initial synced])] (pull-wire u.ship [%mailbox path.act]) + (pull-wire u.ship [%store path.act]) (pull-backlog-subscriptions u.ship path.act) == == diff --git a/pkg/arvo/app/dbug.hoon b/pkg/arvo/app/dbug.hoon index 90124315bd..a45e8d6a2b 100644 --- a/pkg/arvo/app/dbug.hoon +++ b/pkg/arvo/app/dbug.hoon @@ -360,12 +360,13 @@ :- %a %+ turn %+ sort ~(tap by sessions:auth-state:v-eyre) - |= [[@uv a=@da] [@uv b=@da]] - (gth a b) + |= [[@uv a=session:eyre] [@uv b=session:eyre]] + (gth expiry-time.a expiry-time.b) |= [cookie=@uv session:eyre] %- pairs :~ 'cookie'^s+(end 3 4 (rsh 3 2 (scot %x (shax cookie)))) 'expiry'^(time expiry-time) + 'channels'^(numb ~(wyt in channels)) == :: :: /eyre/channels.json diff --git a/pkg/arvo/sys/arvo.hoon b/pkg/arvo/sys/arvo.hoon index 20b5147ce2..0bbf9622f8 100644 --- a/pkg/arvo/sys/arvo.hoon +++ b/pkg/arvo/sys/arvo.hoon @@ -1213,7 +1213,7 @@ :: =/ raw ~& [%hoon-compile `@p`(mug hun)] - (ride %noun hun) + (road |.((ride %noun hun))) :: activate the new compiler gate, producing +ride :: =/ cop .*(0 +.raw) @@ -1226,11 +1226,13 @@ :: :: hot: raw compiler formula :: - => ?: =(nex hoon-version) - [hot=`*`raw .] - ~& [%hoon-compile-upgrade nex] - =/ hot (slum cop [%noun hun]) - .(cop .*(0 +.hot)) + =^ hot=* cop + ?: =(nex hoon-version) + [raw cop] + ~& [%hoon-compile-upgrade nex] + %- road |. + =/ hot (slum cop [%noun hun]) + [hot .*(0 +.hot)] :: extract the hoon core from the outer gate (+ride) :: =/ hoc .*(cop [%0 7]) @@ -1241,7 +1243,7 @@ :: =/ rav ~& [%arvo-compile `@p`(mug hyp) `@p`(mug van)] - (slum cop [hyp van]) + (road |.((slum cop [hyp van]))) :: activate arvo, and extract the arvo core from the outer gate :: =/ voc .*(hoc [%7 +.rav %0 7]) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 43dc11b615..209d54ca48 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -12035,6 +12035,15 @@ ?~ a !! ~_(i.a $(a t.a)) :: +++ road + |* =(trap *) + ^+ $:trap + =/ res (mule trap) + ?- -.res + %& p.res + %| (mean leaf+"road: new" p.res) + == +:: ++ slew :: get axis in vase |= {axe/@ vax/vase} ^- (unit vase) ?. |- ^- ? diff --git a/pkg/arvo/sys/vane/eyre.hoon b/pkg/arvo/sys/vane/eyre.hoon index 5cb26cdf35..5e21a9e750 100644 --- a/pkg/arvo/sys/vane/eyre.hoon +++ b/pkg/arvo/sys/vane/eyre.hoon @@ -970,7 +970,7 @@ =/ first-session=? =(~ sessions.authentication-state.state) =/ expires-at=@da (add now session-timeout) =. sessions.authentication-state.state - (~(put by sessions.authentication-state.state) session expires-at) + (~(put by sessions.authentication-state.state) session [expires-at ~]) :: =/ cookie-line=@t (session-cookie-string session &) @@ -1027,15 +1027,33 @@ (handle-response response) :: delete the requesting session, or all sessions if so specified :: - =. sessions.authentication-state.state - =; all=? - ?: all ~ - (~(del by sessions.authentication-state.state) u.session-id) - ?~ body.request | - =- ?=(^ -) - %+ get-header:http 'all' - (fall (rush q.u.body.request yquy:de-purl:html) ~) - (handle-response response) + =^ channels=(list @t) sessions.authentication-state.state + =* sessions sessions.authentication-state.state + =/ all=? + ?~ body.request | + =- ?=(^ -) + %+ get-header:http 'all' + (fall (rush q.u.body.request yquy:de-purl:html) ~) + ?. all + :_ (~(del by sessions) u.session-id) + %~ tap in + channels:(~(gut by sessions) u.session-id *session) + :_ ~ + %~ tap in + %+ roll ~(val by sessions) + |= [session all=(set @t)] + (~(uni in all) channels) + :: close all affected channels, then send the response + :: + =| moves=(list move) + |- ^- (quip move server-state) + ?~ channels + =^ moz state + (handle-response response) + [(weld moves moz) state] + =^ moz state + (discard-channel:by-channel i.channels |) + $(moves (weld moves moz), channels t.channels) :: +session-id-from-request: attempt to find a session cookie :: ++ session-id-from-request @@ -1326,6 +1344,16 @@ :: =. duct-to-key.channel-state.state (~(put by duct-to-key.channel-state.state) duct channel-id) + :: associate this channel with the session cookie + :: + =. sessions.authentication-state.state + =/ session-id=(unit @uv) + (session-id-from-request:authentication request) + ?~ session-id sessions.authentication-state.state + %+ ~(jab by sessions.authentication-state.state) + u.session-id + |= =session + session(channels (~(put in channels.session) channel-id)) :: initialize sse heartbeat :: =/ heartbeat-time=@da (add now ~s20) @@ -1487,50 +1515,10 @@ $(requests t.requests) :: %delete - =/ unitsession - (~(get by session.channel-state.state) channel-id) - :: - ?~ unitsession - $(requests t.requests) - :: - =/ session u.unitsession - =. session.channel-state.state - (~(del by session.channel-state.state) channel-id) - :: + =^ moves state + (discard-channel channel-id |) =. gall-moves - %+ weld gall-moves - :: - :: produce a list of moves which cancels every gall subscription - :: - %+ turn ~(tap by subscriptions.session) - |= [channel-wire=wire ship=@p app=term =path duc=^duct] - ^- move - :: - [duc %pass channel-wire [%g %deal [our ship] app %leave ~]] - :: - ?: ?=([%& *] state.session) - =. gall-moves - :_ gall-moves - :: - ^- move - ?> ?=([%& *] state.session) - :^ duct.p.state.session %pass /channel/timeout/[channel-id] - [%b %rest date.p.state.session] - :: - $(requests t.requests) - :: - ?> ?=([%| *] state.session) - =. duct-to-key.channel-state.state - (~(del by duct-to-key.channel-state.state) p.state.session) - :: - ?~ heartbeat.session $(requests t.requests) - =. gall-moves - %+ snoc gall-moves - %^ cancel-heartbeat-move - channel-id - date.u.heartbeat.session - duct.u.heartbeat.session - :: + (weld gall-moves moves) $(requests t.requests) :: == @@ -1672,10 +1660,12 @@ channel(heartbeat (some [heartbeat-time duct])) == (snoc http-moves (set-heartbeat-move channel-id heartbeat-time)) - :: +on-channel-timeout: we received a wake to clear an old session + :: +discard-channel: remove a channel from state :: - ++ on-channel-timeout - |= channel-id=@t + :: cleans up state, timers, and gall subscriptions of the channel + :: + ++ discard-channel + |= [channel-id=@t expired=?] ^- [(list move) server-state] :: =/ usession=(unit channel) @@ -1687,6 +1677,10 @@ :_ %_ state session.channel-state (~(del by session.channel-state.state) channel-id) + :: + duct-to-key.channel-state + ?. ?=(%| -.state.session) duct-to-key.channel-state.state + (~(del by duct-to-key.channel-state.state) p.state.session) == =/ heartbeat-cancel=(list move) ?~ heartbeat.session ~ @@ -1695,7 +1689,13 @@ date.u.heartbeat.session duct.u.heartbeat.session == + =/ expire-cancel=(list move) + ?: expired ~ + ?. ?=(%& -.state.session) ~ + =, p.state.session + [(cancel-timeout-move channel-id date duct)]~ %+ weld heartbeat-cancel + %+ weld expire-cancel :: produce a list of moves which cancels every gall subscription :: %+ turn ~(tap by subscriptions.session) @@ -1825,7 +1825,9 @@ :: tough luck, we don't create/revive sessions here :: no-op - :_ (~(put by sessions) u.session-id (add now session-timeout)) + :_ %+ ~(jab by sessions) u.session-id + |= =session + session(expiry-time (add now session-timeout)) =- response-header.http-event(headers -) %^ set-header:http 'set-cookie' (session-cookie-string u.session-id &) @@ -2109,13 +2111,7 @@ [(zing (flop moves)) http-server-gate] :: discard channel state, and cancel any active gall subscriptions :: - =^ mov server-state.ax (on-channel-timeout:by-channel channel-id) - :: cancel channel timer - :: - =/ channel (~(got by session.channel-state) channel-id) - =? mov ?=([%& *] state.channel) - :_ mov - (cancel-timeout-move:by-channel channel-id p.state.channel) + =^ mov server-state.ax (discard-channel:by-channel channel-id |) $(moves [mov moves], inactive t.inactive) :: :: %vega: notifies us of a completed kernel upgrade @@ -2363,10 +2359,10 @@ ?> ?=([%b %wake *] sign) ?^ error.sign [[duct %slip %d %flog %crud %wake u.error.sign]~ http-server-gate] - =/ on-channel-timeout - on-channel-timeout:by-channel:(per-server-event event-args) + =/ discard-channel + discard-channel:by-channel:(per-server-event event-args) =^ moves server-state.ax - (on-channel-timeout i.t.t.wire) + (discard-channel i.t.t.wire &) [moves http-server-gate] :: %heartbeat @@ -2398,11 +2394,9 @@ =* sessions sessions.authentication-state.server-state.ax =. sessions.authentication-state.server-state.ax %- ~(gas by *(map @uv session)) - %+ murn ~(tap in sessions) + %+ skip ~(tap in sessions) |= [cookie=@uv session] - ^- (unit [@uv session]) - ?: (lth expiry-time now) ~ - `[cookie expiry-time] + (lth expiry-time now) :: if there's any cookies left, set a timer for the next expected expiry :: ^- [(list move) _http-server-gate] @@ -2434,7 +2428,18 @@ ++ load => |% +$ axle-2019-10-6 - [date=%~2019.10.6 =server-state] + [date=%~2019.10.6 server-state=server-state-2019-10-6] + :: + +$ server-state-2019-10-6 + $: bindings=(list [=binding =duct =action]) + connections=(map duct outstanding-connection) + authentication-state=sessions=(map @uv @da) + =channel-state + domains=(set turf) + =http-config + ports=[insecure=@ud secure=(unit @ud)] + outgoing-duct=duct + == -- |= old=$%(axle axle-2019-10-6) ^+ ..^$ diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index d07200177c..11c5191940 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -1214,6 +1214,9 @@ :: to properly handle cookie expiration as a security mechanism. :: expiry-time=@da + :: channels: channels opened by this session + :: + channels=(set @t) :: :: TODO: We should add a system for individual capabilities; we should :: mint some sort of long lived cookie for mobile apps which only has @@ -3731,62 +3734,53 @@ :: :: ++s2va:aes:crypto ++ s2va :: AES-128 S2V ~/ %s2va - |= {key/@H ads/(list @)} - =+ res=(maca key `16 0x0) - %^ maca key ~ - |- ^- @uxH + |= [key=@H ads=(list @)] ?~ ads (maca key `16 0x1) + =/ res (maca key `16 0x0) + %+ maca key + |- ^- [[~ @ud] @uxH] ?~ t.ads - ?: (gte (xeb i.ads) 128) - (mix i.ads res) - %+ mix - (doub res) - (mpad (met 3 i.ads) i.ads) + =/ wyt (met 3 i.ads) + ?: (gte wyt 16) + [`wyt (mix i.ads res)] + [`16 (mix (doub res) (mpad wyt i.ads))] %= $ - res %+ mix - (doub res) - (maca key ~ i.ads) ads t.ads + res (mix (doub res) (maca key ~ i.ads)) == :: :: ++s2vb:aes:crypto ++ s2vb :: AES-192 S2V ~/ %s2vb - |= {key/@I ads/(list @)} - =+ res=(macb key `16 0x0) - %^ macb key ~ - |- ^- @uxH + |= [key=@I ads=(list @)] ?~ ads (macb key `16 0x1) + =/ res (macb key `16 0x0) + %+ macb key + |- ^- [[~ @ud] @uxH] ?~ t.ads - ?: (gte (xeb i.ads) 128) - (mix i.ads res) - %+ mix - (doub res) - (mpad (met 3 i.ads) i.ads) + =/ wyt (met 3 i.ads) + ?: (gte wyt 16) + [`wyt (mix i.ads res)] + [`16 (mix (doub res) (mpad wyt i.ads))] %= $ - res %+ mix - (doub res) - (macb key ~ i.ads) ads t.ads + res (mix (doub res) (macb key ~ i.ads)) == :: :: ++s2vc:aes:crypto ++ s2vc :: AES-256 S2V ~/ %s2vc - |= {key/@I ads/(list @)} - =+ res=(macc key `16 0x0) - %^ macc key ~ - |- ^- @uxH + |= [key=@I ads=(list @)] ?~ ads (macc key `16 0x1) + =/ res (macc key `16 0x0) + %+ macc key + |- ^- [[~ @ud] @uxH] ?~ t.ads - ?: (gte (xeb i.ads) 128) - (mix i.ads res) - %+ mix - (doub res) - (mpad (met 3 i.ads) i.ads) + =/ wyt (met 3 i.ads) + ?: (gte wyt 16) + [`wyt (mix i.ads res)] + [`16 (mix (doub res) (mpad wyt i.ads))] %= $ - res %+ mix - (doub res) - (macc key ~ i.ads) ads t.ads + res (mix (doub res) (macc key ~ i.ads)) == :: :: ++siva:aes:crypto ++ siva :: AES-128 SIV diff --git a/pkg/arvo/tests/sys/zuse/crypto/aes.hoon b/pkg/arvo/tests/sys/zuse/crypto/aes.hoon index e3b8126a33..840e7de214 100644 --- a/pkg/arvo/tests/sys/zuse/crypto/aes.hoon +++ b/pkg/arvo/tests/sys/zuse/crypto/aes.hoon @@ -567,6 +567,18 @@ ^- (list vector-siv) :~ :: + :: failed in the wild, see https://github.com/urbit/urbit/pull/3013 + :: + :^ 0xfdef.6253.d284.a940.1b5d.d1b7.fbcd.4489. + 3071.bf93.ace9.37da.7c5d.77d2.1f3e.cda4. + 83be.1c51.a88b.c9ba.8741.e1ee.935b.c0ef. + 888a.feff.0249.bdb6.1344.0ff9.4e1b.fca5 + ad=~ + inp=0x97.0341.38e3.960e.87e1 + :+ iv=0x249f.85e3.c9a8.29b6.3122.ec22.cde6.76df + len=9 + cph=0xdc.bdcd.e4f1.4fd4.2d8d + :: :: from RFC 5297, with extended key :: :^ 0xfffe.fdfc.fbfa.f9f8.f7f6.f5f4.f3f2.f1f0. diff --git a/pkg/interface/dbug/src/js/views/eyre.js b/pkg/interface/dbug/src/js/views/eyre.js index 88e4bde911..738a685cf1 100644 --- a/pkg/interface/dbug/src/js/views/eyre.js +++ b/pkg/interface/dbug/src/js/views/eyre.js @@ -146,7 +146,7 @@ export class Eyre extends Component { const sessionItems = props.authentication.map(s => { return (
- {`${s.cookie} expires ${msToDa(s.expiry)}`} + {`${s.cookie} expires ${msToDa(s.expiry)}, uses ${s.channels} channel(s)`}
); }); diff --git a/sh/ci-tests b/sh/ci-tests index 1ca8f1b3ca..3a53726535 100755 --- a/sh/ci-tests +++ b/sh/ci-tests @@ -2,10 +2,6 @@ set -ex -export STACK_YAML="`pwd`/pkg/hs/stack.yaml" - -stack test urbit-king - if [ "$TRAVIS_PULL_REQUEST" = false ] then diff --git a/sh/test b/sh/test index dac77b5a8a..c3b7f37081 100755 --- a/sh/test +++ b/sh/test @@ -2,8 +2,6 @@ set -e -stack test urbit-king --fast - pkg=$(nix-build nix/ops -A test --no-out-link "$@") hdr () {