spec-3nweb-server 1.8.5 → 1.8.7
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/resources/store.d.ts +2 -2
- package/build/3nstorage/resources/store.js +1 -1
- package/build/3nstorage/resources/users.d.ts +3 -3
- package/build/3nstorage/resources/users.js +1 -1
- package/build/3nstorage/resources/utils.d.ts +6 -0
- package/build/3nstorage/resources/utils.js +41 -0
- package/build/3nstorage/routes/owner/archive-obj-version.js +8 -10
- package/build/3nstorage/routes/owner/cancel-trans.js +5 -4
- package/build/3nstorage/routes/owner/delete-obj.js +7 -8
- package/build/3nstorage/routes/owner/get-archived-obj-ver.js +11 -13
- package/build/3nstorage/routes/owner/get-current-obj.js +7 -6
- package/build/3nstorage/routes/owner/get-obj-status.js +8 -8
- package/build/3nstorage/routes/owner/put-current-obj.js +25 -55
- package/build/3nstorage/routes/owner/session-params.js +2 -0
- package/build/asmail/resources/utils.d.ts +6 -0
- package/build/asmail/resources/utils.js +36 -0
- package/build/asmail/routes/delivery/finalize-delivery.js +3 -2
- package/build/asmail/routes/delivery/pre-flight.js +9 -26
- package/build/asmail/routes/delivery/provide-recipient-pubkey.js +4 -3
- package/build/asmail/routes/delivery/put-metadata.js +13 -21
- package/build/asmail/routes/delivery/put-obj.js +19 -25
- package/build/asmail/routes/delivery/restart-session.d.ts +4 -8
- package/build/asmail/routes/delivery/restart-session.js +10 -23
- package/build/asmail/routes/delivery/sender-authorization.js +5 -5
- package/build/asmail/routes/delivery/start-session.js +9 -24
- package/build/asmail/routes/retrieval/get-message-meta.js +4 -7
- package/build/asmail/routes/retrieval/get-message-obj.js +10 -7
- package/build/asmail/routes/retrieval/list-messages.js +4 -4
- package/build/asmail/routes/retrieval/remove-message.js +3 -2
- package/build/mock/tls-options.js +46 -44
- 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/resources/utils.ts +45 -0
- package/ts-code/3nstorage/routes/owner/archive-obj-version.ts +71 -0
- package/ts-code/3nstorage/routes/owner/cancel-trans.ts +60 -0
- package/ts-code/3nstorage/routes/owner/delete-obj.ts +99 -0
- package/ts-code/3nstorage/routes/owner/get-archived-obj-ver.ts +109 -0
- package/ts-code/3nstorage/routes/owner/get-current-obj.ts +124 -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 +257 -0
- package/ts-code/3nstorage/routes/owner/session-params.ts +50 -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/resources/utils.ts +41 -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 +51 -0
- package/ts-code/asmail/routes/delivery/pre-flight.ts +118 -0
- package/ts-code/asmail/routes/delivery/provide-recipient-pubkey.ts +58 -0
- package/ts-code/asmail/routes/delivery/put-metadata.ts +85 -0
- package/ts-code/asmail/routes/delivery/put-obj.ts +152 -0
- package/ts-code/asmail/routes/delivery/restart-session.ts +117 -0
- package/ts-code/asmail/routes/delivery/sender-authorization.ts +81 -0
- package/ts-code/asmail/routes/delivery/start-session.ts +136 -0
- package/ts-code/asmail/routes/retrieval/get-message-meta.ts +50 -0
- package/ts-code/asmail/routes/retrieval/get-message-obj.ts +106 -0
- package/ts-code/asmail/routes/retrieval/list-messages.ts +68 -0
- package/ts-code/asmail/routes/retrieval/remove-message.ts +48 -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,248 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2015 - 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 { Request, Response, NextFunction, RequestHandler } from 'express';
|
|
19
|
+
import { stringToNumOfBytes } from '../conf-util';
|
|
20
|
+
import { makeErr } from './error-handler';
|
|
21
|
+
import { defer } from '../../lib-common/processes';
|
|
22
|
+
import { BytesFIFOBuffer } from '../../lib-common/byte-streaming/common';
|
|
23
|
+
import { EMPTY_BUFFER } from '../../lib-common/buffer-utils';
|
|
24
|
+
|
|
25
|
+
const HTTP_HEADER = {
|
|
26
|
+
contentType: 'Content-Type',
|
|
27
|
+
contentLength: 'Content-Length'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const TYPES = {
|
|
31
|
+
plain: 'text/plain',
|
|
32
|
+
json: 'application/json',
|
|
33
|
+
bin: 'application/octet-stream'
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function attachByteDrainToRequest(req: Request): void {
|
|
37
|
+
req.on('data', noop);
|
|
38
|
+
req.on('end', noop);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function noop() {}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Use this for empty-body POST and PUT routes, as it does sanitization, and
|
|
45
|
+
* prevents hanging requests, because nothing drains data.
|
|
46
|
+
* @return a middleware function that ensures empty body in requests.
|
|
47
|
+
*/
|
|
48
|
+
export function emptyBody(): RequestHandler {
|
|
49
|
+
return (req, _res, next) => {
|
|
50
|
+
attachByteDrainToRequest(req);
|
|
51
|
+
|
|
52
|
+
// get and check Content-Length
|
|
53
|
+
const contentLength = parseInt(req.get(HTTP_HEADER.contentLength)!, 10);
|
|
54
|
+
if (isNaN(contentLength)) {
|
|
55
|
+
return next(makeErr(411,
|
|
56
|
+
"Content-Length header is required with proper number."));
|
|
57
|
+
}
|
|
58
|
+
if (contentLength !== 0) {
|
|
59
|
+
return next(makeErr(413, "Request body is too long."));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
next();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param req
|
|
68
|
+
* @param expectedLen is an expected non-zero length of a binary body.
|
|
69
|
+
* If body has different length, this function throws.
|
|
70
|
+
* @return a promise, resolvable to request's body bytes, parsed from a request
|
|
71
|
+
* object.
|
|
72
|
+
*/
|
|
73
|
+
export async function parseBinaryBodyWithExpectedSize(
|
|
74
|
+
req: Request, expectedLen: number
|
|
75
|
+
): Promise<Uint8Array> {
|
|
76
|
+
try {
|
|
77
|
+
if (expectedLen < 1) { throw new Error(`Given illegal length value ${expectedLen}`); }
|
|
78
|
+
|
|
79
|
+
// check type
|
|
80
|
+
if (!req.is(TYPES.bin)) {
|
|
81
|
+
throw makeErr(415, `Content-Type must be ${TYPES.bin} for this call.`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// check length declared in header
|
|
85
|
+
const contentLength = parseInt(req.get(HTTP_HEADER.contentLength)!, 10);
|
|
86
|
+
if (isNaN(contentLength)) {
|
|
87
|
+
throw makeErr(411,
|
|
88
|
+
"Content-Length header is required with proper number.");
|
|
89
|
+
}
|
|
90
|
+
if (contentLength !== expectedLen) {
|
|
91
|
+
throw makeErr(400, "Unexpected number of bytes.");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
} catch (err) {
|
|
95
|
+
attachByteDrainToRequest(req);
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const deffered = defer<Uint8Array>();
|
|
100
|
+
const bytes = new BytesFIFOBuffer();
|
|
101
|
+
|
|
102
|
+
// collect body bytes
|
|
103
|
+
let erred = false;
|
|
104
|
+
req.on('data', (chunk: Buffer) => {
|
|
105
|
+
if (erred) { return; }
|
|
106
|
+
if ((bytes.length + chunk.length) <= expectedLen) {
|
|
107
|
+
bytes.push(chunk);
|
|
108
|
+
} else {
|
|
109
|
+
erred = true;
|
|
110
|
+
deffered.reject(makeErr(400, "Request body is longer than expected."));
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
req.on('end', () => {
|
|
114
|
+
if (erred) { return; }
|
|
115
|
+
if (bytes.length === expectedLen) {
|
|
116
|
+
deffered.resolve(bytes.getBytes(undefined)!);
|
|
117
|
+
} else {
|
|
118
|
+
deffered.reject(makeErr(400,
|
|
119
|
+
"Request body is shorter than expected."));
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return deffered.promise;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function byteCollector(
|
|
127
|
+
maxSize: string|number, contentType: string, parser?: RequestHandler
|
|
128
|
+
): RequestHandler {
|
|
129
|
+
const maxSizeNum = stringToNumOfBytes(maxSize);
|
|
130
|
+
if ('string' !== typeof contentType) {
|
|
131
|
+
throw new Error("Given 'contentType' argument must be a string.");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return (req, res, next) => {
|
|
135
|
+
// check Content-Type
|
|
136
|
+
if (!req.is(contentType)) {
|
|
137
|
+
attachByteDrainToRequest(req);
|
|
138
|
+
return next(makeErr(415, "Content-Type must be "+
|
|
139
|
+
contentType+" for this call."));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// get and check Content-Length
|
|
143
|
+
const contentLength = parseInt(req.get(HTTP_HEADER.contentLength)!, 10);
|
|
144
|
+
if (isNaN(contentLength)) {
|
|
145
|
+
attachByteDrainToRequest(req);
|
|
146
|
+
return next(makeErr(411,
|
|
147
|
+
"Content-Length header is required with proper number."));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// enforce agreed limit on request size
|
|
151
|
+
if (contentLength > maxSizeNum) {
|
|
152
|
+
attachByteDrainToRequest(req);
|
|
153
|
+
return next(makeErr(413, "Request body is too long."));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// XXX we may use fifo here, postponing byte copying till moment, when
|
|
157
|
+
// everything is downloaded
|
|
158
|
+
|
|
159
|
+
// set body to be buffer for all expected incoming bytes
|
|
160
|
+
req.body = (contentLength > 0) ?
|
|
161
|
+
Buffer.alloc(contentLength) : EMPTY_BUFFER;
|
|
162
|
+
|
|
163
|
+
// collect incoming bytes into body array
|
|
164
|
+
let bytesRead = 0;
|
|
165
|
+
let erred = false;
|
|
166
|
+
req.on('data', (chunk: Buffer) => {
|
|
167
|
+
if (erred) { return; }
|
|
168
|
+
if ((bytesRead + chunk.length) <= contentLength) {
|
|
169
|
+
chunk.copy(req.body, bytesRead);
|
|
170
|
+
bytesRead += chunk.length;
|
|
171
|
+
} else {
|
|
172
|
+
erred = true;
|
|
173
|
+
req.body = null;
|
|
174
|
+
next(makeErr(413, "Request body is too long."));
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
req.on('end', () => {
|
|
179
|
+
if (erred) { return; }
|
|
180
|
+
if (parser) {
|
|
181
|
+
parser(req, res, next);
|
|
182
|
+
} else {
|
|
183
|
+
next();
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @param maxSize is a maximum allowed body length, given as number of bytes,
|
|
191
|
+
* or string parameter for kb/mb's.
|
|
192
|
+
* @return middleware function, that places all request bytes into Buffer,
|
|
193
|
+
* placed into usual body field of request object.
|
|
194
|
+
*/
|
|
195
|
+
export function binary(maxSize: string|number): RequestHandler {
|
|
196
|
+
return byteCollector(maxSize, TYPES.bin);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @param maxSize is a maximum allowed body length, given as number of bytes,
|
|
201
|
+
* or string parameter for kb/mb's.
|
|
202
|
+
* @param allowNonObject is a boolean flag, which, when true, turns of a check
|
|
203
|
+
* that forces body to be an object.
|
|
204
|
+
* @return middleware function, that parses all request bytes as JSON, placing
|
|
205
|
+
* result into usual body field of request object.
|
|
206
|
+
*/
|
|
207
|
+
export function json(
|
|
208
|
+
maxSize: string|number, allowNonObject?: boolean
|
|
209
|
+
): RequestHandler {
|
|
210
|
+
return byteCollector(maxSize, TYPES.json, (req, _res, next) => {
|
|
211
|
+
try {
|
|
212
|
+
const bodyAsStr = req.body.toString('utf8');
|
|
213
|
+
req.body = ((bodyAsStr === '') ?
|
|
214
|
+
undefined :
|
|
215
|
+
JSON.parse(bodyAsStr)
|
|
216
|
+
);
|
|
217
|
+
} catch (err) {
|
|
218
|
+
return next(
|
|
219
|
+
makeErr(400, "Request body cannot be interpreted as JSON.")
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
if (!allowNonObject
|
|
223
|
+
&& (!req.body || (typeof req.body !== 'object'))) {
|
|
224
|
+
return next(makeErr(400, "Request body is not a JSON object."));
|
|
225
|
+
}
|
|
226
|
+
next();
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @param maxSize is a maximum allowed body length, given as number of bytes, or
|
|
232
|
+
* string parameter for kb/mb's.
|
|
233
|
+
* @return middleware function, that parses all request bytes as utf8 text,
|
|
234
|
+
* placing result into usual body field of request object.
|
|
235
|
+
*/
|
|
236
|
+
export function textPlain(maxSize: string|number): RequestHandler {
|
|
237
|
+
return byteCollector(maxSize, TYPES.plain, (req, _res, next) => {
|
|
238
|
+
try {
|
|
239
|
+
req.body = req.body.toString('utf8');
|
|
240
|
+
} catch (err) {
|
|
241
|
+
return next(makeErr(400,
|
|
242
|
+
"Request body cannot be interpreted as plain utf8 text."));
|
|
243
|
+
}
|
|
244
|
+
next();
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
Object.freeze(exports);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2016, 2020, 2023 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 { Request, ErrorRequestHandler } from 'express';
|
|
19
|
+
import * as http from 'http';
|
|
20
|
+
import { ErrorWithCause, errWithCause as makeErrWithCause } from '../../lib-common/exceptions/error';
|
|
21
|
+
|
|
22
|
+
export interface HttpError extends ErrorWithCause {
|
|
23
|
+
status: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* This creates an error object that should be given to next(), instead of
|
|
28
|
+
* throwing it.
|
|
29
|
+
* @param code is http status code to be attached to produced error object.
|
|
30
|
+
* @param msg goes into error message.
|
|
31
|
+
* @param cause
|
|
32
|
+
*/
|
|
33
|
+
export function makeErr(code: number, msg: string, cause?: any): HttpError {
|
|
34
|
+
const err = makeErrWithCause(cause, msg) as HttpError;
|
|
35
|
+
err.status = code;
|
|
36
|
+
return err;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type ErrLogger = (err: any, req: Request) => void;
|
|
40
|
+
|
|
41
|
+
export function makeErrHandler(log?: ErrLogger): ErrorRequestHandler {
|
|
42
|
+
// Note that when we don't have next, tons of errors show up.
|
|
43
|
+
// I guess, express checks how many arguments js function takes, and
|
|
44
|
+
// gives args respectively. Thus, since express is doing this introspection
|
|
45
|
+
// (magic?), we have to leave next argument, even though we ain't using it.
|
|
46
|
+
return async function (err: HttpError, req, res, next) {
|
|
47
|
+
let resStatus: number;
|
|
48
|
+
let resBody: string;
|
|
49
|
+
if (err && (typeof err.status === 'number')) {
|
|
50
|
+
resStatus = err.status;
|
|
51
|
+
if (resStatus === 500) {
|
|
52
|
+
resBody = http.STATUS_CODES[500]!;
|
|
53
|
+
} else if (err.message) {
|
|
54
|
+
resBody = err.message;
|
|
55
|
+
} else {
|
|
56
|
+
resBody = http.STATUS_CODES[err.status]!;
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
resStatus = 500;
|
|
60
|
+
resBody = http.STATUS_CODES[500]!;
|
|
61
|
+
}
|
|
62
|
+
res.status(resStatus).send(resBody);
|
|
63
|
+
if (log) {
|
|
64
|
+
log(err, req);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function makeErrLoggerToConsole(srvName: string): ErrLogger {
|
|
70
|
+
return (err, req) => {
|
|
71
|
+
if (typeof err.status !== 'number') {
|
|
72
|
+
console.error(`\n --- Error occured in ${srvName}, when handling ${req.method} request to ${req.originalUrl}`);
|
|
73
|
+
console.error(err);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
Object.freeze(exports);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2024 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 { Express } from 'express';
|
|
19
|
+
import { json as parseJSON, binary as parseBinary } from './middleware/body-parsers';
|
|
20
|
+
import { Factory as SessionsFactory } from './resources/sessions';
|
|
21
|
+
import { ComputeDHSharedKey, GetUserPKeyAndKeyGenParams, SessionParams, startPKLogin } from './routes/pub-key-login/start-exchange';
|
|
22
|
+
import { completePKLogin } from './routes/pub-key-login/complete-exchange';
|
|
23
|
+
import * as api from '../lib-common/service-api/pub-key-login';
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export function addPKLLoginRoutes(
|
|
27
|
+
app: Express, urlPrefix: string,
|
|
28
|
+
getUserParamsAndKey: GetUserPKeyAndKeyGenParams,
|
|
29
|
+
sessions: SessionsFactory<SessionParams>,
|
|
30
|
+
computeDHSharedKey: ComputeDHSharedKey
|
|
31
|
+
): void {
|
|
32
|
+
|
|
33
|
+
app.post(urlPrefix + api.start.URL_END,
|
|
34
|
+
sessions.checkSession(),
|
|
35
|
+
parseJSON('1kb'),
|
|
36
|
+
startPKLogin(
|
|
37
|
+
getUserParamsAndKey, sessions.generate, computeDHSharedKey
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
app.post(urlPrefix + api.complete.URL_END,
|
|
41
|
+
sessions.ensureOpenedSession(),
|
|
42
|
+
parseBinary('1kb'),
|
|
43
|
+
completePKLogin()
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2015 - 2016, 2023 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 * as dns from 'dns';
|
|
19
|
+
|
|
20
|
+
export const SC = {
|
|
21
|
+
RECORDS_MISSING: 'records missing',
|
|
22
|
+
DOMAIN_NOT_FOUND: 'domain not found'
|
|
23
|
+
};
|
|
24
|
+
Object.freeze(SC);
|
|
25
|
+
|
|
26
|
+
const DNS_ERR_CODE = {
|
|
27
|
+
NODATA: 'ENODATA',
|
|
28
|
+
NOTFOUND: 'ENOTFOUND'
|
|
29
|
+
};
|
|
30
|
+
Object.freeze(DNS_ERR_CODE);
|
|
31
|
+
|
|
32
|
+
interface DnsError extends Error {
|
|
33
|
+
code: string;
|
|
34
|
+
hostname: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* This implementation extracts exactly one string value for a given service.
|
|
39
|
+
* All other values are ignored, without raising error about misconfiguration.
|
|
40
|
+
* In time we may have several records for the same service type, yet, for now
|
|
41
|
+
* only one TXT per service per domain is considered valid.
|
|
42
|
+
* @param txtRecords are TXT records from dns.
|
|
43
|
+
* @param serviceLabel is a label of service, for which we want to get string
|
|
44
|
+
* value from TXT record.
|
|
45
|
+
* @return string value for a given service among given dns TXT records.
|
|
46
|
+
*/
|
|
47
|
+
function extractPair(
|
|
48
|
+
txtRecords: string[][], serviceLabel: ServiceLabel
|
|
49
|
+
): string|undefined {
|
|
50
|
+
for (const txtRecord of txtRecords) {
|
|
51
|
+
let joinedTXTstanzas = txtRecord.join('');
|
|
52
|
+
let record = getRecordAtStartOf(joinedTXTstanzas);
|
|
53
|
+
while (record) {
|
|
54
|
+
if (record.service === serviceLabel) {
|
|
55
|
+
const value = record.value.trim();
|
|
56
|
+
if (value.length > 0) {
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (record.txtTail) {
|
|
61
|
+
record = getRecordAtStartOf(record.txtTail);
|
|
62
|
+
} else {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const recordsStarts: { [key in ServiceLabel]: string; } = {
|
|
71
|
+
"3nstorage": '3nstorage=',
|
|
72
|
+
asmail: 'asmail=',
|
|
73
|
+
mailerid: 'mailerid='
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function getRecordAtStartOf(txt: string): {
|
|
77
|
+
service: ServiceLabel; value: string; txtTail?: string;
|
|
78
|
+
}|undefined {
|
|
79
|
+
let service: ServiceLabel|undefined = undefined;
|
|
80
|
+
for (const [ label, startSeq ] of Object.entries(recordsStarts)) {
|
|
81
|
+
if (txt.startsWith(startSeq)) {
|
|
82
|
+
service = label as ServiceLabel;
|
|
83
|
+
txt = txt.substring(startSeq.length);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (!service) { return; }
|
|
88
|
+
for (const delimiter of Object.values(recordsStarts)) {
|
|
89
|
+
const endPos = txt.indexOf(delimiter);
|
|
90
|
+
if (endPos >= 0) {
|
|
91
|
+
return {
|
|
92
|
+
service,
|
|
93
|
+
value: txt.substring(0, endPos),
|
|
94
|
+
txtTail: txt.substring(endPos)
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
service,
|
|
100
|
+
value: txt
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export type ServiceLabel = 'asmail' | 'mailerid' | '3nstorage';
|
|
105
|
+
|
|
106
|
+
function resolveTxt(domain: string): Promise<string[][]> {
|
|
107
|
+
return new Promise<string[][]>((resolve, reject) => {
|
|
108
|
+
// As of March 2017, docs for node say that texts given in a callback
|
|
109
|
+
// are string[][], and node works this way, but definition is incorrect.
|
|
110
|
+
// Therefore, need to insert "as any" into resolve function.
|
|
111
|
+
dns.resolveTxt(domain, (err, texts) => {
|
|
112
|
+
if (err) {
|
|
113
|
+
reject(err);
|
|
114
|
+
} else {
|
|
115
|
+
resolve(texts as any);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @param address
|
|
123
|
+
* @return domain string, extracted from a given address
|
|
124
|
+
*/
|
|
125
|
+
function domainOfAddress(address: string): string {
|
|
126
|
+
address = address.trim();
|
|
127
|
+
const indOfAt = address.lastIndexOf('@');
|
|
128
|
+
const domain = ((indOfAt < 0) ? address : address.substring(indOfAt+1));
|
|
129
|
+
return domain;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export async function get3NWebRecords(address: string,
|
|
133
|
+
serviceLabel: ServiceLabel): Promise<string> {
|
|
134
|
+
try {
|
|
135
|
+
const domain = domainOfAddress(address);
|
|
136
|
+
const txtRecords = await resolveTxt(domain);
|
|
137
|
+
const recValue = extractPair(txtRecords, serviceLabel);
|
|
138
|
+
if (!recValue) { throw SC.RECORDS_MISSING; }
|
|
139
|
+
return recValue;
|
|
140
|
+
} catch (err) {
|
|
141
|
+
if ((<DnsError> err).code === DNS_ERR_CODE.NODATA) {
|
|
142
|
+
throw SC.RECORDS_MISSING;
|
|
143
|
+
} else if ((<DnsError> err).code === DNS_ERR_CODE.NOTFOUND) {
|
|
144
|
+
throw SC.DOMAIN_NOT_FOUND;
|
|
145
|
+
} else {
|
|
146
|
+
throw err;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
Object.freeze(exports);
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2015 - 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 * as https from 'https';
|
|
19
|
+
import { SignedLoad, getKeyCert, getPrincipalAddress } from '../../lib-common/jwkeys';
|
|
20
|
+
import * as mid from '../../lib-common/mid-sigs-NaCl-Ed';
|
|
21
|
+
import { get3NWebRecords } from './dns';
|
|
22
|
+
import { MidAuthorizer } from '../routes/sessions/mid-auth';
|
|
23
|
+
import { serviceRoot } from '../../lib-common/service-api/mailer-id/provisioning';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param serviceURL
|
|
27
|
+
* @return a promise, resolvable to MailerId provider's current root
|
|
28
|
+
* certificate.
|
|
29
|
+
*/
|
|
30
|
+
function getRootCert(serviceURL: string): Promise<SignedLoad> {
|
|
31
|
+
return new Promise<SignedLoad>((resolve, reject) => {
|
|
32
|
+
const req = https.request('https://'+serviceURL, (res) => {
|
|
33
|
+
if (res.statusCode === 200) {
|
|
34
|
+
res.setEncoding('utf8');
|
|
35
|
+
let collectedString = '';
|
|
36
|
+
res.on('data', (chunk) => {
|
|
37
|
+
collectedString += chunk;
|
|
38
|
+
});
|
|
39
|
+
res.on('end', () => {
|
|
40
|
+
const infoObj: serviceRoot.Reply = JSON.parse(collectedString);
|
|
41
|
+
const cert = infoObj['current-cert'];
|
|
42
|
+
if (cert) {
|
|
43
|
+
resolve(cert);
|
|
44
|
+
} else {
|
|
45
|
+
reject(new Error(
|
|
46
|
+
"Info file "+serviceURL+", is malformed."));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
res.on('error', (err) => {
|
|
50
|
+
reject(err);
|
|
51
|
+
});
|
|
52
|
+
} else {
|
|
53
|
+
reject(new Error("Cannot get "+serviceURL+
|
|
54
|
+
", returned " +"status code is "+res.statusCode));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
req.on('error', (err) => {
|
|
58
|
+
reject(err);
|
|
59
|
+
});
|
|
60
|
+
req.end();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// TODO need to add caching of certs using domain->(kid->cert)
|
|
65
|
+
// (this will speed things up)
|
|
66
|
+
|
|
67
|
+
export function validator(ownMidService: OwnMidService|undefined): MidAuthorizer {
|
|
68
|
+
return (
|
|
69
|
+
rpDomain, sessionId, userId, assertion, userCert, provCert
|
|
70
|
+
) => validate(
|
|
71
|
+
rpDomain, sessionId, userId, assertion, userCert, provCert, ownMidService
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface OwnMidService { domain: string; getRoot: () => SignedLoad; }
|
|
76
|
+
|
|
77
|
+
async function validate(
|
|
78
|
+
rpDomain: string, sessionId: string, userId: string,
|
|
79
|
+
assertion: SignedLoad, userCert: SignedLoad, provCert: SignedLoad,
|
|
80
|
+
ownMidService: OwnMidService|undefined
|
|
81
|
+
): Promise<boolean> {
|
|
82
|
+
const validAt = Date.now() / 1000;
|
|
83
|
+
try{
|
|
84
|
+
// check that certificate is for the user
|
|
85
|
+
const addressInCert = getPrincipalAddress(userCert);
|
|
86
|
+
if (userId !== addressInCert) { return false; }
|
|
87
|
+
|
|
88
|
+
// check that issuer is the one that provides MailerId service for
|
|
89
|
+
// user's domain
|
|
90
|
+
const issuer = getKeyCert(provCert).issuer;
|
|
91
|
+
const serviceURL = await get3NWebRecords(addressInCert, 'mailerid');
|
|
92
|
+
const domainInRecord = serviceURL.split('/')[0].split(':')[0];
|
|
93
|
+
if (issuer !== domainInRecord) { return false; }
|
|
94
|
+
|
|
95
|
+
// get root certificate and check the whole chain
|
|
96
|
+
const rootCert = ((ownMidService && (issuer === ownMidService.domain)) ?
|
|
97
|
+
ownMidService.getRoot() : await getRootCert(serviceURL)
|
|
98
|
+
);
|
|
99
|
+
const assertInfo = mid.relyingParty.verifyAssertion(
|
|
100
|
+
assertion,
|
|
101
|
+
{ user: userCert, prov: provCert, root: rootCert },
|
|
102
|
+
issuer, validAt
|
|
103
|
+
);
|
|
104
|
+
if ((assertInfo.relyingPartyDomain === rpDomain)
|
|
105
|
+
&& (assertInfo.sessionId === sessionId)) {
|
|
106
|
+
return true;
|
|
107
|
+
} else {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
} catch (e) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
Object.freeze(exports);
|