@blamejs/blamejs-shop 0.5.12 → 0.5.13
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/CHANGELOG.md +2 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +632 -416
- package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
- package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
- package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/.gitignore +2 -0
- package/lib/vendor/blamejs/CHANGELOG.md +122 -0
- package/lib/vendor/blamejs/NOTICE +26 -1
- package/lib/vendor/blamejs/SECURITY.md +1 -1
- package/lib/vendor/blamejs/api-snapshot.json +207 -5
- package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
- package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
- package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
- package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
- package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
- package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
- package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
- package/lib/vendor/blamejs/index.js +6 -0
- package/lib/vendor/blamejs/lib/a2a.js +4 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
- package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
- package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
- package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
- package/lib/vendor/blamejs/lib/archive-read.js +8 -0
- package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
- package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
- package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
- package/lib/vendor/blamejs/lib/audit.js +71 -8
- package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
- package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
- package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
- package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
- package/lib/vendor/blamejs/lib/backup/index.js +16 -5
- package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
- package/lib/vendor/blamejs/lib/base32.js +21 -0
- package/lib/vendor/blamejs/lib/break-glass.js +19 -10
- package/lib/vendor/blamejs/lib/bundler.js +5 -1
- package/lib/vendor/blamejs/lib/cache-status.js +3 -7
- package/lib/vendor/blamejs/lib/calendar.js +21 -1
- package/lib/vendor/blamejs/lib/cbor.js +12 -1
- package/lib/vendor/blamejs/lib/cert.js +29 -11
- package/lib/vendor/blamejs/lib/cli.js +94 -24
- package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
- package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
- package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
- package/lib/vendor/blamejs/lib/content-digest.js +2 -1
- package/lib/vendor/blamejs/lib/cookies.js +13 -3
- package/lib/vendor/blamejs/lib/cose.js +31 -16
- package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
- package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
- package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
- package/lib/vendor/blamejs/lib/crypto.js +314 -19
- package/lib/vendor/blamejs/lib/csp.js +11 -3
- package/lib/vendor/blamejs/lib/daemon.js +270 -24
- package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
- package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
- package/lib/vendor/blamejs/lib/db-query.js +34 -7
- package/lib/vendor/blamejs/lib/db.js +18 -6
- package/lib/vendor/blamejs/lib/dbsc.js +17 -0
- package/lib/vendor/blamejs/lib/dev.js +21 -2
- package/lib/vendor/blamejs/lib/dsr.js +157 -102
- package/lib/vendor/blamejs/lib/external-db.js +41 -2
- package/lib/vendor/blamejs/lib/file-upload.js +25 -7
- package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
- package/lib/vendor/blamejs/lib/forms.js +113 -27
- package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
- package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
- package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
- package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
- package/lib/vendor/blamejs/lib/guard-html.js +26 -53
- package/lib/vendor/blamejs/lib/guard-image.js +24 -5
- package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
- package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
- package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
- package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
- package/lib/vendor/blamejs/lib/guard-time.js +1 -1
- package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
- package/lib/vendor/blamejs/lib/html-balance.js +3 -3
- package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
- package/lib/vendor/blamejs/lib/http-client.js +39 -7
- package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
- package/lib/vendor/blamejs/lib/i18n.js +35 -21
- package/lib/vendor/blamejs/lib/incident-report.js +8 -1
- package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
- package/lib/vendor/blamejs/lib/json-path.js +23 -1
- package/lib/vendor/blamejs/lib/jwk.js +20 -3
- package/lib/vendor/blamejs/lib/link-header.js +2 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream.js +8 -3
- package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
- package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
- package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
- package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
- package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
- package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
- package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
- package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
- package/lib/vendor/blamejs/lib/mail.js +15 -5
- package/lib/vendor/blamejs/lib/metrics.js +268 -63
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
- package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
- package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
- package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
- package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
- package/lib/vendor/blamejs/lib/network-dns.js +21 -2
- package/lib/vendor/blamejs/lib/network-tls.js +69 -7
- package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
- package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
- package/lib/vendor/blamejs/lib/outbox.js +1 -1
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
- package/lib/vendor/blamejs/lib/permissions.js +6 -3
- package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
- package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
- package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
- package/lib/vendor/blamejs/lib/pubsub.js +20 -9
- package/lib/vendor/blamejs/lib/queue-local.js +8 -1
- package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
- package/lib/vendor/blamejs/lib/redact.js +54 -0
- package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
- package/lib/vendor/blamejs/lib/restore.js +19 -0
- package/lib/vendor/blamejs/lib/retention.js +12 -4
- package/lib/vendor/blamejs/lib/router.js +60 -6
- package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
- package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
- package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
- package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
- package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
- package/lib/vendor/blamejs/lib/safe-object.js +80 -0
- package/lib/vendor/blamejs/lib/safe-path.js +52 -4
- package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
- package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
- package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
- package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
- package/lib/vendor/blamejs/lib/scheduler.js +8 -1
- package/lib/vendor/blamejs/lib/security-assert.js +6 -6
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
- package/lib/vendor/blamejs/lib/self-update.js +517 -87
- package/lib/vendor/blamejs/lib/server-timing.js +2 -4
- package/lib/vendor/blamejs/lib/session.js +34 -12
- package/lib/vendor/blamejs/lib/sql.js +15 -1
- package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
- package/lib/vendor/blamejs/lib/static.js +55 -13
- package/lib/vendor/blamejs/lib/storage.js +8 -2
- package/lib/vendor/blamejs/lib/subject.js +6 -1
- package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
- package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
- package/lib/vendor/blamejs/lib/tsa.js +34 -13
- package/lib/vendor/blamejs/lib/uri-template.js +8 -1
- package/lib/vendor/blamejs/lib/vault/index.js +13 -0
- package/lib/vendor/blamejs/lib/vc.js +44 -5
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
- package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
- package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
- package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
- package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
- package/lib/vendor/blamejs/lib/watcher.js +89 -17
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
- package/lib/vendor/blamejs/lib/webhook.js +12 -2
- package/lib/vendor/blamejs/lib/ws-client.js +32 -1
- package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
- package/lib/vendor/blamejs/package-lock.json +2 -2
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
- package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
- package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
- package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
- package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
- package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
- package/lib/vendor/blamejs/socket.yml +94 -0
- package/lib/vendor/blamejs/test/00-primitives.js +605 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
- package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
- package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
- package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
- package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
- package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
- package/lib/vendor/blamejs/test/smoke.js +2 -0
- package/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
- package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
- package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
- package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
- package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
- package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
- package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (c) blamejs contributors
|
|
3
3
|
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* b.mail.server.pop3 — create() opts validation plus command-handler and
|
|
6
|
+
* error-branch behavior driven over a real localhost listener (plaintext
|
|
7
|
+
* AUTHORIZATION path + STLS->TLS upgrade + authenticated TRANSACTION path):
|
|
8
|
+
* the RFC 1939 / RFC 2595 command dispatch (CAPA/STLS/USER/PASS/STAT/LIST/
|
|
9
|
+
* RETR/TOP/UIDL/DELE/RSET/NOOP/QUIT) and its wrong-state / malformed /
|
|
10
|
+
* not-found refusals. Every socket assertion drives the public API.
|
|
11
|
+
*
|
|
12
|
+
* Run standalone: `node test/layer-0-primitives/mail-server-pop3.test.js`
|
|
13
|
+
* Or via smoke: `node test/smoke.js`
|
|
14
|
+
*/
|
|
4
15
|
|
|
5
16
|
var helpers = require("../helpers");
|
|
6
17
|
var check = helpers.check;
|
|
7
18
|
var b = helpers.b;
|
|
8
19
|
|
|
20
|
+
var nodeNet = require("node:net");
|
|
21
|
+
var nodeTls = require("node:tls");
|
|
22
|
+
|
|
23
|
+
var NUL = String.fromCharCode(0);
|
|
24
|
+
|
|
9
25
|
function testSurface() {
|
|
10
26
|
check("namespace", typeof b.mail.server.pop3 === "object");
|
|
11
27
|
check("create fn", typeof b.mail.server.pop3.create === "function");
|
|
@@ -60,17 +76,621 @@ function testBadBoundsRefused() {
|
|
|
60
76
|
{ tlsContext: {}, mailStore: _stubMailStore(), idleTimeoutMs: Infinity });
|
|
61
77
|
}
|
|
62
78
|
|
|
63
|
-
function
|
|
79
|
+
function _readReply(socket, multiline) {
|
|
80
|
+
return new Promise(function (resolve, reject) {
|
|
81
|
+
var buf = "";
|
|
82
|
+
function onData(chunk) {
|
|
83
|
+
buf += chunk.toString("utf8");
|
|
84
|
+
var done = multiline ? (/\r\n\.\r\n$/.test(buf) || /^-ERR/.test(buf)) : /\r\n$/.test(buf);
|
|
85
|
+
if (done) { socket.removeListener("data", onData); socket.removeListener("error", onErr); resolve(buf); }
|
|
86
|
+
}
|
|
87
|
+
function onErr(e) { socket.removeListener("data", onData); reject(e); }
|
|
88
|
+
socket.on("data", onData);
|
|
89
|
+
socket.once("error", onErr);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function _send(socket, line, multiline) {
|
|
93
|
+
var p = _readReply(socket, multiline);
|
|
94
|
+
socket.write(line + "\r\n");
|
|
95
|
+
return p;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function _makeTestTlsContext() {
|
|
99
|
+
var ca = await b.mtlsEngine.generateCa({ name: "pop3-test-ca" });
|
|
100
|
+
var leaf = await b.mtlsEngine.signClientCert({
|
|
101
|
+
cn: "pop3.test", caCertPem: ca.caCertPem, caKeyPem: ca.caKeyPem,
|
|
102
|
+
usage: "server", sans: ["DNS:localhost", "IP:127.0.0.1"], validityDays: 1,
|
|
103
|
+
});
|
|
104
|
+
return { ctx: nodeTls.createSecureContext({ key: leaf.key, cert: leaf.cert }), caPem: ca.caCertPem };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function _stubStore() {
|
|
108
|
+
var msgs = [
|
|
109
|
+
{ msgNum: 1, size: 14, uid: "uid-1", bytes: Buffer.from("Subject: a\r\n\r\nhi") },
|
|
110
|
+
{ msgNum: 2, size: 5, uid: "uid-2", bytes: Buffer.from("world") },
|
|
111
|
+
];
|
|
112
|
+
return {
|
|
113
|
+
openPop3Drop: async function () { return { dropId: "drop-1", count: msgs.length, totalBytes: 19 }; },
|
|
114
|
+
commitPop3Drop: async function () { return { deleted: 0 }; },
|
|
115
|
+
listMessages: async function () { return msgs.map(function (m) { return { msgNum: m.msgNum, size: m.size, uid: m.uid, uidl: m.uid }; }); },
|
|
116
|
+
getMessage: async function (actor, dropId, n) { var f = msgs.find(function (m) { return m.msgNum === n; }); return f ? { size: f.size, rawBytes: f.bytes } : null; },
|
|
117
|
+
markDelete: async function () { return; },
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function _makeServer(extra) {
|
|
122
|
+
var tls = await _makeTestTlsContext();
|
|
123
|
+
var opts = {
|
|
124
|
+
tlsContext: tls.ctx,
|
|
125
|
+
mailStore: _stubStore(),
|
|
126
|
+
auth: { verify: async function (mech, creds) {
|
|
127
|
+
// PASS gives parsed username/password; AUTH gives a raw base64 SASL blob
|
|
128
|
+
// in clientResponse (authzid NUL authcid NUL passwd) for us to decode.
|
|
129
|
+
var username = creds.username, password = creds.password;
|
|
130
|
+
if (creds.clientResponse) {
|
|
131
|
+
var parts = Buffer.from(creds.clientResponse, "base64").toString("utf8").split(NUL);
|
|
132
|
+
username = parts[1]; password = parts[2];
|
|
133
|
+
}
|
|
134
|
+
return password === "good"
|
|
135
|
+
? { ok: true, actor: { username: username, tenantId: "t1" } }
|
|
136
|
+
: { ok: false };
|
|
137
|
+
} },
|
|
138
|
+
};
|
|
139
|
+
if (extra) { Object.keys(extra).forEach(function (k) { opts[k] = extra[k]; }); }
|
|
140
|
+
var srv = b.mail.server.pop3.create(opts);
|
|
141
|
+
var info = await srv.listen({ port: 0, address: "127.0.0.1" });
|
|
142
|
+
return { srv: srv, port: info.port, caPem: tls.caPem };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ---- plaintext AUTHORIZATION path: dispatch + wrong-state + malformed ----
|
|
146
|
+
async function testPlaintextDispatch() {
|
|
147
|
+
var s = await _makeServer();
|
|
148
|
+
var sock = nodeNet.connect(s.port, "127.0.0.1");
|
|
149
|
+
sock.on("error", function () {});
|
|
150
|
+
try {
|
|
151
|
+
check("greeting is +OK", /^\+OK/.test(await _readReply(sock)));
|
|
152
|
+
check("CAPA lists STLS", /STLS/.test(await _send(sock, "CAPA", true)));
|
|
153
|
+
check("RETR before auth refused", /^-ERR/.test(await _send(sock, "RETR 1")));
|
|
154
|
+
check("STAT before auth refused", /^-ERR/.test(await _send(sock, "STAT")));
|
|
155
|
+
check("USER over cleartext refused (RFC 2595)", /^-ERR/.test(await _send(sock, "USER alice")));
|
|
156
|
+
check("unknown verb refused", /^-ERR/.test(await _send(sock, "FLOOP")));
|
|
157
|
+
check("NOOP ok", /^\+OK/.test(await _send(sock, "NOOP")));
|
|
158
|
+
check("empty line refused", /^-ERR/.test(await _send(sock, "")));
|
|
159
|
+
check("QUIT in authorization ok", /^\+OK/.test(await _send(sock, "QUIT")));
|
|
160
|
+
} finally { sock.destroy(); await s.srv.close(); }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ---- STLS->TLS upgrade + authenticated TRANSACTION path ----
|
|
164
|
+
async function testAuthenticatedTransaction() {
|
|
165
|
+
var s = await _makeServer();
|
|
166
|
+
var sock = nodeNet.connect(s.port, "127.0.0.1");
|
|
167
|
+
sock.on("error", function () {});
|
|
168
|
+
await _readReply(sock); // greeting
|
|
169
|
+
check("STLS begins negotiation", /^\+OK/.test(await _send(sock, "STLS")));
|
|
170
|
+
var tls = nodeTls.connect({ socket: sock, ca: s.caPem, servername: "localhost" });
|
|
171
|
+
tls.on("error", function () {});
|
|
172
|
+
await new Promise(function (r, j) { tls.once("secureConnect", r); tls.once("error", j); });
|
|
173
|
+
try {
|
|
174
|
+
check("USER accepted over TLS", /^\+OK/.test(await _send(tls, "USER alice")));
|
|
175
|
+
check("PASS with bad creds refused", /^-ERR/.test(await _send(tls, "PASS wrong")));
|
|
176
|
+
check("USER re-issued after failure", /^\+OK/.test(await _send(tls, "USER alice")));
|
|
177
|
+
check("PASS with good creds authenticates", /^\+OK/.test(await _send(tls, "PASS good")));
|
|
178
|
+
check("USER after auth refused (already authenticated)", /^-ERR/.test(await _send(tls, "USER bob")));
|
|
179
|
+
check("STAT returns count+size", /^\+OK 2 /.test(await _send(tls, "STAT")));
|
|
180
|
+
check("LIST all is multiline", /\r\n\.\r\n$/.test(await _send(tls, "LIST", true)));
|
|
181
|
+
check("LIST single ok", /^\+OK 1 /.test(await _send(tls, "LIST 1")));
|
|
182
|
+
check("LIST out-of-range refused", /^-ERR/.test(await _send(tls, "LIST 99")));
|
|
183
|
+
check("RETR existing returns body", /octets/.test(await _send(tls, "RETR 1", true)));
|
|
184
|
+
check("RETR missing refused", /^-ERR/.test(await _send(tls, "RETR 99")));
|
|
185
|
+
check("RETR non-numeric refused", /^-ERR/.test(await _send(tls, "RETR abc")));
|
|
186
|
+
check("TOP existing ok", /^\+OK/.test(await _send(tls, "TOP 1 0", true)));
|
|
187
|
+
check("TOP missing refused", /^-ERR/.test(await _send(tls, "TOP 99 0")));
|
|
188
|
+
check("UIDL all is multiline", /\r\n\.\r\n$/.test(await _send(tls, "UIDL", true)));
|
|
189
|
+
check("UIDL single ok", /^\+OK 1 /.test(await _send(tls, "UIDL 1")));
|
|
190
|
+
check("DELE marks message", /^\+OK/.test(await _send(tls, "DELE 1")));
|
|
191
|
+
check("NOOP in transaction ok", /^\+OK/.test(await _send(tls, "NOOP")));
|
|
192
|
+
check("RSET clears delete marks", /^\+OK/.test(await _send(tls, "RSET")));
|
|
193
|
+
check("STLS after TLS refused", /^-ERR/.test(await _send(tls, "STLS")));
|
|
194
|
+
check("QUIT commits + closes", /^\+OK/.test(await _send(tls, "QUIT")));
|
|
195
|
+
} finally { tls.destroy(); sock.destroy(); await s.srv.close(); }
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ---- AUTH PLAIN mechanism over TLS ----
|
|
199
|
+
async function testAuthPlainMechanism() {
|
|
200
|
+
var s = await _makeServer();
|
|
201
|
+
var sock = nodeNet.connect(s.port, "127.0.0.1");
|
|
202
|
+
sock.on("error", function () {});
|
|
203
|
+
await _readReply(sock);
|
|
204
|
+
await _send(sock, "STLS");
|
|
205
|
+
var tls = nodeTls.connect({ socket: sock, ca: s.caPem, servername: "localhost" });
|
|
206
|
+
tls.on("error", function () {});
|
|
207
|
+
await new Promise(function (r, j) { tls.once("secureConnect", r); tls.once("error", j); });
|
|
208
|
+
try {
|
|
209
|
+
// SASL PLAIN (RFC 4616): authzid NUL authcid NUL passwd, base64-encoded.
|
|
210
|
+
var sasl = ["", "alice", "good"].join(NUL);
|
|
211
|
+
var authArg = Buffer.from(sasl, "utf8").toString("base64");
|
|
212
|
+
check("AUTH PLAIN with inline creds authenticates", /^\+OK/.test(await _send(tls, "AUTH PLAIN " + authArg)));
|
|
213
|
+
check("STAT after AUTH ok", /^\+OK/.test(await _send(tls, "STAT")));
|
|
214
|
+
} finally { tls.destroy(); sock.destroy(); await s.srv.close(); }
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ---- error / enumeration / malformed-argument branches ----
|
|
218
|
+
async function testEdgeCases() {
|
|
219
|
+
var s = await _makeServer({ maxLineBytes: b.constants.BYTES.bytes(64) });
|
|
220
|
+
var sock = nodeNet.connect(s.port, "127.0.0.1");
|
|
221
|
+
sock.on("error", function () {});
|
|
222
|
+
try {
|
|
223
|
+
await _readReply(sock); // greeting
|
|
224
|
+
check("AUTH with no mechanism enumerates (RFC 5034)", /^\+OK/.test(await _send(sock, "AUTH", true)));
|
|
225
|
+
check("AUTH PLAIN over cleartext refused (RFC 2595)", /^-ERR/.test(await _send(sock, "AUTH PLAIN")));
|
|
226
|
+
check("PASS without prior USER refused", /^-ERR/.test(await _send(sock, "PASS secret")));
|
|
227
|
+
check("APOP handled (refused under strict / no shared secret)", /^-ERR/.test(await _send(sock, "APOP alice deadbeef")));
|
|
228
|
+
check("DELE in authorization refused", /^-ERR/.test(await _send(sock, "DELE 1")));
|
|
229
|
+
// Overlong line: exceeds the 64-byte cap -> -ERR + close.
|
|
230
|
+
var longArg = "USER " + new Array(200).join("a");
|
|
231
|
+
var reply = await _send(sock, longArg);
|
|
232
|
+
check("overlong line refused", /^-ERR/.test(reply));
|
|
233
|
+
} finally { sock.destroy(); await s.srv.close(); }
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ---- raw byte-stream connection collector -------------------------------
|
|
237
|
+
// A single accumulator over the socket lets pipelined / async-window /
|
|
238
|
+
// server-initiated-close scenarios be asserted with helpers.waitUntil
|
|
239
|
+
// (poll, never a bare setTimeout) without interleaving multiple `data`
|
|
240
|
+
// readers on the same socket.
|
|
241
|
+
function _conn(port) {
|
|
242
|
+
var sock = nodeNet.connect(port, "127.0.0.1");
|
|
243
|
+
var acc = "";
|
|
244
|
+
var closed = false;
|
|
245
|
+
sock.on("data", function (chunk) { acc += chunk.toString("utf8"); });
|
|
246
|
+
sock.on("error", function () {});
|
|
247
|
+
sock.on("close", function () { closed = true; });
|
|
248
|
+
return {
|
|
249
|
+
sock: sock,
|
|
250
|
+
text: function () { return acc; },
|
|
251
|
+
isClosed: function () { return closed; },
|
|
252
|
+
send: function (line) { try { sock.write(line + "\r\n"); } catch (_e) { /* socket down */ } },
|
|
253
|
+
writeRaw: function (buf) { try { sock.write(buf); } catch (_e) { /* socket down */ } },
|
|
254
|
+
waitFor: function (re, label) {
|
|
255
|
+
return helpers.waitUntil(function () { return re.test(acc); },
|
|
256
|
+
{ timeoutMs: 5000, label: "pop3 reply: " + (label || String(re)) });
|
|
257
|
+
},
|
|
258
|
+
waitClosed: function (label) {
|
|
259
|
+
return helpers.waitUntil(function () { return closed; },
|
|
260
|
+
{ timeoutMs: 5000, label: "pop3 close: " + (label || "connection") });
|
|
261
|
+
},
|
|
262
|
+
destroy: function () { try { sock.destroy(); } catch (_e) { /* idempotent */ } },
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Drive one command sequence on a fresh connection and assert the reply.
|
|
267
|
+
async function _driveOnce(port, lines, expectRe, label) {
|
|
268
|
+
var c = _conn(port);
|
|
269
|
+
try {
|
|
270
|
+
await c.waitFor(/ready\r\n/, label + " greeting");
|
|
271
|
+
lines.forEach(function (ln) { c.send(ln); });
|
|
272
|
+
await c.waitFor(expectRe, label);
|
|
273
|
+
check(label, expectRe.test(c.text()));
|
|
274
|
+
} finally { c.destroy(); }
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// One authenticator that covers every mechanism the listener drives:
|
|
278
|
+
// PASS (username/password), AUTH PLAIN (base64 authzid NUL authcid NUL
|
|
279
|
+
// passwd via clientResponse), and APOP (username + digest). A `boom`
|
|
280
|
+
// credential makes verify throw (exercises the .catch branch); `good`
|
|
281
|
+
// authenticates; anything else fails closed.
|
|
282
|
+
function _fullVerify() {
|
|
283
|
+
return async function (mech, creds) {
|
|
284
|
+
if (mech === "APOP") {
|
|
285
|
+
if (creds.digest === "boom") throw new Error("apop-verify-boom");
|
|
286
|
+
return creds.digest === "good"
|
|
287
|
+
? { ok: true, actor: { username: creds.username, tenantId: "t1" } }
|
|
288
|
+
: { ok: false };
|
|
289
|
+
}
|
|
290
|
+
var username = creds.username, password = creds.password;
|
|
291
|
+
if (creds.clientResponse) {
|
|
292
|
+
var parts = Buffer.from(creds.clientResponse, "base64").toString("utf8").split(NUL);
|
|
293
|
+
username = parts[1]; password = parts[2];
|
|
294
|
+
}
|
|
295
|
+
if (password === "boom") throw new Error("pass-verify-boom");
|
|
296
|
+
return password === "good"
|
|
297
|
+
? { ok: true, actor: { username: username, tenantId: "t1" } }
|
|
298
|
+
: { ok: false };
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Permissive listener with the full authenticator — the profile that
|
|
303
|
+
// exercises the USER/PASS/APOP/AUTH transaction path over plaintext
|
|
304
|
+
// (permissive opts out of the cleartext-auth refusal) so the deep
|
|
305
|
+
// error/verify branches are reachable without a TLS handshake per case.
|
|
306
|
+
async function _makeFullServer(extra) {
|
|
307
|
+
var merged = { profile: "permissive", auth: { verify: _fullVerify(), mechanisms: ["PLAIN"] } };
|
|
308
|
+
if (extra) { Object.keys(extra).forEach(function (k) { merged[k] = extra[k]; }); }
|
|
309
|
+
return _makeServer(merged);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function _saslBlob(user, pass) {
|
|
313
|
+
return Buffer.from(["", user, pass].join(NUL), "utf8").toString("base64");
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ---- create()-time tenant-scope validation ----
|
|
317
|
+
function testTenantScopeCreateValidation() {
|
|
318
|
+
var e1 = null;
|
|
319
|
+
try { b.mail.server.pop3.create({ tlsContext: {}, mailStore: _stubMailStore(), tenantScope: {} }); }
|
|
320
|
+
catch (e) { e1 = e; }
|
|
321
|
+
check("tenantScope without .check refused at create",
|
|
322
|
+
e1 && e1.code === "mail-server-pop3/bad-tenant-scope");
|
|
323
|
+
var e2 = null;
|
|
324
|
+
try { b.mail.server.pop3.create({ tlsContext: {}, mailStore: _stubMailStore(), tenantScope: { check: function () {} } }); }
|
|
325
|
+
catch (e) { e2 = e; }
|
|
326
|
+
check("tenantScope without agentTenantId refused at create",
|
|
327
|
+
e2 && e2.code === "mail-server-pop3/no-agent-tenant-id");
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// ---- cross-tenant AUTH refusal (and same-tenant accept) ----
|
|
331
|
+
async function testTenantScopeEnforcement() {
|
|
332
|
+
var s1 = await _makeFullServer({
|
|
333
|
+
tenantScope: { check: function () { var e = new Error("wrong tenant"); e.code = "agent-tenant/cross-tenant"; throw e; } },
|
|
334
|
+
agentTenantId: "agent-1",
|
|
335
|
+
});
|
|
336
|
+
try {
|
|
337
|
+
await _driveOnce(s1.port, ["USER alice", "PASS good"], /cross-tenant/, "cross-tenant auth refused");
|
|
338
|
+
} finally { await s1.srv.close(); }
|
|
339
|
+
|
|
340
|
+
var s2 = await _makeFullServer({
|
|
341
|
+
tenantScope: { check: function () { /* same tenant — accept */ } },
|
|
342
|
+
agentTenantId: "agent-1",
|
|
343
|
+
});
|
|
344
|
+
try {
|
|
345
|
+
await _driveOnce(s2.port, ["USER alice", "PASS good"], /Logged in/, "same-tenant auth accepted");
|
|
346
|
+
} finally { await s2.srv.close(); }
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// ---- CAPA advertises wired SASL mechanisms (uppercased) ----
|
|
350
|
+
async function testCapaAdvertisesSasl() {
|
|
351
|
+
var s = await _makeServer({ auth: { verify: _fullVerify(), mechanisms: ["plain", "login"] } });
|
|
352
|
+
var c = _conn(s.port);
|
|
353
|
+
try {
|
|
354
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
355
|
+
c.send("CAPA");
|
|
356
|
+
await c.waitFor(/\r\n\.\r\n/, "capa terminator");
|
|
357
|
+
check("CAPA advertises wired SASL mechanisms uppercased", /SASL PLAIN LOGIN\r\n/.test(c.text()));
|
|
358
|
+
} finally { c.destroy(); await s.srv.close(); }
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// ---- idle timeout closes an authorization-state connection ----
|
|
362
|
+
async function testIdleTimeoutClosesConnection() {
|
|
363
|
+
await helpers.withTestTimeout("pop3 idle timeout", async function () {
|
|
364
|
+
var s = await _makeServer({ idleTimeoutMs: 300 });
|
|
365
|
+
var c = _conn(s.port);
|
|
366
|
+
try {
|
|
367
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
368
|
+
await c.waitFor(/-ERR Idle timeout/, "idle timeout -ERR");
|
|
369
|
+
check("idle connection receives -ERR Idle timeout", /-ERR Idle timeout/.test(c.text()));
|
|
370
|
+
await c.waitClosed("idle timeout close");
|
|
371
|
+
check("idle connection is closed by the listener", c.isClosed());
|
|
372
|
+
} finally { c.destroy(); await s.srv.close(); }
|
|
373
|
+
}, { timeoutMs: 8000 });
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// ---- server survives a peer RST (socket error handler) ----
|
|
377
|
+
async function testSocketErrorSurvived() {
|
|
378
|
+
var s = await _makeServer();
|
|
379
|
+
var c1 = _conn(s.port);
|
|
380
|
+
try {
|
|
381
|
+
await c1.waitFor(/ready\r\n/, "greeting");
|
|
382
|
+
// Abort with an RST so the server-side socket emits 'error'
|
|
383
|
+
// (ECONNRESET) rather than a clean FIN — exercises the socket
|
|
384
|
+
// error handler; the listener must stay up.
|
|
385
|
+
if (typeof c1.sock.resetAndDestroy === "function") c1.sock.resetAndDestroy();
|
|
386
|
+
else c1.sock.destroy(new Error("reset"));
|
|
387
|
+
var c2 = _conn(s.port);
|
|
388
|
+
try {
|
|
389
|
+
await c2.waitFor(/ready\r\n/, "post-reset greeting");
|
|
390
|
+
check("listener survives a peer RST and still serves new connections",
|
|
391
|
+
/ready/.test(c2.text()));
|
|
392
|
+
} finally { c2.destroy(); }
|
|
393
|
+
} finally { c1.destroy(); await s.srv.close(); }
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// ---- overlong line with no CRLF is refused + closed ----
|
|
397
|
+
async function testLineTooLongNoCrlf() {
|
|
398
|
+
var s = await _makeServer({ maxLineBytes: b.constants.BYTES.bytes(64) });
|
|
399
|
+
var c = _conn(s.port);
|
|
400
|
+
try {
|
|
401
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
402
|
+
// 99 bytes, no CRLF — buffer exceeds the 64-byte cap before a line
|
|
403
|
+
// terminator arrives → -ERR + close (distinct from the guard's
|
|
404
|
+
// line-too-long, which needs a terminated line).
|
|
405
|
+
c.writeRaw(Buffer.from(new Array(100).join("A"), "utf8"));
|
|
406
|
+
await c.waitFor(/-ERR Line too long/, "unterminated overlong line");
|
|
407
|
+
check("unterminated overlong line refused", /-ERR Line too long \(cap 64\)/.test(c.text()));
|
|
408
|
+
await c.waitClosed("overlong line close");
|
|
409
|
+
} finally { c.destroy(); await s.srv.close(); }
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// ---- STLS / AUTH / APOP refused once in TRANSACTION state ----
|
|
413
|
+
async function testPostAuthWrongState() {
|
|
414
|
+
var s = await _makeFullServer();
|
|
415
|
+
var c = _conn(s.port);
|
|
416
|
+
try {
|
|
417
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
418
|
+
c.send("USER alice"); c.send("PASS good");
|
|
419
|
+
await c.waitFor(/Logged in/, "authenticated");
|
|
420
|
+
c.send("STLS");
|
|
421
|
+
await c.waitFor(/STLS only valid in AUTHORIZATION/, "STLS wrong-state");
|
|
422
|
+
c.send("AUTH PLAIN " + _saslBlob("alice", "good"));
|
|
423
|
+
await c.waitFor(/AUTH only valid in AUTHORIZATION/, "AUTH wrong-state");
|
|
424
|
+
c.send("APOP alice deadbeef");
|
|
425
|
+
await c.waitFor(/APOP only valid in AUTHORIZATION/, "APOP wrong-state");
|
|
426
|
+
check("STLS refused in TRANSACTION (RFC 2595 §4)", /STLS only valid in AUTHORIZATION/.test(c.text()));
|
|
427
|
+
check("AUTH refused in TRANSACTION", /AUTH only valid in AUTHORIZATION/.test(c.text()));
|
|
428
|
+
check("APOP refused in TRANSACTION", /APOP only valid in AUTHORIZATION/.test(c.text()));
|
|
429
|
+
} finally { c.destroy(); await s.srv.close(); }
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// ---- STLS handshake failure (onError) closes the connection ----
|
|
433
|
+
async function testStlsHandshakeFailureClosed() {
|
|
434
|
+
await helpers.withTestTimeout("pop3 stls handshake failure", async function () {
|
|
435
|
+
var s = await _makeServer();
|
|
436
|
+
var c = _conn(s.port);
|
|
437
|
+
try {
|
|
438
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
439
|
+
c.send("STLS");
|
|
440
|
+
await c.waitFor(/Begin TLS negotiation/, "stls ack");
|
|
441
|
+
// Feed non-TLS bytes where a ClientHello is expected → the server
|
|
442
|
+
// TLS socket errors → onError → tls_handshake_failed + close.
|
|
443
|
+
c.writeRaw(Buffer.from("this-is-not-a-tls-clienthello-record\r\n\r\n", "utf8"));
|
|
444
|
+
await c.waitClosed("stls handshake failure close");
|
|
445
|
+
check("failed STLS handshake closes the connection", c.isClosed());
|
|
446
|
+
} finally { c.destroy(); await s.srv.close(); }
|
|
447
|
+
}, { timeoutMs: 8000 });
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// ---- post-handshake idle timeout (STLS onTimeout) ----
|
|
451
|
+
async function testTlsIdleTimeoutClosed() {
|
|
452
|
+
await helpers.withTestTimeout("pop3 tls idle timeout", async function () {
|
|
453
|
+
var s = await _makeServer({ idleTimeoutMs: 400 });
|
|
454
|
+
var sock = nodeNet.connect(s.port, "127.0.0.1");
|
|
455
|
+
sock.on("error", function () {});
|
|
456
|
+
var tls = null;
|
|
457
|
+
try {
|
|
458
|
+
await _readReply(sock); // greeting
|
|
459
|
+
await _send(sock, "STLS"); // +OK Begin TLS negotiation
|
|
460
|
+
tls = nodeTls.connect({ socket: sock, ca: s.caPem, servername: "localhost" });
|
|
461
|
+
tls.on("error", function () {});
|
|
462
|
+
await new Promise(function (r, j) { tls.once("secureConnect", r); tls.once("error", j); });
|
|
463
|
+
// The idle timer is armed only after a successful handshake; go
|
|
464
|
+
// idle so the post-handshake timer fires onTimeout(tlsSocket).
|
|
465
|
+
var got = "";
|
|
466
|
+
var tlsClosed = false;
|
|
467
|
+
tls.on("data", function (ch) { got += ch.toString("utf8"); });
|
|
468
|
+
tls.on("close", function () { tlsClosed = true; });
|
|
469
|
+
await helpers.waitUntil(function () { return /-ERR Idle timeout/.test(got) || tlsClosed; },
|
|
470
|
+
{ timeoutMs: 6000, label: "post-handshake idle timeout" });
|
|
471
|
+
check("post-handshake idle fires onTimeout and closes",
|
|
472
|
+
/-ERR Idle timeout/.test(got) || tlsClosed);
|
|
473
|
+
} finally {
|
|
474
|
+
if (tls) tls.destroy();
|
|
475
|
+
sock.destroy();
|
|
476
|
+
await s.srv.close();
|
|
477
|
+
}
|
|
478
|
+
}, { timeoutMs: 9000 });
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// ---- USER arriving in the auth window (actor set, drop pending) ----
|
|
482
|
+
async function testUserDuringAuthWindowRefused() {
|
|
483
|
+
await helpers.withTestTimeout("pop3 user-during-auth-window", async function () {
|
|
484
|
+
var releaseOpen = null;
|
|
485
|
+
var openGate = new Promise(function (res) { releaseOpen = res; });
|
|
486
|
+
var openCalled = false;
|
|
487
|
+
var store = _stubStore();
|
|
488
|
+
store.openPop3Drop = async function () {
|
|
489
|
+
openCalled = true; await openGate;
|
|
490
|
+
return { dropId: "drop-1", count: 0, totalBytes: 0 };
|
|
491
|
+
};
|
|
492
|
+
var s = await _makeFullServer({ mailStore: store });
|
|
493
|
+
var c = _conn(s.port);
|
|
494
|
+
try {
|
|
495
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
496
|
+
c.send("USER alice");
|
|
497
|
+
await c.waitFor(/Send password/, "user ack");
|
|
498
|
+
c.send("PASS good");
|
|
499
|
+
// state.actor is set synchronously before openPop3Drop is awaited;
|
|
500
|
+
// wait until the drop-open is in flight (stage still authorization).
|
|
501
|
+
await helpers.waitUntil(function () { return openCalled; },
|
|
502
|
+
{ timeoutMs: 5000, label: "openPop3Drop invoked" });
|
|
503
|
+
c.send("USER bob");
|
|
504
|
+
await c.waitFor(/Already authenticated/, "USER during auth-window");
|
|
505
|
+
check("USER during the pending-drop window is refused as already-authenticated",
|
|
506
|
+
/Already authenticated/.test(c.text()));
|
|
507
|
+
releaseOpen();
|
|
508
|
+
await c.waitFor(/Logged in/, "auth completes after gate release");
|
|
509
|
+
} finally {
|
|
510
|
+
if (releaseOpen) releaseOpen();
|
|
511
|
+
c.destroy(); await s.srv.close();
|
|
512
|
+
}
|
|
513
|
+
}, { timeoutMs: 9000 });
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// ---- USER / APOP refused over cleartext under balanced ----
|
|
517
|
+
async function testClearttextRefusedBalanced() {
|
|
518
|
+
var s = await _makeServer({ profile: "balanced" });
|
|
519
|
+
try {
|
|
520
|
+
// balanced lets USER/APOP past the wire-protocol guard pre-TLS, but
|
|
521
|
+
// the listener's defense-in-depth refuses the cleartext credential.
|
|
522
|
+
await _driveOnce(s.port, ["USER alice"], /USER refused over cleartext/, "USER over cleartext refused (balanced)");
|
|
523
|
+
await _driveOnce(s.port, ["APOP alice deadbeef"], /APOP refused over cleartext/, "APOP over cleartext refused (balanced)");
|
|
524
|
+
} finally { await s.srv.close(); }
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// ---- listener with no authenticator wired ----
|
|
528
|
+
async function testNoAuthConfigured() {
|
|
529
|
+
var s = await _makeServer({ profile: "permissive", auth: null });
|
|
530
|
+
try {
|
|
531
|
+
await _driveOnce(s.port, ["USER alice", "PASS secret"], /AUTH not configured on this listener/, "PASS with no authConfig");
|
|
532
|
+
await _driveOnce(s.port, ["APOP alice deadbeef"], /AUTH not configured/, "APOP with no authConfig");
|
|
533
|
+
await _driveOnce(s.port, ["AUTH PLAIN " + _saslBlob("alice", "good")], /AUTH not configured/, "AUTH with no authConfig");
|
|
534
|
+
} finally { await s.srv.close(); }
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// ---- PASS branches: no prior USER, verify-throw, auth-failure budget ----
|
|
538
|
+
async function testPassBranches() {
|
|
539
|
+
var s1 = await _makeFullServer();
|
|
540
|
+
try {
|
|
541
|
+
await _driveOnce(s1.port, ["PASS secret"], /PASS only valid after USER/, "PASS before USER refused");
|
|
542
|
+
} finally { await s1.srv.close(); }
|
|
543
|
+
|
|
544
|
+
var s2 = await _makeFullServer();
|
|
545
|
+
try {
|
|
546
|
+
await _driveOnce(s2.port, ["USER alice", "PASS boom"], /Authentication failed/, "PASS verify-throw refused");
|
|
547
|
+
} finally { await s2.srv.close(); }
|
|
548
|
+
|
|
549
|
+
var s3 = await _makeFullServer({ rateLimit: { authFailuresPerIpPer15Min: 1 } });
|
|
550
|
+
var c = _conn(s3.port);
|
|
551
|
+
try {
|
|
552
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
553
|
+
c.send("USER alice"); c.send("PASS wrong");
|
|
554
|
+
await c.waitFor(/Authentication failed/, "first PASS failure");
|
|
555
|
+
c.send("USER alice"); c.send("PASS wrong");
|
|
556
|
+
await c.waitFor(/Too many AUTH failures/, "PASS budget exhausted");
|
|
557
|
+
check("PASS past the auth-failure budget is refused + closed", /Too many AUTH failures/.test(c.text()));
|
|
558
|
+
await c.waitClosed("PASS rate-limit close");
|
|
559
|
+
} finally { c.destroy(); await s3.srv.close(); }
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// ---- APOP verify branches under permissive ----
|
|
563
|
+
async function testApopMechanism() {
|
|
564
|
+
var s = await _makeFullServer();
|
|
565
|
+
try {
|
|
566
|
+
await _driveOnce(s.port, ["APOP alice good"], /Logged in/, "APOP success authenticates");
|
|
567
|
+
await _driveOnce(s.port, ["APOP alice nope"], /Authentication failed/, "APOP bad digest refused");
|
|
568
|
+
await _driveOnce(s.port, ["APOP alice boom"], /Authentication failed/, "APOP verify-throw refused");
|
|
569
|
+
} finally { await s.srv.close(); }
|
|
570
|
+
|
|
571
|
+
var s2 = await _makeFullServer({ rateLimit: { authFailuresPerIpPer15Min: 1 } });
|
|
572
|
+
var c = _conn(s2.port);
|
|
573
|
+
try {
|
|
574
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
575
|
+
c.send("APOP alice nope");
|
|
576
|
+
await c.waitFor(/Authentication failed/, "first APOP failure");
|
|
577
|
+
c.send("APOP alice nope");
|
|
578
|
+
await c.waitFor(/Too many AUTH failures/, "APOP budget exhausted");
|
|
579
|
+
check("APOP past the auth-failure budget is refused + closed", /Too many AUTH failures/.test(c.text()));
|
|
580
|
+
await c.waitClosed("APOP rate-limit close");
|
|
581
|
+
} finally { c.destroy(); await s2.srv.close(); }
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// ---- AUTH verify branches under permissive ----
|
|
585
|
+
async function testAuthMechanismBranches() {
|
|
586
|
+
var s1 = await _makeFullServer();
|
|
587
|
+
try {
|
|
588
|
+
await _driveOnce(s1.port, ["AUTH PLAIN " + _saslBlob("alice", "wrong")], /Authentication failed/, "AUTH PLAIN bad creds refused");
|
|
589
|
+
} finally { await s1.srv.close(); }
|
|
590
|
+
|
|
591
|
+
var s2 = await _makeFullServer();
|
|
592
|
+
try {
|
|
593
|
+
await _driveOnce(s2.port, ["AUTH PLAIN " + _saslBlob("alice", "boom")], /Authentication failed/, "AUTH PLAIN verify-throw refused");
|
|
594
|
+
} finally { await s2.srv.close(); }
|
|
595
|
+
|
|
596
|
+
var s3 = await _makeFullServer({ rateLimit: { authFailuresPerIpPer15Min: 1 } });
|
|
597
|
+
var c = _conn(s3.port);
|
|
598
|
+
try {
|
|
599
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
600
|
+
c.send("AUTH PLAIN " + _saslBlob("alice", "wrong"));
|
|
601
|
+
await c.waitFor(/Authentication failed/, "first AUTH failure");
|
|
602
|
+
c.send("AUTH PLAIN " + _saslBlob("alice", "wrong"));
|
|
603
|
+
await c.waitFor(/Too many AUTH failures/, "AUTH budget exhausted");
|
|
604
|
+
check("AUTH past the auth-failure budget is refused + closed", /Too many AUTH failures/.test(c.text()));
|
|
605
|
+
await c.waitClosed("AUTH rate-limit close");
|
|
606
|
+
} finally { c.destroy(); await s3.srv.close(); }
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// ---- backend openPop3Drop rejection surfaces -ERR ----
|
|
610
|
+
async function testOpenDropRejects() {
|
|
611
|
+
var store = _stubStore();
|
|
612
|
+
store.openPop3Drop = async function () { throw new Error("drop-locked"); };
|
|
613
|
+
var s = await _makeFullServer({ mailStore: store });
|
|
614
|
+
var c = _conn(s.port);
|
|
615
|
+
try {
|
|
616
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
617
|
+
c.send("USER alice"); c.send("PASS good");
|
|
618
|
+
await c.waitFor(/Cannot open drop/, "open-drop rejection");
|
|
619
|
+
check("openPop3Drop rejection surfaces -ERR Cannot open drop",
|
|
620
|
+
/Cannot open drop: drop-locked/.test(c.text()));
|
|
621
|
+
} finally { c.destroy(); await s.srv.close(); }
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// ---- UPDATE-state commit rejection surfaces -ERR + close ----
|
|
625
|
+
async function testQuitCommitFails() {
|
|
626
|
+
var store = _stubStore();
|
|
627
|
+
store.commitPop3Drop = async function () { throw new Error("commit-broke"); };
|
|
628
|
+
var s = await _makeFullServer({ mailStore: store });
|
|
629
|
+
var c = _conn(s.port);
|
|
630
|
+
try {
|
|
631
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
632
|
+
c.send("USER alice"); c.send("PASS good");
|
|
633
|
+
await c.waitFor(/Logged in/, "authenticated");
|
|
634
|
+
c.send("QUIT");
|
|
635
|
+
await c.waitFor(/Commit failed/, "commit rejection");
|
|
636
|
+
check("QUIT commit rejection surfaces -ERR Commit failed",
|
|
637
|
+
/Commit failed: commit-broke/.test(c.text()));
|
|
638
|
+
await c.waitClosed("commit-fail close");
|
|
639
|
+
} finally { c.destroy(); await s.srv.close(); }
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// ---- RSET routes through mailStore.resetPop3Drop when present ----
|
|
643
|
+
async function testRsetInvokesResetPop3Drop() {
|
|
644
|
+
var resetCalled = false;
|
|
645
|
+
var store = _stubStore();
|
|
646
|
+
store.resetPop3Drop = async function () { resetCalled = true; };
|
|
647
|
+
var s = await _makeFullServer({ mailStore: store });
|
|
648
|
+
var c = _conn(s.port);
|
|
649
|
+
try {
|
|
650
|
+
await c.waitFor(/ready\r\n/, "greeting");
|
|
651
|
+
c.send("USER alice"); c.send("PASS good");
|
|
652
|
+
await c.waitFor(/Logged in/, "authenticated");
|
|
653
|
+
c.send("RSET");
|
|
654
|
+
await c.waitFor(/delete marks cleared/, "rset ok");
|
|
655
|
+
await helpers.waitUntil(function () { return resetCalled; },
|
|
656
|
+
{ timeoutMs: 5000, label: "resetPop3Drop invoked" });
|
|
657
|
+
check("RSET routes through mailStore.resetPop3Drop when present", resetCalled);
|
|
658
|
+
} finally { c.destroy(); await s.srv.close(); }
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
async function run() {
|
|
64
662
|
testSurface();
|
|
65
663
|
testRequiresTlsContext();
|
|
66
664
|
testRequiresMailStore();
|
|
67
665
|
testRequiresMailStoreOpenPop3Drop();
|
|
68
666
|
testBadBoundsRefused();
|
|
667
|
+
testTenantScopeCreateValidation();
|
|
668
|
+
await testPlaintextDispatch();
|
|
669
|
+
await testAuthenticatedTransaction();
|
|
670
|
+
await testAuthPlainMechanism();
|
|
671
|
+
await testEdgeCases();
|
|
672
|
+
await testTenantScopeEnforcement();
|
|
673
|
+
await testCapaAdvertisesSasl();
|
|
674
|
+
await testIdleTimeoutClosesConnection();
|
|
675
|
+
await testSocketErrorSurvived();
|
|
676
|
+
await testLineTooLongNoCrlf();
|
|
677
|
+
await testPostAuthWrongState();
|
|
678
|
+
await testStlsHandshakeFailureClosed();
|
|
679
|
+
await testTlsIdleTimeoutClosed();
|
|
680
|
+
await testUserDuringAuthWindowRefused();
|
|
681
|
+
await testClearttextRefusedBalanced();
|
|
682
|
+
await testNoAuthConfigured();
|
|
683
|
+
await testPassBranches();
|
|
684
|
+
await testApopMechanism();
|
|
685
|
+
await testAuthMechanismBranches();
|
|
686
|
+
await testOpenDropRejects();
|
|
687
|
+
await testQuitCommitFails();
|
|
688
|
+
await testRsetInvokesResetPop3Drop();
|
|
69
689
|
}
|
|
70
690
|
|
|
71
691
|
module.exports = { run: run };
|
|
72
692
|
|
|
73
693
|
if (require.main === module) {
|
|
74
|
-
|
|
75
|
-
|
|
694
|
+
run().then(function () { console.log("[mail-server-pop3] OK"); },
|
|
695
|
+
function (e) { process.stderr.write("FAIL: " + (e && e.stack || e) + "\n"); process.exit(1); });
|
|
76
696
|
}
|