spec-3nweb-server 1.8.4 → 1.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitlab-ci-linux.yml +50 -0
- package/.gitlab-ci-mac.yml +29 -0
- package/.gitlab-ci-windows.yml +29 -0
- package/.gitlab-ci.yml +63 -0
- package/build/3nstorage/routes/owner/archive-obj-version.js +2 -2
- package/build/3nstorage/routes/owner/cancel-trans.js +2 -2
- package/build/3nstorage/routes/owner/delete-obj.js +2 -2
- package/build/3nstorage/routes/owner/get-current-obj.js +3 -4
- package/build/3nstorage/routes/owner/param-setter.js +2 -6
- package/build/asmail/routes/config/param-setter.js +2 -2
- package/build/asmail/routes/delivery/finalize-delivery.js +2 -2
- package/build/asmail/routes/delivery/put-obj.js +2 -2
- package/build/asmail/routes/delivery/sender-authorization.js +2 -2
- package/build/asmail/routes/retrieval/remove-message.js +2 -2
- package/build/cli/signup-cmd.js +0 -1
- package/build/lib-server/routes/sessions/close.js +2 -2
- package/build/lib-server/routes/sessions/mid-auth.js +2 -5
- package/build/main.js +12 -15
- package/build/mock/tls-options.js +46 -44
- package/build/signup/routes/add.js +4 -4
- package/build/tests/admin-proto/signup.d.ts +1 -0
- package/build/tests/admin-proto/signup.js +235 -0
- package/build/tests/jasmine.d.ts +1 -0
- package/build/tests/jasmine.js +32 -0
- package/build/tests/libs-for-tests/3nstorage.d.ts +22 -0
- package/build/tests/libs-for-tests/3nstorage.js +123 -0
- package/build/tests/libs-for-tests/asmail.d.ts +22 -0
- package/build/tests/libs-for-tests/asmail.js +179 -0
- package/build/tests/libs-for-tests/assert.d.ts +1 -0
- package/build/tests/libs-for-tests/assert.js +26 -0
- package/build/tests/libs-for-tests/async-jasmine.d.ts +7 -0
- package/build/tests/libs-for-tests/async-jasmine.js +77 -0
- package/build/tests/libs-for-tests/bytes-equal.d.ts +1 -0
- package/build/tests/libs-for-tests/bytes-equal.js +34 -0
- package/build/tests/libs-for-tests/json-copy.d.ts +1 -0
- package/build/tests/libs-for-tests/json-copy.js +45 -0
- package/build/tests/libs-for-tests/json-equal.d.ts +4 -0
- package/build/tests/libs-for-tests/json-equal.js +67 -0
- package/build/tests/libs-for-tests/mailerid.d.ts +13 -0
- package/build/tests/libs-for-tests/mailerid.js +114 -0
- package/build/tests/libs-for-tests/pkl.d.ts +28 -0
- package/build/tests/libs-for-tests/pkl.js +89 -0
- package/build/tests/libs-for-tests/server-components/3nstorage.d.ts +20 -0
- package/build/tests/libs-for-tests/server-components/3nstorage.js +200 -0
- package/build/tests/libs-for-tests/server-components/admin.d.ts +6 -0
- package/build/tests/libs-for-tests/server-components/admin.js +43 -0
- package/build/tests/libs-for-tests/server-components/asmail.d.ts +16 -0
- package/build/tests/libs-for-tests/server-components/asmail.js +143 -0
- package/build/tests/libs-for-tests/server-components/component.d.ts +13 -0
- package/build/tests/libs-for-tests/server-components/component.js +77 -0
- package/build/tests/libs-for-tests/server-components/mailerid.d.ts +10 -0
- package/build/tests/libs-for-tests/server-components/mailerid.js +103 -0
- package/build/tests/libs-for-tests/server-runner.d.ts +15 -0
- package/build/tests/libs-for-tests/server-runner.js +69 -0
- package/build/tests/libs-for-tests/spec-assembly.d.ts +6 -0
- package/build/tests/libs-for-tests/spec-assembly.js +55 -0
- package/build/tests/libs-for-tests/ws-utils.d.ts +3 -0
- package/build/tests/libs-for-tests/ws-utils.js +59 -0
- package/build/tests/libs-for-tests/xhr-utils.d.ts +61 -0
- package/build/tests/libs-for-tests/xhr-utils.js +154 -0
- package/build/tests/protocols/3nstorage/owner/specs/archive-obj-ver.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/archive-obj-ver.js +84 -0
- package/build/tests/protocols/3nstorage/owner/specs/archive-root-ver.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/archive-root-ver.js +78 -0
- package/build/tests/protocols/3nstorage/owner/specs/delete-archive-obj-ver.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/delete-archive-obj-ver.js +83 -0
- package/build/tests/protocols/3nstorage/owner/specs/delete-archive-root-ver.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/delete-archive-root-ver.js +77 -0
- package/build/tests/protocols/3nstorage/owner/specs/delete-obj.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/delete-obj.js +75 -0
- package/build/tests/protocols/3nstorage/owner/specs/events.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/events.js +91 -0
- package/build/tests/protocols/3nstorage/owner/specs/get-current-obj.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/get-current-obj.js +269 -0
- package/build/tests/protocols/3nstorage/owner/specs/get-current-root.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/get-current-root.js +262 -0
- package/build/tests/protocols/3nstorage/owner/specs/get-obj-status.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/get-obj-status.js +79 -0
- package/build/tests/protocols/3nstorage/owner/specs/get-root-status.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/get-root-status.js +72 -0
- package/build/tests/protocols/3nstorage/owner/specs/put-current-obj.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/put-current-obj.js +287 -0
- package/build/tests/protocols/3nstorage/owner/specs/put-current-root.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/put-current-root.js +274 -0
- package/build/tests/protocols/3nstorage/owner/specs/trans-cancel-root.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/trans-cancel-root.js +73 -0
- package/build/tests/protocols/3nstorage/owner/specs/trans-cancel.d.ts +2 -0
- package/build/tests/protocols/3nstorage/owner/specs/trans-cancel.js +72 -0
- package/build/tests/protocols/3nstorage/owner/test-utils.d.ts +14 -0
- package/build/tests/protocols/3nstorage/owner/test-utils.js +54 -0
- package/build/tests/protocols/3nstorage/owner.d.ts +1 -0
- package/build/tests/protocols/3nstorage/owner.js +138 -0
- package/build/tests/protocols/asmail/config.d.ts +1 -0
- package/build/tests/protocols/asmail/config.js +117 -0
- package/build/tests/protocols/asmail/delivery/specs/finalize-delivery.d.ts +2 -0
- package/build/tests/protocols/asmail/delivery/specs/finalize-delivery.js +60 -0
- package/build/tests/protocols/asmail/delivery/specs/provide-recipient-pubkey.d.ts +2 -0
- package/build/tests/protocols/asmail/delivery/specs/provide-recipient-pubkey.js +68 -0
- package/build/tests/protocols/asmail/delivery/specs/put-metadata.d.ts +2 -0
- package/build/tests/protocols/asmail/delivery/specs/put-metadata.js +83 -0
- package/build/tests/protocols/asmail/delivery/specs/put-obj.d.ts +2 -0
- package/build/tests/protocols/asmail/delivery/specs/put-obj.js +123 -0
- package/build/tests/protocols/asmail/delivery/specs/restart-session.d.ts +2 -0
- package/build/tests/protocols/asmail/delivery/specs/restart-session.js +79 -0
- package/build/tests/protocols/asmail/delivery/specs/start-session.d.ts +2 -0
- package/build/tests/protocols/asmail/delivery/specs/start-session.js +64 -0
- package/build/tests/protocols/asmail/delivery/test-utils.d.ts +16 -0
- package/build/tests/protocols/asmail/delivery/test-utils.js +46 -0
- package/build/tests/protocols/asmail/delivery.d.ts +1 -0
- package/build/tests/protocols/asmail/delivery.js +46 -0
- package/build/tests/protocols/asmail/retrieval/specs/events.d.ts +2 -0
- package/build/tests/protocols/asmail/retrieval/specs/events.js +62 -0
- package/build/tests/protocols/asmail/retrieval/specs/get-message-meta.d.ts +2 -0
- package/build/tests/protocols/asmail/retrieval/specs/get-message-meta.js +70 -0
- package/build/tests/protocols/asmail/retrieval/specs/get-message-obj.d.ts +2 -0
- package/build/tests/protocols/asmail/retrieval/specs/get-message-obj.js +166 -0
- package/build/tests/protocols/asmail/retrieval/specs/list-messages.d.ts +2 -0
- package/build/tests/protocols/asmail/retrieval/specs/list-messages.js +96 -0
- package/build/tests/protocols/asmail/retrieval/specs/remove-message.d.ts +2 -0
- package/build/tests/protocols/asmail/retrieval/specs/remove-message.js +66 -0
- package/build/tests/protocols/asmail/retrieval/test-utils.d.ts +17 -0
- package/build/tests/protocols/asmail/retrieval/test-utils.js +46 -0
- package/build/tests/protocols/asmail/retrieval.d.ts +1 -0
- package/build/tests/protocols/asmail/retrieval.js +92 -0
- package/build/tests/protocols/mailerid.d.ts +1 -0
- package/build/tests/protocols/mailerid.js +210 -0
- package/build/tests/shared-checks/check-mid-login.d.ts +2 -0
- package/build/tests/shared-checks/check-mid-login.js +131 -0
- package/build/tests/shared-checks/requests.d.ts +20 -0
- package/build/tests/shared-checks/requests.js +123 -0
- package/package.json +1 -1
- package/packing/create-deb.sh +57 -0
- package/packing/deb/lib/systemd/system/3nweb.service +11 -0
- package/packing/deb/postinst +44 -0
- package/packing/deb/usr/share/doc/3nweb-server/conf-for-postinstall.yaml +19 -0
- package/packing/deb/usr/share/doc/3nweb-server/copyright +22 -0
- package/publish-task.sh +10 -0
- package/push-to-github.sh +105 -0
- package/ts-code/3nstorage/3nstorage-app.ts +99 -0
- package/ts-code/3nstorage/owner.ts +178 -0
- package/ts-code/3nstorage/resources/sessions.ts +37 -0
- package/ts-code/3nstorage/resources/store.ts +896 -0
- package/ts-code/3nstorage/resources/users.ts +258 -0
- package/ts-code/3nstorage/routes/owner/archive-obj-version.ts +73 -0
- package/ts-code/3nstorage/routes/owner/cancel-trans.ts +58 -0
- package/ts-code/3nstorage/routes/owner/delete-obj.ts +103 -0
- package/ts-code/3nstorage/routes/owner/get-archived-obj-ver.ts +111 -0
- package/ts-code/3nstorage/routes/owner/get-current-obj.ts +122 -0
- package/ts-code/3nstorage/routes/owner/get-obj-status.ts +55 -0
- package/ts-code/3nstorage/routes/owner/param-getter.ts +51 -0
- package/ts-code/3nstorage/routes/owner/param-setter.ts +50 -0
- package/ts-code/3nstorage/routes/owner/put-current-obj.ts +284 -0
- package/ts-code/3nstorage/routes/owner/session-params.ts +49 -0
- package/ts-code/3nstorage/shared.ts +43 -0
- package/ts-code/asmail/asmail-app.ts +91 -0
- package/ts-code/asmail/config.ts +96 -0
- package/ts-code/asmail/delivery.ts +94 -0
- package/ts-code/asmail/resources/delivery-sessions.ts +118 -0
- package/ts-code/asmail/resources/inbox.ts +696 -0
- package/ts-code/asmail/resources/recipients.ts +495 -0
- package/ts-code/asmail/resources/sessions.ts +37 -0
- package/ts-code/asmail/retrieval.ts +96 -0
- package/ts-code/asmail/routes/config/param-getter.ts +49 -0
- package/ts-code/asmail/routes/config/param-setter.ts +49 -0
- package/ts-code/asmail/routes/delivery/finalize-delivery.ts +50 -0
- package/ts-code/asmail/routes/delivery/pre-flight.ts +132 -0
- package/ts-code/asmail/routes/delivery/provide-recipient-pubkey.ts +58 -0
- package/ts-code/asmail/routes/delivery/put-metadata.ts +94 -0
- package/ts-code/asmail/routes/delivery/put-obj.ts +166 -0
- package/ts-code/asmail/routes/delivery/restart-session.ts +130 -0
- package/ts-code/asmail/routes/delivery/sender-authorization.ts +81 -0
- package/ts-code/asmail/routes/delivery/start-session.ts +151 -0
- package/ts-code/asmail/routes/retrieval/get-message-meta.ts +53 -0
- package/ts-code/asmail/routes/retrieval/get-message-obj.ts +109 -0
- package/ts-code/asmail/routes/retrieval/list-messages.ts +70 -0
- package/ts-code/asmail/routes/retrieval/remove-message.ts +47 -0
- package/ts-code/cli/index.ts +82 -0
- package/ts-code/cli/run-cmd.ts +81 -0
- package/ts-code/cli/show-sample-config.ts +78 -0
- package/ts-code/cli/signup-cmd.ts +229 -0
- package/ts-code/cli/user-cmd.ts +68 -0
- package/ts-code/cli/utils.ts +105 -0
- package/ts-code/config/default-confs.ts +22 -0
- package/ts-code/config/from-yaml.ts +35 -0
- package/ts-code/config/letsencrypt.ts +77 -0
- package/ts-code/config/signup.ts +137 -0
- package/ts-code/lib-common/admin-api/signup.ts +120 -0
- package/ts-code/lib-common/assert.ts +22 -0
- package/ts-code/lib-common/async-fs-node.ts +656 -0
- package/ts-code/lib-common/buffer-utils.ts +124 -0
- package/ts-code/lib-common/byte-streaming/common.ts +166 -0
- package/ts-code/lib-common/bytes-equal.ts +25 -0
- package/ts-code/lib-common/canonical-address.ts +92 -0
- package/ts-code/lib-common/exceptions/error.ts +44 -0
- package/ts-code/lib-common/exceptions/file.ts +84 -0
- package/ts-code/lib-common/exceptions/http.ts +69 -0
- package/ts-code/lib-common/ipc/generic-ipc.ts +750 -0
- package/ts-code/lib-common/ipc/ws-ipc.ts +117 -0
- package/ts-code/lib-common/json-equal.ts +55 -0
- package/ts-code/lib-common/json-utils.ts +130 -0
- package/ts-code/lib-common/jwkeys.ts +246 -0
- package/ts-code/lib-common/map-of-sets.ts +60 -0
- package/ts-code/lib-common/mid-sigs-NaCl-Ed.ts +677 -0
- package/ts-code/lib-common/objs-on-disk/file-layout.ts +480 -0
- package/ts-code/lib-common/objs-on-disk/obj-file.ts +325 -0
- package/ts-code/lib-common/objs-on-disk/utils.ts +201 -0
- package/ts-code/lib-common/objs-on-disk/v1-obj-file-format.ts +329 -0
- package/ts-code/lib-common/processes.ts +501 -0
- package/ts-code/lib-common/random-node.ts +79 -0
- package/ts-code/lib-common/service-api/3nstorage/owner.ts +559 -0
- package/ts-code/lib-common/service-api/3nstorage/root-route.ts +22 -0
- package/ts-code/lib-common/service-api/asmail/config.ts +144 -0
- package/ts-code/lib-common/service-api/asmail/delivery.ts +250 -0
- package/ts-code/lib-common/service-api/asmail/retrieval.ts +238 -0
- package/ts-code/lib-common/service-api/asmail/root-route.ts +22 -0
- package/ts-code/lib-common/service-api/ipc-api.ts +44 -0
- package/ts-code/lib-common/service-api/locker.ts +44 -0
- package/ts-code/lib-common/service-api/mailer-id/login.ts +80 -0
- package/ts-code/lib-common/service-api/mailer-id/provisioning.ts +64 -0
- package/ts-code/lib-common/service-api/mailer-id/root-route.ts +25 -0
- package/ts-code/lib-common/service-api/pub-key-login.ts +75 -0
- package/ts-code/lib-common/service-api/web-socket-base.ts +87 -0
- package/ts-code/lib-common/session-encryptor.ts +54 -0
- package/ts-code/lib-common/time-window-cache.ts +74 -0
- package/ts-code/lib-common/transferable.d.ts +30 -0
- package/ts-code/lib-server/conf-util.ts +35 -0
- package/ts-code/lib-server/mid-access.ts +45 -0
- package/ts-code/lib-server/middleware/body-parsers.ts +248 -0
- package/ts-code/lib-server/middleware/error-handler.ts +79 -0
- package/ts-code/lib-server/pkl-access.ts +46 -0
- package/ts-code/lib-server/resources/dns.ts +151 -0
- package/ts-code/lib-server/resources/mailerid-authorizer.ts +115 -0
- package/ts-code/lib-server/resources/mem-backed-sessions-factory.ts +132 -0
- package/ts-code/lib-server/resources/server-data-folders.ts +160 -0
- package/ts-code/lib-server/resources/server-key-for-pkl-challenge.ts +41 -0
- package/ts-code/lib-server/resources/sessions.ts +232 -0
- package/ts-code/lib-server/resources/user-files.ts +147 -0
- package/ts-code/lib-server/routes/pub-key-login/complete-exchange.ts +63 -0
- package/ts-code/lib-server/routes/pub-key-login/start-exchange.ts +189 -0
- package/ts-code/lib-server/routes/sessions/close.ts +27 -0
- package/ts-code/lib-server/routes/sessions/mid-auth.ts +77 -0
- package/ts-code/lib-server/routes/sessions/start.ts +116 -0
- package/ts-code/lib-server/web-sockets/app.ts +339 -0
- package/ts-code/lib-server/web-sockets/server-events.ts +63 -0
- package/ts-code/lib.ts +29 -0
- package/ts-code/locker/locker-app.ts +60 -0
- package/ts-code/locker/resources/lockers.ts +17 -0
- package/ts-code/locker/resources/sessions.ts +37 -0
- package/ts-code/locker/routes/create-locker.ts +47 -0
- package/ts-code/mailerId/mailerId-app.ts +107 -0
- package/ts-code/mailerId/resources/certifier.ts +181 -0
- package/ts-code/mailerId/resources/sessions.ts +44 -0
- package/ts-code/mailerId/resources/users.ts +88 -0
- package/ts-code/mailerId/routes/certify.ts +68 -0
- package/ts-code/main.ts +304 -0
- package/ts-code/mock/dns.ts +106 -0
- package/ts-code/mock/mock-as-child-proc.ts +130 -0
- package/ts-code/mock/node-child-ipc.ts +69 -0
- package/ts-code/mock/run-in-proc.ts +111 -0
- package/ts-code/mock/tls-options.ts +73 -0
- package/ts-code/services.ts +138 -0
- package/ts-code/signup/resources/users.ts +429 -0
- package/ts-code/signup/routes/add.ts +65 -0
- package/ts-code/signup/routes/get-available-addresses.ts +49 -0
- package/ts-code/signup/routes/get-available-domains.ts +45 -0
- package/ts-code/signup/signup-app.ts +54 -0
- package/ts-code/signup/signup-tokens.ts +148 -0
- package/ts-code/tests/admin-proto/signup.ts +277 -0
- package/ts-code/tests/jasmine.ts +37 -0
- package/ts-code/tests/libs-for-tests/3nstorage.ts +144 -0
- package/ts-code/tests/libs-for-tests/asmail.ts +220 -0
- package/ts-code/tests/libs-for-tests/assert.ts +22 -0
- package/ts-code/tests/libs-for-tests/async-jasmine.ts +89 -0
- package/ts-code/tests/libs-for-tests/bytes-equal.ts +25 -0
- package/ts-code/tests/libs-for-tests/json-copy.ts +38 -0
- package/ts-code/tests/libs-for-tests/json-equal.ts +55 -0
- package/ts-code/tests/libs-for-tests/mailerid.ts +123 -0
- package/ts-code/tests/libs-for-tests/pkl.ts +127 -0
- package/ts-code/tests/libs-for-tests/server-components/3nstorage.ts +206 -0
- package/ts-code/tests/libs-for-tests/server-components/admin.ts +49 -0
- package/ts-code/tests/libs-for-tests/server-components/asmail.ts +152 -0
- package/ts-code/tests/libs-for-tests/server-components/component.ts +90 -0
- package/ts-code/tests/libs-for-tests/server-components/mailerid.ts +114 -0
- package/ts-code/tests/libs-for-tests/server-runner.ts +82 -0
- package/ts-code/tests/libs-for-tests/spec-assembly.ts +60 -0
- package/ts-code/tests/libs-for-tests/ws-utils.ts +61 -0
- package/ts-code/tests/libs-for-tests/xhr-utils.ts +179 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/archive-obj-ver.ts +100 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/archive-root-ver.ts +91 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/delete-archive-obj-ver.ts +99 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/delete-archive-root-ver.ts +90 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/delete-obj.ts +84 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/events.ts +125 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/get-current-obj.ts +298 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/get-current-root.ts +290 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/get-obj-status.ts +88 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/get-root-status.ts +80 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/put-current-obj.ts +366 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/put-current-root.ts +329 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/trans-cancel-root.ts +86 -0
- package/ts-code/tests/protocols/3nstorage/owner/specs/trans-cancel.ts +86 -0
- package/ts-code/tests/protocols/3nstorage/owner/test-utils.ts +72 -0
- package/ts-code/tests/protocols/3nstorage/owner.ts +198 -0
- package/ts-code/tests/protocols/asmail/config.ts +172 -0
- package/ts-code/tests/protocols/asmail/delivery/specs/finalize-delivery.ts +69 -0
- package/ts-code/tests/protocols/asmail/delivery/specs/provide-recipient-pubkey.ts +88 -0
- package/ts-code/tests/protocols/asmail/delivery/specs/put-metadata.ts +102 -0
- package/ts-code/tests/protocols/asmail/delivery/specs/put-obj.ts +156 -0
- package/ts-code/tests/protocols/asmail/delivery/specs/restart-session.ts +97 -0
- package/ts-code/tests/protocols/asmail/delivery/specs/start-session.ts +79 -0
- package/ts-code/tests/protocols/asmail/delivery/test-utils.ts +64 -0
- package/ts-code/tests/protocols/asmail/delivery.ts +56 -0
- package/ts-code/tests/protocols/asmail/retrieval/specs/events.ts +78 -0
- package/ts-code/tests/protocols/asmail/retrieval/specs/get-message-meta.ts +80 -0
- package/ts-code/tests/protocols/asmail/retrieval/specs/get-message-obj.ts +197 -0
- package/ts-code/tests/protocols/asmail/retrieval/specs/list-messages.ts +110 -0
- package/ts-code/tests/protocols/asmail/retrieval/specs/remove-message.ts +74 -0
- package/ts-code/tests/protocols/asmail/retrieval/test-utils.ts +60 -0
- package/ts-code/tests/protocols/asmail/retrieval.ts +115 -0
- package/ts-code/tests/protocols/mailerid.ts +271 -0
- package/ts-code/tests/shared-checks/check-mid-login.ts +164 -0
- package/ts-code/tests/shared-checks/requests.ts +135 -0
- package/ts-code/tsconfig.json +11 -0
- package/ts-code/web3n.d.ts +1068 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2016, 2025 3NSoft Inc.
|
|
3
|
+
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
|
7
|
+
version.
|
|
8
|
+
|
|
9
|
+
This program is distributed in the hope that it will be useful, but
|
|
10
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
12
|
+
See the GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License along with
|
|
15
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { afterAllAsync, beforeAllAsync, itAsync } from '../libs-for-tests/async-jasmine';
|
|
19
|
+
import { MailerIdComponent } from '../libs-for-tests/server-components/mailerid';
|
|
20
|
+
import { getMidRoot } from '../libs-for-tests/mailerid';
|
|
21
|
+
import { doJsonRequest, RequestOpts, doBodylessRequest, doBinaryRequest } from '../libs-for-tests/xhr-utils';
|
|
22
|
+
import { certify as certApi } from '../../lib-common/service-api/mailer-id/provisioning';
|
|
23
|
+
import * as pklApi from '../../lib-common/service-api/pub-key-login';
|
|
24
|
+
import { isLikeSignedKeyCert } from '../../lib-common/jwkeys';
|
|
25
|
+
import { expectNonAcceptanceOfBadJsonRequest, expectNonAcceptanceOfBadSessionId, UNAUTHORIZED_STATUS, expectNonAcceptanceOfBadType, expectNonAcceptanceOfLongBody } from '../shared-checks/requests';
|
|
26
|
+
import { base64 } from '../../lib-common/buffer-utils';
|
|
27
|
+
import { secret_box as sbox } from 'ecma-nacl';
|
|
28
|
+
import { decryptSessionParamsForCurve25519, startPKLSession, doPubKeyLogin, User } from '../libs-for-tests/pkl';
|
|
29
|
+
import { user as midUser, relyingParty } from '../../lib-common/mid-sigs-NaCl-Ed';
|
|
30
|
+
import { bytesSync as randomBytes } from '../../lib-common/random-node';
|
|
31
|
+
import { toCanonicalAddress } from '../../lib-common/canonical-address';
|
|
32
|
+
import { deepEqual } from '../libs-for-tests/json-equal';
|
|
33
|
+
import { JsonKey } from '../../lib-common/jwkeys';
|
|
34
|
+
import { bytesEqual } from '../libs-for-tests/bytes-equal';
|
|
35
|
+
|
|
36
|
+
describe('MailerId', () => {
|
|
37
|
+
|
|
38
|
+
let midServer: MailerIdComponent;
|
|
39
|
+
const midServiceDomain = 'mailerid.service.domain';
|
|
40
|
+
const signupDomains = [ 'company.inc', 'personal.net' ];
|
|
41
|
+
let user1: User;
|
|
42
|
+
let user2: User;
|
|
43
|
+
|
|
44
|
+
beforeAllAsync(async () => {
|
|
45
|
+
midServer = new MailerIdComponent(signupDomains, midServiceDomain);
|
|
46
|
+
await midServer.start();
|
|
47
|
+
user1 = await midServer.addUser(`Bob Johnson @${signupDomains[0]}`);
|
|
48
|
+
user2 = await midServer.addUser(`William Young @${signupDomains[1]}`);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
afterAllAsync(async () => {
|
|
52
|
+
await midServer.stop();
|
|
53
|
+
midServer = (undefined as any);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
itAsync('provides root certificates', async () => {
|
|
57
|
+
|
|
58
|
+
let reqOpts: RequestOpts= {
|
|
59
|
+
url: midServer.midUrl,
|
|
60
|
+
method: 'GET',
|
|
61
|
+
responseType: 'json'
|
|
62
|
+
};
|
|
63
|
+
let rep = await doBodylessRequest<any>(reqOpts);
|
|
64
|
+
expect(rep.status).withContext('status code for OK reply').toBe(200);
|
|
65
|
+
expect(Array.isArray(rep.data["previous-certs"])).toBe(true);
|
|
66
|
+
expect(isLikeSignedKeyCert(rep.data["current-cert"])).toBe(true);
|
|
67
|
+
expect(typeof rep.data["provisioning"]).toBe('string');
|
|
68
|
+
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('provisioning stage', () => {
|
|
72
|
+
|
|
73
|
+
let provUrl: string;
|
|
74
|
+
|
|
75
|
+
beforeAllAsync(async () => {
|
|
76
|
+
provUrl = await midServer.getProvUrl();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// TODO refactor Public Key Login into shared-checks spec, similarly to
|
|
80
|
+
// MailerId login, so as to reuse it where PKL is used.
|
|
81
|
+
|
|
82
|
+
async function testFirstReqFor(useDefaultKey: boolean): Promise<void> {
|
|
83
|
+
|
|
84
|
+
let reqOpts: RequestOpts= {
|
|
85
|
+
url: provUrl + pklApi.start.URL_END,
|
|
86
|
+
method: 'POST',
|
|
87
|
+
responseType: 'json'
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// request with known user id
|
|
91
|
+
let req: pklApi.start.Request = (useDefaultKey ?
|
|
92
|
+
{ userId: user1.id } :
|
|
93
|
+
{ userId: user1.id, kid: user1.loginLabeledSKey.kid });
|
|
94
|
+
let rep = await doJsonRequest<pklApi.start.Reply>(reqOpts, req);
|
|
95
|
+
expect(rep.status).withContext('status code for OK reply').toBe(pklApi.start.SC.ok);
|
|
96
|
+
expect(typeof rep.data).toBe('object');
|
|
97
|
+
expect(typeof rep.data.sessionId).toBe('string');
|
|
98
|
+
expect(() => {
|
|
99
|
+
// note that this user uses NaCl's box (Curve25519)
|
|
100
|
+
decryptSessionParamsForCurve25519(rep.data, user1.loginDefaultSKey);
|
|
101
|
+
}).not.toThrow();
|
|
102
|
+
|
|
103
|
+
// duplicating request, with session id now in a header
|
|
104
|
+
reqOpts.sessionId = rep.data.sessionId;
|
|
105
|
+
rep = await doJsonRequest<pklApi.start.Reply>(reqOpts, req);
|
|
106
|
+
expect(rep.status).withContext('reaction to duplicate request').toBe(pklApi.ERR_SC.duplicate);
|
|
107
|
+
delete reqOpts.sessionId;
|
|
108
|
+
|
|
109
|
+
// when user id is unknown
|
|
110
|
+
req = { userId: 'unknown user @some.domain' };
|
|
111
|
+
rep = await doJsonRequest<pklApi.start.Reply>(reqOpts, req);
|
|
112
|
+
expect(rep.status).withContext('status code for an unknown user id').toBe(pklApi.start.SC.unknownUser);
|
|
113
|
+
req = { userId: 'unknown user @'+signupDomains[0] };
|
|
114
|
+
rep = await doJsonRequest<pklApi.start.Reply>(reqOpts, req);
|
|
115
|
+
expect(rep.status).withContext('status code for an unknown user id').toBe(pklApi.start.SC.unknownUser);
|
|
116
|
+
|
|
117
|
+
// requests with bad user ids and with bad json's
|
|
118
|
+
let badIds = [ '', ' ', '\t', '\n', // equivalent to empty string
|
|
119
|
+
5, null, undefined, {} ]; // non-strings
|
|
120
|
+
let badJSONs: any[] = [ 'bar', 5, null, undefined, [ 'blah' ],
|
|
121
|
+
{ a: 1 } ];
|
|
122
|
+
for (let id of badIds) {
|
|
123
|
+
req = { userId: <string> id };
|
|
124
|
+
badJSONs.push(req);
|
|
125
|
+
}
|
|
126
|
+
const REQ_SIZE_LIMIT = 1024;
|
|
127
|
+
await expectNonAcceptanceOfBadJsonRequest(reqOpts,
|
|
128
|
+
REQ_SIZE_LIMIT, badJSONs);
|
|
129
|
+
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
itAsync('starts with Public Key Login, using default key',
|
|
133
|
+
() => testFirstReqFor(true));
|
|
134
|
+
|
|
135
|
+
itAsync('starts with Public Key Login, using non-default (labeled) key',
|
|
136
|
+
() => testFirstReqFor(false));
|
|
137
|
+
|
|
138
|
+
async function testSecondReqFor(useDefaultKey: boolean): Promise<void> {
|
|
139
|
+
|
|
140
|
+
let exchangeParams = await startPKLSession(
|
|
141
|
+
provUrl, user1, useDefaultKey);
|
|
142
|
+
|
|
143
|
+
let reqOpts: RequestOpts= {
|
|
144
|
+
url: provUrl + pklApi.complete.URL_END,
|
|
145
|
+
method: 'POST',
|
|
146
|
+
sessionId: exchangeParams.sessionId,
|
|
147
|
+
responseType: 'arraybuffer'
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
let rep = await doBinaryRequest<Uint8Array>(
|
|
151
|
+
reqOpts, exchangeParams.crypto.encResponse);
|
|
152
|
+
expect(rep.status).withContext('status code for successful login completion').toBe(pklApi.complete.SC.ok);
|
|
153
|
+
expect(rep.data.length).toBe(sbox.POLY_LENGTH);
|
|
154
|
+
expect(bytesEqual(rep.data, exchangeParams.crypto.serverVerificationBytes)).withContext('returned bytes must be a missing poly part from the challenge, to verify to client, that server knows user\'s public key').toBe(true);
|
|
155
|
+
|
|
156
|
+
// repeating request is not ok
|
|
157
|
+
rep = await doBinaryRequest<Uint8Array>(
|
|
158
|
+
reqOpts, exchangeParams.crypto.encResponse);
|
|
159
|
+
expect(rep.status).withContext('reaction to duplicate request').toBe(pklApi.ERR_SC.duplicate);
|
|
160
|
+
|
|
161
|
+
// send incorrect challenge response
|
|
162
|
+
for (let i=0; i < exchangeParams.crypto.encResponse.length; i+=1) {
|
|
163
|
+
let exchange2 = await startPKLSession(provUrl, user2, useDefaultKey);
|
|
164
|
+
let badReply = exchange2.crypto.encResponse;
|
|
165
|
+
badReply[i] ^= 1;
|
|
166
|
+
reqOpts.sessionId = exchange2.sessionId;
|
|
167
|
+
let rep = await doBinaryRequest<Uint8Array>(reqOpts, badReply);
|
|
168
|
+
expect(rep.status).toBe(pklApi.complete.SC.authFailed);
|
|
169
|
+
}
|
|
170
|
+
let exchange2 = await startPKLSession(provUrl, user2, useDefaultKey);
|
|
171
|
+
let badReply = exchange2.crypto.encResponse.subarray(5);
|
|
172
|
+
reqOpts.sessionId = exchange2.sessionId;
|
|
173
|
+
rep = await doBinaryRequest<Uint8Array>(reqOpts, badReply);
|
|
174
|
+
expect(rep.status).toBe(pklApi.complete.SC.authFailed);
|
|
175
|
+
|
|
176
|
+
// bad session id
|
|
177
|
+
await expectNonAcceptanceOfBadSessionId(reqOpts);
|
|
178
|
+
|
|
179
|
+
// too long
|
|
180
|
+
const REQ_SIZE_LIMIT = 1024;
|
|
181
|
+
exchange2 = await startPKLSession(provUrl, user2, useDefaultKey);
|
|
182
|
+
reqOpts.sessionId = exchange2.sessionId;
|
|
183
|
+
await expectNonAcceptanceOfLongBody(reqOpts,
|
|
184
|
+
'application/octet-stream', REQ_SIZE_LIMIT);
|
|
185
|
+
|
|
186
|
+
// wrong type
|
|
187
|
+
await expectNonAcceptanceOfBadType(reqOpts,
|
|
188
|
+
'application/octet-stream', exchange2.crypto.encResponse);
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
itAsync('second request completes Public Key Login, using default key',
|
|
193
|
+
() => testSecondReqFor(true));
|
|
194
|
+
|
|
195
|
+
itAsync('second request completes Public Key Login, with non-default key',
|
|
196
|
+
() => testSecondReqFor(true));
|
|
197
|
+
|
|
198
|
+
itAsync('certifies user\'s MailerId public key', async () => {
|
|
199
|
+
|
|
200
|
+
let midSigningPair = midUser.generateSigningKeyPair(randomBytes);
|
|
201
|
+
let reqData: certApi.Request = {
|
|
202
|
+
pkey: midSigningPair.pkey,
|
|
203
|
+
duration: 12*60*60
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
let sessParams = await doPubKeyLogin(provUrl, user1);
|
|
207
|
+
|
|
208
|
+
let reqOpts: RequestOpts= {
|
|
209
|
+
url: provUrl + certApi.URL_END,
|
|
210
|
+
method: 'POST',
|
|
211
|
+
sessionId: sessParams.sessionId,
|
|
212
|
+
responseType: 'arraybuffer'
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
let encrBody = sessParams.sessEncr.packJSON(reqData);
|
|
216
|
+
let rep = await doBinaryRequest<Uint8Array>(reqOpts, encrBody);
|
|
217
|
+
expect(rep.status).withContext('status code for OK reply').toBe(certApi.SC.ok);
|
|
218
|
+
let repData: certApi.Reply = sessParams.sessEncr.openJSON(rep.data);
|
|
219
|
+
let pkeyAndAddress = relyingParty.verifyChainAndGetUserKey({
|
|
220
|
+
root: await getMidRoot(midServer.midUrl),
|
|
221
|
+
prov: repData.provCert,
|
|
222
|
+
user: repData.userCert
|
|
223
|
+
},
|
|
224
|
+
midServer.midServiceDomain,
|
|
225
|
+
Date.now()/1000);
|
|
226
|
+
expect(pkeyAndAddress.address).withContext('certificate must be issued for session\'s user canonical address.').toBe(toCanonicalAddress(user1.id));
|
|
227
|
+
let pkeyFromCert: JsonKey = {
|
|
228
|
+
alg: pkeyAndAddress.pkey.alg,
|
|
229
|
+
kid: pkeyAndAddress.pkey.kid,
|
|
230
|
+
use: pkeyAndAddress.pkey.use,
|
|
231
|
+
k: base64.pack(pkeyAndAddress.pkey.k)
|
|
232
|
+
};
|
|
233
|
+
expect(deepEqual(pkeyFromCert, midSigningPair.pkey)).withContext('public key should be exactly the same as given one.').toBe(true);
|
|
234
|
+
|
|
235
|
+
// session is closed at this request
|
|
236
|
+
rep = await doBinaryRequest<Uint8Array>(
|
|
237
|
+
reqOpts, sessParams.sessEncr.packJSON(reqData));
|
|
238
|
+
expect(rep.status).withContext('session should be closed.').toBe(UNAUTHORIZED_STATUS);
|
|
239
|
+
|
|
240
|
+
// messed up cipher body
|
|
241
|
+
sessParams = await doPubKeyLogin(provUrl, user1);
|
|
242
|
+
reqOpts.sessionId = sessParams.sessionId;
|
|
243
|
+
encrBody[20] ^= 1;
|
|
244
|
+
rep = await doBinaryRequest<Uint8Array>(reqOpts, encrBody);
|
|
245
|
+
expect(rep.status).toBe(certApi.SC.cryptoVerifFail);
|
|
246
|
+
|
|
247
|
+
// empty body
|
|
248
|
+
sessParams = await doPubKeyLogin(provUrl, user1);
|
|
249
|
+
reqOpts.sessionId = sessParams.sessionId;
|
|
250
|
+
rep = await doBinaryRequest<Uint8Array>(reqOpts, new Uint8Array(0));
|
|
251
|
+
expect(rep.status).toBe(certApi.SC.cryptoVerifFail);
|
|
252
|
+
|
|
253
|
+
// set session for fuzzing below
|
|
254
|
+
sessParams = await doPubKeyLogin(provUrl, user1);
|
|
255
|
+
reqOpts.sessionId = sessParams.sessionId;
|
|
256
|
+
|
|
257
|
+
// too long
|
|
258
|
+
const REQ_SIZE_LIMIT = 16*1024;
|
|
259
|
+
await expectNonAcceptanceOfLongBody(reqOpts,
|
|
260
|
+
'application/octet-stream', REQ_SIZE_LIMIT);
|
|
261
|
+
|
|
262
|
+
// wrong type
|
|
263
|
+
encrBody = sessParams.sessEncr.packJSON(reqData);
|
|
264
|
+
await expectNonAcceptanceOfBadType(reqOpts,
|
|
265
|
+
'application/octet-stream', encrBody);
|
|
266
|
+
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
});
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2016, 2025 3NSoft Inc.
|
|
3
|
+
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
|
7
|
+
version.
|
|
8
|
+
|
|
9
|
+
This program is distributed in the hope that it will be useful, but
|
|
10
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
12
|
+
See the GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License along with
|
|
15
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { itAsync } from '../libs-for-tests/async-jasmine';
|
|
19
|
+
import { authSession, startSession, ERR_SC } from '../../lib-common/service-api/mailer-id/login';
|
|
20
|
+
import { doJsonRequest, RequestOpts } from '../libs-for-tests/xhr-utils';
|
|
21
|
+
import { startMidSession, provisionMidSigner, User } from '../libs-for-tests/mailerid';
|
|
22
|
+
import { expectNonAcceptanceOfBadJsonRequest, expectNonAcceptanceOfBadSessionId } from './requests';
|
|
23
|
+
import * as mid from '../../lib-common/mid-sigs-NaCl-Ed';
|
|
24
|
+
import { bytesSync as randomBytes } from '../../lib-common/random-node';
|
|
25
|
+
import { parse as parseUrl, resolve as resolveUrl } from 'url';
|
|
26
|
+
|
|
27
|
+
export function midLoginSpecs(
|
|
28
|
+
loginUrl: () => string,
|
|
29
|
+
user: () => User
|
|
30
|
+
): () => void {
|
|
31
|
+
return () => {
|
|
32
|
+
|
|
33
|
+
itAsync('first request starts session', async () => {
|
|
34
|
+
|
|
35
|
+
const reqOpts: RequestOpts= {
|
|
36
|
+
url: resolveUrl(loginUrl(), startSession.URL_END),
|
|
37
|
+
method: 'POST',
|
|
38
|
+
responseType: 'json'
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// request with known user id
|
|
42
|
+
let req: startSession.Request = { userId: user().id };
|
|
43
|
+
let rep = await doJsonRequest<startSession.Reply>(reqOpts, req);
|
|
44
|
+
expect(rep.status).withContext('status for ok reply').toBe(startSession.SC.ok);
|
|
45
|
+
expect(typeof rep.data).toBe('object');
|
|
46
|
+
expect(typeof rep.data.sessionId).withContext('session id be in reply').toBe('string');
|
|
47
|
+
|
|
48
|
+
// duplicating request, with session id now in a header
|
|
49
|
+
reqOpts.sessionId = rep.data.sessionId;
|
|
50
|
+
rep = await doJsonRequest<startSession.Reply>(reqOpts, req);
|
|
51
|
+
expect(rep.status).withContext('reaction to duplicate request').toBe(ERR_SC.duplicate);
|
|
52
|
+
delete reqOpts.sessionId;
|
|
53
|
+
|
|
54
|
+
// when user id is unknown
|
|
55
|
+
req = { userId: 'unknown user @some.domain' };
|
|
56
|
+
rep = await doJsonRequest<startSession.Reply>(reqOpts, req);
|
|
57
|
+
expect(rep.status).withContext('status code for an unknown user id').toBe(startSession.SC.unknownUser);
|
|
58
|
+
|
|
59
|
+
// requests with bad json's
|
|
60
|
+
const badIds = [ '', ' ', '\t', '\n', // equivalent to empty string
|
|
61
|
+
5, null, undefined, {} ]; // non-strings
|
|
62
|
+
const badJSONs: any[] = [ 'bar', 5, null, undefined, [ 'blah' ],
|
|
63
|
+
{ a: 1 } ];
|
|
64
|
+
for (const id of badIds) {
|
|
65
|
+
req = { userId: <string> id };
|
|
66
|
+
badJSONs.push(req);
|
|
67
|
+
}
|
|
68
|
+
const REQ_SIZE_LIMIT = 1024;
|
|
69
|
+
await expectNonAcceptanceOfBadJsonRequest(reqOpts,
|
|
70
|
+
REQ_SIZE_LIMIT, badJSONs);
|
|
71
|
+
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
itAsync('second request authenticates session', async () => {
|
|
75
|
+
|
|
76
|
+
const url = loginUrl();
|
|
77
|
+
let sessionId = await startMidSession(url, user().id);
|
|
78
|
+
const uInfo = user();
|
|
79
|
+
|
|
80
|
+
let midSigner = await provisionMidSigner(uInfo.midUrl, uInfo);
|
|
81
|
+
|
|
82
|
+
const reqOpts: RequestOpts= {
|
|
83
|
+
url: resolveUrl(loginUrl(), authSession.URL_END),
|
|
84
|
+
method: 'POST',
|
|
85
|
+
responseType: 'json',
|
|
86
|
+
sessionId
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const serviceDomain = parseUrl(loginUrl()).hostname;
|
|
90
|
+
if (!serviceDomain) { throw new Error(
|
|
91
|
+
`Cannot get hostname from ${loginUrl()}`); }
|
|
92
|
+
const req: authSession.Request = {
|
|
93
|
+
assertion: midSigner.generateAssertionFor(
|
|
94
|
+
serviceDomain, sessionId),
|
|
95
|
+
provCert: midSigner.providerCert,
|
|
96
|
+
userCert: midSigner.userCert
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
let rep = await doJsonRequest<void>(reqOpts, req);
|
|
100
|
+
expect(rep.status).withContext('status for ok reply').toBe(authSession.SC.ok);
|
|
101
|
+
|
|
102
|
+
// repeating request is not ok
|
|
103
|
+
rep = await doJsonRequest<void>(reqOpts, req);
|
|
104
|
+
expect(rep.status).withContext('reaction to duplicate request').toBe(ERR_SC.duplicate);
|
|
105
|
+
|
|
106
|
+
// wrong assertion is from a different session
|
|
107
|
+
sessionId = await startMidSession(url, user().id);
|
|
108
|
+
reqOpts.sessionId = sessionId;
|
|
109
|
+
rep = await doJsonRequest<void>(reqOpts, req);
|
|
110
|
+
expect(rep.status).withContext('status for autherization failure').toBe(authSession.SC.authFailed);
|
|
111
|
+
|
|
112
|
+
// wrong domain in assertion
|
|
113
|
+
sessionId = await startMidSession(url, user().id);
|
|
114
|
+
reqOpts.sessionId = sessionId;
|
|
115
|
+
req.assertion = midSigner.generateAssertionFor(
|
|
116
|
+
'other.domain', sessionId);
|
|
117
|
+
rep = await doJsonRequest<void>(reqOpts, req);
|
|
118
|
+
expect(rep.status).withContext('status for autherization failure').toBe(authSession.SC.authFailed);
|
|
119
|
+
|
|
120
|
+
// fake certs
|
|
121
|
+
const fakeRoot = mid.idProvider.generateRootKey(
|
|
122
|
+
uInfo.midUrl, 365*12*60*60, randomBytes);
|
|
123
|
+
const fakeProvider = mid.idProvider.generateProviderKey(
|
|
124
|
+
uInfo.midUrl, 30*12*60*60, fakeRoot.skey, randomBytes);
|
|
125
|
+
const fakeIdCertifier = mid.idProvider.makeIdProviderCertifier(
|
|
126
|
+
uInfo.midUrl, 24*60*60, fakeProvider.skey);
|
|
127
|
+
const fakeUserKeys = mid.user.generateSigningKeyPair(randomBytes);
|
|
128
|
+
const fakeUserCert = fakeIdCertifier.certify(
|
|
129
|
+
fakeUserKeys.pkey, user().id);
|
|
130
|
+
midSigner = mid.user.makeMailerIdSigner(
|
|
131
|
+
fakeUserKeys.skey, fakeUserCert, fakeProvider.cert);
|
|
132
|
+
sessionId = await startMidSession(url, user().id);
|
|
133
|
+
reqOpts.sessionId = sessionId;
|
|
134
|
+
req.assertion = midSigner.generateAssertionFor(
|
|
135
|
+
serviceDomain, sessionId);
|
|
136
|
+
req.userCert = fakeUserCert; // keep unrelated provCert
|
|
137
|
+
rep = await doJsonRequest<void>(reqOpts, req);
|
|
138
|
+
expect(rep.status).withContext('status for autherization failure').toBe(authSession.SC.authFailed);
|
|
139
|
+
sessionId = await startMidSession(url, user().id);
|
|
140
|
+
reqOpts.sessionId = sessionId;
|
|
141
|
+
req.assertion = midSigner.generateAssertionFor(
|
|
142
|
+
serviceDomain, sessionId);
|
|
143
|
+
req.provCert = fakeProvider.cert;
|
|
144
|
+
req.userCert = fakeUserCert;
|
|
145
|
+
rep = await doJsonRequest<void>(reqOpts, req);
|
|
146
|
+
expect(rep.status).withContext('status for autherization failure').toBe(authSession.SC.authFailed);
|
|
147
|
+
|
|
148
|
+
// bad json
|
|
149
|
+
const REQ_SIZE_LIMIT = 4*1024;
|
|
150
|
+
sessionId = await startMidSession(url, user().id);
|
|
151
|
+
reqOpts.sessionId = sessionId;
|
|
152
|
+
const badJSONs: any[] = [ 1, null, undefined, 'string' ];
|
|
153
|
+
await expectNonAcceptanceOfBadJsonRequest(reqOpts, REQ_SIZE_LIMIT,
|
|
154
|
+
badJSONs);
|
|
155
|
+
|
|
156
|
+
// bad session id
|
|
157
|
+
await expectNonAcceptanceOfBadSessionId(reqOpts);
|
|
158
|
+
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
Object.freeze(exports);
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2016, 2019, 2025 3NSoft Inc.
|
|
3
|
+
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
|
7
|
+
version.
|
|
8
|
+
|
|
9
|
+
This program is distributed in the hope that it will be useful, but
|
|
10
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
12
|
+
See the GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License along with
|
|
15
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { doJsonRequest, RequestOpts, request } from '../libs-for-tests/xhr-utils';
|
|
19
|
+
import { randomBytes } from 'crypto';
|
|
20
|
+
import { utf8 } from '../../lib-common/buffer-utils';
|
|
21
|
+
import { copy } from '../libs-for-tests/json-copy';
|
|
22
|
+
import { ConnectException } from '../../lib-common/exceptions/http';
|
|
23
|
+
|
|
24
|
+
const LONG_BODY_STATUS = 413;
|
|
25
|
+
const MALFORMED_BODY_STATUS = 400;
|
|
26
|
+
const WRONG_CONTENT_TYPE_STATUS = 415;
|
|
27
|
+
export const UNAUTHORIZED_STATUS = 401;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* This function should test json-expecting routes.
|
|
31
|
+
* @param opts
|
|
32
|
+
* @param maxBodyLen
|
|
33
|
+
* @param badJSONs
|
|
34
|
+
* @return a promise, resolvable when all checks are done.
|
|
35
|
+
*/
|
|
36
|
+
export async function expectNonAcceptanceOfBadJsonRequest(
|
|
37
|
+
opts: RequestOpts, maxBodyLen: number, badJSONs: any[]
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
|
|
40
|
+
// bad json
|
|
41
|
+
for (const badReq of badJSONs) {
|
|
42
|
+
const rep = await doJsonRequest<void>(opts, badReq);
|
|
43
|
+
expect(rep.status).withContext(`status code for malformed request: ${JSON.stringify(badReq)}`).toBe(MALFORMED_BODY_STATUS);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// bad non-json bodies
|
|
47
|
+
const badBodies = [ Buffer.alloc(0), randomBytes(Math.floor(maxBodyLen/2)) ];
|
|
48
|
+
for (const bytes of badBodies) {
|
|
49
|
+
const req = request<void>('application/json', opts);
|
|
50
|
+
req.xhr.send(bytes);
|
|
51
|
+
const rep = await req.promise;
|
|
52
|
+
expect(rep.status).withContext('status code for malformed request').toBe(MALFORMED_BODY_STATUS);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// wrong content type
|
|
56
|
+
await expectNonAcceptanceOfBadType(opts, 'application/json',
|
|
57
|
+
utf8.pack(JSON.stringify({})));
|
|
58
|
+
|
|
59
|
+
// request that is too long (>maxBodyLen)
|
|
60
|
+
await expectNonAcceptanceOfLongBody(opts, 'application/json', maxBodyLen);
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export declare type BodyType =
|
|
65
|
+
'application/octet-stream' | 'text/plain' | 'application/json';
|
|
66
|
+
|
|
67
|
+
const bodyTypes = [ 'application/octet-stream',
|
|
68
|
+
'text/plain', 'application/json', undefined ];
|
|
69
|
+
|
|
70
|
+
export async function expectNonAcceptanceOfBadType(
|
|
71
|
+
opts: RequestOpts, correctType: BodyType, body: Uint8Array
|
|
72
|
+
): Promise<void> {
|
|
73
|
+
for (const bt of bodyTypes) {
|
|
74
|
+
if (correctType === bt) { continue; }
|
|
75
|
+
const req = request<void>(bt, opts);
|
|
76
|
+
req.xhr.send(body);
|
|
77
|
+
const rep = await req.promise;
|
|
78
|
+
expect(rep.status).withContext('status code for wrong content type request').toBe(WRONG_CONTENT_TYPE_STATUS);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function expectNonAcceptanceOfLongBody(
|
|
83
|
+
opts: RequestOpts, bodyType: BodyType, maxBodyLen: number
|
|
84
|
+
): Promise<void> {
|
|
85
|
+
const badReq = randomBytes(maxBodyLen+1);
|
|
86
|
+
const req = request<void>(bodyType, opts);
|
|
87
|
+
req.xhr.send(badReq);
|
|
88
|
+
try {
|
|
89
|
+
const rep = await req.promise;
|
|
90
|
+
expect(rep.status).withContext('status code for long request').toBe(LONG_BODY_STATUS);
|
|
91
|
+
} catch (exc) {
|
|
92
|
+
const cantConnect = (exc as ConnectException).runtimeException &&
|
|
93
|
+
((exc as ConnectException).type === 'http-connect');
|
|
94
|
+
expect(cantConnect).withContext(`server can close connection on a long reply, resulting in a can't connect error on a client side`).toBe(true);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function expectNonAcceptanceOfNonEmptyBody(
|
|
99
|
+
opts: RequestOpts
|
|
100
|
+
): Promise<void> {
|
|
101
|
+
const badReq = randomBytes(1);
|
|
102
|
+
const req = request<void>(undefined, opts);
|
|
103
|
+
req.xhr.send(badReq);
|
|
104
|
+
const rep = await req.promise;
|
|
105
|
+
expect(rep.status).withContext('status code for long request').toBe(LONG_BODY_STATUS);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @param opts
|
|
110
|
+
* @param hasBody is a flag, telling if body should be sent with the request.
|
|
111
|
+
* Default value is false, for no body in request.
|
|
112
|
+
*/
|
|
113
|
+
export async function expectNonAcceptanceOfBadSessionId(
|
|
114
|
+
opts: RequestOpts, hasBody = false
|
|
115
|
+
): Promise<void> {
|
|
116
|
+
opts = copy(opts);
|
|
117
|
+
|
|
118
|
+
// missing session id
|
|
119
|
+
delete opts.sessionId;
|
|
120
|
+
let req = request<void>(undefined, opts);
|
|
121
|
+
if (hasBody) { req.xhr.send(randomBytes(5)); }
|
|
122
|
+
else { req.xhr.send(); }
|
|
123
|
+
let rep = await req.promise;
|
|
124
|
+
expect(rep.status).withContext('status code when required session id is missing').toBe(UNAUTHORIZED_STATUS);
|
|
125
|
+
|
|
126
|
+
// invalid session id
|
|
127
|
+
opts.sessionId = 'bogus session id';
|
|
128
|
+
req = request<void>(undefined, opts);
|
|
129
|
+
if (hasBody) { req.xhr.send(randomBytes(5)); }
|
|
130
|
+
else { req.xhr.send(); }
|
|
131
|
+
rep = await req.promise;
|
|
132
|
+
expect(rep.status).withContext('status code for an invalid session id').toBe(UNAUTHORIZED_STATUS);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
Object.freeze(exports);
|