TUN-8333: Bump go-jose dependency to v4
This commit is contained in:
parent
a1a9f3813e
commit
687682120c
15
go.mod
15
go.mod
|
@ -4,14 +4,15 @@ go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/coredns/coredns v1.10.0
|
github.com/coredns/coredns v1.10.0
|
||||||
github.com/coreos/go-oidc/v3 v3.6.0
|
github.com/coreos/go-oidc/v3 v3.10.0
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0
|
github.com/coreos/go-systemd/v22 v22.5.0
|
||||||
github.com/facebookgo/grace v0.0.0-20180706040059-75cf19382434
|
github.com/facebookgo/grace v0.0.0-20180706040059-75cf19382434
|
||||||
|
github.com/fortytw2/leaktest v1.3.0
|
||||||
github.com/fsnotify/fsnotify v1.4.9
|
github.com/fsnotify/fsnotify v1.4.9
|
||||||
github.com/getsentry/sentry-go v0.16.0
|
github.com/getsentry/sentry-go v0.16.0
|
||||||
github.com/go-chi/chi/v5 v5.0.8
|
github.com/go-chi/chi/v5 v5.0.8
|
||||||
github.com/go-chi/cors v1.2.1
|
github.com/go-chi/cors v1.2.1
|
||||||
github.com/go-jose/go-jose/v3 v3.0.0
|
github.com/go-jose/go-jose/v4 v4.0.1
|
||||||
github.com/gobwas/ws v1.0.4
|
github.com/gobwas/ws v1.0.4
|
||||||
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
|
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
|
||||||
github.com/google/gopacket v1.1.19
|
github.com/google/gopacket v1.1.19
|
||||||
|
@ -35,11 +36,11 @@ require (
|
||||||
go.opentelemetry.io/otel/trace v1.21.0
|
go.opentelemetry.io/otel/trace v1.21.0
|
||||||
go.opentelemetry.io/proto/otlp v1.0.0
|
go.opentelemetry.io/proto/otlp v1.0.0
|
||||||
go.uber.org/automaxprocs v1.4.0
|
go.uber.org/automaxprocs v1.4.0
|
||||||
golang.org/x/crypto v0.16.0
|
golang.org/x/crypto v0.21.0
|
||||||
golang.org/x/net v0.19.0
|
golang.org/x/net v0.21.0
|
||||||
golang.org/x/sync v0.4.0
|
golang.org/x/sync v0.4.0
|
||||||
golang.org/x/sys v0.15.0
|
golang.org/x/sys v0.18.0
|
||||||
golang.org/x/term v0.15.0
|
golang.org/x/term v0.18.0
|
||||||
google.golang.org/protobuf v1.31.0
|
google.golang.org/protobuf v1.31.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
|
@ -60,7 +61,6 @@ require (
|
||||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
||||||
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect
|
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
||||||
github.com/fortytw2/leaktest v1.3.0 // indirect
|
|
||||||
github.com/go-logr/logr v1.3.0 // indirect
|
github.com/go-logr/logr v1.3.0 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
|
@ -82,7 +82,6 @@ require (
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/common v0.37.0 // indirect
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
github.com/prometheus/procfs v0.8.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||||
go.uber.org/mock v0.3.0 // indirect
|
go.uber.org/mock v0.3.0 // indirect
|
||||||
|
|
29
go.sum
29
go.sum
|
@ -60,8 +60,8 @@ github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0=
|
||||||
github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4=
|
github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4=
|
||||||
github.com/coredns/coredns v1.10.0 h1:jCfuWsBjTs0dapkkhISfPCzn5LqvSRtrFtaf/Tjj4DI=
|
github.com/coredns/coredns v1.10.0 h1:jCfuWsBjTs0dapkkhISfPCzn5LqvSRtrFtaf/Tjj4DI=
|
||||||
github.com/coredns/coredns v1.10.0/go.mod h1:CIfRU5TgpuoIiJBJ4XrofQzfFQpPFh32ERpUevrSlaw=
|
github.com/coredns/coredns v1.10.0/go.mod h1:CIfRU5TgpuoIiJBJ4XrofQzfFQpPFh32ERpUevrSlaw=
|
||||||
github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o=
|
github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
|
||||||
github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc=
|
github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
@ -108,8 +108,8 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
|
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
|
||||||
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
|
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||||
|
@ -322,10 +322,6 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
|
||||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
|
||||||
github.com/quic-go/quic-go v0.40.1-0.20231203135336-87ef8ec48d55 h1:I4N3ZRnkZPbDN935Tg8QDf8fRpHp3bZ0U0/L42jBgNE=
|
|
||||||
github.com/quic-go/quic-go v0.40.1-0.20231203135336-87ef8ec48d55/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
|
|
||||||
github.com/quic-go/quic-go v0.40.1-0.20240101045026-22b7f7744eb6 h1:OI4WiysowCcxLtcZMGBZildo12di3ljcMN4vWdUQpoU=
|
github.com/quic-go/quic-go v0.40.1-0.20240101045026-22b7f7744eb6 h1:OI4WiysowCcxLtcZMGBZildo12di3ljcMN4vWdUQpoU=
|
||||||
github.com/quic-go/quic-go v0.40.1-0.20240101045026-22b7f7744eb6/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
github.com/quic-go/quic-go v0.40.1-0.20240101045026-22b7f7744eb6/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
@ -391,12 +387,11 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
@ -468,8 +463,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -538,12 +533,12 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|
|
@ -3,7 +3,8 @@ package management
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/jwt"
|
"github.com/go-jose/go-jose/v4"
|
||||||
|
"github.com/go-jose/go-jose/v4/jwt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type managementTokenClaims struct {
|
type managementTokenClaims struct {
|
||||||
|
@ -37,7 +38,7 @@ func (t *actor) verify() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseToken(token string) (*managementTokenClaims, error) {
|
func parseToken(token string) (*managementTokenClaims, error) {
|
||||||
jwt, err := jwt.ParseSigned(token)
|
jwt, err := jwt.ParseSigned(token, []jose.SignatureAlgorithm{jose.ES256})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("malformed jwt: %v", err)
|
return nil, fmt.Errorf("malformed jwt: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3"
|
"github.com/go-jose/go-jose/v4"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/jwt"
|
"github.com/go-jose/go-jose/v4"
|
||||||
|
"github.com/go-jose/go-jose/v4/jwt"
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
gossh "golang.org/x/crypto/ssh"
|
gossh "golang.org/x/crypto/ssh"
|
||||||
|
@ -51,6 +52,8 @@ type errorResponse struct {
|
||||||
|
|
||||||
var mockRequest func(url, contentType string, body io.Reader) (*http.Response, error) = nil
|
var mockRequest func(url, contentType string, body io.Reader) (*http.Response, error) = nil
|
||||||
|
|
||||||
|
var signatureAlgs = []jose.SignatureAlgorithm{jose.RS256}
|
||||||
|
|
||||||
// GenerateShortLivedCertificate generates and stores a keypair for short lived certs
|
// GenerateShortLivedCertificate generates and stores a keypair for short lived certs
|
||||||
func GenerateShortLivedCertificate(appURL *url.URL, token string) error {
|
func GenerateShortLivedCertificate(appURL *url.URL, token string) error {
|
||||||
fullName, err := cfpath.GenerateSSHCertFilePathFromURL(appURL, keyName)
|
fullName, err := cfpath.GenerateSSHCertFilePathFromURL(appURL, keyName)
|
||||||
|
@ -87,7 +90,7 @@ func SignCert(token, pubKey string) (string, error) {
|
||||||
return "", errors.New("invalid token")
|
return "", errors.New("invalid token")
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedToken, err := jwt.ParseSigned(token)
|
parsedToken, err := jwt.ParseSigned(token, signatureAlgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "failed to parse JWT")
|
return "", errors.Wrap(err, "failed to parse JWT")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
package sshgen
|
package sshgen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -14,8 +16,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3"
|
"github.com/go-jose/go-jose/v4"
|
||||||
"github.com/go-jose/go-jose/v3/jwt"
|
"github.com/go-jose/go-jose/v4/jwt"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/config"
|
"github.com/cloudflare/cloudflared/config"
|
||||||
|
@ -103,13 +105,16 @@ func tokenGenerator() string {
|
||||||
Expiry: jwt.NewNumericDate(exp),
|
Expiry: jwt.NewNumericDate(exp),
|
||||||
}
|
}
|
||||||
|
|
||||||
key := []byte("secret")
|
key, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||||
signer, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: key}, (&jose.SignerOptions{}).WithType("JWT"))
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
signer, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.RS256, Key: key}, (&jose.SignerOptions{}).WithType("JWT"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
signedToken, err := jwt.Signed(signer).Claims(claims).CompactSerialize()
|
signedToken, err := jwt.Signed(signer).Claims(claims).Serialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3"
|
"github.com/go-jose/go-jose/v4"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ const (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
userAgent = "DEV"
|
userAgent = "DEV"
|
||||||
|
signatureAlgs = []jose.SignatureAlgorithm{jose.RS256}
|
||||||
)
|
)
|
||||||
|
|
||||||
type AppInfo struct {
|
type AppInfo struct {
|
||||||
|
@ -415,7 +416,7 @@ func getTokenIfExists(path string) (*jose.JSONWebSignature, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
token, err := jose.ParseSigned(string(content))
|
token, err := jose.ParseSigned(string(content), signatureAlgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package oidc
|
package oidc
|
||||||
|
|
||||||
|
import jose "github.com/go-jose/go-jose/v4"
|
||||||
|
|
||||||
// JOSE asymmetric signing algorithm values as defined by RFC 7518
|
// JOSE asymmetric signing algorithm values as defined by RFC 7518
|
||||||
//
|
//
|
||||||
// see: https://tools.ietf.org/html/rfc7518#section-3.1
|
// see: https://tools.ietf.org/html/rfc7518#section-3.1
|
||||||
|
@ -15,3 +17,16 @@ const (
|
||||||
PS512 = "PS512" // RSASSA-PSS using SHA512 and MGF1-SHA512
|
PS512 = "PS512" // RSASSA-PSS using SHA512 and MGF1-SHA512
|
||||||
EdDSA = "EdDSA" // Ed25519 using SHA-512
|
EdDSA = "EdDSA" // Ed25519 using SHA-512
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var allAlgs = []jose.SignatureAlgorithm{
|
||||||
|
jose.RS256,
|
||||||
|
jose.RS384,
|
||||||
|
jose.RS512,
|
||||||
|
jose.ES256,
|
||||||
|
jose.ES384,
|
||||||
|
jose.ES512,
|
||||||
|
jose.PS256,
|
||||||
|
jose.PS384,
|
||||||
|
jose.PS512,
|
||||||
|
jose.EdDSA,
|
||||||
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
jose "github.com/go-jose/go-jose/v3"
|
jose "github.com/go-jose/go-jose/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StaticKeySet is a verifier that validates JWT against a static set of public keys.
|
// StaticKeySet is a verifier that validates JWT against a static set of public keys.
|
||||||
|
@ -25,7 +25,9 @@ type StaticKeySet struct {
|
||||||
|
|
||||||
// VerifySignature compares the signature against a static set of public keys.
|
// VerifySignature compares the signature against a static set of public keys.
|
||||||
func (s *StaticKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) {
|
func (s *StaticKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) {
|
||||||
jws, err := jose.ParseSigned(jwt)
|
// Algorithms are already checked by Verifier, so this parse method accepts
|
||||||
|
// any algorithm.
|
||||||
|
jws, err := jose.ParseSigned(jwt, allAlgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parsing jwt: %v", err)
|
return nil, fmt.Errorf("parsing jwt: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -127,8 +129,13 @@ var parsedJWTKey contextKey
|
||||||
func (r *RemoteKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) {
|
func (r *RemoteKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) {
|
||||||
jws, ok := ctx.Value(parsedJWTKey).(*jose.JSONWebSignature)
|
jws, ok := ctx.Value(parsedJWTKey).(*jose.JSONWebSignature)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
// The algorithm values are already enforced by the Validator, which also sets
|
||||||
|
// the context value above to pre-parsed signature.
|
||||||
|
//
|
||||||
|
// Practically, this codepath isn't called in normal use of this package, but
|
||||||
|
// if it is, the algorithms have already been checked.
|
||||||
var err error
|
var err error
|
||||||
jws, err = jose.ParseSigned(jwt)
|
jws, err = jose.ParseSigned(jwt, allAlgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
|
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -159,7 +166,7 @@ func (r *RemoteKeySet) verify(ctx context.Context, jws *jose.JSONWebSignature) (
|
||||||
// https://openid.net/specs/openid-connect-core-1_0.html#RotateSigKeys
|
// https://openid.net/specs/openid-connect-core-1_0.html#RotateSigKeys
|
||||||
keys, err := r.keysFromRemote(ctx)
|
keys, err := r.keysFromRemote(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("fetching keys %v", err)
|
return nil, fmt.Errorf("fetching keys %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
|
@ -228,11 +235,11 @@ func (r *RemoteKeySet) updateKeys() ([]jose.JSONWebKey, error) {
|
||||||
|
|
||||||
resp, err := doRequest(r.ctx, req)
|
resp, err := doRequest(r.ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("oidc: get keys failed %v", err)
|
return nil, fmt.Errorf("oidc: get keys failed %w", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to read response body: %v", err)
|
return nil, fmt.Errorf("unable to read response body: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -79,7 +79,7 @@ func getClient(ctx context.Context) *http.Client {
|
||||||
// provider, err := oidc.NewProvider(ctx, discoveryBaseURL)
|
// provider, err := oidc.NewProvider(ctx, discoveryBaseURL)
|
||||||
//
|
//
|
||||||
// This is insecure because validating the correct issuer is critical for multi-tenant
|
// This is insecure because validating the correct issuer is critical for multi-tenant
|
||||||
// proivders. Any overrides here MUST be carefully reviewed.
|
// providers. Any overrides here MUST be carefully reviewed.
|
||||||
func InsecureIssuerURLContext(ctx context.Context, issuerURL string) context.Context {
|
func InsecureIssuerURLContext(ctx context.Context, issuerURL string) context.Context {
|
||||||
return context.WithValue(ctx, issuerURLKey, issuerURL)
|
return context.WithValue(ctx, issuerURLKey, issuerURL)
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,7 @@ type Provider struct {
|
||||||
issuer string
|
issuer string
|
||||||
authURL string
|
authURL string
|
||||||
tokenURL string
|
tokenURL string
|
||||||
|
deviceAuthURL string
|
||||||
userInfoURL string
|
userInfoURL string
|
||||||
jwksURL string
|
jwksURL string
|
||||||
algorithms []string
|
algorithms []string
|
||||||
|
@ -131,6 +132,7 @@ type providerJSON struct {
|
||||||
Issuer string `json:"issuer"`
|
Issuer string `json:"issuer"`
|
||||||
AuthURL string `json:"authorization_endpoint"`
|
AuthURL string `json:"authorization_endpoint"`
|
||||||
TokenURL string `json:"token_endpoint"`
|
TokenURL string `json:"token_endpoint"`
|
||||||
|
DeviceAuthURL string `json:"device_authorization_endpoint"`
|
||||||
JWKSURL string `json:"jwks_uri"`
|
JWKSURL string `json:"jwks_uri"`
|
||||||
UserInfoURL string `json:"userinfo_endpoint"`
|
UserInfoURL string `json:"userinfo_endpoint"`
|
||||||
Algorithms []string `json:"id_token_signing_alg_values_supported"`
|
Algorithms []string `json:"id_token_signing_alg_values_supported"`
|
||||||
|
@ -165,6 +167,9 @@ type ProviderConfig struct {
|
||||||
// TokenURL is the endpoint used by the provider to support the OAuth 2.0
|
// TokenURL is the endpoint used by the provider to support the OAuth 2.0
|
||||||
// token endpoint.
|
// token endpoint.
|
||||||
TokenURL string
|
TokenURL string
|
||||||
|
// DeviceAuthURL is the endpoint used by the provider to support the OAuth 2.0
|
||||||
|
// device authorization endpoint.
|
||||||
|
DeviceAuthURL string
|
||||||
// UserInfoURL is the endpoint used by the provider to support the OpenID
|
// UserInfoURL is the endpoint used by the provider to support the OpenID
|
||||||
// Connect UserInfo flow.
|
// Connect UserInfo flow.
|
||||||
//
|
//
|
||||||
|
@ -188,6 +193,7 @@ func (p *ProviderConfig) NewProvider(ctx context.Context) *Provider {
|
||||||
issuer: p.IssuerURL,
|
issuer: p.IssuerURL,
|
||||||
authURL: p.AuthURL,
|
authURL: p.AuthURL,
|
||||||
tokenURL: p.TokenURL,
|
tokenURL: p.TokenURL,
|
||||||
|
deviceAuthURL: p.DeviceAuthURL,
|
||||||
userInfoURL: p.UserInfoURL,
|
userInfoURL: p.UserInfoURL,
|
||||||
jwksURL: p.JWKSURL,
|
jwksURL: p.JWKSURL,
|
||||||
algorithms: p.Algorithms,
|
algorithms: p.Algorithms,
|
||||||
|
@ -211,7 +217,7 @@ func NewProvider(ctx context.Context, issuer string) (*Provider, error) {
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to read response body: %v", err)
|
return nil, fmt.Errorf("unable to read response body: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -243,6 +249,7 @@ func NewProvider(ctx context.Context, issuer string) (*Provider, error) {
|
||||||
issuer: issuerURL,
|
issuer: issuerURL,
|
||||||
authURL: p.AuthURL,
|
authURL: p.AuthURL,
|
||||||
tokenURL: p.TokenURL,
|
tokenURL: p.TokenURL,
|
||||||
|
deviceAuthURL: p.DeviceAuthURL,
|
||||||
userInfoURL: p.UserInfoURL,
|
userInfoURL: p.UserInfoURL,
|
||||||
jwksURL: p.JWKSURL,
|
jwksURL: p.JWKSURL,
|
||||||
algorithms: algs,
|
algorithms: algs,
|
||||||
|
@ -273,7 +280,7 @@ func (p *Provider) Claims(v interface{}) error {
|
||||||
|
|
||||||
// Endpoint returns the OAuth2 auth and token endpoints for the given provider.
|
// Endpoint returns the OAuth2 auth and token endpoints for the given provider.
|
||||||
func (p *Provider) Endpoint() oauth2.Endpoint {
|
func (p *Provider) Endpoint() oauth2.Endpoint {
|
||||||
return oauth2.Endpoint{AuthURL: p.authURL, TokenURL: p.tokenURL}
|
return oauth2.Endpoint{AuthURL: p.authURL, DeviceAuthURL: p.deviceAuthURL, TokenURL: p.tokenURL}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserInfoEndpoint returns the OpenID Connect userinfo endpoint for the given
|
// UserInfoEndpoint returns the OpenID Connect userinfo endpoint for the given
|
||||||
|
@ -332,7 +339,7 @@ func (p *Provider) UserInfo(ctx context.Context, tokenSource oauth2.TokenSource)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,12 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
jose "github.com/go-jose/go-jose/v3"
|
jose "github.com/go-jose/go-jose/v4"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ func resolveDistributedClaim(ctx context.Context, verifier *IDTokenVerifier, src
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to read response body: %v", err)
|
return nil, fmt.Errorf("unable to read response body: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,16 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
jws, err := jose.ParseSigned(rawIDToken)
|
var supportedSigAlgs []jose.SignatureAlgorithm
|
||||||
|
for _, alg := range v.config.SupportedSigningAlgs {
|
||||||
|
supportedSigAlgs = append(supportedSigAlgs, jose.SignatureAlgorithm(alg))
|
||||||
|
}
|
||||||
|
if len(supportedSigAlgs) == 0 {
|
||||||
|
// If no algorithms were specified by both the config and discovery, default
|
||||||
|
// to the one mandatory algorithm "RS256".
|
||||||
|
supportedSigAlgs = []jose.SignatureAlgorithm{jose.RS256}
|
||||||
|
}
|
||||||
|
jws, err := jose.ParseSigned(rawIDToken, supportedSigAlgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
|
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -322,17 +331,7 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("oidc: multiple signatures on id token not supported")
|
return nil, fmt.Errorf("oidc: multiple signatures on id token not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
sig := jws.Signatures[0]
|
sig := jws.Signatures[0]
|
||||||
supportedSigAlgs := v.config.SupportedSigningAlgs
|
|
||||||
if len(supportedSigAlgs) == 0 {
|
|
||||||
supportedSigAlgs = []string{RS256}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !contains(supportedSigAlgs, sig.Header.Algorithm) {
|
|
||||||
return nil, fmt.Errorf("oidc: id token signed with unsupported algorithm, expected %q got %q", supportedSigAlgs, sig.Header.Algorithm)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.sigAlgorithm = sig.Header.Algorithm
|
t.sigAlgorithm = sig.Header.Algorithm
|
||||||
|
|
||||||
ctx = context.WithValue(ctx, parsedJWTKey, jws)
|
ctx = context.WithValue(ctx, parsedJWTKey, jws)
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
Serious about security
|
|
||||||
======================
|
|
||||||
|
|
||||||
Square recognizes the important contributions the security research community
|
|
||||||
can make. We therefore encourage reporting security issues with the code
|
|
||||||
contained in this repository.
|
|
||||||
|
|
||||||
If you believe you have discovered a security vulnerability, please follow the
|
|
||||||
guidelines at <https://bugcrowd.com/squareopensource>.
|
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
/*-
|
|
||||||
* Copyright 2016 Zbigniew Mandziejewicz
|
|
||||||
* Copyright 2016 Square, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jwt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
jose "github.com/go-jose/go-jose/v3"
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
// JSONWebToken represents a JSON Web Token (as specified in RFC7519).
|
|
||||||
type JSONWebToken struct {
|
|
||||||
payload func(k interface{}) ([]byte, error)
|
|
||||||
unverifiedPayload func() []byte
|
|
||||||
Headers []jose.Header
|
|
||||||
}
|
|
||||||
|
|
||||||
type NestedJSONWebToken struct {
|
|
||||||
enc *jose.JSONWebEncryption
|
|
||||||
Headers []jose.Header
|
|
||||||
}
|
|
||||||
|
|
||||||
// Claims deserializes a JSONWebToken into dest using the provided key.
|
|
||||||
func (t *JSONWebToken) Claims(key interface{}, dest ...interface{}) error {
|
|
||||||
b, err := t.payload(key)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, d := range dest {
|
|
||||||
if err := json.Unmarshal(b, d); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnsafeClaimsWithoutVerification deserializes the claims of a
|
|
||||||
// JSONWebToken into the dests. For signed JWTs, the claims are not
|
|
||||||
// verified. This function won't work for encrypted JWTs.
|
|
||||||
func (t *JSONWebToken) UnsafeClaimsWithoutVerification(dest ...interface{}) error {
|
|
||||||
if t.unverifiedPayload == nil {
|
|
||||||
return fmt.Errorf("go-jose/go-jose: Cannot get unverified claims")
|
|
||||||
}
|
|
||||||
claims := t.unverifiedPayload()
|
|
||||||
for _, d := range dest {
|
|
||||||
if err := json.Unmarshal(claims, d); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *NestedJSONWebToken) Decrypt(decryptionKey interface{}) (*JSONWebToken, error) {
|
|
||||||
b, err := t.enc.Decrypt(decryptionKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sig, err := ParseSigned(string(b))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return sig, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseSigned parses token from JWS form.
|
|
||||||
func ParseSigned(s string) (*JSONWebToken, error) {
|
|
||||||
sig, err := jose.ParseSigned(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
headers := make([]jose.Header, len(sig.Signatures))
|
|
||||||
for i, signature := range sig.Signatures {
|
|
||||||
headers[i] = signature.Header
|
|
||||||
}
|
|
||||||
|
|
||||||
return &JSONWebToken{
|
|
||||||
payload: sig.Verify,
|
|
||||||
unverifiedPayload: sig.UnsafePayloadWithoutVerification,
|
|
||||||
Headers: headers,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseEncrypted parses token from JWE form.
|
|
||||||
func ParseEncrypted(s string) (*JSONWebToken, error) {
|
|
||||||
enc, err := jose.ParseEncrypted(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &JSONWebToken{
|
|
||||||
payload: enc.Decrypt,
|
|
||||||
Headers: []jose.Header{enc.Header},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseSignedAndEncrypted parses signed-then-encrypted token from JWE form.
|
|
||||||
func ParseSignedAndEncrypted(s string) (*NestedJSONWebToken, error) {
|
|
||||||
enc, err := jose.ParseEncrypted(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
contentType, _ := enc.Header.ExtraHeaders[jose.HeaderContentType].(string)
|
|
||||||
if strings.ToUpper(contentType) != "JWT" {
|
|
||||||
return nil, ErrInvalidContentType
|
|
||||||
}
|
|
||||||
|
|
||||||
return &NestedJSONWebToken{
|
|
||||||
enc: enc,
|
|
||||||
Headers: []jose.Header{enc.Header},
|
|
||||||
}, nil
|
|
||||||
}
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
# v4.0.1
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- An attacker could send a JWE containing compressed data that used large
|
||||||
|
amounts of memory and CPU when decompressed by `Decrypt` or `DecryptMulti`.
|
||||||
|
Those functions now return an error if the decompressed data would exceed
|
||||||
|
250kB or 10x the compressed size (whichever is larger). Thanks to
|
||||||
|
Enze Wang@Alioth and Jianjun Chen@Zhongguancun Lab (@zer0yu and @chenjj)
|
||||||
|
for reporting.
|
||||||
|
|
||||||
|
# v4.0.0
|
||||||
|
|
||||||
|
This release makes some breaking changes in order to more thoroughly
|
||||||
|
address the vulnerabilities discussed in [Three New Attacks Against JSON Web
|
||||||
|
Tokens][1], "Sign/encrypt confusion", "Billion hash attack", and "Polyglot
|
||||||
|
token".
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Limit JWT encryption types (exclude password or public key types) (#78)
|
||||||
|
- Enforce minimum length for HMAC keys (#85)
|
||||||
|
- jwt: match any audience in a list, rather than requiring all audiences (#81)
|
||||||
|
- jwt: accept only Compact Serialization (#75)
|
||||||
|
- jws: Add expected algorithms for signatures (#74)
|
||||||
|
- Require specifying expected algorithms for ParseEncrypted,
|
||||||
|
ParseSigned, ParseDetached, jwt.ParseEncrypted, jwt.ParseSigned,
|
||||||
|
jwt.ParseSignedAndEncrypted (#69, #74)
|
||||||
|
- Usually there is a small, known set of appropriate algorithms for a program
|
||||||
|
to use and it's a mistake to allow unexpected algorithms. For instance the
|
||||||
|
"billion hash attack" relies in part on programs accepting the PBES2
|
||||||
|
encryption algorithm and doing the necessary work even if they weren't
|
||||||
|
specifically configured to allow PBES2.
|
||||||
|
- Revert "Strip padding off base64 strings" (#82)
|
||||||
|
- The specs require base64url encoding without padding.
|
||||||
|
- Minimum supported Go version is now 1.21
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- ParseSignedCompact, ParseSignedJSON, ParseEncryptedCompact, ParseEncryptedJSON.
|
||||||
|
- These allow parsing a specific serialization, as opposed to ParseSigned and
|
||||||
|
ParseEncrypted, which try to automatically detect which serialization was
|
||||||
|
provided. It's common to require a specific serialization for a specific
|
||||||
|
protocol - for instance JWT requires Compact serialization.
|
||||||
|
|
||||||
|
[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
|
||||||
|
|
||||||
|
# v3.0.2
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- DecryptMulti: handle decompression error (#19)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- jwe/CompactSerialize: improve performance (#67)
|
||||||
|
- Increase the default number of PBKDF2 iterations to 600k (#48)
|
||||||
|
- Return the proper algorithm for ECDSA keys (#45)
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- Add Thumbprint support for opaque signers (#38)
|
||||||
|
|
||||||
|
# v3.0.1
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- Security issue: an attacker specifying a large "p2c" value can cause
|
||||||
|
JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large
|
||||||
|
amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the
|
||||||
|
disclosure and to Tom Tervoort for originally publishing the category of attack.
|
||||||
|
https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
|
|
@ -1,10 +1,9 @@
|
||||||
# Go JOSE
|
# Go JOSE
|
||||||
|
|
||||||
[![godoc](http://img.shields.io/badge/godoc-jose_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2)
|
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4)
|
||||||
[![godoc](http://img.shields.io/badge/godoc-jwt_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2/jwt)
|
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt)
|
||||||
[![license](http://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE)
|
[![license](https://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE)
|
||||||
[![build](https://travis-ci.org/go-jose/go-jose.svg?branch=master)](https://travis-ci.org/go-jose/go-jose)
|
[![test](https://img.shields.io/github/checks-status/go-jose/go-jose/v4)](https://github.com/go-jose/go-jose/actions)
|
||||||
[![coverage](https://coveralls.io/repos/github/go-jose/go-jose/badge.svg?branch=master)](https://coveralls.io/r/go-jose/go-jose)
|
|
||||||
|
|
||||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||||
and Encryption set of standards. This includes support for JSON Web Encryption,
|
and Encryption set of standards. This includes support for JSON Web Encryption,
|
||||||
|
@ -21,13 +20,13 @@ US maintained blocked list.
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The implementation follows the
|
The implementation follows the
|
||||||
[JSON Web Encryption](http://dx.doi.org/10.17487/RFC7516) (RFC 7516),
|
[JSON Web Encryption](https://dx.doi.org/10.17487/RFC7516) (RFC 7516),
|
||||||
[JSON Web Signature](http://dx.doi.org/10.17487/RFC7515) (RFC 7515), and
|
[JSON Web Signature](https://dx.doi.org/10.17487/RFC7515) (RFC 7515), and
|
||||||
[JSON Web Token](http://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications.
|
[JSON Web Token](https://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications.
|
||||||
Tables of supported algorithms are shown below. The library supports both
|
Tables of supported algorithms are shown below. The library supports both
|
||||||
the compact and JWS/JWE JSON Serialization formats, and has optional support for
|
the compact and JWS/JWE JSON Serialization formats, and has optional support for
|
||||||
multiple recipients. It also comes with a small command-line utility
|
multiple recipients. It also comes with a small command-line utility
|
||||||
([`jose-util`](https://github.com/go-jose/go-jose/tree/master/jose-util))
|
([`jose-util`](https://pkg.go.dev/github.com/go-jose/go-jose/jose-util))
|
||||||
for dealing with JOSE messages in a shell.
|
for dealing with JOSE messages in a shell.
|
||||||
|
|
||||||
**Note**: We use a forked version of the `encoding/json` package from the Go
|
**Note**: We use a forked version of the `encoding/json` package from the Go
|
||||||
|
@ -38,29 +37,22 @@ libraries in other languages.
|
||||||
|
|
||||||
### Versions
|
### Versions
|
||||||
|
|
||||||
[Version 2](https://gopkg.in/go-jose/go-jose.v2)
|
[Version 4](https://github.com/go-jose/go-jose)
|
||||||
([branch](https://github.com/go-jose/go-jose/tree/v2),
|
([branch](https://github.com/go-jose/go-jose/tree/main),
|
||||||
[doc](https://godoc.org/gopkg.in/go-jose/go-jose.v2)) is the current stable version:
|
[doc](https://pkg.go.dev/github.com/go-jose/go-jose/v4), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version:
|
||||||
|
|
||||||
import "gopkg.in/go-jose/go-jose.v2"
|
import "github.com/go-jose/go-jose/v4"
|
||||||
|
|
||||||
[Version 3](https://github.com/go-jose/go-jose)
|
The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which
|
||||||
([branch](https://github.com/go-jose/go-jose/tree/master),
|
are still useable but not actively developed anymore.
|
||||||
[doc](https://godoc.org/github.com/go-jose/go-jose)) is the under development/unstable version (not released yet):
|
|
||||||
|
|
||||||
import "github.com/go-jose/go-jose/v3"
|
Version 3, in this repo, is still receiving security fixes but not functionality
|
||||||
|
updates.
|
||||||
All new feature development takes place on the `master` branch, which we are
|
|
||||||
preparing to release as version 3 soon. Version 2 will continue to receive
|
|
||||||
critical bug and security fixes. Note that starting with version 3 we are
|
|
||||||
using Go modules for versioning instead of `gopkg.in` as before. Version 3 also will require Go version 1.13 or higher.
|
|
||||||
|
|
||||||
Version 1 (on the `v1` branch) is frozen and not supported anymore.
|
|
||||||
|
|
||||||
### Supported algorithms
|
### Supported algorithms
|
||||||
|
|
||||||
See below for a table of supported algorithms. Algorithm identifiers match
|
See below for a table of supported algorithms. Algorithm identifiers match
|
||||||
the names in the [JSON Web Algorithms](http://dx.doi.org/10.17487/RFC7518)
|
the names in the [JSON Web Algorithms](https://dx.doi.org/10.17487/RFC7518)
|
||||||
standard where possible. The Godoc reference has a list of constants.
|
standard where possible. The Godoc reference has a list of constants.
|
||||||
|
|
||||||
Key encryption | Algorithm identifier(s)
|
Key encryption | Algorithm identifier(s)
|
||||||
|
@ -103,20 +95,20 @@ allows attaching a key id.
|
||||||
|
|
||||||
Algorithm(s) | Corresponding types
|
Algorithm(s) | Corresponding types
|
||||||
:------------------------- | -------------------------------
|
:------------------------- | -------------------------------
|
||||||
RSA | *[rsa.PublicKey](http://golang.org/pkg/crypto/rsa/#PublicKey), *[rsa.PrivateKey](http://golang.org/pkg/crypto/rsa/#PrivateKey)
|
RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey)
|
||||||
ECDH, ECDSA | *[ecdsa.PublicKey](http://golang.org/pkg/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](http://golang.org/pkg/crypto/ecdsa/#PrivateKey)
|
ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey)
|
||||||
EdDSA<sup>1</sup> | [ed25519.PublicKey](https://godoc.org/pkg/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://godoc.org/pkg/crypto/ed25519#PrivateKey)
|
EdDSA<sup>1</sup> | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey)
|
||||||
AES, HMAC | []byte
|
AES, HMAC | []byte
|
||||||
|
|
||||||
<sup>1. Only available in version 2 or later of the package</sup>
|
<sup>1. Only available in version 2 or later of the package</sup>
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
[![godoc](http://img.shields.io/badge/godoc-jose_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2)
|
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4)
|
||||||
[![godoc](http://img.shields.io/badge/godoc-jwt_package-blue.svg?style=flat)](https://godoc.org/gopkg.in/go-jose/go-jose.v2/jwt)
|
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt)
|
||||||
|
|
||||||
Examples can be found in the Godoc
|
Examples can be found in the Godoc
|
||||||
reference for this package. The
|
reference for this package. The
|
||||||
[`jose-util`](https://github.com/go-jose/go-jose/tree/master/jose-util)
|
[`jose-util`](https://github.com/go-jose/go-jose/tree/v4/jose-util)
|
||||||
subdirectory also contains a small command-line utility which might be useful
|
subdirectory also contains a small command-line utility which might be useful
|
||||||
as an example as well.
|
as an example as well.
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Security Policy
|
||||||
|
This document explains how to contact the Let's Encrypt security team to report security vulnerabilities.
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ----------|
|
||||||
|
| >= v3 | ✓ |
|
||||||
|
| v2 | ✗ |
|
||||||
|
| v1 | ✗ |
|
||||||
|
|
||||||
|
## Reporting a vulnerability
|
||||||
|
|
||||||
|
Please see [https://letsencrypt.org/contact/#security](https://letsencrypt.org/contact/#security) for the email address to report a vulnerability. Ensure that the subject line for your report contains the word `vulnerability` and is descriptive. Your email should be acknowledged within 24 hours. If you do not receive a response within 24 hours, please follow-up again with another email.
|
|
@ -29,8 +29,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
josecipher "github.com/go-jose/go-jose/v3/cipher"
|
josecipher "github.com/go-jose/go-jose/v4/cipher"
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A generic RSA-based encrypter/verifier
|
// A generic RSA-based encrypter/verifier
|
||||||
|
@ -285,6 +285,9 @@ func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm
|
||||||
|
|
||||||
switch alg {
|
switch alg {
|
||||||
case RS256, RS384, RS512:
|
case RS256, RS384, RS512:
|
||||||
|
// TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the
|
||||||
|
// random parameter is legacy and ignored, and it can be nil.
|
||||||
|
// https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1
|
||||||
out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
|
out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
|
||||||
case PS256, PS384, PS512:
|
case PS256, PS384, PS512:
|
||||||
out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
|
out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
|
|
@ -21,9 +21,8 @@ import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Encrypter represents an encrypter which produces an encrypted JWE object.
|
// Encrypter represents an encrypter which produces an encrypted JWE object.
|
||||||
|
@ -76,14 +75,24 @@ type recipientKeyInfo struct {
|
||||||
type EncrypterOptions struct {
|
type EncrypterOptions struct {
|
||||||
Compression CompressionAlgorithm
|
Compression CompressionAlgorithm
|
||||||
|
|
||||||
// Optional map of additional keys to be inserted into the protected header
|
// Optional map of name/value pairs to be inserted into the protected
|
||||||
// of a JWS object. Some specifications which make use of JWS like to insert
|
// header of a JWS object. Some specifications which make use of
|
||||||
// additional values here. All values must be JSON-serializable.
|
// JWS require additional values here.
|
||||||
|
//
|
||||||
|
// Values will be serialized by [json.Marshal] and must be valid inputs to
|
||||||
|
// that function.
|
||||||
|
//
|
||||||
|
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||||
ExtraHeaders map[HeaderKey]interface{}
|
ExtraHeaders map[HeaderKey]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||||
// if necessary. It returns itself and so can be used in a fluent style.
|
// if necessary, and returns the updated EncrypterOptions.
|
||||||
|
//
|
||||||
|
// The v parameter will be serialized by [json.Marshal] and must be a valid
|
||||||
|
// input to that function.
|
||||||
|
//
|
||||||
|
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||||
func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions {
|
func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions {
|
||||||
if eo.ExtraHeaders == nil {
|
if eo.ExtraHeaders == nil {
|
||||||
eo.ExtraHeaders = map[HeaderKey]interface{}{}
|
eo.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||||
|
@ -112,6 +121,16 @@ func (eo *EncrypterOptions) WithType(typ ContentType) *EncrypterOptions {
|
||||||
// be generated.
|
// be generated.
|
||||||
type Recipient struct {
|
type Recipient struct {
|
||||||
Algorithm KeyAlgorithm
|
Algorithm KeyAlgorithm
|
||||||
|
// Key must have one of these types:
|
||||||
|
// - ed25519.PublicKey
|
||||||
|
// - *ecdsa.PublicKey
|
||||||
|
// - *rsa.PublicKey
|
||||||
|
// - *JSONWebKey
|
||||||
|
// - JSONWebKey
|
||||||
|
// - []byte (a symmetric key)
|
||||||
|
// - Any type that satisfies the OpaqueKeyEncrypter interface
|
||||||
|
//
|
||||||
|
// The type of Key must match the value of Algorithm.
|
||||||
Key interface{}
|
Key interface{}
|
||||||
KeyID string
|
KeyID string
|
||||||
PBES2Count int
|
PBES2Count int
|
||||||
|
@ -150,16 +169,17 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
|
||||||
switch rcpt.Algorithm {
|
switch rcpt.Algorithm {
|
||||||
case DIRECT:
|
case DIRECT:
|
||||||
// Direct encryption mode must be treated differently
|
// Direct encryption mode must be treated differently
|
||||||
if reflect.TypeOf(rawKey) != reflect.TypeOf([]byte{}) {
|
keyBytes, ok := rawKey.([]byte)
|
||||||
|
if !ok {
|
||||||
return nil, ErrUnsupportedKeyType
|
return nil, ErrUnsupportedKeyType
|
||||||
}
|
}
|
||||||
if encrypter.cipher.keySize() != len(rawKey.([]byte)) {
|
if encrypter.cipher.keySize() != len(keyBytes) {
|
||||||
return nil, ErrInvalidKeySize
|
return nil, ErrInvalidKeySize
|
||||||
}
|
}
|
||||||
encrypter.keyGenerator = staticKeyGenerator{
|
encrypter.keyGenerator = staticKeyGenerator{
|
||||||
key: rawKey.([]byte),
|
key: keyBytes,
|
||||||
}
|
}
|
||||||
recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, rawKey.([]byte))
|
recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, keyBytes)
|
||||||
recipientInfo.keyID = keyID
|
recipientInfo.keyID = keyID
|
||||||
if rcpt.KeyID != "" {
|
if rcpt.KeyID != "" {
|
||||||
recipientInfo.keyID = rcpt.KeyID
|
recipientInfo.keyID = rcpt.KeyID
|
||||||
|
@ -168,16 +188,16 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
|
||||||
return encrypter, nil
|
return encrypter, nil
|
||||||
case ECDH_ES:
|
case ECDH_ES:
|
||||||
// ECDH-ES (w/o key wrapping) is similar to DIRECT mode
|
// ECDH-ES (w/o key wrapping) is similar to DIRECT mode
|
||||||
typeOf := reflect.TypeOf(rawKey)
|
keyDSA, ok := rawKey.(*ecdsa.PublicKey)
|
||||||
if typeOf != reflect.TypeOf(&ecdsa.PublicKey{}) {
|
if !ok {
|
||||||
return nil, ErrUnsupportedKeyType
|
return nil, ErrUnsupportedKeyType
|
||||||
}
|
}
|
||||||
encrypter.keyGenerator = ecKeyGenerator{
|
encrypter.keyGenerator = ecKeyGenerator{
|
||||||
size: encrypter.cipher.keySize(),
|
size: encrypter.cipher.keySize(),
|
||||||
algID: string(enc),
|
algID: string(enc),
|
||||||
publicKey: rawKey.(*ecdsa.PublicKey),
|
publicKey: keyDSA,
|
||||||
}
|
}
|
||||||
recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, rawKey.(*ecdsa.PublicKey))
|
recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, keyDSA)
|
||||||
recipientInfo.keyID = keyID
|
recipientInfo.keyID = keyID
|
||||||
if rcpt.KeyID != "" {
|
if rcpt.KeyID != "" {
|
||||||
recipientInfo.keyID = rcpt.KeyID
|
recipientInfo.keyID = rcpt.KeyID
|
||||||
|
@ -270,9 +290,8 @@ func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKey
|
||||||
recipient, err := makeJWERecipient(alg, encryptionKey.Key)
|
recipient, err := makeJWERecipient(alg, encryptionKey.Key)
|
||||||
recipient.keyID = encryptionKey.KeyID
|
recipient.keyID = encryptionKey.KeyID
|
||||||
return recipient, err
|
return recipient, err
|
||||||
}
|
case OpaqueKeyEncrypter:
|
||||||
if encrypter, ok := encryptionKey.(OpaqueKeyEncrypter); ok {
|
return newOpaqueKeyEncrypter(alg, encryptionKey)
|
||||||
return newOpaqueKeyEncrypter(alg, encrypter)
|
|
||||||
}
|
}
|
||||||
return recipientKeyInfo{}, ErrUnsupportedKeyType
|
return recipientKeyInfo{}, ErrUnsupportedKeyType
|
||||||
}
|
}
|
||||||
|
@ -300,11 +319,11 @@ func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) {
|
||||||
return newDecrypter(decryptionKey.Key)
|
return newDecrypter(decryptionKey.Key)
|
||||||
case *JSONWebKey:
|
case *JSONWebKey:
|
||||||
return newDecrypter(decryptionKey.Key)
|
return newDecrypter(decryptionKey.Key)
|
||||||
}
|
case OpaqueKeyDecrypter:
|
||||||
if okd, ok := decryptionKey.(OpaqueKeyDecrypter); ok {
|
return &opaqueKeyDecrypter{decrypter: decryptionKey}, nil
|
||||||
return &opaqueKeyDecrypter{decrypter: okd}, nil
|
default:
|
||||||
}
|
|
||||||
return nil, ErrUnsupportedKeyType
|
return nil, ErrUnsupportedKeyType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of encrypt method producing a JWE object.
|
// Implementation of encrypt method producing a JWE object.
|
||||||
|
@ -403,9 +422,27 @@ func (ctx *genericEncrypter) Options() EncrypterOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt and validate the object and return the plaintext. Note that this
|
// Decrypt and validate the object and return the plaintext. This
|
||||||
// function does not support multi-recipient, if you desire multi-recipient
|
// function does not support multi-recipient. If you desire multi-recipient
|
||||||
// decryption use DecryptMulti instead.
|
// decryption use DecryptMulti instead.
|
||||||
|
//
|
||||||
|
// The decryptionKey argument must contain a private or symmetric key
|
||||||
|
// and must have one of these types:
|
||||||
|
// - *ecdsa.PrivateKey
|
||||||
|
// - *rsa.PrivateKey
|
||||||
|
// - *JSONWebKey
|
||||||
|
// - JSONWebKey
|
||||||
|
// - *JSONWebKeySet
|
||||||
|
// - JSONWebKeySet
|
||||||
|
// - []byte (a symmetric key)
|
||||||
|
// - string (a symmetric key)
|
||||||
|
// - Any type that satisfies the OpaqueKeyDecrypter interface.
|
||||||
|
//
|
||||||
|
// Note that ed25519 is only available for signatures, not encryption, so is
|
||||||
|
// not an option here.
|
||||||
|
//
|
||||||
|
// Automatically decompresses plaintext, but returns an error if the decompressed
|
||||||
|
// data would be >250kB or >10x the size of the compressed data, whichever is larger.
|
||||||
func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) {
|
func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) {
|
||||||
headers := obj.mergedHeaders(nil)
|
headers := obj.mergedHeaders(nil)
|
||||||
|
|
||||||
|
@ -462,15 +499,24 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
||||||
// The "zip" header parameter may only be present in the protected header.
|
// The "zip" header parameter may only be present in the protected header.
|
||||||
if comp := obj.protected.getCompression(); comp != "" {
|
if comp := obj.protected.getCompression(); comp != "" {
|
||||||
plaintext, err = decompress(comp, plaintext)
|
plaintext, err = decompress(comp, plaintext)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return plaintext, err
|
return plaintext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptMulti decrypts and validates the object and returns the plaintexts,
|
// DecryptMulti decrypts and validates the object and returns the plaintexts,
|
||||||
// with support for multiple recipients. It returns the index of the recipient
|
// with support for multiple recipients. It returns the index of the recipient
|
||||||
// for which the decryption was successful, the merged headers for that recipient,
|
// for which the decryption was successful, the merged headers for that recipient,
|
||||||
// and the plaintext.
|
// and the plaintext.
|
||||||
|
//
|
||||||
|
// The decryptionKey argument must have one of the types allowed for the
|
||||||
|
// decryptionKey argument of Decrypt().
|
||||||
|
//
|
||||||
|
// Automatically decompresses plaintext, but returns an error if the decompressed
|
||||||
|
// data would be >250kB or >3x the size of the compressed data, whichever is larger.
|
||||||
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
|
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
|
||||||
globalHeaders := obj.mergedHeaders(nil)
|
globalHeaders := obj.mergedHeaders(nil)
|
||||||
|
|
||||||
|
@ -532,7 +578,10 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
|
||||||
|
|
||||||
// The "zip" header parameter may only be present in the protected header.
|
// The "zip" header parameter may only be present in the protected header.
|
||||||
if comp := obj.protected.getCompression(); comp != "" {
|
if comp := obj.protected.getCompression(); comp != "" {
|
||||||
plaintext, _ = decompress(comp, plaintext)
|
plaintext, err = decompress(comp, plaintext)
|
||||||
|
if err != nil {
|
||||||
|
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sanitized, err := headers.sanitized()
|
sanitized, err := headers.sanitized()
|
|
@ -15,13 +15,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||||
and Encryption set of standards. It implements encryption and signing based on
|
and Encryption set of standards. It implements encryption and signing based on
|
||||||
the JSON Web Encryption and JSON Web Signature standards, with optional JSON Web
|
the JSON Web Encryption and JSON Web Signature standards, with optional JSON Web
|
||||||
Token support available in a sub-package. The library supports both the compact
|
Token support available in a sub-package. The library supports both the compact
|
||||||
and JWS/JWE JSON Serialization formats, and has optional support for multiple
|
and JWS/JWE JSON Serialization formats, and has optional support for multiple
|
||||||
recipients.
|
recipients.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package jose
|
package jose
|
|
@ -21,12 +21,13 @@ import (
|
||||||
"compress/flate"
|
"compress/flate"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Helper function to serialize known-good objects.
|
// Helper function to serialize known-good objects.
|
||||||
|
@ -85,7 +86,7 @@ func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress with DEFLATE
|
// deflate compresses the input.
|
||||||
func deflate(input []byte) ([]byte, error) {
|
func deflate(input []byte) ([]byte, error) {
|
||||||
output := new(bytes.Buffer)
|
output := new(bytes.Buffer)
|
||||||
|
|
||||||
|
@ -97,15 +98,24 @@ func deflate(input []byte) ([]byte, error) {
|
||||||
return output.Bytes(), err
|
return output.Bytes(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompress with DEFLATE
|
// inflate decompresses the input.
|
||||||
|
//
|
||||||
|
// Errors if the decompressed data would be >250kB or >10x the size of the
|
||||||
|
// compressed data, whichever is larger.
|
||||||
func inflate(input []byte) ([]byte, error) {
|
func inflate(input []byte) ([]byte, error) {
|
||||||
output := new(bytes.Buffer)
|
output := new(bytes.Buffer)
|
||||||
reader := flate.NewReader(bytes.NewBuffer(input))
|
reader := flate.NewReader(bytes.NewBuffer(input))
|
||||||
|
|
||||||
_, err := io.Copy(output, reader)
|
maxCompressedSize := max(250_000, 10*int64(len(input)))
|
||||||
if err != nil {
|
|
||||||
|
limit := maxCompressedSize + 1
|
||||||
|
n, err := io.CopyN(output, reader, limit)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if n == limit {
|
||||||
|
return nil, fmt.Errorf("uncompressed data would be too large (>%d bytes)", maxCompressedSize)
|
||||||
|
}
|
||||||
|
|
||||||
err = reader.Close()
|
err = reader.Close()
|
||||||
return output.Bytes(), err
|
return output.Bytes(), err
|
||||||
|
@ -154,7 +164,7 @@ func (b *byteBuffer) UnmarshalJSON(data []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
decoded, err := base64URLDecode(encoded)
|
decoded, err := base64.RawURLEncoding.DecodeString(encoded)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -184,8 +194,35 @@ func (b byteBuffer) toInt() int {
|
||||||
return int(b.bigInt().Int64())
|
return int(b.bigInt().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
// base64URLDecode is implemented as defined in https://www.rfc-editor.org/rfc/rfc7515.html#appendix-C
|
func base64EncodeLen(sl []byte) int {
|
||||||
func base64URLDecode(value string) ([]byte, error) {
|
return base64.RawURLEncoding.EncodedLen(len(sl))
|
||||||
value = strings.TrimRight(value, "=")
|
}
|
||||||
return base64.RawURLEncoding.DecodeString(value)
|
|
||||||
|
func base64JoinWithDots(inputs ...[]byte) string {
|
||||||
|
if len(inputs) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count of dots.
|
||||||
|
totalCount := len(inputs) - 1
|
||||||
|
|
||||||
|
for _, input := range inputs {
|
||||||
|
totalCount += base64EncodeLen(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make([]byte, totalCount)
|
||||||
|
startEncode := 0
|
||||||
|
for i, input := range inputs {
|
||||||
|
base64.RawURLEncoding.Encode(out[startEncode:], input)
|
||||||
|
|
||||||
|
if i == len(inputs)-1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
startEncode += base64EncodeLen(input)
|
||||||
|
out[startEncode] = '.'
|
||||||
|
startEncode++
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(out)
|
||||||
}
|
}
|
|
@ -75,14 +75,13 @@ import (
|
||||||
//
|
//
|
||||||
// The JSON null value unmarshals into an interface, map, pointer, or slice
|
// The JSON null value unmarshals into an interface, map, pointer, or slice
|
||||||
// by setting that Go value to nil. Because null is often used in JSON to mean
|
// by setting that Go value to nil. Because null is often used in JSON to mean
|
||||||
// ``not present,'' unmarshaling a JSON null into any other Go type has no effect
|
// “not present,” unmarshaling a JSON null into any other Go type has no effect
|
||||||
// on the value and produces no error.
|
// on the value and produces no error.
|
||||||
//
|
//
|
||||||
// When unmarshaling quoted strings, invalid UTF-8 or
|
// When unmarshaling quoted strings, invalid UTF-8 or
|
||||||
// invalid UTF-16 surrogate pairs are not treated as an error.
|
// invalid UTF-16 surrogate pairs are not treated as an error.
|
||||||
// Instead, they are replaced by the Unicode replacement
|
// Instead, they are replaced by the Unicode replacement
|
||||||
// character U+FFFD.
|
// character U+FFFD.
|
||||||
//
|
|
||||||
func Unmarshal(data []byte, v interface{}) error {
|
func Unmarshal(data []byte, v interface{}) error {
|
||||||
// Check for well-formedness.
|
// Check for well-formedness.
|
||||||
// Avoids filling out half a data structure
|
// Avoids filling out half a data structure
|
|
@ -58,6 +58,7 @@ import (
|
||||||
// becomes a member of the object unless
|
// becomes a member of the object unless
|
||||||
// - the field's tag is "-", or
|
// - the field's tag is "-", or
|
||||||
// - the field is empty and its tag specifies the "omitempty" option.
|
// - the field is empty and its tag specifies the "omitempty" option.
|
||||||
|
//
|
||||||
// The empty values are false, 0, any
|
// The empty values are false, 0, any
|
||||||
// nil pointer or interface value, and any array, slice, map, or string of
|
// nil pointer or interface value, and any array, slice, map, or string of
|
||||||
// length zero. The object's default key string is the struct field name
|
// length zero. The object's default key string is the struct field name
|
||||||
|
@ -133,7 +134,6 @@ import (
|
||||||
// JSON cannot represent cyclic data structures and Marshal does not
|
// JSON cannot represent cyclic data structures and Marshal does not
|
||||||
// handle them. Passing cyclic structures to Marshal will result in
|
// handle them. Passing cyclic structures to Marshal will result in
|
||||||
// an infinite recursion.
|
// an infinite recursion.
|
||||||
//
|
|
||||||
func Marshal(v interface{}) ([]byte, error) {
|
func Marshal(v interface{}) ([]byte, error) {
|
||||||
e := &encodeState{}
|
e := &encodeState{}
|
||||||
err := e.marshal(v)
|
err := e.marshal(v)
|
|
@ -240,7 +240,6 @@ var _ Unmarshaler = (*RawMessage)(nil)
|
||||||
// Number, for JSON numbers
|
// Number, for JSON numbers
|
||||||
// string, for JSON string literals
|
// string, for JSON string literals
|
||||||
// nil, for JSON null
|
// nil, for JSON null
|
||||||
//
|
|
||||||
type Token interface{}
|
type Token interface{}
|
||||||
|
|
||||||
const (
|
const (
|
148
vendor/github.com/go-jose/go-jose/v3/jwe.go → vendor/github.com/go-jose/go-jose/v4/jwe.go
generated
vendored
148
vendor/github.com/go-jose/go-jose/v3/jwe.go → vendor/github.com/go-jose/go-jose/v4/jwe.go
generated
vendored
|
@ -18,10 +18,11 @@ package jose
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
|
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
|
||||||
|
@ -104,29 +105,75 @@ func (obj JSONWebEncryption) computeAuthData() []byte {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseEncrypted parses an encrypted message in compact or JWE JSON Serialization format.
|
func containsKeyAlgorithm(haystack []KeyAlgorithm, needle KeyAlgorithm) bool {
|
||||||
func ParseEncrypted(input string) (*JSONWebEncryption, error) {
|
for _, algorithm := range haystack {
|
||||||
input = stripWhitespace(input)
|
if algorithm == needle {
|
||||||
if strings.HasPrefix(input, "{") {
|
return true
|
||||||
return parseEncryptedFull(input)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return parseEncryptedCompact(input)
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseEncryptedFull parses a message in compact format.
|
func containsContentEncryption(haystack []ContentEncryption, needle ContentEncryption) bool {
|
||||||
func parseEncryptedFull(input string) (*JSONWebEncryption, error) {
|
for _, algorithm := range haystack {
|
||||||
|
if algorithm == needle {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseEncrypted parses an encrypted message in JWE Compact or JWE JSON Serialization.
|
||||||
|
//
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2
|
||||||
|
//
|
||||||
|
// The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc"
|
||||||
|
// header parameters respectively. They must be nonempty, and each "alg" or "enc" header in
|
||||||
|
// parsed data must contain a value that is present in the corresponding parameter. That
|
||||||
|
// includes the protected and unprotected headers as well as all recipients. To accept
|
||||||
|
// multiple algorithms, pass a slice of all the algorithms you want to accept.
|
||||||
|
func ParseEncrypted(input string,
|
||||||
|
keyEncryptionAlgorithms []KeyAlgorithm,
|
||||||
|
contentEncryption []ContentEncryption,
|
||||||
|
) (*JSONWebEncryption, error) {
|
||||||
|
input = stripWhitespace(input)
|
||||||
|
if strings.HasPrefix(input, "{") {
|
||||||
|
return ParseEncryptedJSON(input, keyEncryptionAlgorithms, contentEncryption)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParseEncryptedCompact(input, keyEncryptionAlgorithms, contentEncryption)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseEncryptedJSON parses a message in JWE JSON Serialization.
|
||||||
|
//
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2
|
||||||
|
func ParseEncryptedJSON(
|
||||||
|
input string,
|
||||||
|
keyEncryptionAlgorithms []KeyAlgorithm,
|
||||||
|
contentEncryption []ContentEncryption,
|
||||||
|
) (*JSONWebEncryption, error) {
|
||||||
var parsed rawJSONWebEncryption
|
var parsed rawJSONWebEncryption
|
||||||
err := json.Unmarshal([]byte(input), &parsed)
|
err := json.Unmarshal([]byte(input), &parsed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed.sanitized()
|
return parsed.sanitized(keyEncryptionAlgorithms, contentEncryption)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sanitized produces a cleaned-up JWE object from the raw JSON.
|
// sanitized produces a cleaned-up JWE object from the raw JSON.
|
||||||
func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
func (parsed *rawJSONWebEncryption) sanitized(
|
||||||
|
keyEncryptionAlgorithms []KeyAlgorithm,
|
||||||
|
contentEncryption []ContentEncryption,
|
||||||
|
) (*JSONWebEncryption, error) {
|
||||||
|
if len(keyEncryptionAlgorithms) == 0 {
|
||||||
|
return nil, errors.New("go-jose/go-jose: no key algorithms provided")
|
||||||
|
}
|
||||||
|
if len(contentEncryption) == 0 {
|
||||||
|
return nil, errors.New("go-jose/go-jose: no content encryption algorithms provided")
|
||||||
|
}
|
||||||
|
|
||||||
obj := &JSONWebEncryption{
|
obj := &JSONWebEncryption{
|
||||||
original: parsed,
|
original: parsed,
|
||||||
unprotected: parsed.Unprotected,
|
unprotected: parsed.Unprotected,
|
||||||
|
@ -170,7 +217,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||||
} else {
|
} else {
|
||||||
obj.recipients = make([]recipientInfo, len(parsed.Recipients))
|
obj.recipients = make([]recipientInfo, len(parsed.Recipients))
|
||||||
for r := range parsed.Recipients {
|
for r := range parsed.Recipients {
|
||||||
encryptedKey, err := base64URLDecode(parsed.Recipients[r].EncryptedKey)
|
encryptedKey, err := base64.RawURLEncoding.DecodeString(parsed.Recipients[r].EncryptedKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -185,10 +232,31 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, recipient := range obj.recipients {
|
for i, recipient := range obj.recipients {
|
||||||
headers := obj.mergedHeaders(&recipient)
|
headers := obj.mergedHeaders(&recipient)
|
||||||
if headers.getAlgorithm() == "" || headers.getEncryption() == "" {
|
if headers.getAlgorithm() == "" {
|
||||||
return nil, fmt.Errorf("go-jose/go-jose: message is missing alg/enc headers")
|
return nil, fmt.Errorf(`go-jose/go-jose: recipient %d: missing header "alg"`, i)
|
||||||
|
}
|
||||||
|
if headers.getEncryption() == "" {
|
||||||
|
return nil, fmt.Errorf(`go-jose/go-jose: recipient %d: missing header "enc"`, i)
|
||||||
|
}
|
||||||
|
err := validateAlgEnc(headers, keyEncryptionAlgorithms, contentEncryption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("go-jose/go-jose: recipient %d: %s", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj.protected != nil {
|
||||||
|
err := validateAlgEnc(*obj.protected, keyEncryptionAlgorithms, contentEncryption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("go-jose/go-jose: protected header: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if obj.unprotected != nil {
|
||||||
|
err := validateAlgEnc(*obj.unprotected, keyEncryptionAlgorithms, contentEncryption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("go-jose/go-jose: unprotected header: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,34 +268,52 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseEncryptedCompact parses a message in compact format.
|
func validateAlgEnc(headers rawHeader, keyAlgorithms []KeyAlgorithm, contentEncryption []ContentEncryption) error {
|
||||||
func parseEncryptedCompact(input string) (*JSONWebEncryption, error) {
|
alg := headers.getAlgorithm()
|
||||||
|
enc := headers.getEncryption()
|
||||||
|
if alg != "" && !containsKeyAlgorithm(keyAlgorithms, alg) {
|
||||||
|
return fmt.Errorf("unexpected key algorithm %q; expected %q", alg, keyAlgorithms)
|
||||||
|
}
|
||||||
|
if alg != "" && !containsContentEncryption(contentEncryption, enc) {
|
||||||
|
return fmt.Errorf("unexpected content encryption algorithm %q; expected %q", enc, contentEncryption)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseEncryptedCompact parses a message in JWE Compact Serialization.
|
||||||
|
//
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1
|
||||||
|
func ParseEncryptedCompact(
|
||||||
|
input string,
|
||||||
|
keyAlgorithms []KeyAlgorithm,
|
||||||
|
contentEncryption []ContentEncryption,
|
||||||
|
) (*JSONWebEncryption, error) {
|
||||||
parts := strings.Split(input, ".")
|
parts := strings.Split(input, ".")
|
||||||
if len(parts) != 5 {
|
if len(parts) != 5 {
|
||||||
return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts")
|
return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts")
|
||||||
}
|
}
|
||||||
|
|
||||||
rawProtected, err := base64URLDecode(parts[0])
|
rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedKey, err := base64URLDecode(parts[1])
|
encryptedKey, err := base64.RawURLEncoding.DecodeString(parts[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
iv, err := base64URLDecode(parts[2])
|
iv, err := base64.RawURLEncoding.DecodeString(parts[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ciphertext, err := base64URLDecode(parts[3])
|
ciphertext, err := base64.RawURLEncoding.DecodeString(parts[3])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tag, err := base64URLDecode(parts[4])
|
tag, err := base64.RawURLEncoding.DecodeString(parts[4])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -240,7 +326,7 @@ func parseEncryptedCompact(input string) (*JSONWebEncryption, error) {
|
||||||
Tag: newBuffer(tag),
|
Tag: newBuffer(tag),
|
||||||
}
|
}
|
||||||
|
|
||||||
return raw.sanitized()
|
return raw.sanitized(keyAlgorithms, contentEncryption)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompactSerialize serializes an object using the compact serialization format.
|
// CompactSerialize serializes an object using the compact serialization format.
|
||||||
|
@ -252,13 +338,13 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) {
|
||||||
|
|
||||||
serializedProtected := mustSerializeJSON(obj.protected)
|
serializedProtected := mustSerializeJSON(obj.protected)
|
||||||
|
|
||||||
return fmt.Sprintf(
|
return base64JoinWithDots(
|
||||||
"%s.%s.%s.%s.%s",
|
serializedProtected,
|
||||||
base64.RawURLEncoding.EncodeToString(serializedProtected),
|
obj.recipients[0].encryptedKey,
|
||||||
base64.RawURLEncoding.EncodeToString(obj.recipients[0].encryptedKey),
|
obj.iv,
|
||||||
base64.RawURLEncoding.EncodeToString(obj.iv),
|
obj.ciphertext,
|
||||||
base64.RawURLEncoding.EncodeToString(obj.ciphertext),
|
obj.tag,
|
||||||
base64.RawURLEncoding.EncodeToString(obj.tag)), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FullSerialize serializes an object using the full JSON serialization format.
|
// FullSerialize serializes an object using the full JSON serialization format.
|
|
@ -35,7 +35,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing.
|
// rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing.
|
||||||
|
@ -67,9 +67,21 @@ type rawJSONWebKey struct {
|
||||||
X5tSHA256 string `json:"x5t#S256,omitempty"`
|
X5tSHA256 string `json:"x5t#S256,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONWebKey represents a public or private key in JWK format.
|
// JSONWebKey represents a public or private key in JWK format. It can be
|
||||||
|
// marshaled into JSON and unmarshaled from JSON.
|
||||||
type JSONWebKey struct {
|
type JSONWebKey struct {
|
||||||
// Cryptographic key, can be a symmetric or asymmetric key.
|
// Key is the Go in-memory representation of this key. It must have one
|
||||||
|
// of these types:
|
||||||
|
// - ed25519.PublicKey
|
||||||
|
// - ed25519.PrivateKey
|
||||||
|
// - *ecdsa.PublicKey
|
||||||
|
// - *ecdsa.PrivateKey
|
||||||
|
// - *rsa.PublicKey
|
||||||
|
// - *rsa.PrivateKey
|
||||||
|
// - []byte (a symmetric key)
|
||||||
|
//
|
||||||
|
// When marshaling this JSONWebKey into JSON, the "kty" header parameter
|
||||||
|
// will be automatically set based on the type of this field.
|
||||||
Key interface{}
|
Key interface{}
|
||||||
// Key identifier, parsed from `kid` header.
|
// Key identifier, parsed from `kid` header.
|
||||||
KeyID string
|
KeyID string
|
||||||
|
@ -254,7 +266,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||||
|
|
||||||
// x5t parameters are base64url-encoded SHA thumbprints
|
// x5t parameters are base64url-encoded SHA thumbprints
|
||||||
// See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8
|
// See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8
|
||||||
x5tSHA1bytes, err := base64URLDecode(raw.X5tSHA1)
|
x5tSHA1bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("go-jose/go-jose: invalid JWK, x5t header has invalid encoding")
|
return errors.New("go-jose/go-jose: invalid JWK, x5t header has invalid encoding")
|
||||||
}
|
}
|
||||||
|
@ -274,7 +286,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||||
|
|
||||||
k.CertificateThumbprintSHA1 = x5tSHA1bytes
|
k.CertificateThumbprintSHA1 = x5tSHA1bytes
|
||||||
|
|
||||||
x5tSHA256bytes, err := base64URLDecode(raw.X5tSHA256)
|
x5tSHA256bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA256)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
|
return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
|
||||||
}
|
}
|
||||||
|
@ -389,6 +401,8 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
||||||
input, err = rsaThumbprintInput(key.N, key.E)
|
input, err = rsaThumbprintInput(key.N, key.E)
|
||||||
case ed25519.PrivateKey:
|
case ed25519.PrivateKey:
|
||||||
input, err = edThumbprintInput(ed25519.PublicKey(key[32:]))
|
input, err = edThumbprintInput(ed25519.PublicKey(key[32:]))
|
||||||
|
case OpaqueSigner:
|
||||||
|
return key.Public().Thumbprint(hash)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing.
|
// rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing.
|
||||||
|
@ -75,22 +75,41 @@ type Signature struct {
|
||||||
original *rawSignatureInfo
|
original *rawSignatureInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseSigned parses a signed message in compact or JWS JSON Serialization format.
|
// ParseSigned parses a signed message in JWS Compact or JWS JSON Serialization.
|
||||||
func ParseSigned(signature string) (*JSONWebSignature, error) {
|
//
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7515#section-7
|
||||||
|
func ParseSigned(
|
||||||
|
signature string,
|
||||||
|
signatureAlgorithms []SignatureAlgorithm,
|
||||||
|
) (*JSONWebSignature, error) {
|
||||||
signature = stripWhitespace(signature)
|
signature = stripWhitespace(signature)
|
||||||
if strings.HasPrefix(signature, "{") {
|
if strings.HasPrefix(signature, "{") {
|
||||||
return parseSignedFull(signature)
|
return ParseSignedJSON(signature, signatureAlgorithms)
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseSignedCompact(signature, nil)
|
return parseSignedCompact(signature, nil, signatureAlgorithms)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseSignedCompact parses a message in JWS Compact Serialization.
|
||||||
|
//
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7515#section-7.1
|
||||||
|
func ParseSignedCompact(
|
||||||
|
signature string,
|
||||||
|
signatureAlgorithms []SignatureAlgorithm,
|
||||||
|
) (*JSONWebSignature, error) {
|
||||||
|
return parseSignedCompact(signature, nil, signatureAlgorithms)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDetached parses a signed message in compact serialization format with detached payload.
|
// ParseDetached parses a signed message in compact serialization format with detached payload.
|
||||||
func ParseDetached(signature string, payload []byte) (*JSONWebSignature, error) {
|
func ParseDetached(
|
||||||
|
signature string,
|
||||||
|
payload []byte,
|
||||||
|
signatureAlgorithms []SignatureAlgorithm,
|
||||||
|
) (*JSONWebSignature, error) {
|
||||||
if payload == nil {
|
if payload == nil {
|
||||||
return nil, errors.New("go-jose/go-jose: nil payload")
|
return nil, errors.New("go-jose/go-jose: nil payload")
|
||||||
}
|
}
|
||||||
return parseSignedCompact(stripWhitespace(signature), payload)
|
return parseSignedCompact(stripWhitespace(signature), payload, signatureAlgorithms)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a header value
|
// Get a header value
|
||||||
|
@ -137,19 +156,36 @@ func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature
|
||||||
return authData.Bytes(), nil
|
return authData.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseSignedFull parses a message in full format.
|
// ParseSignedJSON parses a message in JWS JSON Serialization.
|
||||||
func parseSignedFull(input string) (*JSONWebSignature, error) {
|
//
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7515#section-7.2
|
||||||
|
func ParseSignedJSON(
|
||||||
|
input string,
|
||||||
|
signatureAlgorithms []SignatureAlgorithm,
|
||||||
|
) (*JSONWebSignature, error) {
|
||||||
var parsed rawJSONWebSignature
|
var parsed rawJSONWebSignature
|
||||||
err := json.Unmarshal([]byte(input), &parsed)
|
err := json.Unmarshal([]byte(input), &parsed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed.sanitized()
|
return parsed.sanitized(signatureAlgorithms)
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsSignatureAlgorithm(haystack []SignatureAlgorithm, needle SignatureAlgorithm) bool {
|
||||||
|
for _, algorithm := range haystack {
|
||||||
|
if algorithm == needle {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// sanitized produces a cleaned-up JWS object from the raw JSON.
|
// sanitized produces a cleaned-up JWS object from the raw JSON.
|
||||||
func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgorithm) (*JSONWebSignature, error) {
|
||||||
|
if len(signatureAlgorithms) == 0 {
|
||||||
|
return nil, errors.New("go-jose/go-jose: no signature algorithms specified")
|
||||||
|
}
|
||||||
if parsed.Payload == nil {
|
if parsed.Payload == nil {
|
||||||
return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message")
|
return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message")
|
||||||
}
|
}
|
||||||
|
@ -198,6 +234,12 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alg := SignatureAlgorithm(signature.Header.Algorithm)
|
||||||
|
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
|
||||||
|
return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q",
|
||||||
|
alg, signatureAlgorithms)
|
||||||
|
}
|
||||||
|
|
||||||
if signature.header != nil {
|
if signature.header != nil {
|
||||||
signature.Unprotected, err = signature.header.sanitized()
|
signature.Unprotected, err = signature.header.sanitized()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -241,6 +283,12 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alg := SignatureAlgorithm(obj.Signatures[i].Header.Algorithm)
|
||||||
|
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
|
||||||
|
return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q",
|
||||||
|
alg, signatureAlgorithms)
|
||||||
|
}
|
||||||
|
|
||||||
if obj.Signatures[i].header != nil {
|
if obj.Signatures[i].header != nil {
|
||||||
obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized()
|
obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -274,7 +322,11 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseSignedCompact parses a message in compact format.
|
// parseSignedCompact parses a message in compact format.
|
||||||
func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) {
|
func parseSignedCompact(
|
||||||
|
input string,
|
||||||
|
payload []byte,
|
||||||
|
signatureAlgorithms []SignatureAlgorithm,
|
||||||
|
) (*JSONWebSignature, error) {
|
||||||
parts := strings.Split(input, ".")
|
parts := strings.Split(input, ".")
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
|
return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
|
||||||
|
@ -284,19 +336,19 @@ func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error)
|
||||||
return nil, fmt.Errorf("go-jose/go-jose: payload is not detached")
|
return nil, fmt.Errorf("go-jose/go-jose: payload is not detached")
|
||||||
}
|
}
|
||||||
|
|
||||||
rawProtected, err := base64URLDecode(parts[0])
|
rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if payload == nil {
|
if payload == nil {
|
||||||
payload, err = base64URLDecode(parts[1])
|
payload, err = base64.RawURLEncoding.DecodeString(parts[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := base64URLDecode(parts[2])
|
signature, err := base64.RawURLEncoding.DecodeString(parts[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -306,7 +358,7 @@ func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error)
|
||||||
Protected: newBuffer(rawProtected),
|
Protected: newBuffer(rawProtected),
|
||||||
Signature: newBuffer(signature),
|
Signature: newBuffer(signature),
|
||||||
}
|
}
|
||||||
return raw.sanitized()
|
return raw.sanitized(signatureAlgorithms)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
|
func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
|
||||||
|
@ -314,15 +366,18 @@ func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
|
||||||
return "", ErrNotSupported
|
return "", ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
serializedProtected := base64.RawURLEncoding.EncodeToString(mustSerializeJSON(obj.Signatures[0].protected))
|
serializedProtected := mustSerializeJSON(obj.Signatures[0].protected)
|
||||||
payload := ""
|
|
||||||
signature := base64.RawURLEncoding.EncodeToString(obj.Signatures[0].Signature)
|
|
||||||
|
|
||||||
|
var payload []byte
|
||||||
if !detached {
|
if !detached {
|
||||||
payload = base64.RawURLEncoding.EncodeToString(obj.payload)
|
payload = obj.payload
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s.%s.%s", serializedProtected, payload, signature), nil
|
return base64JoinWithDots(
|
||||||
|
serializedProtected,
|
||||||
|
payload,
|
||||||
|
obj.Signatures[0].Signature,
|
||||||
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompactSerialize serializes an object using the compact serialization format.
|
// CompactSerialize serializes an object using the compact serialization format.
|
|
@ -21,13 +21,13 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3"
|
"github.com/go-jose/go-jose/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Builder is a utility for making JSON Web Tokens. Calls can be chained, and
|
// Builder is a utility for making JSON Web Tokens. Calls can be chained, and
|
||||||
// errors are accumulated until the final call to CompactSerialize/FullSerialize.
|
// errors are accumulated until the final call to Serialize.
|
||||||
type Builder interface {
|
type Builder interface {
|
||||||
// Claims encodes claims into JWE/JWS form. Multiple calls will merge claims
|
// Claims encodes claims into JWE/JWS form. Multiple calls will merge claims
|
||||||
// into single JSON object. If you are passing private claims, make sure to set
|
// into single JSON object. If you are passing private claims, make sure to set
|
||||||
|
@ -36,15 +36,13 @@ type Builder interface {
|
||||||
Claims(i interface{}) Builder
|
Claims(i interface{}) Builder
|
||||||
// Token builds a JSONWebToken from provided data.
|
// Token builds a JSONWebToken from provided data.
|
||||||
Token() (*JSONWebToken, error)
|
Token() (*JSONWebToken, error)
|
||||||
// FullSerialize serializes a token using the JWS/JWE JSON Serialization format.
|
// Serialize serializes a token.
|
||||||
FullSerialize() (string, error)
|
Serialize() (string, error)
|
||||||
// CompactSerialize serializes a token using the compact serialization format.
|
|
||||||
CompactSerialize() (string, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NestedBuilder is a utility for making Signed-Then-Encrypted JSON Web Tokens.
|
// NestedBuilder is a utility for making Signed-Then-Encrypted JSON Web Tokens.
|
||||||
// Calls can be chained, and errors are accumulated until final call to
|
// Calls can be chained, and errors are accumulated until final call to
|
||||||
// CompactSerialize/FullSerialize.
|
// Serialize.
|
||||||
type NestedBuilder interface {
|
type NestedBuilder interface {
|
||||||
// Claims encodes claims into JWE/JWS form. Multiple calls will merge claims
|
// Claims encodes claims into JWE/JWS form. Multiple calls will merge claims
|
||||||
// into single JSON object. If you are passing private claims, make sure to set
|
// into single JSON object. If you are passing private claims, make sure to set
|
||||||
|
@ -53,10 +51,8 @@ type NestedBuilder interface {
|
||||||
Claims(i interface{}) NestedBuilder
|
Claims(i interface{}) NestedBuilder
|
||||||
// Token builds a NestedJSONWebToken from provided data.
|
// Token builds a NestedJSONWebToken from provided data.
|
||||||
Token() (*NestedJSONWebToken, error)
|
Token() (*NestedJSONWebToken, error)
|
||||||
// FullSerialize serializes a token using the JSON Serialization format.
|
// Serialize serializes a token.
|
||||||
FullSerialize() (string, error)
|
Serialize() (string, error)
|
||||||
// CompactSerialize serializes a token using the compact serialization format.
|
|
||||||
CompactSerialize() (string, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type builder struct {
|
type builder struct {
|
||||||
|
@ -194,7 +190,7 @@ func (b *signedBuilder) Token() (*JSONWebToken, error) {
|
||||||
return b.builder.token(sig.Verify, h)
|
return b.builder.token(sig.Verify, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *signedBuilder) CompactSerialize() (string, error) {
|
func (b *signedBuilder) Serialize() (string, error) {
|
||||||
sig, err := b.sign()
|
sig, err := b.sign()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -203,15 +199,6 @@ func (b *signedBuilder) CompactSerialize() (string, error) {
|
||||||
return sig.CompactSerialize()
|
return sig.CompactSerialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *signedBuilder) FullSerialize() (string, error) {
|
|
||||||
sig, err := b.sign()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return sig.FullSerialize(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *signedBuilder) sign() (*jose.JSONWebSignature, error) {
|
func (b *signedBuilder) sign() (*jose.JSONWebSignature, error) {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return nil, b.err
|
return nil, b.err
|
||||||
|
@ -232,7 +219,7 @@ func (b *encryptedBuilder) Claims(i interface{}) Builder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *encryptedBuilder) CompactSerialize() (string, error) {
|
func (b *encryptedBuilder) Serialize() (string, error) {
|
||||||
enc, err := b.encrypt()
|
enc, err := b.encrypt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -241,15 +228,6 @@ func (b *encryptedBuilder) CompactSerialize() (string, error) {
|
||||||
return enc.CompactSerialize()
|
return enc.CompactSerialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *encryptedBuilder) FullSerialize() (string, error) {
|
|
||||||
enc, err := b.encrypt()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return enc.FullSerialize(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *encryptedBuilder) Token() (*JSONWebToken, error) {
|
func (b *encryptedBuilder) Token() (*JSONWebToken, error) {
|
||||||
enc, err := b.encrypt()
|
enc, err := b.encrypt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -280,6 +258,8 @@ func (b *nestedBuilder) Claims(i interface{}) NestedBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Token produced a token suitable for serialization. It cannot be decrypted
|
||||||
|
// without serializing and then deserializing.
|
||||||
func (b *nestedBuilder) Token() (*NestedJSONWebToken, error) {
|
func (b *nestedBuilder) Token() (*NestedJSONWebToken, error) {
|
||||||
enc, err := b.signAndEncrypt()
|
enc, err := b.signAndEncrypt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -287,12 +267,13 @@ func (b *nestedBuilder) Token() (*NestedJSONWebToken, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &NestedJSONWebToken{
|
return &NestedJSONWebToken{
|
||||||
|
allowedSignatureAlgorithms: nil,
|
||||||
enc: enc,
|
enc: enc,
|
||||||
Headers: []jose.Header{enc.Header},
|
Headers: []jose.Header{enc.Header},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *nestedBuilder) CompactSerialize() (string, error) {
|
func (b *nestedBuilder) Serialize() (string, error) {
|
||||||
enc, err := b.signAndEncrypt()
|
enc, err := b.signAndEncrypt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Claims represents public claim values (as specified in RFC 7519).
|
// Claims represents public claim values (as specified in RFC 7519).
|
||||||
|
@ -119,7 +119,7 @@ func (s Audience) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal([]string(s))
|
return json.Marshal([]string(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
//Contains checks whether a given string is included in the Audience
|
// Contains checks whether a given string is included in the Audience
|
||||||
func (s Audience) Contains(v string) bool {
|
func (s Audience) Contains(v string) bool {
|
||||||
for _, a := range s {
|
for _, a := range s {
|
||||||
if a == v {
|
if a == v {
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Package jwt provides an implementation of the JSON Web Token standard.
|
Package jwt provides an implementation of the JSON Web Token standard.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package jwt
|
package jwt
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*-
|
||||||
|
* Copyright 2016 Zbigniew Mandziejewicz
|
||||||
|
* Copyright 2016 Square, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
jose "github.com/go-jose/go-jose/v4"
|
||||||
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// JSONWebToken represents a JSON Web Token (as specified in RFC7519).
|
||||||
|
type JSONWebToken struct {
|
||||||
|
payload func(k interface{}) ([]byte, error)
|
||||||
|
unverifiedPayload func() []byte
|
||||||
|
Headers []jose.Header
|
||||||
|
}
|
||||||
|
|
||||||
|
type NestedJSONWebToken struct {
|
||||||
|
enc *jose.JSONWebEncryption
|
||||||
|
Headers []jose.Header
|
||||||
|
// Used when parsing and decrypting an input
|
||||||
|
allowedSignatureAlgorithms []jose.SignatureAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claims deserializes a JSONWebToken into dest using the provided key.
|
||||||
|
func (t *JSONWebToken) Claims(key interface{}, dest ...interface{}) error {
|
||||||
|
b, err := t.payload(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, d := range dest {
|
||||||
|
if err := json.Unmarshal(b, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsafeClaimsWithoutVerification deserializes the claims of a
|
||||||
|
// JSONWebToken into the dests. For signed JWTs, the claims are not
|
||||||
|
// verified. This function won't work for encrypted JWTs.
|
||||||
|
func (t *JSONWebToken) UnsafeClaimsWithoutVerification(dest ...interface{}) error {
|
||||||
|
if t.unverifiedPayload == nil {
|
||||||
|
return fmt.Errorf("go-jose/go-jose: Cannot get unverified claims")
|
||||||
|
}
|
||||||
|
claims := t.unverifiedPayload()
|
||||||
|
for _, d := range dest {
|
||||||
|
if err := json.Unmarshal(claims, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *NestedJSONWebToken) Decrypt(decryptionKey interface{}) (*JSONWebToken, error) {
|
||||||
|
b, err := t.enc.Decrypt(decryptionKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := ParseSigned(string(b), t.allowedSignatureAlgorithms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseSigned parses token from JWS form.
|
||||||
|
func ParseSigned(s string, signatureAlgorithms []jose.SignatureAlgorithm) (*JSONWebToken, error) {
|
||||||
|
sig, err := jose.ParseSignedCompact(s, signatureAlgorithms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
headers := make([]jose.Header, len(sig.Signatures))
|
||||||
|
for i, signature := range sig.Signatures {
|
||||||
|
headers[i] = signature.Header
|
||||||
|
}
|
||||||
|
|
||||||
|
return &JSONWebToken{
|
||||||
|
payload: sig.Verify,
|
||||||
|
unverifiedPayload: sig.UnsafePayloadWithoutVerification,
|
||||||
|
Headers: headers,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateKeyEncryptionAlgorithm(algs []jose.KeyAlgorithm) error {
|
||||||
|
for _, alg := range algs {
|
||||||
|
switch alg {
|
||||||
|
case jose.ED25519,
|
||||||
|
jose.RSA1_5,
|
||||||
|
jose.RSA_OAEP,
|
||||||
|
jose.RSA_OAEP_256,
|
||||||
|
jose.ECDH_ES,
|
||||||
|
jose.ECDH_ES_A128KW,
|
||||||
|
jose.ECDH_ES_A192KW,
|
||||||
|
jose.ECDH_ES_A256KW:
|
||||||
|
return fmt.Errorf("asymmetric encryption algorithms not supported for JWT: "+
|
||||||
|
"invalid key encryption algorithm: %s", alg)
|
||||||
|
case jose.PBES2_HS256_A128KW,
|
||||||
|
jose.PBES2_HS384_A192KW,
|
||||||
|
jose.PBES2_HS512_A256KW:
|
||||||
|
return fmt.Errorf("password-based encryption not supported for JWT: "+
|
||||||
|
"invalid key encryption algorithm: %s", alg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseEncryptedCompact(
|
||||||
|
s string,
|
||||||
|
keyAlgorithms []jose.KeyAlgorithm,
|
||||||
|
contentEncryption []jose.ContentEncryption,
|
||||||
|
) (*jose.JSONWebEncryption, error) {
|
||||||
|
err := validateKeyEncryptionAlgorithm(keyAlgorithms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
enc, err := jose.ParseEncryptedCompact(s, keyAlgorithms, contentEncryption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return enc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseEncrypted parses token from JWE form.
|
||||||
|
//
|
||||||
|
// The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc"
|
||||||
|
// header parameters respectively. They must be nonempty, and each "alg" or "enc" header in
|
||||||
|
// parsed data must contain a value that is present in the corresponding parameter. That
|
||||||
|
// includes the protected and unprotected headers as well as all recipients. To accept
|
||||||
|
// multiple algorithms, pass a slice of all the algorithms you want to accept.
|
||||||
|
func ParseEncrypted(s string,
|
||||||
|
keyAlgorithms []jose.KeyAlgorithm,
|
||||||
|
contentEncryption []jose.ContentEncryption,
|
||||||
|
) (*JSONWebToken, error) {
|
||||||
|
enc, err := parseEncryptedCompact(s, keyAlgorithms, contentEncryption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &JSONWebToken{
|
||||||
|
payload: enc.Decrypt,
|
||||||
|
Headers: []jose.Header{enc.Header},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseSignedAndEncrypted parses signed-then-encrypted token from JWE form.
|
||||||
|
//
|
||||||
|
// The encryptionKeyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc"
|
||||||
|
// header parameters, respectively, of the outer JWE. They must be nonempty, and each "alg" or "enc"
|
||||||
|
// header in parsed data must contain a value that is present in the corresponding parameter. That
|
||||||
|
// includes the protected and unprotected headers as well as all recipients. To accept
|
||||||
|
// multiple algorithms, pass a slice of all the algorithms you want to accept.
|
||||||
|
//
|
||||||
|
// The signatureAlgorithms parameter is used to validate the "alg" header parameter of the
|
||||||
|
// inner JWS. It must be nonempty, and the "alg" header in the inner JWS must contain a value
|
||||||
|
// that is present in the parameter.
|
||||||
|
func ParseSignedAndEncrypted(s string,
|
||||||
|
encryptionKeyAlgorithms []jose.KeyAlgorithm,
|
||||||
|
contentEncryption []jose.ContentEncryption,
|
||||||
|
signatureAlgorithms []jose.SignatureAlgorithm,
|
||||||
|
) (*NestedJSONWebToken, error) {
|
||||||
|
enc, err := parseEncryptedCompact(s, encryptionKeyAlgorithms, contentEncryption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contentType, _ := enc.Header.ExtraHeaders[jose.HeaderContentType].(string)
|
||||||
|
if strings.ToUpper(contentType) != "JWT" {
|
||||||
|
return nil, ErrInvalidContentType
|
||||||
|
}
|
||||||
|
|
||||||
|
return &NestedJSONWebToken{
|
||||||
|
allowedSignatureAlgorithms: signatureAlgorithms,
|
||||||
|
enc: enc,
|
||||||
|
Headers: []jose.Header{enc.Header},
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -33,8 +33,9 @@ type Expected struct {
|
||||||
Issuer string
|
Issuer string
|
||||||
// Subject matches the "sub" claim exactly.
|
// Subject matches the "sub" claim exactly.
|
||||||
Subject string
|
Subject string
|
||||||
// Audience matches the values in "aud" claim, regardless of their order.
|
// AnyAudience matches if there is a non-empty intersection between
|
||||||
Audience Audience
|
// its values and the values in the "aud" claim.
|
||||||
|
AnyAudience Audience
|
||||||
// ID matches the "jti" claim exactly.
|
// ID matches the "jti" claim exactly.
|
||||||
ID string
|
ID string
|
||||||
// Time matches the "exp", "nbf" and "iat" claims with leeway.
|
// Time matches the "exp", "nbf" and "iat" claims with leeway.
|
||||||
|
@ -88,12 +89,18 @@ func (c Claims) ValidateWithLeeway(e Expected, leeway time.Duration) error {
|
||||||
return ErrInvalidID
|
return ErrInvalidID
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(e.Audience) != 0 {
|
if len(e.AnyAudience) != 0 {
|
||||||
for _, v := range e.Audience {
|
var intersection bool
|
||||||
if !c.Audience.Contains(v) {
|
for _, v := range e.AnyAudience {
|
||||||
return ErrInvalidAudience
|
if c.Audience.Contains(v) {
|
||||||
|
intersection = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !intersection {
|
||||||
|
return ErrInvalidAudience
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate using the e.Time, or time.Now if not provided
|
// validate using the e.Time, or time.Now if not provided
|
|
@ -121,7 +121,7 @@ func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
|
||||||
return oke.encrypter.encryptKey(cek, alg)
|
return oke.encrypter.encryptKey(cek, alg)
|
||||||
}
|
}
|
||||||
|
|
||||||
//OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
|
// OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
|
||||||
type OpaqueKeyDecrypter interface {
|
type OpaqueKeyDecrypter interface {
|
||||||
DecryptKey(encryptedKey []byte, header Header) ([]byte, error)
|
DecryptKey(encryptedKey []byte, header Header) ([]byte, error)
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeyAlgorithm represents a key management algorithm.
|
// KeyAlgorithm represents a key management algorithm.
|
||||||
|
@ -183,8 +183,13 @@ type Header struct {
|
||||||
// Unverified certificate chain parsed from x5c header.
|
// Unverified certificate chain parsed from x5c header.
|
||||||
certificates []*x509.Certificate
|
certificates []*x509.Certificate
|
||||||
|
|
||||||
// Any headers not recognised above get unmarshalled
|
// At parse time, each header parameter with a name other than "kid",
|
||||||
// from JSON in a generic manner and placed in this map.
|
// "jwk", "alg", "nonce", or "x5c" will have its value passed to
|
||||||
|
// [json.Unmarshal] to unmarshal it into an interface value.
|
||||||
|
// The resulting value will be stored in this map, with the header
|
||||||
|
// parameter name as the key.
|
||||||
|
//
|
||||||
|
// [json.Unmarshal]: https://pkg.go.dev/encoding/json#Unmarshal
|
||||||
ExtraHeaders map[HeaderKey]interface{}
|
ExtraHeaders map[HeaderKey]interface{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/json"
|
"github.com/go-jose/go-jose/v4/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NonceSource represents a source of random nonces to go into JWS objects
|
// NonceSource represents a source of random nonces to go into JWS objects
|
||||||
|
@ -40,6 +40,20 @@ type Signer interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SigningKey represents an algorithm/key used to sign a message.
|
// SigningKey represents an algorithm/key used to sign a message.
|
||||||
|
//
|
||||||
|
// Key must have one of these types:
|
||||||
|
// - ed25519.PrivateKey
|
||||||
|
// - *ecdsa.PrivateKey
|
||||||
|
// - *rsa.PrivateKey
|
||||||
|
// - *JSONWebKey
|
||||||
|
// - JSONWebKey
|
||||||
|
// - []byte (an HMAC key)
|
||||||
|
// - Any type that satisfies the OpaqueSigner interface
|
||||||
|
//
|
||||||
|
// If the key is an HMAC key, it must have at least as many bytes as the relevant hash output:
|
||||||
|
// - HS256: 32 bytes
|
||||||
|
// - HS384: 48 bytes
|
||||||
|
// - HS512: 64 bytes
|
||||||
type SigningKey struct {
|
type SigningKey struct {
|
||||||
Algorithm SignatureAlgorithm
|
Algorithm SignatureAlgorithm
|
||||||
Key interface{}
|
Key interface{}
|
||||||
|
@ -52,12 +66,22 @@ type SignerOptions struct {
|
||||||
|
|
||||||
// Optional map of additional keys to be inserted into the protected header
|
// Optional map of additional keys to be inserted into the protected header
|
||||||
// of a JWS object. Some specifications which make use of JWS like to insert
|
// of a JWS object. Some specifications which make use of JWS like to insert
|
||||||
// additional values here. All values must be JSON-serializable.
|
// additional values here.
|
||||||
|
//
|
||||||
|
// Values will be serialized by [json.Marshal] and must be valid inputs to
|
||||||
|
// that function.
|
||||||
|
//
|
||||||
|
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||||
ExtraHeaders map[HeaderKey]interface{}
|
ExtraHeaders map[HeaderKey]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||||
// if necessary. It returns itself and so can be used in a fluent style.
|
// if necessary, and returns the updated SignerOptions.
|
||||||
|
//
|
||||||
|
// The v argument will be serialized by [json.Marshal] and must be a valid
|
||||||
|
// input to that function.
|
||||||
|
//
|
||||||
|
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||||
func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions {
|
func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions {
|
||||||
if so.ExtraHeaders == nil {
|
if so.ExtraHeaders == nil {
|
||||||
so.ExtraHeaders = map[HeaderKey]interface{}{}
|
so.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||||
|
@ -173,11 +197,11 @@ func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
|
||||||
return newVerifier(verificationKey.Key)
|
return newVerifier(verificationKey.Key)
|
||||||
case *JSONWebKey:
|
case *JSONWebKey:
|
||||||
return newVerifier(verificationKey.Key)
|
return newVerifier(verificationKey.Key)
|
||||||
}
|
case OpaqueVerifier:
|
||||||
if ov, ok := verificationKey.(OpaqueVerifier); ok {
|
return &opaqueVerifier{verifier: verificationKey}, nil
|
||||||
return &opaqueVerifier{verifier: ov}, nil
|
default:
|
||||||
}
|
|
||||||
return nil, ErrUnsupportedKeyType
|
return nil, ErrUnsupportedKeyType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
|
func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
|
||||||
|
@ -204,11 +228,11 @@ func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipient
|
||||||
return newJWKSigner(alg, signingKey)
|
return newJWKSigner(alg, signingKey)
|
||||||
case *JSONWebKey:
|
case *JSONWebKey:
|
||||||
return newJWKSigner(alg, *signingKey)
|
return newJWKSigner(alg, *signingKey)
|
||||||
}
|
case OpaqueSigner:
|
||||||
if signer, ok := signingKey.(OpaqueSigner); ok {
|
return newOpaqueSigner(alg, signingKey)
|
||||||
return newOpaqueSigner(alg, signer)
|
default:
|
||||||
}
|
|
||||||
return recipientSigInfo{}, ErrUnsupportedKeyType
|
return recipientSigInfo{}, ErrUnsupportedKeyType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) {
|
func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) {
|
||||||
|
@ -321,12 +345,26 @@ func (ctx *genericSigner) Options() SignerOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify validates the signature on the object and returns the payload.
|
// Verify validates the signature on the object and returns the payload.
|
||||||
// This function does not support multi-signature, if you desire multi-sig
|
// This function does not support multi-signature. If you desire multi-signature
|
||||||
// verification use VerifyMulti instead.
|
// verification use VerifyMulti instead.
|
||||||
//
|
//
|
||||||
// Be careful when verifying signatures based on embedded JWKs inside the
|
// Be careful when verifying signatures based on embedded JWKs inside the
|
||||||
// payload header. You cannot assume that the key received in a payload is
|
// payload header. You cannot assume that the key received in a payload is
|
||||||
// trusted.
|
// trusted.
|
||||||
|
//
|
||||||
|
// The verificationKey argument must have one of these types:
|
||||||
|
// - ed25519.PublicKey
|
||||||
|
// - *ecdsa.PublicKey
|
||||||
|
// - *rsa.PublicKey
|
||||||
|
// - *JSONWebKey
|
||||||
|
// - JSONWebKey
|
||||||
|
// - []byte (an HMAC key)
|
||||||
|
// - Any type that implements the OpaqueVerifier interface.
|
||||||
|
//
|
||||||
|
// If the key is an HMAC key, it must have at least as many bytes as the relevant hash output:
|
||||||
|
// - HS256: 32 bytes
|
||||||
|
// - HS384: 48 bytes
|
||||||
|
// - HS512: 64 bytes
|
||||||
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
|
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
|
||||||
err := obj.DetachedVerify(obj.payload, verificationKey)
|
err := obj.DetachedVerify(obj.payload, verificationKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -346,6 +384,9 @@ func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
|
||||||
// most cases, you will probably want to use Verify instead. DetachedVerify
|
// most cases, you will probably want to use Verify instead. DetachedVerify
|
||||||
// is only useful if you have a payload and signature that are separated from
|
// is only useful if you have a payload and signature that are separated from
|
||||||
// each other.
|
// each other.
|
||||||
|
//
|
||||||
|
// The verificationKey argument must have one of the types allowed for the
|
||||||
|
// verificationKey argument of JSONWebSignature.Verify().
|
||||||
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
|
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
|
||||||
key := tryJWKS(verificationKey, obj.headers()...)
|
key := tryJWKS(verificationKey, obj.headers()...)
|
||||||
verifier, err := newVerifier(key)
|
verifier, err := newVerifier(key)
|
||||||
|
@ -388,6 +429,9 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
|
||||||
// returns the index of the signature that was verified, along with the signature
|
// returns the index of the signature that was verified, along with the signature
|
||||||
// object and the payload. We return the signature and index to guarantee that
|
// object and the payload. We return the signature and index to guarantee that
|
||||||
// callers are getting the verified value.
|
// callers are getting the verified value.
|
||||||
|
//
|
||||||
|
// The verificationKey argument must have one of the types allowed for the
|
||||||
|
// verificationKey argument of JSONWebSignature.Verify().
|
||||||
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
|
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
|
||||||
idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey)
|
idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -405,6 +449,9 @@ func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signa
|
||||||
// DetachedVerifyMulti is only useful if you have a payload and signature that are
|
// DetachedVerifyMulti is only useful if you have a payload and signature that are
|
||||||
// separated from each other, and the signature can have multiple signers at the
|
// separated from each other, and the signature can have multiple signers at the
|
||||||
// same time.
|
// same time.
|
||||||
|
//
|
||||||
|
// The verificationKey argument must have one of the types allowed for the
|
||||||
|
// verificationKey argument of JSONWebSignature.Verify().
|
||||||
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
|
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
|
||||||
key := tryJWKS(verificationKey, obj.headers()...)
|
key := tryJWKS(verificationKey, obj.headers()...)
|
||||||
verifier, err := newVerifier(key)
|
verifier, err := newVerifier(key)
|
|
@ -32,7 +32,7 @@ import (
|
||||||
|
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
|
|
||||||
josecipher "github.com/go-jose/go-jose/v3/cipher"
|
josecipher "github.com/go-jose/go-jose/v4/cipher"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RandReader is a cryptographically secure random number generator (stubbed out in tests).
|
// RandReader is a cryptographically secure random number generator (stubbed out in tests).
|
||||||
|
@ -40,12 +40,17 @@ var RandReader = rand.Reader
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// RFC7518 recommends a minimum of 1,000 iterations:
|
// RFC7518 recommends a minimum of 1,000 iterations:
|
||||||
// https://tools.ietf.org/html/rfc7518#section-4.8.1.2
|
// - https://tools.ietf.org/html/rfc7518#section-4.8.1.2
|
||||||
|
//
|
||||||
// NIST recommends a minimum of 10,000:
|
// NIST recommends a minimum of 10,000:
|
||||||
// https://pages.nist.gov/800-63-3/sp800-63b.html
|
// - https://pages.nist.gov/800-63-3/sp800-63b.html
|
||||||
// 1Password uses 100,000:
|
//
|
||||||
// https://support.1password.com/pbkdf2/
|
// 1Password increased in 2023 from 100,000 to 650,000:
|
||||||
defaultP2C = 100000
|
// - https://support.1password.com/pbkdf2/
|
||||||
|
//
|
||||||
|
// OWASP recommended 600,000 in Dec 2022:
|
||||||
|
// - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
|
||||||
|
defaultP2C = 600000
|
||||||
// Default salt size: 128 bits
|
// Default salt size: 128 bits
|
||||||
defaultP2SSize = 16
|
defaultP2SSize = 16
|
||||||
)
|
)
|
||||||
|
@ -415,6 +420,11 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
|
||||||
if p2c <= 0 {
|
if p2c <= 0 {
|
||||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: must be a positive integer")
|
return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: must be a positive integer")
|
||||||
}
|
}
|
||||||
|
if p2c > 1000000 {
|
||||||
|
// An unauthenticated attacker can set a high P2C value. Set an upper limit to avoid
|
||||||
|
// DoS attacks.
|
||||||
|
return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: too high")
|
||||||
|
}
|
||||||
|
|
||||||
// salt is UTF8(Alg) || 0x00 || Salt Input
|
// salt is UTF8(Alg) || 0x00 || Salt Input
|
||||||
alg := headers.getAlgorithm()
|
alg := headers.getAlgorithm()
|
||||||
|
@ -444,7 +454,7 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
|
||||||
func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||||
mac, err := ctx.hmac(payload, alg)
|
mac, err := ctx.hmac(payload, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Signature{}, errors.New("go-jose/go-jose: failed to compute hmac")
|
return Signature{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return Signature{
|
return Signature{
|
||||||
|
@ -476,12 +486,24 @@ func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureA
|
||||||
func (ctx symmetricMac) hmac(payload []byte, alg SignatureAlgorithm) ([]byte, error) {
|
func (ctx symmetricMac) hmac(payload []byte, alg SignatureAlgorithm) ([]byte, error) {
|
||||||
var hash func() hash.Hash
|
var hash func() hash.Hash
|
||||||
|
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7518#section-3.2
|
||||||
|
// A key of the same size as the hash output (for instance, 256 bits for
|
||||||
|
// "HS256") or larger MUST be used
|
||||||
switch alg {
|
switch alg {
|
||||||
case HS256:
|
case HS256:
|
||||||
|
if len(ctx.key)*8 < 256 {
|
||||||
|
return nil, ErrInvalidKeySize
|
||||||
|
}
|
||||||
hash = sha256.New
|
hash = sha256.New
|
||||||
case HS384:
|
case HS384:
|
||||||
|
if len(ctx.key)*8 < 384 {
|
||||||
|
return nil, ErrInvalidKeySize
|
||||||
|
}
|
||||||
hash = sha512.New384
|
hash = sha512.New384
|
||||||
case HS512:
|
case HS512:
|
||||||
|
if len(ctx.key)*8 < 512 {
|
||||||
|
return nil, ErrInvalidKeySize
|
||||||
|
}
|
||||||
hash = sha512.New
|
hash = sha512.New
|
||||||
default:
|
default:
|
||||||
return nil, ErrUnsupportedAlgorithm
|
return nil, ErrUnsupportedAlgorithm
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.7 && amd64 && gc && !purego
|
//go:build amd64 && gc && !purego
|
||||||
|
|
||||||
package blake2b
|
package blake2b
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.7 && amd64 && gc && !purego
|
//go:build amd64 && gc && !purego
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.7 && amd64 && gc && !purego
|
|
||||||
|
|
||||||
package blake2b
|
|
||||||
|
|
||||||
import "golang.org/x/sys/cpu"
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
useSSE4 = cpu.X86.HasSSE41
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
|
|
||||||
|
|
||||||
func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
|
||||||
if useSSE4 {
|
|
||||||
hashBlocksSSE4(h, c, flag, blocks)
|
|
||||||
} else {
|
|
||||||
hashBlocksGeneric(h, c, flag, blocks)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,8 +2,6 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.9
|
|
||||||
|
|
||||||
package blake2b
|
package blake2b
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.13
|
|
||||||
|
|
||||||
package poly1305
|
|
||||||
|
|
||||||
// Generic fallbacks for the math/bits intrinsics, copied from
|
|
||||||
// src/math/bits/bits.go. They were added in Go 1.12, but Add64 and Sum64 had
|
|
||||||
// variable time fallbacks until Go 1.13.
|
|
||||||
|
|
||||||
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
|
|
||||||
sum = x + y + carry
|
|
||||||
carryOut = ((x & y) | ((x | y) &^ sum)) >> 63
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
|
|
||||||
diff = x - y - borrow
|
|
||||||
borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func bitsMul64(x, y uint64) (hi, lo uint64) {
|
|
||||||
const mask32 = 1<<32 - 1
|
|
||||||
x0 := x & mask32
|
|
||||||
x1 := x >> 32
|
|
||||||
y0 := y & mask32
|
|
||||||
y1 := y >> 32
|
|
||||||
w0 := x0 * y0
|
|
||||||
t := x1*y0 + w0>>32
|
|
||||||
w1 := t & mask32
|
|
||||||
w2 := t >> 32
|
|
||||||
w1 += x0 * y1
|
|
||||||
hi = x1*y1 + w2 + w1>>32
|
|
||||||
lo = x * y
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build go1.13
|
|
||||||
|
|
||||||
package poly1305
|
|
||||||
|
|
||||||
import "math/bits"
|
|
||||||
|
|
||||||
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
|
|
||||||
return bits.Add64(x, y, carry)
|
|
||||||
}
|
|
||||||
|
|
||||||
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
|
|
||||||
return bits.Sub64(x, y, borrow)
|
|
||||||
}
|
|
||||||
|
|
||||||
func bitsMul64(x, y uint64) (hi, lo uint64) {
|
|
||||||
return bits.Mul64(x, y)
|
|
||||||
}
|
|
|
@ -7,7 +7,10 @@
|
||||||
|
|
||||||
package poly1305
|
package poly1305
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"math/bits"
|
||||||
|
)
|
||||||
|
|
||||||
// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag
|
// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag
|
||||||
// for a 64 bytes message is approximately
|
// for a 64 bytes message is approximately
|
||||||
|
@ -114,13 +117,13 @@ type uint128 struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func mul64(a, b uint64) uint128 {
|
func mul64(a, b uint64) uint128 {
|
||||||
hi, lo := bitsMul64(a, b)
|
hi, lo := bits.Mul64(a, b)
|
||||||
return uint128{lo, hi}
|
return uint128{lo, hi}
|
||||||
}
|
}
|
||||||
|
|
||||||
func add128(a, b uint128) uint128 {
|
func add128(a, b uint128) uint128 {
|
||||||
lo, c := bitsAdd64(a.lo, b.lo, 0)
|
lo, c := bits.Add64(a.lo, b.lo, 0)
|
||||||
hi, c := bitsAdd64(a.hi, b.hi, c)
|
hi, c := bits.Add64(a.hi, b.hi, c)
|
||||||
if c != 0 {
|
if c != 0 {
|
||||||
panic("poly1305: unexpected overflow")
|
panic("poly1305: unexpected overflow")
|
||||||
}
|
}
|
||||||
|
@ -155,8 +158,8 @@ func updateGeneric(state *macState, msg []byte) {
|
||||||
// hide leading zeroes. For full chunks, that's 1 << 128, so we can just
|
// hide leading zeroes. For full chunks, that's 1 << 128, so we can just
|
||||||
// add 1 to the most significant (2¹²⁸) limb, h2.
|
// add 1 to the most significant (2¹²⁸) limb, h2.
|
||||||
if len(msg) >= TagSize {
|
if len(msg) >= TagSize {
|
||||||
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
|
h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
|
||||||
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
|
h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
|
||||||
h2 += c + 1
|
h2 += c + 1
|
||||||
|
|
||||||
msg = msg[TagSize:]
|
msg = msg[TagSize:]
|
||||||
|
@ -165,8 +168,8 @@ func updateGeneric(state *macState, msg []byte) {
|
||||||
copy(buf[:], msg)
|
copy(buf[:], msg)
|
||||||
buf[len(msg)] = 1
|
buf[len(msg)] = 1
|
||||||
|
|
||||||
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
|
h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
|
||||||
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
|
h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
|
||||||
h2 += c
|
h2 += c
|
||||||
|
|
||||||
msg = nil
|
msg = nil
|
||||||
|
@ -219,9 +222,9 @@ func updateGeneric(state *macState, msg []byte) {
|
||||||
m3 := h2r1
|
m3 := h2r1
|
||||||
|
|
||||||
t0 := m0.lo
|
t0 := m0.lo
|
||||||
t1, c := bitsAdd64(m1.lo, m0.hi, 0)
|
t1, c := bits.Add64(m1.lo, m0.hi, 0)
|
||||||
t2, c := bitsAdd64(m2.lo, m1.hi, c)
|
t2, c := bits.Add64(m2.lo, m1.hi, c)
|
||||||
t3, _ := bitsAdd64(m3.lo, m2.hi, c)
|
t3, _ := bits.Add64(m3.lo, m2.hi, c)
|
||||||
|
|
||||||
// Now we have the result as 4 64-bit limbs, and we need to reduce it
|
// Now we have the result as 4 64-bit limbs, and we need to reduce it
|
||||||
// modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do
|
// modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do
|
||||||
|
@ -243,14 +246,14 @@ func updateGeneric(state *macState, msg []byte) {
|
||||||
|
|
||||||
// To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c.
|
// To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c.
|
||||||
|
|
||||||
h0, c = bitsAdd64(h0, cc.lo, 0)
|
h0, c = bits.Add64(h0, cc.lo, 0)
|
||||||
h1, c = bitsAdd64(h1, cc.hi, c)
|
h1, c = bits.Add64(h1, cc.hi, c)
|
||||||
h2 += c
|
h2 += c
|
||||||
|
|
||||||
cc = shiftRightBy2(cc)
|
cc = shiftRightBy2(cc)
|
||||||
|
|
||||||
h0, c = bitsAdd64(h0, cc.lo, 0)
|
h0, c = bits.Add64(h0, cc.lo, 0)
|
||||||
h1, c = bitsAdd64(h1, cc.hi, c)
|
h1, c = bits.Add64(h1, cc.hi, c)
|
||||||
h2 += c
|
h2 += c
|
||||||
|
|
||||||
// h2 is at most 3 + 1 + 1 = 5, making the whole of h at most
|
// h2 is at most 3 + 1 + 1 = 5, making the whole of h at most
|
||||||
|
@ -287,9 +290,9 @@ func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
|
||||||
// in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the
|
// in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the
|
||||||
// result if the subtraction underflows, and t otherwise.
|
// result if the subtraction underflows, and t otherwise.
|
||||||
|
|
||||||
hMinusP0, b := bitsSub64(h0, p0, 0)
|
hMinusP0, b := bits.Sub64(h0, p0, 0)
|
||||||
hMinusP1, b := bitsSub64(h1, p1, b)
|
hMinusP1, b := bits.Sub64(h1, p1, b)
|
||||||
_, b = bitsSub64(h2, p2, b)
|
_, b = bits.Sub64(h2, p2, b)
|
||||||
|
|
||||||
// h = h if h < p else h - p
|
// h = h if h < p else h - p
|
||||||
h0 = select64(b, h0, hMinusP0)
|
h0 = select64(b, h0, hMinusP0)
|
||||||
|
@ -301,8 +304,8 @@ func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
|
||||||
//
|
//
|
||||||
// by just doing a wide addition with the 128 low bits of h and discarding
|
// by just doing a wide addition with the 128 low bits of h and discarding
|
||||||
// the overflow.
|
// the overflow.
|
||||||
h0, c := bitsAdd64(h0, s[0], 0)
|
h0, c := bits.Add64(h0, s[0], 0)
|
||||||
h1, _ = bitsAdd64(h1, s[1], c)
|
h1, _ = bits.Add64(h1, s[1], c)
|
||||||
|
|
||||||
binary.LittleEndian.PutUint64(out[0:8], h0)
|
binary.LittleEndian.PutUint64(out[0:8], h0)
|
||||||
binary.LittleEndian.PutUint64(out[8:16], h1)
|
binary.LittleEndian.PutUint64(out[8:16], h1)
|
||||||
|
|
|
@ -19,15 +19,14 @@
|
||||||
|
|
||||||
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
|
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
|
||||||
MULLD r0, h0, t0; \
|
MULLD r0, h0, t0; \
|
||||||
MULLD r0, h1, t4; \
|
|
||||||
MULHDU r0, h0, t1; \
|
MULHDU r0, h0, t1; \
|
||||||
|
MULLD r0, h1, t4; \
|
||||||
MULHDU r0, h1, t5; \
|
MULHDU r0, h1, t5; \
|
||||||
ADDC t4, t1, t1; \
|
ADDC t4, t1, t1; \
|
||||||
MULLD r0, h2, t2; \
|
MULLD r0, h2, t2; \
|
||||||
ADDZE t5; \
|
|
||||||
MULHDU r1, h0, t4; \
|
MULHDU r1, h0, t4; \
|
||||||
MULLD r1, h0, h0; \
|
MULLD r1, h0, h0; \
|
||||||
ADD t5, t2, t2; \
|
ADDE t5, t2, t2; \
|
||||||
ADDC h0, t1, t1; \
|
ADDC h0, t1, t1; \
|
||||||
MULLD h2, r1, t3; \
|
MULLD h2, r1, t3; \
|
||||||
ADDZE t4, h0; \
|
ADDZE t4, h0; \
|
||||||
|
@ -37,13 +36,11 @@
|
||||||
ADDE t5, t3, t3; \
|
ADDE t5, t3, t3; \
|
||||||
ADDC h0, t2, t2; \
|
ADDC h0, t2, t2; \
|
||||||
MOVD $-4, t4; \
|
MOVD $-4, t4; \
|
||||||
MOVD t0, h0; \
|
|
||||||
MOVD t1, h1; \
|
|
||||||
ADDZE t3; \
|
ADDZE t3; \
|
||||||
ANDCC $3, t2, h2; \
|
RLDICL $0, t2, $62, h2; \
|
||||||
AND t2, t4, t0; \
|
AND t2, t4, h0; \
|
||||||
ADDC t0, h0, h0; \
|
ADDC t0, h0, h0; \
|
||||||
ADDE t3, h1, h1; \
|
ADDE t3, t1, h1; \
|
||||||
SLD $62, t3, t4; \
|
SLD $62, t3, t4; \
|
||||||
SRD $2, t2; \
|
SRD $2, t2; \
|
||||||
ADDZE h2; \
|
ADDZE h2; \
|
||||||
|
@ -75,6 +72,7 @@ TEXT ·update(SB), $0-32
|
||||||
loop:
|
loop:
|
||||||
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
|
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
|
||||||
|
|
||||||
|
PCALIGN $16
|
||||||
multiply:
|
multiply:
|
||||||
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
|
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
|
||||||
ADD $-16, R5
|
ADD $-16, R5
|
||||||
|
|
|
@ -187,9 +187,11 @@ type channel struct {
|
||||||
pending *buffer
|
pending *buffer
|
||||||
extPending *buffer
|
extPending *buffer
|
||||||
|
|
||||||
// windowMu protects myWindow, the flow-control window.
|
// windowMu protects myWindow, the flow-control window, and myConsumed,
|
||||||
|
// the number of bytes consumed since we last increased myWindow
|
||||||
windowMu sync.Mutex
|
windowMu sync.Mutex
|
||||||
myWindow uint32
|
myWindow uint32
|
||||||
|
myConsumed uint32
|
||||||
|
|
||||||
// writeMu serializes calls to mux.conn.writePacket() and
|
// writeMu serializes calls to mux.conn.writePacket() and
|
||||||
// protects sentClose and packetPool. This mutex must be
|
// protects sentClose and packetPool. This mutex must be
|
||||||
|
@ -332,14 +334,24 @@ func (ch *channel) handleData(packet []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *channel) adjustWindow(n uint32) error {
|
func (c *channel) adjustWindow(adj uint32) error {
|
||||||
c.windowMu.Lock()
|
c.windowMu.Lock()
|
||||||
// Since myWindow is managed on our side, and can never exceed
|
// Since myConsumed and myWindow are managed on our side, and can never
|
||||||
// the initial window setting, we don't worry about overflow.
|
// exceed the initial window setting, we don't worry about overflow.
|
||||||
c.myWindow += uint32(n)
|
c.myConsumed += adj
|
||||||
|
var sendAdj uint32
|
||||||
|
if (channelWindowSize-c.myWindow > 3*c.maxIncomingPayload) ||
|
||||||
|
(c.myWindow < channelWindowSize/2) {
|
||||||
|
sendAdj = c.myConsumed
|
||||||
|
c.myConsumed = 0
|
||||||
|
c.myWindow += sendAdj
|
||||||
|
}
|
||||||
c.windowMu.Unlock()
|
c.windowMu.Unlock()
|
||||||
|
if sendAdj == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return c.sendMessage(windowAdjustMsg{
|
return c.sendMessage(windowAdjustMsg{
|
||||||
AdditionalBytes: uint32(n),
|
AdditionalBytes: sendAdj,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan
|
||||||
|
|
||||||
if err := conn.clientHandshake(addr, &fullConf); err != nil {
|
if err := conn.clientHandshake(addr, &fullConf); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
|
return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %w", err)
|
||||||
}
|
}
|
||||||
conn.mux = newMux(conn.transport)
|
conn.mux = newMux(conn.transport)
|
||||||
return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
|
return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
|
||||||
|
|
|
@ -35,6 +35,16 @@ type keyingTransport interface {
|
||||||
// direction will be effected if a msgNewKeys message is sent
|
// direction will be effected if a msgNewKeys message is sent
|
||||||
// or received.
|
// or received.
|
||||||
prepareKeyChange(*algorithms, *kexResult) error
|
prepareKeyChange(*algorithms, *kexResult) error
|
||||||
|
|
||||||
|
// setStrictMode sets the strict KEX mode, notably triggering
|
||||||
|
// sequence number resets on sending or receiving msgNewKeys.
|
||||||
|
// If the sequence number is already > 1 when setStrictMode
|
||||||
|
// is called, an error is returned.
|
||||||
|
setStrictMode() error
|
||||||
|
|
||||||
|
// setInitialKEXDone indicates to the transport that the initial key exchange
|
||||||
|
// was completed
|
||||||
|
setInitialKEXDone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handshakeTransport implements rekeying on top of a keyingTransport
|
// handshakeTransport implements rekeying on top of a keyingTransport
|
||||||
|
@ -100,6 +110,10 @@ type handshakeTransport struct {
|
||||||
|
|
||||||
// The session ID or nil if first kex did not complete yet.
|
// The session ID or nil if first kex did not complete yet.
|
||||||
sessionID []byte
|
sessionID []byte
|
||||||
|
|
||||||
|
// strictMode indicates if the other side of the handshake indicated
|
||||||
|
// that we should be following the strict KEX protocol restrictions.
|
||||||
|
strictMode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type pendingKex struct {
|
type pendingKex struct {
|
||||||
|
@ -209,7 +223,10 @@ func (t *handshakeTransport) readLoop() {
|
||||||
close(t.incoming)
|
close(t.incoming)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if p[0] == msgIgnore || p[0] == msgDebug {
|
// If this is the first kex, and strict KEX mode is enabled,
|
||||||
|
// we don't ignore any messages, as they may be used to manipulate
|
||||||
|
// the packet sequence numbers.
|
||||||
|
if !(t.sessionID == nil && t.strictMode) && (p[0] == msgIgnore || p[0] == msgDebug) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t.incoming <- p
|
t.incoming <- p
|
||||||
|
@ -441,6 +458,11 @@ func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
|
||||||
return successPacket, nil
|
return successPacket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
kexStrictClient = "kex-strict-c-v00@openssh.com"
|
||||||
|
kexStrictServer = "kex-strict-s-v00@openssh.com"
|
||||||
|
)
|
||||||
|
|
||||||
// sendKexInit sends a key change message.
|
// sendKexInit sends a key change message.
|
||||||
func (t *handshakeTransport) sendKexInit() error {
|
func (t *handshakeTransport) sendKexInit() error {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
|
@ -454,7 +476,6 @@ func (t *handshakeTransport) sendKexInit() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := &kexInitMsg{
|
msg := &kexInitMsg{
|
||||||
KexAlgos: t.config.KeyExchanges,
|
|
||||||
CiphersClientServer: t.config.Ciphers,
|
CiphersClientServer: t.config.Ciphers,
|
||||||
CiphersServerClient: t.config.Ciphers,
|
CiphersServerClient: t.config.Ciphers,
|
||||||
MACsClientServer: t.config.MACs,
|
MACsClientServer: t.config.MACs,
|
||||||
|
@ -464,6 +485,13 @@ func (t *handshakeTransport) sendKexInit() error {
|
||||||
}
|
}
|
||||||
io.ReadFull(rand.Reader, msg.Cookie[:])
|
io.ReadFull(rand.Reader, msg.Cookie[:])
|
||||||
|
|
||||||
|
// We mutate the KexAlgos slice, in order to add the kex-strict extension algorithm,
|
||||||
|
// and possibly to add the ext-info extension algorithm. Since the slice may be the
|
||||||
|
// user owned KeyExchanges, we create our own slice in order to avoid using user
|
||||||
|
// owned memory by mistake.
|
||||||
|
msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+2) // room for kex-strict and ext-info
|
||||||
|
msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
|
||||||
|
|
||||||
isServer := len(t.hostKeys) > 0
|
isServer := len(t.hostKeys) > 0
|
||||||
if isServer {
|
if isServer {
|
||||||
for _, k := range t.hostKeys {
|
for _, k := range t.hostKeys {
|
||||||
|
@ -488,17 +516,24 @@ func (t *handshakeTransport) sendKexInit() error {
|
||||||
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat)
|
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t.sessionID == nil {
|
||||||
|
msg.KexAlgos = append(msg.KexAlgos, kexStrictServer)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
|
msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
|
||||||
|
|
||||||
// As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what
|
// As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what
|
||||||
// algorithms the server supports for public key authentication. See RFC
|
// algorithms the server supports for public key authentication. See RFC
|
||||||
// 8308, Section 2.1.
|
// 8308, Section 2.1.
|
||||||
|
//
|
||||||
|
// We also send the strict KEX mode extension algorithm, in order to opt
|
||||||
|
// into the strict KEX mode.
|
||||||
if firstKeyExchange := t.sessionID == nil; firstKeyExchange {
|
if firstKeyExchange := t.sessionID == nil; firstKeyExchange {
|
||||||
msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1)
|
|
||||||
msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
|
|
||||||
msg.KexAlgos = append(msg.KexAlgos, "ext-info-c")
|
msg.KexAlgos = append(msg.KexAlgos, "ext-info-c")
|
||||||
|
msg.KexAlgos = append(msg.KexAlgos, kexStrictClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
packet := Marshal(msg)
|
packet := Marshal(msg)
|
||||||
|
@ -604,6 +639,13 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t.sessionID == nil && ((isClient && contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && contains(clientInit.KexAlgos, kexStrictClient))) {
|
||||||
|
t.strictMode = true
|
||||||
|
if err := t.conn.setStrictMode(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We don't send FirstKexFollows, but we handle receiving it.
|
// We don't send FirstKexFollows, but we handle receiving it.
|
||||||
//
|
//
|
||||||
// RFC 4253 section 7 defines the kex and the agreement method for
|
// RFC 4253 section 7 defines the kex and the agreement method for
|
||||||
|
@ -679,6 +721,12 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||||
return unexpectedMessageError(msgNewKeys, packet[0])
|
return unexpectedMessageError(msgNewKeys, packet[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if firstKeyExchange {
|
||||||
|
// Indicates to the transport that the first key exchange is completed
|
||||||
|
// after receiving SSH_MSG_NEWKEYS.
|
||||||
|
t.conn.setInitialKEXDone()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,7 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
|
||||||
} else {
|
} else {
|
||||||
for _, algo := range fullConf.PublicKeyAuthAlgorithms {
|
for _, algo := range fullConf.PublicKeyAuthAlgorithms {
|
||||||
if !contains(supportedPubKeyAuthAlgos, algo) {
|
if !contains(supportedPubKeyAuthAlgos, algo) {
|
||||||
|
c.Close()
|
||||||
return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo)
|
return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,6 +221,7 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
|
||||||
// Check if the config contains any unsupported key exchanges
|
// Check if the config contains any unsupported key exchanges
|
||||||
for _, kex := range fullConf.KeyExchanges {
|
for _, kex := range fullConf.KeyExchanges {
|
||||||
if _, ok := serverForbiddenKexAlgos[kex]; ok {
|
if _, ok := serverForbiddenKexAlgos[kex]; ok {
|
||||||
|
c.Close()
|
||||||
return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
|
return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,9 @@ type transport struct {
|
||||||
rand io.Reader
|
rand io.Reader
|
||||||
isClient bool
|
isClient bool
|
||||||
io.Closer
|
io.Closer
|
||||||
|
|
||||||
|
strictMode bool
|
||||||
|
initialKEXDone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// packetCipher represents a combination of SSH encryption/MAC
|
// packetCipher represents a combination of SSH encryption/MAC
|
||||||
|
@ -74,6 +77,18 @@ type connectionState struct {
|
||||||
pendingKeyChange chan packetCipher
|
pendingKeyChange chan packetCipher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *transport) setStrictMode() error {
|
||||||
|
if t.reader.seqNum != 1 {
|
||||||
|
return errors.New("ssh: sequence number != 1 when strict KEX mode requested")
|
||||||
|
}
|
||||||
|
t.strictMode = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *transport) setInitialKEXDone() {
|
||||||
|
t.initialKEXDone = true
|
||||||
|
}
|
||||||
|
|
||||||
// prepareKeyChange sets up key material for a keychange. The key changes in
|
// prepareKeyChange sets up key material for a keychange. The key changes in
|
||||||
// both directions are triggered by reading and writing a msgNewKey packet
|
// both directions are triggered by reading and writing a msgNewKey packet
|
||||||
// respectively.
|
// respectively.
|
||||||
|
@ -112,11 +127,12 @@ func (t *transport) printPacket(p []byte, write bool) {
|
||||||
// Read and decrypt next packet.
|
// Read and decrypt next packet.
|
||||||
func (t *transport) readPacket() (p []byte, err error) {
|
func (t *transport) readPacket() (p []byte, err error) {
|
||||||
for {
|
for {
|
||||||
p, err = t.reader.readPacket(t.bufReader)
|
p, err = t.reader.readPacket(t.bufReader, t.strictMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) {
|
// in strict mode we pass through DEBUG and IGNORE packets only during the initial KEX
|
||||||
|
if len(p) == 0 || (t.strictMode && !t.initialKEXDone) || (p[0] != msgIgnore && p[0] != msgDebug) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +143,7 @@ func (t *transport) readPacket() (p []byte, err error) {
|
||||||
return p, err
|
return p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
|
func (s *connectionState) readPacket(r *bufio.Reader, strictMode bool) ([]byte, error) {
|
||||||
packet, err := s.packetCipher.readCipherPacket(s.seqNum, r)
|
packet, err := s.packetCipher.readCipherPacket(s.seqNum, r)
|
||||||
s.seqNum++
|
s.seqNum++
|
||||||
if err == nil && len(packet) == 0 {
|
if err == nil && len(packet) == 0 {
|
||||||
|
@ -140,6 +156,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
|
||||||
select {
|
select {
|
||||||
case cipher := <-s.pendingKeyChange:
|
case cipher := <-s.pendingKeyChange:
|
||||||
s.packetCipher = cipher
|
s.packetCipher = cipher
|
||||||
|
if strictMode {
|
||||||
|
s.seqNum = 0
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("ssh: got bogus newkeys message")
|
return nil, errors.New("ssh: got bogus newkeys message")
|
||||||
}
|
}
|
||||||
|
@ -170,10 +189,10 @@ func (t *transport) writePacket(packet []byte) error {
|
||||||
if debugTransport {
|
if debugTransport {
|
||||||
t.printPacket(packet, true)
|
t.printPacket(packet, true)
|
||||||
}
|
}
|
||||||
return t.writer.writePacket(t.bufWriter, t.rand, packet)
|
return t.writer.writePacket(t.bufWriter, t.rand, packet, t.strictMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
|
func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte, strictMode bool) error {
|
||||||
changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
|
changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
|
||||||
|
|
||||||
err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet)
|
err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet)
|
||||||
|
@ -188,6 +207,9 @@ func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []
|
||||||
select {
|
select {
|
||||||
case cipher := <-s.pendingKeyChange:
|
case cipher := <-s.pendingKeyChange:
|
||||||
s.packetCipher = cipher
|
s.packetCipher = cipher
|
||||||
|
if strictMode {
|
||||||
|
s.seqNum = 0
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
panic("ssh: no key material for msgNewKeys")
|
panic("ssh: no key material for msgNewKeys")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1510,13 +1510,12 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *Framer) maxHeaderStringLen() int {
|
func (fr *Framer) maxHeaderStringLen() int {
|
||||||
v := fr.maxHeaderListSize()
|
v := int(fr.maxHeaderListSize())
|
||||||
if uint32(int(v)) == v {
|
if v < 0 {
|
||||||
return int(v)
|
// If maxHeaderListSize overflows an int, use no limit (0).
|
||||||
}
|
|
||||||
// They had a crazy big number for MaxHeaderBytes anyway,
|
|
||||||
// so give them unlimited header lengths:
|
|
||||||
return 0
|
return 0
|
||||||
|
}
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
|
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
@ -248,6 +248,7 @@ struct ltchars {
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/netfilter/nfnetlink.h>
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
#include <linux/netfilter/nf_tables.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/net_namespace.h>
|
#include <linux/net_namespace.h>
|
||||||
#include <linux/nfc.h>
|
#include <linux/nfc.h>
|
||||||
|
@ -283,10 +284,6 @@ struct ltchars {
|
||||||
#include <asm/termbits.h>
|
#include <asm/termbits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MSG_FASTOPEN
|
|
||||||
#define MSG_FASTOPEN 0x20000000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PTRACE_GETREGS
|
#ifndef PTRACE_GETREGS
|
||||||
#define PTRACE_GETREGS 0xc
|
#define PTRACE_GETREGS 0xc
|
||||||
#endif
|
#endif
|
||||||
|
@ -295,14 +292,6 @@ struct ltchars {
|
||||||
#define PTRACE_SETREGS 0xd
|
#define PTRACE_SETREGS 0xd
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SOL_NETLINK
|
|
||||||
#define SOL_NETLINK 270
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SOL_SMC
|
|
||||||
#define SOL_SMC 286
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SOL_BLUETOOTH
|
#ifdef SOL_BLUETOOTH
|
||||||
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
|
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
|
||||||
// but it is already in bluetooth_linux.go
|
// but it is already in bluetooth_linux.go
|
||||||
|
@ -319,10 +308,23 @@ struct ltchars {
|
||||||
#undef TIPC_WAIT_FOREVER
|
#undef TIPC_WAIT_FOREVER
|
||||||
#define TIPC_WAIT_FOREVER 0xffffffff
|
#define TIPC_WAIT_FOREVER 0xffffffff
|
||||||
|
|
||||||
// Copied from linux/l2tp.h
|
// Copied from linux/netfilter/nf_nat.h
|
||||||
// Including linux/l2tp.h here causes conflicts between linux/in.h
|
// Including linux/netfilter/nf_nat.h here causes conflicts between linux/in.h
|
||||||
// and netinet/in.h included via net/route.h above.
|
// and netinet/in.h.
|
||||||
#define IPPROTO_L2TP 115
|
#define NF_NAT_RANGE_MAP_IPS (1 << 0)
|
||||||
|
#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1)
|
||||||
|
#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2)
|
||||||
|
#define NF_NAT_RANGE_PERSISTENT (1 << 3)
|
||||||
|
#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4)
|
||||||
|
#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5)
|
||||||
|
#define NF_NAT_RANGE_NETMAP (1 << 6)
|
||||||
|
#define NF_NAT_RANGE_PROTO_RANDOM_ALL \
|
||||||
|
(NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
|
||||||
|
#define NF_NAT_RANGE_MASK \
|
||||||
|
(NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \
|
||||||
|
NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \
|
||||||
|
NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET | \
|
||||||
|
NF_NAT_RANGE_NETMAP)
|
||||||
|
|
||||||
// Copied from linux/hid.h.
|
// Copied from linux/hid.h.
|
||||||
// Keep in sync with the size of the referenced fields.
|
// Keep in sync with the size of the referenced fields.
|
||||||
|
@ -582,7 +584,7 @@ ccflags="$@"
|
||||||
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
|
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
|
||||||
$2 ~ /^KEYCTL_/ ||
|
$2 ~ /^KEYCTL_/ ||
|
||||||
$2 ~ /^PERF_/ ||
|
$2 ~ /^PERF_/ ||
|
||||||
$2 ~ /^SECCOMP_MODE_/ ||
|
$2 ~ /^SECCOMP_/ ||
|
||||||
$2 ~ /^SEEK_/ ||
|
$2 ~ /^SEEK_/ ||
|
||||||
$2 ~ /^SCHED_/ ||
|
$2 ~ /^SCHED_/ ||
|
||||||
$2 ~ /^SPLICE_/ ||
|
$2 ~ /^SPLICE_/ ||
|
||||||
|
@ -603,6 +605,9 @@ ccflags="$@"
|
||||||
$2 ~ /^FSOPT_/ ||
|
$2 ~ /^FSOPT_/ ||
|
||||||
$2 ~ /^WDIO[CFS]_/ ||
|
$2 ~ /^WDIO[CFS]_/ ||
|
||||||
$2 ~ /^NFN/ ||
|
$2 ~ /^NFN/ ||
|
||||||
|
$2 !~ /^NFT_META_IIFTYPE/ &&
|
||||||
|
$2 ~ /^NFT_/ ||
|
||||||
|
$2 ~ /^NF_NAT_/ ||
|
||||||
$2 ~ /^XDP_/ ||
|
$2 ~ /^XDP_/ ||
|
||||||
$2 ~ /^RWF_/ ||
|
$2 ~ /^RWF_/ ||
|
||||||
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build darwin && go1.12
|
//go:build darwin
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
@ -169,25 +170,26 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
func Uname(uname *Utsname) error {
|
func Uname(uname *Utsname) error {
|
||||||
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
||||||
n := unsafe.Sizeof(uname.Sysname)
|
n := unsafe.Sizeof(uname.Sysname)
|
||||||
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
|
// Suppress ENOMEM errors to be compatible with the C library __xuname() implementation.
|
||||||
|
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
|
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
|
||||||
n = unsafe.Sizeof(uname.Nodename)
|
n = unsafe.Sizeof(uname.Nodename)
|
||||||
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
|
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
|
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
|
||||||
n = unsafe.Sizeof(uname.Release)
|
n = unsafe.Sizeof(uname.Release)
|
||||||
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
|
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mib = []_C_int{CTL_KERN, KERN_VERSION}
|
mib = []_C_int{CTL_KERN, KERN_VERSION}
|
||||||
n = unsafe.Sizeof(uname.Version)
|
n = unsafe.Sizeof(uname.Version)
|
||||||
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
|
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +207,7 @@ func Uname(uname *Utsname) error {
|
||||||
|
|
||||||
mib = []_C_int{CTL_HW, HW_MACHINE}
|
mib = []_C_int{CTL_HW, HW_MACHINE}
|
||||||
n = unsafe.Sizeof(uname.Machine)
|
n = unsafe.Sizeof(uname.Machine)
|
||||||
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
|
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1849,6 +1849,105 @@ func Dup2(oldfd, newfd int) error {
|
||||||
//sys Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error)
|
//sys Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error)
|
||||||
//sys Fsopen(fsName string, flags int) (fd int, err error)
|
//sys Fsopen(fsName string, flags int) (fd int, err error)
|
||||||
//sys Fspick(dirfd int, pathName string, flags int) (fd int, err error)
|
//sys Fspick(dirfd int, pathName string, flags int) (fd int, err error)
|
||||||
|
|
||||||
|
//sys fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error)
|
||||||
|
|
||||||
|
func fsconfigCommon(fd int, cmd uint, key string, value *byte, aux int) (err error) {
|
||||||
|
var keyp *byte
|
||||||
|
if keyp, err = BytePtrFromString(key); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return fsconfig(fd, cmd, keyp, value, aux)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FsconfigSetFlag is equivalent to fsconfig(2) called
|
||||||
|
// with cmd == FSCONFIG_SET_FLAG.
|
||||||
|
//
|
||||||
|
// fd is the filesystem context to act upon.
|
||||||
|
// key the parameter key to set.
|
||||||
|
func FsconfigSetFlag(fd int, key string) (err error) {
|
||||||
|
return fsconfigCommon(fd, FSCONFIG_SET_FLAG, key, nil, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FsconfigSetString is equivalent to fsconfig(2) called
|
||||||
|
// with cmd == FSCONFIG_SET_STRING.
|
||||||
|
//
|
||||||
|
// fd is the filesystem context to act upon.
|
||||||
|
// key the parameter key to set.
|
||||||
|
// value is the parameter value to set.
|
||||||
|
func FsconfigSetString(fd int, key string, value string) (err error) {
|
||||||
|
var valuep *byte
|
||||||
|
if valuep, err = BytePtrFromString(value); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return fsconfigCommon(fd, FSCONFIG_SET_STRING, key, valuep, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FsconfigSetBinary is equivalent to fsconfig(2) called
|
||||||
|
// with cmd == FSCONFIG_SET_BINARY.
|
||||||
|
//
|
||||||
|
// fd is the filesystem context to act upon.
|
||||||
|
// key the parameter key to set.
|
||||||
|
// value is the parameter value to set.
|
||||||
|
func FsconfigSetBinary(fd int, key string, value []byte) (err error) {
|
||||||
|
if len(value) == 0 {
|
||||||
|
return EINVAL
|
||||||
|
}
|
||||||
|
return fsconfigCommon(fd, FSCONFIG_SET_BINARY, key, &value[0], len(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FsconfigSetPath is equivalent to fsconfig(2) called
|
||||||
|
// with cmd == FSCONFIG_SET_PATH.
|
||||||
|
//
|
||||||
|
// fd is the filesystem context to act upon.
|
||||||
|
// key the parameter key to set.
|
||||||
|
// path is a non-empty path for specified key.
|
||||||
|
// atfd is a file descriptor at which to start lookup from or AT_FDCWD.
|
||||||
|
func FsconfigSetPath(fd int, key string, path string, atfd int) (err error) {
|
||||||
|
var valuep *byte
|
||||||
|
if valuep, err = BytePtrFromString(path); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return fsconfigCommon(fd, FSCONFIG_SET_PATH, key, valuep, atfd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FsconfigSetPathEmpty is equivalent to fsconfig(2) called
|
||||||
|
// with cmd == FSCONFIG_SET_PATH_EMPTY. The same as
|
||||||
|
// FconfigSetPath but with AT_PATH_EMPTY implied.
|
||||||
|
func FsconfigSetPathEmpty(fd int, key string, path string, atfd int) (err error) {
|
||||||
|
var valuep *byte
|
||||||
|
if valuep, err = BytePtrFromString(path); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return fsconfigCommon(fd, FSCONFIG_SET_PATH_EMPTY, key, valuep, atfd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FsconfigSetFd is equivalent to fsconfig(2) called
|
||||||
|
// with cmd == FSCONFIG_SET_FD.
|
||||||
|
//
|
||||||
|
// fd is the filesystem context to act upon.
|
||||||
|
// key the parameter key to set.
|
||||||
|
// value is a file descriptor to be assigned to specified key.
|
||||||
|
func FsconfigSetFd(fd int, key string, value int) (err error) {
|
||||||
|
return fsconfigCommon(fd, FSCONFIG_SET_FD, key, nil, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FsconfigCreate is equivalent to fsconfig(2) called
|
||||||
|
// with cmd == FSCONFIG_CMD_CREATE.
|
||||||
|
//
|
||||||
|
// fd is the filesystem context to act upon.
|
||||||
|
func FsconfigCreate(fd int) (err error) {
|
||||||
|
return fsconfig(fd, FSCONFIG_CMD_CREATE, nil, nil, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FsconfigReconfigure is equivalent to fsconfig(2) called
|
||||||
|
// with cmd == FSCONFIG_CMD_RECONFIGURE.
|
||||||
|
//
|
||||||
|
// fd is the filesystem context to act upon.
|
||||||
|
func FsconfigReconfigure(fd int) (err error) {
|
||||||
|
return fsconfig(fd, FSCONFIG_CMD_RECONFIGURE, nil, nil, 0)
|
||||||
|
}
|
||||||
|
|
||||||
//sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
|
//sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
|
||||||
//sysnb Getpgid(pid int) (pgid int, err error)
|
//sysnb Getpgid(pid int) (pgid int, err error)
|
||||||
|
|
||||||
|
|
|
@ -1785,6 +1785,8 @@ const (
|
||||||
LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20
|
LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20
|
||||||
LANDLOCK_ACCESS_FS_TRUNCATE = 0x4000
|
LANDLOCK_ACCESS_FS_TRUNCATE = 0x4000
|
||||||
LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2
|
LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2
|
||||||
|
LANDLOCK_ACCESS_NET_BIND_TCP = 0x1
|
||||||
|
LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2
|
||||||
LANDLOCK_CREATE_RULESET_VERSION = 0x1
|
LANDLOCK_CREATE_RULESET_VERSION = 0x1
|
||||||
LINUX_REBOOT_CMD_CAD_OFF = 0x0
|
LINUX_REBOOT_CMD_CAD_OFF = 0x0
|
||||||
LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
|
LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
|
||||||
|
@ -2127,6 +2129,60 @@ const (
|
||||||
NFNL_SUBSYS_QUEUE = 0x3
|
NFNL_SUBSYS_QUEUE = 0x3
|
||||||
NFNL_SUBSYS_ULOG = 0x4
|
NFNL_SUBSYS_ULOG = 0x4
|
||||||
NFS_SUPER_MAGIC = 0x6969
|
NFS_SUPER_MAGIC = 0x6969
|
||||||
|
NFT_CHAIN_FLAGS = 0x7
|
||||||
|
NFT_CHAIN_MAXNAMELEN = 0x100
|
||||||
|
NFT_CT_MAX = 0x17
|
||||||
|
NFT_DATA_RESERVED_MASK = 0xffffff00
|
||||||
|
NFT_DATA_VALUE_MAXLEN = 0x40
|
||||||
|
NFT_EXTHDR_OP_MAX = 0x4
|
||||||
|
NFT_FIB_RESULT_MAX = 0x3
|
||||||
|
NFT_INNER_MASK = 0xf
|
||||||
|
NFT_LOGLEVEL_MAX = 0x8
|
||||||
|
NFT_NAME_MAXLEN = 0x100
|
||||||
|
NFT_NG_MAX = 0x1
|
||||||
|
NFT_OBJECT_CONNLIMIT = 0x5
|
||||||
|
NFT_OBJECT_COUNTER = 0x1
|
||||||
|
NFT_OBJECT_CT_EXPECT = 0x9
|
||||||
|
NFT_OBJECT_CT_HELPER = 0x3
|
||||||
|
NFT_OBJECT_CT_TIMEOUT = 0x7
|
||||||
|
NFT_OBJECT_LIMIT = 0x4
|
||||||
|
NFT_OBJECT_MAX = 0xa
|
||||||
|
NFT_OBJECT_QUOTA = 0x2
|
||||||
|
NFT_OBJECT_SECMARK = 0x8
|
||||||
|
NFT_OBJECT_SYNPROXY = 0xa
|
||||||
|
NFT_OBJECT_TUNNEL = 0x6
|
||||||
|
NFT_OBJECT_UNSPEC = 0x0
|
||||||
|
NFT_OBJ_MAXNAMELEN = 0x100
|
||||||
|
NFT_OSF_MAXGENRELEN = 0x10
|
||||||
|
NFT_QUEUE_FLAG_BYPASS = 0x1
|
||||||
|
NFT_QUEUE_FLAG_CPU_FANOUT = 0x2
|
||||||
|
NFT_QUEUE_FLAG_MASK = 0x3
|
||||||
|
NFT_REG32_COUNT = 0x10
|
||||||
|
NFT_REG32_SIZE = 0x4
|
||||||
|
NFT_REG_MAX = 0x4
|
||||||
|
NFT_REG_SIZE = 0x10
|
||||||
|
NFT_REJECT_ICMPX_MAX = 0x3
|
||||||
|
NFT_RT_MAX = 0x4
|
||||||
|
NFT_SECMARK_CTX_MAXLEN = 0x100
|
||||||
|
NFT_SET_MAXNAMELEN = 0x100
|
||||||
|
NFT_SOCKET_MAX = 0x3
|
||||||
|
NFT_TABLE_F_MASK = 0x3
|
||||||
|
NFT_TABLE_MAXNAMELEN = 0x100
|
||||||
|
NFT_TRACETYPE_MAX = 0x3
|
||||||
|
NFT_TUNNEL_F_MASK = 0x7
|
||||||
|
NFT_TUNNEL_MAX = 0x1
|
||||||
|
NFT_TUNNEL_MODE_MAX = 0x2
|
||||||
|
NFT_USERDATA_MAXLEN = 0x100
|
||||||
|
NFT_XFRM_KEY_MAX = 0x6
|
||||||
|
NF_NAT_RANGE_MAP_IPS = 0x1
|
||||||
|
NF_NAT_RANGE_MASK = 0x7f
|
||||||
|
NF_NAT_RANGE_NETMAP = 0x40
|
||||||
|
NF_NAT_RANGE_PERSISTENT = 0x8
|
||||||
|
NF_NAT_RANGE_PROTO_OFFSET = 0x20
|
||||||
|
NF_NAT_RANGE_PROTO_RANDOM = 0x4
|
||||||
|
NF_NAT_RANGE_PROTO_RANDOM_ALL = 0x14
|
||||||
|
NF_NAT_RANGE_PROTO_RANDOM_FULLY = 0x10
|
||||||
|
NF_NAT_RANGE_PROTO_SPECIFIED = 0x2
|
||||||
NILFS_SUPER_MAGIC = 0x3434
|
NILFS_SUPER_MAGIC = 0x3434
|
||||||
NL0 = 0x0
|
NL0 = 0x0
|
||||||
NL1 = 0x100
|
NL1 = 0x100
|
||||||
|
@ -2411,6 +2467,7 @@ const (
|
||||||
PR_MCE_KILL_GET = 0x22
|
PR_MCE_KILL_GET = 0x22
|
||||||
PR_MCE_KILL_LATE = 0x0
|
PR_MCE_KILL_LATE = 0x0
|
||||||
PR_MCE_KILL_SET = 0x1
|
PR_MCE_KILL_SET = 0x1
|
||||||
|
PR_MDWE_NO_INHERIT = 0x2
|
||||||
PR_MDWE_REFUSE_EXEC_GAIN = 0x1
|
PR_MDWE_REFUSE_EXEC_GAIN = 0x1
|
||||||
PR_MPX_DISABLE_MANAGEMENT = 0x2c
|
PR_MPX_DISABLE_MANAGEMENT = 0x2c
|
||||||
PR_MPX_ENABLE_MANAGEMENT = 0x2b
|
PR_MPX_ENABLE_MANAGEMENT = 0x2b
|
||||||
|
@ -2615,8 +2672,9 @@ const (
|
||||||
RTAX_FEATURES = 0xc
|
RTAX_FEATURES = 0xc
|
||||||
RTAX_FEATURE_ALLFRAG = 0x8
|
RTAX_FEATURE_ALLFRAG = 0x8
|
||||||
RTAX_FEATURE_ECN = 0x1
|
RTAX_FEATURE_ECN = 0x1
|
||||||
RTAX_FEATURE_MASK = 0xf
|
RTAX_FEATURE_MASK = 0x1f
|
||||||
RTAX_FEATURE_SACK = 0x2
|
RTAX_FEATURE_SACK = 0x2
|
||||||
|
RTAX_FEATURE_TCP_USEC_TS = 0x10
|
||||||
RTAX_FEATURE_TIMESTAMP = 0x4
|
RTAX_FEATURE_TIMESTAMP = 0x4
|
||||||
RTAX_HOPLIMIT = 0xa
|
RTAX_HOPLIMIT = 0xa
|
||||||
RTAX_INITCWND = 0xb
|
RTAX_INITCWND = 0xb
|
||||||
|
@ -2859,9 +2917,38 @@ const (
|
||||||
SCM_RIGHTS = 0x1
|
SCM_RIGHTS = 0x1
|
||||||
SCM_TIMESTAMP = 0x1d
|
SCM_TIMESTAMP = 0x1d
|
||||||
SC_LOG_FLUSH = 0x100000
|
SC_LOG_FLUSH = 0x100000
|
||||||
|
SECCOMP_ADDFD_FLAG_SEND = 0x2
|
||||||
|
SECCOMP_ADDFD_FLAG_SETFD = 0x1
|
||||||
|
SECCOMP_FILTER_FLAG_LOG = 0x2
|
||||||
|
SECCOMP_FILTER_FLAG_NEW_LISTENER = 0x8
|
||||||
|
SECCOMP_FILTER_FLAG_SPEC_ALLOW = 0x4
|
||||||
|
SECCOMP_FILTER_FLAG_TSYNC = 0x1
|
||||||
|
SECCOMP_FILTER_FLAG_TSYNC_ESRCH = 0x10
|
||||||
|
SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV = 0x20
|
||||||
|
SECCOMP_GET_ACTION_AVAIL = 0x2
|
||||||
|
SECCOMP_GET_NOTIF_SIZES = 0x3
|
||||||
|
SECCOMP_IOCTL_NOTIF_RECV = 0xc0502100
|
||||||
|
SECCOMP_IOCTL_NOTIF_SEND = 0xc0182101
|
||||||
|
SECCOMP_IOC_MAGIC = '!'
|
||||||
SECCOMP_MODE_DISABLED = 0x0
|
SECCOMP_MODE_DISABLED = 0x0
|
||||||
SECCOMP_MODE_FILTER = 0x2
|
SECCOMP_MODE_FILTER = 0x2
|
||||||
SECCOMP_MODE_STRICT = 0x1
|
SECCOMP_MODE_STRICT = 0x1
|
||||||
|
SECCOMP_RET_ACTION = 0x7fff0000
|
||||||
|
SECCOMP_RET_ACTION_FULL = 0xffff0000
|
||||||
|
SECCOMP_RET_ALLOW = 0x7fff0000
|
||||||
|
SECCOMP_RET_DATA = 0xffff
|
||||||
|
SECCOMP_RET_ERRNO = 0x50000
|
||||||
|
SECCOMP_RET_KILL = 0x0
|
||||||
|
SECCOMP_RET_KILL_PROCESS = 0x80000000
|
||||||
|
SECCOMP_RET_KILL_THREAD = 0x0
|
||||||
|
SECCOMP_RET_LOG = 0x7ffc0000
|
||||||
|
SECCOMP_RET_TRACE = 0x7ff00000
|
||||||
|
SECCOMP_RET_TRAP = 0x30000
|
||||||
|
SECCOMP_RET_USER_NOTIF = 0x7fc00000
|
||||||
|
SECCOMP_SET_MODE_FILTER = 0x1
|
||||||
|
SECCOMP_SET_MODE_STRICT = 0x0
|
||||||
|
SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP = 0x1
|
||||||
|
SECCOMP_USER_NOTIF_FLAG_CONTINUE = 0x1
|
||||||
SECRETMEM_MAGIC = 0x5345434d
|
SECRETMEM_MAGIC = 0x5345434d
|
||||||
SECURITYFS_MAGIC = 0x73636673
|
SECURITYFS_MAGIC = 0x73636673
|
||||||
SEEK_CUR = 0x1
|
SEEK_CUR = 0x1
|
||||||
|
@ -3021,6 +3108,7 @@ const (
|
||||||
SOL_TIPC = 0x10f
|
SOL_TIPC = 0x10f
|
||||||
SOL_TLS = 0x11a
|
SOL_TLS = 0x11a
|
||||||
SOL_UDP = 0x11
|
SOL_UDP = 0x11
|
||||||
|
SOL_VSOCK = 0x11f
|
||||||
SOL_X25 = 0x106
|
SOL_X25 = 0x106
|
||||||
SOL_XDP = 0x11b
|
SOL_XDP = 0x11b
|
||||||
SOMAXCONN = 0x1000
|
SOMAXCONN = 0x1000
|
||||||
|
|
|
@ -281,6 +281,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -282,6 +282,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -288,6 +288,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -278,6 +278,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -275,6 +275,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -281,6 +281,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x80
|
SFD_NONBLOCK = 0x80
|
||||||
SIOCATMARK = 0x40047307
|
SIOCATMARK = 0x40047307
|
||||||
|
|
|
@ -281,6 +281,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x80
|
SFD_NONBLOCK = 0x80
|
||||||
SIOCATMARK = 0x40047307
|
SIOCATMARK = 0x40047307
|
||||||
|
|
|
@ -281,6 +281,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x80
|
SFD_NONBLOCK = 0x80
|
||||||
SIOCATMARK = 0x40047307
|
SIOCATMARK = 0x40047307
|
||||||
|
|
|
@ -281,6 +281,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x80
|
SFD_NONBLOCK = 0x80
|
||||||
SIOCATMARK = 0x40047307
|
SIOCATMARK = 0x40047307
|
||||||
|
|
|
@ -336,6 +336,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -340,6 +340,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -340,6 +340,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -272,6 +272,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -344,6 +344,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x23
|
SCM_TIMESTAMPNS = 0x23
|
||||||
SCM_TXTIME = 0x3d
|
SCM_TXTIME = 0x3d
|
||||||
SCM_WIFI_STATUS = 0x29
|
SCM_WIFI_STATUS = 0x29
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
|
||||||
SFD_CLOEXEC = 0x80000
|
SFD_CLOEXEC = 0x80000
|
||||||
SFD_NONBLOCK = 0x800
|
SFD_NONBLOCK = 0x800
|
||||||
SIOCATMARK = 0x8905
|
SIOCATMARK = 0x8905
|
||||||
|
|
|
@ -335,6 +335,9 @@ const (
|
||||||
SCM_TIMESTAMPNS = 0x21
|
SCM_TIMESTAMPNS = 0x21
|
||||||
SCM_TXTIME = 0x3f
|
SCM_TXTIME = 0x3f
|
||||||
SCM_WIFI_STATUS = 0x25
|
SCM_WIFI_STATUS = 0x25
|
||||||
|
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||||
|
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
|
||||||
|
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
|
||||||
SFD_CLOEXEC = 0x400000
|
SFD_CLOEXEC = 0x400000
|
||||||
SFD_NONBLOCK = 0x4000
|
SFD_NONBLOCK = 0x4000
|
||||||
SF_FP = 0x38
|
SF_FP = 0x38
|
||||||
|
|
|
@ -906,6 +906,16 @@ func Fspick(dirfd int, pathName string, flags int) (fd int, err error) {
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error) {
|
||||||
|
_, _, e1 := Syscall6(SYS_FSCONFIG, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(value)), uintptr(aux), 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Getdents(fd int, buf []byte) (n int, err error) {
|
func Getdents(fd int, buf []byte) (n int, err error) {
|
||||||
var _p0 unsafe.Pointer
|
var _p0 unsafe.Pointer
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
|
|
|
@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
|
||||||
var libc_unveil_trampoline_addr uintptr
|
var libc_unveil_trampoline_addr uintptr
|
||||||
|
|
||||||
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
|
||||||
var libc_unveil_trampoline_addr uintptr
|
var libc_unveil_trampoline_addr uintptr
|
||||||
|
|
||||||
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
|
||||||
var libc_unveil_trampoline_addr uintptr
|
var libc_unveil_trampoline_addr uintptr
|
||||||
|
|
||||||
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
|
||||||
var libc_unveil_trampoline_addr uintptr
|
var libc_unveil_trampoline_addr uintptr
|
||||||
|
|
||||||
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
|
||||||
var libc_unveil_trampoline_addr uintptr
|
var libc_unveil_trampoline_addr uintptr
|
||||||
|
|
||||||
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
|
||||||
var libc_unveil_trampoline_addr uintptr
|
var libc_unveil_trampoline_addr uintptr
|
||||||
|
|
||||||
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
|
||||||
var libc_unveil_trampoline_addr uintptr
|
var libc_unveil_trampoline_addr uintptr
|
||||||
|
|
||||||
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -448,4 +448,8 @@ const (
|
||||||
SYS_SET_MEMPOLICY_HOME_NODE = 450
|
SYS_SET_MEMPOLICY_HOME_NODE = 450
|
||||||
SYS_CACHESTAT = 451
|
SYS_CACHESTAT = 451
|
||||||
SYS_FCHMODAT2 = 452
|
SYS_FCHMODAT2 = 452
|
||||||
|
SYS_MAP_SHADOW_STACK = 453
|
||||||
|
SYS_FUTEX_WAKE = 454
|
||||||
|
SYS_FUTEX_WAIT = 455
|
||||||
|
SYS_FUTEX_REQUEUE = 456
|
||||||
)
|
)
|
||||||
|
|
|
@ -371,4 +371,7 @@ const (
|
||||||
SYS_CACHESTAT = 451
|
SYS_CACHESTAT = 451
|
||||||
SYS_FCHMODAT2 = 452
|
SYS_FCHMODAT2 = 452
|
||||||
SYS_MAP_SHADOW_STACK = 453
|
SYS_MAP_SHADOW_STACK = 453
|
||||||
|
SYS_FUTEX_WAKE = 454
|
||||||
|
SYS_FUTEX_WAIT = 455
|
||||||
|
SYS_FUTEX_REQUEUE = 456
|
||||||
)
|
)
|
||||||
|
|
|
@ -412,4 +412,8 @@ const (
|
||||||
SYS_SET_MEMPOLICY_HOME_NODE = 450
|
SYS_SET_MEMPOLICY_HOME_NODE = 450
|
||||||
SYS_CACHESTAT = 451
|
SYS_CACHESTAT = 451
|
||||||
SYS_FCHMODAT2 = 452
|
SYS_FCHMODAT2 = 452
|
||||||
|
SYS_MAP_SHADOW_STACK = 453
|
||||||
|
SYS_FUTEX_WAKE = 454
|
||||||
|
SYS_FUTEX_WAIT = 455
|
||||||
|
SYS_FUTEX_REQUEUE = 456
|
||||||
)
|
)
|
||||||
|
|
|
@ -315,4 +315,8 @@ const (
|
||||||
SYS_SET_MEMPOLICY_HOME_NODE = 450
|
SYS_SET_MEMPOLICY_HOME_NODE = 450
|
||||||
SYS_CACHESTAT = 451
|
SYS_CACHESTAT = 451
|
||||||
SYS_FCHMODAT2 = 452
|
SYS_FCHMODAT2 = 452
|
||||||
|
SYS_MAP_SHADOW_STACK = 453
|
||||||
|
SYS_FUTEX_WAKE = 454
|
||||||
|
SYS_FUTEX_WAIT = 455
|
||||||
|
SYS_FUTEX_REQUEUE = 456
|
||||||
)
|
)
|
||||||
|
|
|
@ -309,4 +309,8 @@ const (
|
||||||
SYS_SET_MEMPOLICY_HOME_NODE = 450
|
SYS_SET_MEMPOLICY_HOME_NODE = 450
|
||||||
SYS_CACHESTAT = 451
|
SYS_CACHESTAT = 451
|
||||||
SYS_FCHMODAT2 = 452
|
SYS_FCHMODAT2 = 452
|
||||||
|
SYS_MAP_SHADOW_STACK = 453
|
||||||
|
SYS_FUTEX_WAKE = 454
|
||||||
|
SYS_FUTEX_WAIT = 455
|
||||||
|
SYS_FUTEX_REQUEUE = 456
|
||||||
)
|
)
|
||||||
|
|
|
@ -432,4 +432,8 @@ const (
|
||||||
SYS_SET_MEMPOLICY_HOME_NODE = 4450
|
SYS_SET_MEMPOLICY_HOME_NODE = 4450
|
||||||
SYS_CACHESTAT = 4451
|
SYS_CACHESTAT = 4451
|
||||||
SYS_FCHMODAT2 = 4452
|
SYS_FCHMODAT2 = 4452
|
||||||
|
SYS_MAP_SHADOW_STACK = 4453
|
||||||
|
SYS_FUTEX_WAKE = 4454
|
||||||
|
SYS_FUTEX_WAIT = 4455
|
||||||
|
SYS_FUTEX_REQUEUE = 4456
|
||||||
)
|
)
|
||||||
|
|
|
@ -362,4 +362,8 @@ const (
|
||||||
SYS_SET_MEMPOLICY_HOME_NODE = 5450
|
SYS_SET_MEMPOLICY_HOME_NODE = 5450
|
||||||
SYS_CACHESTAT = 5451
|
SYS_CACHESTAT = 5451
|
||||||
SYS_FCHMODAT2 = 5452
|
SYS_FCHMODAT2 = 5452
|
||||||
|
SYS_MAP_SHADOW_STACK = 5453
|
||||||
|
SYS_FUTEX_WAKE = 5454
|
||||||
|
SYS_FUTEX_WAIT = 5455
|
||||||
|
SYS_FUTEX_REQUEUE = 5456
|
||||||
)
|
)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue